amcap sample code 分析初步 --学习通用filter graph的构建技术

学习通用filter graph的构建技术

1 构造filter


我们现在要向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), 以及代表硬件(WDMVFW)的包裝Filter,必须通过枚举的方式来创建.

 


构造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,


 

todo:关于使用枚举的类型

后续补充

 


2 得到filter未连接pin

代码里暂时没使用,略过

2.5 【重要】补充filter的基础知识

补充一个陆其明推荐的 mpeg合成的filter设计

这里先不上图,直接一句话。

Video stream --> mpeg video encoder --> mpeg mux filter (合成)--> file writer

音频前两个是独立的,后续合并到mux

 

3 连接两个filter

关键词 addfilter

首先看搜索结果,没有使用书上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

再次分析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( pEncoderpMPEG2Demux_

//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

当前只看到encodermux的连接,其他写文件等filter connect 后续待发现。

 


4 【大量需要分析,未完成】寻找接口初步QueryInterface 

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,


关键词 findFilter

寻找FindPin为关键词,增加findfilter

本质上,是使用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的变更出发

amcap源代码,visual studio 亲测通过,打开摄像头设备。 // File: AMCap.h // // Desc: DirectShow sample code - audio/video capture. // // Copyright (c) Microsoft Corporation. All rights reserved. //------------------------------------------------------------------------------ // Macros #define SAFE_RELEASE(x) { if (x) x->Release(); x = NULL; } // device notification definitions #if (WINVER < 0x0500) #define DBT_DEVTYP_DEVICEINTERFACE 0x00000005 // device interface class #define DEVICE_NOTIFY_WINDOW_HANDLE 0x00000000 typedef PVOID HDEVNOTIFY; #endif extern "C" { typedef BOOL (/* WINUSERAPI */ WINAPI *PUnregisterDeviceNotification)( IN HDEVNOTIFY Handle ); typedef HDEVNOTIFY (/* WINUSERAPI */ WINAPI *PRegisterDeviceNotificationA)( IN HANDLE hRecipient, IN LPVOID NotificationFilter, IN DWORD Flags ); typedef HDEVNOTIFY (/* WINUSERAPI */ WINAPI *PRegisterDeviceNotificationW)( IN HANDLE hRecipient, IN LPVOID NotificationFilter, IN DWORD Flags ); } #ifdef UNICODE #define PRegisterDeviceNotification PRegisterDeviceNotificationW #else #define PRegisterDeviceNotification PRegisterDeviceNotificationA #endif // !UNICODE #if (WINVER < 0x0500) typedef struct _DEV_BROADCAST_DEVICEINTERFACE_A { DWORD dbcc_size; DWORD dbcc_devicetype; DWORD dbcc_reserved; GUID dbcc_classguid; char dbcc_name[1]; } DEV_BROADCAST_DEVICEINTERFACE_A, *PDEV_BROADCAST_DEVICEINTERFACE_A; typedef struct _DEV_BROADCAST_DEVICEINTERFACE_W { DWORD dbcc_size; DWORD dbcc_devicetype; DWORD dbcc_reserved; GUID dbcc_classguid; wchar_t dbcc_name[1]; } DEV_BROADCAST_DEVICEINTERFACE_W, *PDEV_BROADCAST_DEVICEINTERFACE_W; #ifdef UNICODE typedef DEV_BROADCAST_DEVICEINTERFACE_W DEV_BROADCAST_DEVICEINTERFACE; typedef PDEV_BROADCAST_DEVICEINTERFACE_W PDEV_BROADCAST_DEVICEINTERFACE; #else typedef DEV_BROADCAST_DEVICEINTERFACE_A DEV_BROADCAST_DEVICEINTERFACE; typedef PDEV_BROADCAST_DEVICEINTERFACE_A PDEV_BROADCAST_DEVICEINTERFACE; #endif // UNICODE #endif // WINVER
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值