编写自己的DirectShow Filter,除了编写实现功能的代码之外,要使自己的DLL称为一个Filter,还有一个重要的工作需要做,那就是注册信息。DirectShow Filter有两种信息注册,一种是包含Filter的DLL作为COM组件的注册信息,一种是注册Filter种类信息。
当应用程序通过CoCreateInstane创建Filter的时候,通过第一中注册信息定位DLL。
第二种信息注册后,可以通过系统设备枚举器和Filter Mapped定位到Filter,这种信息不是必须注册,当不注册时候,Filter被默认为CLSID_LegacyAmFilterCategory类型。
注册Filter种类信息分一下步骤:
一、声明Filter信息
AMOVIESETUP_MEDIATYPE、AMOVIESETUP_PIN、AMOVIESETUP_FILTER 1.AMOVIESETUP_MEDIATYPE typedef struct { const CLSID *clsMajorType;//主媒体类型 const CLSID *clsMinorType;//子媒体类型,可以使用MEDIASUBTYPE_NULL } REGPINTYPES; typedef REGPINTYPES AMOVIESETUP_MEDIATYPE, * PAMOVIESETUP_MEDIATYPE, * LPAMOVIESETUP_MEDIATYPE; 2.AMOVIESETUP_PIN typedef struct { LPWSTR strName;//已经废弃,可以填充Output或者是Input,表示pin的类型 BOOL bRendered;//TRUE表示这是Render的Input Pin,其他的都使用FALSE BOOL bOutput;//TRUE表示这是output Pin。 BOOL bZero;//TRUE表示Filter可以包含0个这个pin的实例。 BOOL bMany;//TRUE表示Filter可以包含两个或以上的这个pin的实例。 const CLSID *clsConnectsToFilter;//已经废弃,填充CLSID_NULL const WCHAR *strConnectsToPin;//已经废弃,填充NULL UINT nMediaTypes;//pin能支持多少中媒体类型 const REGPINTYPES *lpMediaType;// AMOVIESETUP_MEDIATYPE对象,描述媒体类型 } REGFILTERPINS; typedef REGFILTERPINS AMOVIESETUP_PIN, * PAMOVIESETUP_PIN, * LPAMOVIESETUP_PIN; 3.AMOVIESETUP_FILTER typedef struct _AMOVIESETUP_FILTER { const CLSID *clsID;//Filter的CLASSID const WCHAR *strName;//Filter的名字 DWORD dwMerit;// UINT nPins;//lpPin中AMOVIESETUP_PIN对象的个数 const AMOVIESETUP_PIN *lpPin;// AMOVIESETUP_PIN对象指针 } AMOVIESETUP_FILTER, * PAMOVIESETUP_FILTER, * FAR LPAMOVIESETUP_FILTER;
二、声明类工厂
CFactoryTemplate g_Templates[] = { { L"MyFilter"//Filter名字 , &CLSID_MyFilter//Filter的CLASSID , CMySourceFilter::CreateInstance//Filter的实例化接口 , NULL , &sudBallax }// AMOVIESETUP_FILTER对象 }; int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
三、重载DllRegisterServer
REGFILTER2 rf2FilterReg = { 1, // Pin使用AMOVIESETUP_PIN,所以版本为1 MERIT_NORMAL, // Merit. 1, // Number of pins. &sudPins // Pointer to pin information. }; STDAPI DllRegisterServer(void) { HRESULT hr; IFilterMapper2 *pFM2 = NULL; //此处注册DLL信息 hr = AMovieDllRegisterServer2(TRUE); if (FAILED(hr)) return hr; //以下注册Filter信息 hr = CoCreateInstance(CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER, IID_IFilterMapper2, (void **)&pFM2); if (FAILED(hr)) return hr; hr = pFM2->RegisterFilter( CLSID_SomeFilter, // Filter CLSID. g_wszName, // Filter name. NULL, // Device moniker. &CLSID_VideoCompressorCategory, // Video compressor category. g_wszName, // Instance data. &rf2FilterReg // Pointer to filter information. ); pFM2->Release(); return hr; }
四、注销Filter的函数
STDAPI DllUnregisterServer() { HRESULT hr; IFilterMapper2 *pFM2 = NULL; hr = AMovieDllRegisterServer2(FALSE); if (FAILED(hr)) return hr; hr = CoCreateInstance(CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER, IID_IFilterMapper2, (void **)&pFM2); if (FAILED(hr)) return hr; hr = pFM2->UnregisterFilter(&CLSID_VideoCompressorCategory, g_wszName, CLSID_SomeFilter); pFM2->Release(); return hr; }
IFilterMapper2的RegisterFilter接口注册Filter信息,接口的第四个参数决定Filter属于什么种类,如果使用CLSID_VideoCompressorCategory,在GraphEdit中看到的Filter就在Video Capture Source中。