虽然网上已有很多关于DirectShow写source filter的资料,不过很多刚开始学的朋友总说讲的不是很清楚(可能其中作者省略了许多他认为简
单的过程),读者总希望看到象第一步怎么做,第二步怎么做....这样的demo。其实写你的第一个filter是有一定难度的,只要过了这关以后
就容易多了。
由于最近需要自己写一个push推模式的source filter,加上刚激活了Blog,不好意思Blog上没有一篇文章,所以将写这个filter的过程写下来
,为了照顾刚开始学的朋友,我采用第一步第二步....这样的方式尽可能的讲解详细,相信你按照这个步骤一定没问题的,对于vc中DirectSho
w开发环境的配置,这里不做讲解。下面开始:
(vc 6.0 + DirectShow 9.0)
我也记得刚学时候的迷茫,所以会尽量详细每个过程,所以很多是sdk的例子我没改动它,没讲的是我提供的源代码里面我加有比较详细的注释
,可以配合我提供的源代码一起看。
第一步:建立工程
File->New->Project选择Win32 Dynamic-Link Library,(由于是个demo,名字我用的Push_Test_01)->Next后选择A simple DLL project(这里
为了避免自己写DllMain的麻烦,所以没选An empty DLL project)->可以Finish了
到这里工程建立结束。
第二步:相关设置和需要加入的文件等操作
首先将Debug方式改为Release。接着Project->Seetings->Link里的Output file
name从Release/Push_Test_01.dll改为Release/Push_Test_01.ax。
在工程目录下建立一个文本文件,修改名字为Push_Test_01.def。将其加入工程:Project->Add to project->Files 选择Push_Test_01.def后
加入。
对Push_Test_01.def进行修改,FileView->Source Files 双击Push_Test_01.def后输入:
LIBRARY Push_Test_01.ax
EXPORTS
DllMain PRIVATE
DllGetClassObject PRIVATE
DllCanUnloadNow PRIVATE
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE
,确定project->Seetings->link下Object/library modules里面为:
strmbase.lib msvcrt.lib quartz.lib vfw32.lib winmm.lib kernel32.lib advapi32.lib version.lib largeint.lib user32.lib
gdi32.lib comctl32.lib ole32.lib olepro32.lib oleaut32.lib uuid.lib
添加头文件:
#include
#include
#include
生成全球唯一标识,这里这样
DEFINE_GUID(CLSID_PushTest,
0xfd501041, 0x8ebe, 0x11ce, 0x81, 0x83, 0x00, 0xaa, 0x00, 0x57, 0x7d, 0xa1);
第三步:注册等函数的添加
首先修改入口函数,并添加注册和反注册函数,操作后的内容如下:
//注册
STDAPI DllRegisterServer()
{
return AMovieDllRegisterServer2(TRUE);
}
//反注册
STDAPI DllUnregisterServer()
{
return AMovieDllRegisterServer2(FALSE);
}
//filter的入口函数
extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
BOOL APIENTRY DllMain(HANDLE hModule,
DWORD dwReason,
LPVOID lpReserved)
{
return DllEntryPoint((HINSTANCE)(hModule), dwReason, lpReserved);
}
此时编译会有class CFactoryTemplate没实现等错误,下面我们来实现它。
添加下面的代码,每个地方我基本都加了大体意思的注释:
/**************开始填写注册信息***************/
//媒体类型
const AMOVIESETUP_MEDIATYPE sudOpPinTypes =
{
&MEDIATYPE_Video, // Major type 主类型
&MEDIASUBTYPE_NULL // Minor type sub类型,可以为MEDIASUBTYPE_NULL
};
//pin的信息
const AMOVIESETUP_PIN sudOpPin =
{
L"Output", // Pin string name pin的名字
FALSE, // Is it rendered 输入pin有用,输出pin一般为FALSE
TRUE, // Is it an output TRUE表示是输出pin,不然是输入pin
FALSE, // Can we have none 是否能不实例化
FALSE, // Can we have many 是否能创建多个同这样类型的pin
&CLSID_NULL, // Connects to filter 连接的filter类
NULL, // Connects to pin 该pin要连接的pin的类
1, // Number of types 该pin支持的媒体类型
&sudOpPinTypes // Pin details 该pin的媒体类型的描述
};
const AMOVIESETUP_FILTER sudBallax =
{
&CLSID_PushTest, // Filter CLSID 该filter的类标志
L"Push_Test", // String name 该filter的名字
MERIT_DO_NOT_USE, // Filter merit 该filter的Merit值
1, // Number pins 该filter的pin的数目
&sudOpPin // Pin details 该filter的pin的描述
};
//创建实例时用,有类,名字等需要的信息
CFactoryTemplate g_Templates[] = {
{
L"Push_Test" //filter的名字
, &CLSID_PushTest //对象的类标识
, PushTestFilter::CreateInstance //创建一个实例用的函数
, NULL //
, &sudBallax //filter的注册信息
}
};
int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
通过上面的注释,我们看到该filter有一个输出pin,支持Video类型等等信息,不多说了。
这里主要对PushTestFilter::CreateInstance //创建一个实例用的函数
说明一下!!PushTestFilter就是我们的filter类!!在下面实现它。
第四步:filter类