在DirectShow 中有很多Samples,WavDest就是其中一个,这个Fliter主要用于将采集到的视频流写入到指定的文件,文件格式是.WAV。如下来看看具体的代码实现。
对于每一个Filter都有一个固定的注册区代码,这是必不可少,如下代码;
// {3C78B8E2-6C4D-11d1-ADE2-0000F8754B99} static const GUID CLSID_WavDest = { 0x3c78b8e2, 0x6c4d, 0x11d1, { 0xad, 0xe2, 0x0, 0x0, 0xf8, 0x75, 0x4b, 0x99 } }; const AMOVIESETUP_FILTER sudWavDest = { &CLSID_WavDest, // clsID L"WAV Dest", // strName MERIT_DO_NOT_USE, // dwMerit 0, // nPins 0 // lpPin }; // Global data CFactoryTemplate g_Templates[]= { {L"WAV Dest", &CLSID_WavDest, CWavDestFilter::CreateInstance, NULL, &sudWavDest}, }; int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
这个Filter主要用于将采集的数据保存在指定的文件当中,因此它的最佳的父类应该是CTransformFilter,还有几个函数也是必须需要实现的如CreateInstance、Transform等,如下来看看CreateInstance是如何实现的。
if(SUCCEEDED(*phr)) { // Create an output pin so we can have control over the connection // media type. CWavDestOutputPin *pOut = new CWavDestOutputPin(this, phr); if(pOut) { if(SUCCEEDED(*phr)) { m_pOutput = pOut; } else { delete pOut; } } else { *phr = E_OUTOFMEMORY; } // // NOTE!: If we've created our own output pin we must also create // the input pin ourselves because the CTransformFilter base class // will create an extra output pin if the input pin wasn't created. // CTransformInputPin *pIn = new CTransformInputPin(NAME("Transform input pin"), this, // Owner filter phr, // Result code L"In"); // Pin name // a failed return code should delete the object if(pIn) { if(SUCCEEDED(*phr)) { m_pInput = pIn; } else { delete pIn; } } else { *phr = E_OUTOFMEMORY; } }
再来看看Transform代码是如何实现,还有WavDest是如何将数据保存到文件当中;在WavDest中数据处理流程是Transform函数->
Copy函数->StopStreaming函数,其中StopStreaming函数用于保存数据,该函数代码如下;
IStream *pStream; if(m_pOutput->IsConnected() == FALSE) return E_FAIL; IPin * pDwnstrmInputPin = m_pOutput->GetConnected(); if(!pDwnstrmInputPin) return E_FAIL; HRESULT hr = ((IMemInputPin *) pDwnstrmInputPin)->QueryInterface(IID_IStream, (void **)&pStream); if(SUCCEEDED(hr)) { BYTE *pb = (BYTE *)_alloca(m_cbHeader); RIFFLIST *pRiffWave = (RIFFLIST *)pb; RIFFCHUNK *pRiffFmt = (RIFFCHUNK *)(pRiffWave + 1); RIFFCHUNK *pRiffData = (RIFFCHUNK *)(((BYTE *)(pRiffFmt + 1)) + m_pInput->CurrentMediaType().FormatLength()); pRiffData->fcc = FCC('data'); pRiffData->cb = m_cbWavData; pRiffFmt->fcc = FCC('fmt '); pRiffFmt->cb = m_pInput->CurrentMediaType().FormatLength(); CopyMemory(pRiffFmt + 1, m_pInput->CurrentMediaType().Format(), pRiffFmt->cb); pRiffWave->fcc = FCC('RIFF'); pRiffWave->cb = m_cbWavData + m_cbHeader - sizeof(RIFFCHUNK); pRiffWave->fccListType = FCC('WAVE'); LARGE_INTEGER li; ZeroMemory(&li, sizeof(li)); hr = pStream->Seek(li, STREAM_SEEK_SET, 0); if(SUCCEEDED(hr)) { hr = pStream->Write(pb, m_cbHeader, 0); } pStream->Release(); }
其他代码都是常规实现,具体代码可以查看Directshow C++目录下的Samples.