我们现在要向Filter Graph中加入一个AVI Mux Filter代码如
IBaseFilter *pMux; hr=AddFilterByCLSXD(pGraph, CLSID_Avidest, L"AVI Mux", ipMux); if {SUCCEEDED(hr)) /* …•/ pMux->Release{); }
并不是所有的Filter都能通过CoCreatcInstance函數来创建,大部分注册在Audio Canpressore 目录下的 Filter (它们使用 了CLSID__ACMWrapper包装 Filter).
大部分注册在 Video Compressors 下的 Filter (它们用 CLSID_AV1Co包装Filter), 以及代表硬件(WDM或VFW)的包裝Filter,必须通过枚举的方式来创建.
看看代码里,搜索所有的CoCreateInstance,在amcap.cpp里,有一处知道,其他待续
amcap.cpp(893): HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC, amcap.cpp(2802): hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, amcap.cpp(3907): hr = CoCreateInstance((REFCLSID)CLSID_CaptureGraphBuilder2,
后续补充
代码里暂时没使用,略过
补充一个陆其明推荐的 mpeg合成的filter设计
这里先不上图,直接一句话。
Video stream --> mpeg video encoder --> mpeg mux filter (合成)--> file writer
音频前两个是独立的,后续合并到mux
首先看搜索结果,没有使用书上addfilterbyclsid,基本都是封装的addfilter
关注前面搜索结果
amcap.cpp(1104): hr = gcap.pFg->AddFilter(gcap.pVCap, gcap.wachFriendlyName); amcap.cpp(1294): hr = gcap.pFg->AddFilter(gcap.pACap, wachAudioFriendlyName); SampleCGB.cpp(335): hr = graph_->AddFilter( pMPEG2Demux_, L"Dump" ); SampleCGB.cpp(640): return graph_->AddFilter( static_cast<IBaseFilter *>( pMPEG2Demux_ ),L"MPEG2 Demux" ); SampleCGB.cpp(846): hr = graph_->AddFilter( pFilter, L"Encoder" ); SampleCGB.cpp(901): hr = graph_->AddFilter( pEncoder, L"Encoder" ); SampleCGB.cpp(1112): hr = graph_->AddFilter( pFilter, NULL ); SampleCGB.cpp(1255): hr = graph_->AddFilter( pEncoder, L"Audio Encoder" ); SampleCGB.cpp(1276): hr = graph_->AddFilter( pEncoder, L"Audio Encoder" ); SampleCGB.cpp(1311): hr = graph_->AddFilter( pFilter, L"Audio Encoder" ); SampleCGB.cpp(1393): hr = graph_->AddFilter( pVMR, L"VMR" ); SampleCGB.cpp(1500): hr = graph_->AddFilter( pAudioRenderer, L"Audio renderer" );
|
以下为例,有个问题,就是第二个参数,待分解。
// Add the video capture filter to the graph with its friendly name hr = gcap.pFg->AddFilter(gcap.pVCap,gcap.wachFriendlyName); if(hr != NOERROR) { ErrMsg(TEXT("Error %x: Cannot add vidcap to filtergraph"), hr); goto InitCapFiltersFail; } |
再次分析connectfilter,搜索代码,只有samplergb.cpp有,主程序没有
结果是
SampleCGB.h(190): HRESULT ConnectFilters(CComPtr<IBaseFilter> pUpFilter, SampleCGB.cpp(1018): HRESULT hr = ConnectFilters( SampleCGB.cpp(1121): hr = ConnectFilters( pEncoder, pFilter ); SampleCGB.cpp(1131): hr = ConnectFilters( pFilter, pMPEG2Demux_ ); SampleCGB.cpp(1258): SUCCEEDED( ConnectFilters( pEncoder, pMultiplexer ) ) SampleCGB.cpp(1279): SUCCEEDED( ConnectFilters( pEncoder, pMultiplexer ) ) SampleCGB.cpp(1324): hr = ConnectFilters( pFilter, pMultiplexer );
|
分析是
SampleCGB.h(190): HRESULT ConnectFilters(CComPtr<IBaseFilter> pUpFilter, SampleCGB.cpp(1018): HRESULT hr = ConnectFilters( pEncoder,pMPEG2Demux_ //try adirectconnection between codec and MPEG2Demux //意图尝试,函数位置同下,如果不成功,就分别连接。 SampleCGB.cpp(1121): hr = ConnectFilters( pEncoder, pFilter ); //在ISampleCaptureGraphBuilder::ConnectMultiplexerToMPEG2Demux( SampleCGB.cpp(1131): hr = ConnectFilters( pFilter, pMPEG2Demux_ ); //在ISampleCaptureGraphBuilder::ConnectMultiplexerToMPEG2Demux(
SampleCGB.cpp(1258): SUCCEEDED( ConnectFilters( pEncoder, pMultiplexer ) ) SampleCGB.cpp(1279): SUCCEEDED( ConnectFilters( pEncoder, pMultiplexer ) ) SampleCGB.cpp(1324): hr = ConnectFilters( pFilter, pMultiplexer ); |
回到基础上,
Video stream -->mpeg video encoder --> mpeg mux filter (合成)--> file writer
当前只看到encoder和mux的连接,其他写文件等filter connect 后续待发现。
以queryInterface为关键词,看到大量使用的地方,一句话来说,这是一个使用频率很高的api,必须要懂。
amcap.cpp(146): STDMETHODIMP QueryInterface(REFIID iid, void **p) amcap.cpp(804): if(S_OK == punk->QueryInterface(IID_IBaseFilter, (void **) &pf)) amcap.cpp(1204): if(pP->QueryInterface(IID_IKsPropertySet, amcap.cpp(1441): hr = gcap.pRender->QueryInterface(IID_IConfigAviMux, (void **)&gcap.pConfigAviMux); amcap.cpp(1514): gcap.pSink->QueryInterface( IID_IBaseFilter, reinterpret_cast<void **>( &sink ) ); amcap.cpp(1575): hr = gcap.pFg->QueryInterface(IID_IVideoWindow, (void **)&gcap.pVW); amcap.cpp(1625): hr = gcap.pFg->QueryInterface(IID_IMediaEventEx, (void **)&gcap.pME); amcap.cpp(1771): hr = gcap.pFg->QueryInterface(IID_IVideoWindow, (void **)&gcap.pVW); amcap.cpp(1844): hr = gcap.pFg->QueryInterface(IID_IMediaEventEx, (void **)&gcap.pME); amcap.cpp(1883): HRESULT hr = gcap.pFg->QueryInterface(IID_IMediaControl, (void **)&pMC); amcap.cpp(1917): HRESULT hr = gcap.pFg->QueryInterface(IID_IMediaControl, (void **)&pMC); amcap.cpp(1976): hr = gcap.pFg->QueryInterface(IID_IMediaControl, (void **)&pMC); //以上分别有start stop catpute等
//void MakeMenuOptions()以下 amcap.cpp(2081): HRESULT hr = gcap.pFg->QueryInterface(IID_IMediaControl, (void **)&pMC); amcap.cpp(2228): hr = gcap.pACap->QueryInterface(IID_ISpecifyPropertyPages, (void **)&pSpec); amcap.cpp(2262): hr = gcap.pVCap->QueryInterface(IID_ISpecifyPropertyPages, (void **)&pSpec); amcap.cpp(2289): hr = pSC->QueryInterface(IID_ISpecifyPropertyPages, (void **)&pSpec); amcap.cpp(2319): hr = pSC->QueryInterface(IID_ISpecifyPropertyPages, (void **)&pSpec); amcap.cpp(2349): hr = pX->QueryInterface(IID_IBaseFilter, (void **)&pXF); amcap.cpp(2352): hr = pX->QueryInterface(IID_ISpecifyPropertyPages, (void **)&pSpec); amcap.cpp(2370): hr = pX2->QueryInterface(IID_ISpecifyPropertyPages, (void **)&pSpec); amcap.cpp(2402): hr = pTV->QueryInterface(IID_ISpecifyPropertyPages, (void **)&pSpec); amcap.cpp(2430): hr = pSC->QueryInterface(IID_ISpecifyPropertyPages, (void **)&pSpec); amcap.cpp(2453): hr = pTVA->QueryInterface(IID_ISpecifyPropertyPages, (void **)&pSpec);
//以下: //AppCommand()Process all of our WM_COMMAND messages. amcap.cpp(3346): hr = gcap.pVCap->QueryInterface(IID_ISpecifyPropertyPages, amcap.cpp(3396): hr = pSC->QueryInterface(IID_ISpecifyPropertyPages, amcap.cpp(3472): hr = pSC->QueryInterface(IID_ISpecifyPropertyPages, amcap.cpp(3508): hr = pX->QueryInterface(IID_ISpecifyPropertyPages, amcap.cpp(3537): hr = pTV->QueryInterface(IID_ISpecifyPropertyPages, amcap.cpp(3557): hr = gcap.pACap->QueryInterface(IID_ISpecifyPropertyPages, amcap.cpp(3586): hr = pSC->QueryInterface(IID_ISpecifyPropertyPages, amcap.cpp(3618): hr = pX->QueryInterface(IID_IBaseFilter, (void **)&pXF); amcap.cpp(3626): hr = pX2->QueryInterface(IID_ISpecifyPropertyPages, amcap.cpp(3653): hr = pTVA->QueryInterface(IID_ISpecifyPropertyPages,
|
本质上,是使用queryInterface函数寻找
结果很多,尤其在amcap函数中,
以关键词FindPin搜索,结果如下,画出重点分析区域
AMCap\SampleCGB.h(96): STDMETHOD(FindPin)( IUnknown *pSource, AMCap\SampleCGB.h(136): HRESULT FindPin( AMCap\amcap.cpp(1320): hr = gcap.pBuilder->FindPin(gcap.pVCap, PINDIR_OUTPUT, &PIN_CATEGORY_VBI, AMCap\amcap.cpp(1323): hr = gcap.pBuilder->FindPin(gcap.pVCap, PINDIR_OUTPUT, &PIN_CATEGORY_CC, AMCap\SampleCGB.cpp(199):ISampleCaptureGraphBuilder::FindPin( IUnknown *pSource, AMCap\SampleCGB.cpp(207): return graphBuilder2_->FindPin( pSource, pindir, pCategory, pType, AMCap\SampleCGB.cpp(508):HRESULT ISampleCaptureGraphBuilder::FindPin( AMCap\SampleCGB.cpp(804): hr = FindPin( pFilter, pinMedium, PINDIR_INPUT, TRUE, pPin ); AMCap\SampleCGB.cpp(1419): hr = graphBuilder2_->FindPin( AMCap\SampleCGB.cpp(1507): hr = graphBuilder2_->FindPin(
|
当前分析以上findpin,发现主要集中在寻找pin,执行关闭操作
// create the capture filters of the graph. We need to keep them loaded from // the beginning, so we can set parameters on them and have them remembered // BOOL InitCapFilters() { //********// SkipAudio: // Can this filter do closed captioning? IPin *pPin; hr = gcap.pBuilder->FindPin(gcap.pVCap, PINDIR_OUTPUT, &PIN_CATEGORY_VBI, NULL, FALSE, 0, &pPin);//------------------请关注此 if(hr != S_OK) hr = gcap.pBuilder->FindPin(gcap.pVCap, PINDIR_OUTPUT, &PIN_CATEGORY_CC, NULL, FALSE, 0, &pPin); if(hr == S_OK) { pPin->Release(); gcap.fCCAvail = TRUE; } else { gcap.fCapCC = FALSE; // can't capture it, then }
以上都是以局部api来看使用,这样脱离功能的学习,有点片面。
最好从功能角度上出发.下一步结合amcap的变更出发