开发Transform filter 引用自(智慧的鱼 http://blog.csdn.net/aoosang/)

摘要:本篇文档主要讲述了利用Directshow开发传输filter 时应该注意的一些事情。


在开发自己的filter之前,看看DMO(DirectX Media Object)是否满足你的要求,因为DMO可以做许多和filter相同的工作,但是开发DMO比开发filter要简单多了。开发transform filter主要有下面的几个步骤,努力的遵循吧
第一步选择一个基类
下面的基类适合开发transform filter。
CTransformFilter就是为了transform filter而设计的基类,这个类中有分开的输入和输出buffers,这种类型的filter有时也称作copy-transform filter,当一个copy-transform filter接收到一个输入samples的时候,它就将sample写入到一块新的输出buffer中,然后将这个新的buffer传递给下一个filter。
CTransInPlaceFilter,这个类型的filter在原来的buffer里修改data,也叫trans-in-place filters.
当这种类型的filter接收到一个sample,它改变这个sample中的数据,然后将sample传递下去,这种类型的输入pin和输出pin总是按照某个媒体类型连接起来。
CVideoTransformFilter这个类型的filter仅仅是为了视频解码器设计的。从CTransFormFilter派生而来,但是这个filter可以根据下游的render自动的丢弃data。
CBaseFilter是个总基类,所有的filter都是从这个类派生出去的。如果上面的filter都不适合你,那么你只有自己从这个基类中派生了。
第二步声明自己的Filter 类
首先声明一个从基类派生的c++类
class CRleFilter : public CTransformFilter
{
/* Declarations will go here. */
};
每个filter类都需要连接的pin类。根据你的需要,你要派生和你的filter连接的pin类。
你还要给你的filter设置一个不能重复的CLSID,你可以利用Guidgen or Uuidgen来产生一个128位CLSID,切忌不要拷贝其它的filter的。有很多种方法来声明CLSID,下面的例子使用了DEFINE_GUID宏。
[RleFilt.h]
// {1915C5C7-02AA-415f-890F-76D94C85AAF1}
DEFINE_GUID(CLSID_RLEFilter,
0x1915c5c7, 0x2aa, 0x415f, 0x89, 0xf, 0x76, 0xd9, 0x4c, 0x85, 0xaa, 0xf1);

[RleFilt.cpp]
#include <initguid.h>
#include "RleFilt.h"
然后,给你的filter写一个构造函数
CRleFilter::CRleFilter()
: CTransformFilter(NAME("My RLE Encoder"), 0, CLSID_RLEFilter)
{
/* Initialize any private variables here. */
}
注意,构造函数中有个参数就是我前面定义的CLSID。
第三步 支持媒体类戏协议
当两个pin连接的时候,他们必须就某种媒体类型达成一致协议,否则连接失败,数据媒体类型描述了数据的格式,如果没有媒体类型,一个filter可能传递一种类型的数据,然后其它的filte却不能识别这种数据。
Pin连接的时候达成协议的机制主要通过IPin::ReceiveConnection方法来实现的。输出pin用某种媒体类型作参数调用输入pin上的这个方法,输入pin要么接受,要么拒绝。如果输入pin拒绝连接,那么输出pin更改一下媒体类型继续连接,直至所有的媒体类型都连接一遍,如果没有找到合适的媒体的类型,那么连接失败。
在输入pin也可以通过IPin::EnumMediaTypes方法来任意的枚举它所支持的媒体类型list。输出pin可以通过这个list也可以检查是否支持某种媒体类型。
CTransformFilter实现一个通用的框架。如下
1 输入pin没有首选的媒体类型,这个主要看上游的filter提议的媒体类型。对于视频数据,媒体类型包括图片的大小,和桢率,这个信息必须由上游的源filter或者parser filter提供。对于音频数据,设置的数据格式就小了许多,因此,要重载输入pin的CBasePin::GetMediaType
2 当上游的filter提议一个媒体类型进行连接的时候,输入pin就调用
CTransformFilter::CheckInputType方法,这个方法拒绝和接受媒体类型。
3 只有输入pin连接以后,输出pin才能够连接,这个是属于transform filter的一个特性。大多数情况下,filter在设置输出pin的type之前一定要设置好输入pin的类型
4当输出pin没有连接的时候,它向下游filter连接的时候,要枚举本filter支持的媒体类型,形成一个list,他通过调用CTransformFilter::GetMediaType方法来产生这个list,输出pin会就下游filter所支持的所有的媒体类型进行连接
5 为了检测输入pin是否支持某个特定的输出媒体类型,输出pin通过调用CTransformFilter::CheckTransform方法。
上面列出的三个CTransformFilter方法都是纯虚函数,因此你的filter必须实现这三个函数
当上游的filter连接的时候提议一个媒体类型,那么输入pin就会调用函数
virtual HRESULT CheckInputType(const CMediaType* mtIn) pure;
这个函数包含了一个CMediaType类型的对象指针,这个类型封装了一个AM_MEDIA_TYPE结构。在这个函数中,你要检查AM_MEDIA_TYPE结构的中相关的field,如果该结构中有任何fied不合法,就返回VFW_E_TYPE_NOT_ACCEPTED,如果所有的媒体类型都是正确的,返还S_OK
,例如,在RLE编码filter,输入类型必须是8位或者4位的没有压缩的RGB视频。没有必要支持其它的输入格式,例如16,24位,因为那样,filter还得进行转换。下面的例子假定filter只支持8位的视频,不支持4位的视频
HRESULT CRleFilter::CheckInputType(const CMediaType *mtIn)
{

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值