3How to Register DirectShow Filters.

3How to Register DirectShow Filters.
Directshow的filter一般都注册在两个地方
1 包含filter的DLL一般都注册为filter的COM 服务器,当用户调用CoCreateInstance来创建一个filter的时候,微软的COM库就从这个注册表的入口加载DLL。
2 另外,filter可以注册到filter 种类里,这样,System Device Enumerator and the Filter Mapper就可以找到filter了。
第二种注册不是必须的,只要filter注册成为com服务器,一个应用程序就可以创建一个filter 并将它加入到 filter Graph中,但是,如果你想要你的filter 可以被System Device Enumerator and the Filter Mapper发现,你必须注册到filter 种类里。
Com服务器的入口注册有下列以些键值
HKEY_CLASSES_ROOT
CLSID
Filter CLSID
REG_SZ: (Default) = Friendly name

InprocServer32
REG_SZ: (Default) = File name of the DLL
REG_SZ: ThreadingModel = Both
注册成filter 种类里需要下面的键值
HKEY_CLASSES_ROOT
CLSID
Category
Instance
Filter CLSID
REG_SZ: CLSID = Filter CLSID
REG_BINARY: FilterData = Filter information
REG_SZ: FriendlyName = Friendly name
Category is the GUID of a filter category.
所有的filter信息在注册表的filter种类都如下所示
HKEY_CLASSES_ROOT\CLSID\{DA4E3DA0-D07D-11d0-BD50-00A0C911CE86}\Instance
1 声明filter信息Declaring Filter Information
第一步要声明filter的信息,directshow定义了如下的结构来声明filter ,pin和media Types
Structure Description
AMOVIESETUP_FILTER Describes a filter.
AMOVIESETUP_PIN Describes a pin.
AMOVIESETUP_MEDIATYPE Describes a media type.
这些结构是必须的。
AMOVEIESETUP_FILTER结构包含一个指针指向AMOVIESETUP_PIN结构数组,这两个结构中都有一个指针指向AMOVEIESETUP_MEDIATYPE。这些结构提供了足够的信息可以让IFilterMapper2指针找到filter 的位置。但是,这并不能完全描述一个filter,例如,如果一个filter创建了一个pin的多个实例,你只需要声明一个AMOVIESETUP_PIN结构即可。同样,一个filter 没有必须支持注册的所有的媒体类型,也没有必要注册所有的媒体类型。
在你的DLL中声明一些全局的Set_up结构变量,如下
static const WCHAR g_wszName[] = L"Some Filter";

AMOVIESETUP_MEDIATYPE sudMediaTypes[] = {
{ &MEDIATYPE_Video, &MEDIASUBTYPE_RGB24 },
{ &MEDIATYPE_Video, &MEDIASUBTYPE_RGB32 },
};

AMOVIESETUP_PIN sudOutputPin = {
L"", // Obsolete, not used.
FALSE, // Is this pin rendered?
TRUE, // Is it an output pin?
FALSE, // Can the filter create zero instances?
FALSE, // Does the filter create multiple instances?
&GUID_NULL, // Obsolete.
NULL, // Obsolete.
2, // Number of media types.
sudMediaTypes // Pointer to media types.
};

