DirectShow Filter注册步骤及注册函数详解(转)

为了用.def文件创建DLL,往该工程中加入一个文本文件,命名为MyDll.def,再在该文件中加入如下代码:

LIBRARY MyFilter.ax
EXPORTS
DllMain PRIVATE
DllGetClassObject PRIVATE
DllCanUnloadNow PRIVATE
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE

其中LIBRARY语句说明该def文件是属于相应DLL的,EXPORTS语句下列出要导出的函数名称。我们可以在.def文件中的导出函数后加@n,如Max@1,Min@2,表示要导出的函数顺序号,在进行显式连时可以用到它。该DLL编译成功后,打开工程中的Debug目录,同样也会看到MyDll.dll和MyDll.lib文件。

然后要定义这些函数的实现了,其实这些工作dshow的基类里都已经替我们做好了,我们所要做的就拿来用就是了,最重要的三个函数的实现一般如下 

STDAPI DllRegisterServer()
{
  return AMovieDllRegisterServer2(TRUE);
}
STDAPI DllUnregisterServer()
{
  return AMovieDllRegisterServer2(FALSE);
}
extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason,  LPVOID lpReserved)
{
   return DllEntryPoint((HINSTANCE)(hModule), dwReason, lpReserved);
}

其中DllEntryPoint 是在C:\DX90SDK\Samples\C++\DirectShow\BaseClasses\dllentry.cpp定义的,如果感兴趣我们可以去看看它的定义。 AMovieDllRegisterServer2函数是在下面 C:\DX90SDK\Samples\C++\DirectShow\BaseClasses\dllsetup.cpp这个文件定义的,具体实现可以自己看看。

提示:也可以不定义和导出DllMain函数,而在VC的项目设置中指定一个入口函数,比如在VC的菜单中选择Project—Settings—Link, 在弹出的对话框中的Caregory中选择Output,然后在Entry-point symbol中输入DllEntryPoint@12。

l         如果安装的SDK版本是9.0以前的,编译Debug版本时。还需要确认定义了DEBUG宏,即在VC的菜单中选择VC的菜单中选择Project—Settings—C/C++,在弹出的对话框中的Category中选择Preprocessor,然后在Preprocessor definitions中确认已经定义DEBUG.

提示:配置Filter开发环境的捷径,如对照着SDK中的Filter例子项目逐项copy—paste过来;或者复制一个Filter例子项目,并直接在它的基础上修改,开发新的Filter.

另外,除了配置Filter项目外,还需将Direct SDK的Include和lib目录配置到VC的系统目录中去,并且放在标准的VC目录之前,以保证编译器能够拿到最新版本的源文件。配置方法为,打开VC,选择菜单项Tools—Options—Directories,在弹出的对话框中的Show directories for中选择Include files, 配置如下:

D:\DXSDK90\Include

D:\DXSDK90\SAMPLES\C++\DIRECTSHOW\BASECLASSES

D:\DXSDK90\SAMPLES\C++\COMMON\INCLUDE

C:\Program Files\Microsoft Visual Studio\VC98\INCLUDE

C:\Program Files\Microsoft Visual Studio\VC98\MFC\INCLUDE

C:\Program Files\Microsoft Visual Studio\VC98\ATL\INCLUDE

再在Show directories for中选择Library files, 配置如下:

D:\DXSDK90\Lib

D:\DXSDK90\SAMPLES\C++\DIRECTSHOW\BASECLASSES\DEBUG

D:\DXSDK90\SAMPLES\C++\DIRECTSHOW\BASECLASSES\RESEASE

C:\PROGRAM FILES\MICROSOFT SDK\LIB

C:\Program Files\Microsoft Visual Studio\VC98\LIB

C:\Program Files\Microsoft Visual Studio\VC98\MFC\LIB

 

 

编写自己的 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 中。

posted @ 2014-08-06 17:46  江君令  阅读(944)  评论(0编辑  收藏  举报