stdapi dllunregisterserver()
{
return amoviedllregisterserver2( false );
}
当然,在dllregisterserver and dllunregisterserver 函数中,你可以根据需要定制自己的注册信息,如果你的组件包含一个过滤器,你就要自己来做一下额外的工作了,具体的你可以下节how to register directshow filters.
在你的module-definition (.def) file文件中,除了进入点函数,你要导出下面的函数,实例如
exports
dllgetclassobject private
dllcanunloadnow private
dllregisterserver private
dllunregisterserver private
你可以用regsvr32.exe来注册你的组件
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;