1、选择所要创建的filter的用途,据此来选择基类。基类可以从CTransformFilter、CTransInPlaceFilter、CVideoTransformFilter和CBaseFilter中来选取。
(1) CTransInPlaceFilter提供了本地处理Sample的机制(Sample可以认为是存储一个视频帧的结构),当一个trans-in-place filter收到一个sample时,你可以通过重载它的Transform()函数来修改其中的数据,trans-in-place filter会在Transform()函数执行完后直接把这个sample传递给下一个filter。
(2) CTransformFilter完成的功能与CTransInPlaceFilter一样,它们的区别就是CTransformFilter总是把上游filter传递过来的sample复制一份,并把复制后的sample传递给下一个filter。当然,你可以通过重载Transform()函数来控制这个过程,包括修改其中的数据(这也是自己写filter的原因)。
(3)CVideoTransformFilter与CTransformFilter一样,只是多加了质量控制功能。
(4)以上三个filter都继承于CBaseFilter,所以如果想对filter进行更多的控制,就要直接从CBaseFilter来继承,但是所要做的工作也最多。
在这个例子中,我选择CTransformFilter,因为CTransInPlaceFilter太简单了,dx9sdk中的例子NullNull就是一个完整的CTransInPlaceFilter的框架,并且只是一个框架,什么工作也没有做,如果要用的话直接修改就可以用了。
2、在vc中选择win32 dll,创建一个dll,名字随便取,这里我取SplitFilter,选择空dll。
3、
然后,创建一个类CSplitFilter,继承自CTransformFilter,当然要选择public方式。
4、为filter生成一个
CLSID,可以使用Guidgen,它的用法是在命令行中打Guidgen,然后回车,Guidgen就执行了,单击New GUID就会生成一个新的GUID;单击Copy就可以把新生成的GUID复制到剪贴板上。然后在SplitFilter.h文件上粘贴进来,最后是这个样子:
//
// GUID
//
// {3DCD790F-B7A0-429a-B9E1-3CE3255D8D1C}
DEFINE_GUID(<<name>>,
0x3dcd790f, 0xb7a0, 0x429a, 0xb9, 0xe1, 0x3c, 0xe3, 0x25, 0x5d, 0x8d, 0x1c);
然后把其中的<<name>>换成自己设置的名字,如下:
// {3DCD790F-B7A0-429a-B9E1-3CE3255D8D1C}
DEFINE_GUID(CLSID_SplitFilter,
0x3dcd790f, 0xb7a0, 0x429a, 0xb9, 0xe1, 0x3c, 0xe3, 0x25, 0x5d, 0x8d, 0x1c);
然后在SplitFilter.cpp中加入#include <initguid.h>
再来修改构造函数,形式如下:
CSplitFilter::CSplitFilter() : CTransformFilter(NAME("SplitFilter"), 0, CLSID_SplitFilter)
{
}
5、处理媒体类型
首先要明白一点,两个filter连接,也就是两个filter的输出pin和输入pin在进行连接,这个工作是由输出pin发起的,由输入pin来检查媒体类型是否匹配,并决定是否接受这个连接。在CTransformFilter中协商媒体类型的工作是由CTransformFilter来完成的,这个工作本来是应该由pin来完成的,但是CTransformFilter中的pin只是简单的调用CTransformFilter中相应的函数而已,所以我们所有的工作只是重载CTransformFilter中的三个虚函数而已:
(1)实现CheckInputType(const CMediaType *mtIn)(不要问我如何添加这个函数,如果这个都不会的话趁早别看dshow了,赶紧去看vc的书去)。这个函数是由输入pin来调用,当上游输出pin要来进行连接的时候,我们的filter的输入pin就会调用这个函数来检查是否支持上游输出pin的媒体类型。其中的CMediaType类是对AM_MEDIA_TYPE结构的封装,AM_MEDIA_TYPE包含了有关的媒体类型,具体可查阅dxsdk文档。因为我这里只是写一个框架来为大家演示,功能只是传递sample,并不对数据有任何的修改,所以任何的格式都可以,所以不管什么格式我们都应该返回ok,实际函数如下:
HRESULT CSplitFilter::CheckInputType(const CMediaType *mtIn)
{
// Everything is good.
return S_OK;
}</