AMOVIESETUP_FILTER sudFilterReg = {
&CLSID_SomeFilter, // Filter CLSID.
g_wszName, // Filter name.
MERIT_NORMAL, // Merit.
1, // Number of pin types.
&sudOutputPin // Pointer to pin information.
};
Filter的名字被声明成静态全局变量,因为它有可能在其它地方用到。
2 声明类厂模板数组Declaring the Factory Template
CFactoryTemplate g_Templates[] = {
{
g_wszName, // Name.上面定义的全局变量
&CLSID_SomeFilter, // CLSID.
CSomeFilter::CreateInstance, // Creation function.
NULL,
&sudFilterReg // Pointer to filter information.
}
};
int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
3生成DllRegisterServer
最后一步是生成DllRegisterServer函数,包含组件的DLL必须导出这个函数,这个函数在安装的时候被调用,或者当用户运行Regsvr32.exe时调用到。
简单的实现如下
STDAPI DllRegisterServer(void)
{
return AMovieDllRegisterServer2(TRUE);
}
AMovieDllRegisterServer2对于g_Templates数组中的所有组件都创建注册表入口,但是这个函数有一些限制,第一,它将所有的filter都注册到"DirectShow Filters"类下(CLSID_LegacyAmFilterCategory),其实并非所有的filter都属于这个种类。例如,捕捉filter和压缩filter就有他们自己的种类,第二,如果你的filte支持一个硬件设备,你必须要注册额外的两个信息the medium and the pin category.,但是AMovieDLLRegisterServer2并不支持,pin 的种类定义了一个pin的函数方法。Mediums和硬件的驱动有关。
如果你要注册filter的种类,medium或者pin的种类,你可以在DllRegisterServer()中调用IFilterMapper2::RegisterFilter,这个方法有个REGFILTER2结构,包含了filter的信息。
为了支持复杂的情况,REGFILTER2结构支持两种不同格式pin的注册,dwVersion表示两种格式
如果dwVersion为1,pin的类型就是AMOVIESETUP_PIN
如果dwVersion为2,拼得类型就是REGFILTERPINS2.
REGFILTERPINS2.结构中包含mediums和pin的categories
下面的例子演示了,如何在DllRegistServer中调用IFilterMapper2::RegisterFilter
REGFILTER2 rf2FilterReg = {
1, // Version 1 (no pin mediums or pin category).
MERIT_NORMAL, // Merit.
1, // Number of pins.
&sudPins // Pointer to pin information.
};

STDAPI DllRegisterServer(void)
{
HRESULT hr;
IFilterMapper2 *pFM2 = NULL;

hr = AMovieDllRegisterServer2(TRUE);
if (FAILED(hr))
return hr;

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;
}
4filter注册指南
Filter的注册信息决定了,在filter Graph管理器中如何Intelligent Connect.。因此,你必须要遵从下列的规则,使得你的filter能够正常运行。
1 你是否需要在注册表中保存你的filter数据,对于许多filter来说,没有必要让filter Mapper和System Device Enumerator来发现你的filter,只要你注册了你的filter,你的应用程序通过
ConCreateInstance方法来创建你的filter,此时,忽略了类厂模板中的AMOVIESETUP_FILTER结构,缺点是,在GraphEdit中看不到你的filter。
2选择正确的filter 种类,缺省的Directshow Filters可能适用于大多数的filter,但是如果你的filter有特殊的用处,你要选择一个恰当的种类
3避免在pin的AMOVIESETUP_MEDIATYPE结构中使用MEDIATYPE_None, MEDIASUBTYPE_None, or GUID_NULL,IFilterMapper2会将这些视做通配符。
4下面是一些建议的最小******不明白
Type of filter Recommended merit
Default renderer MERIT_PREFERRED. For standard media types, however, a custom renderer should never be the default.
Non-default renderer MERIT_DO_NOT_USE or MERIT_UNLIKELY
Mux MERIT_DO_NOT_USE
Decoder MERIT_NORMAL
Spitter, parser MERIT_NORMAL or lower
Special purpose filter; any filter that is created directly by the application MERIT_DO_NOT_USE
Capture MERIT_DO_NOT_USE
"Fallback" filter; for example, the Color Space Converter Filter
MERIT_UNLIKELY

5不要将接受24位RGB的filter注册到Directshow filter,你的filter将会干扰Color Space Converter filter.工作
5 反注册
为了反注册filter,
要提供一个DllUnregisterServer方法,在这个方法中,调用AMovieDllRegisterServer2,注意传递参数,FASLE,如果你是使用IFilterMapper2::RegisterFilter注册的你的filter,那么你必须要用IFilterMapper2::UnregisterFilter方法来反注册你的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;
}

原文地址:https://www.cnblogs.com/wqj1212/p/2443076.html