aduadu

aduadu

0个粉丝

98

问答

0

专栏

45

资料

aduadu  发布于  2008-06-04 21:23:10
采纳率 0%
98个问答
3620

DirectShow系统初级指南

 
如何写自己的Filter

  首先,从VC++的项目开始(请确认你已经给VC++ 配置好了DirectX的开发环境)。写自己的Filter,第一步是使用VC++建立一个Filter的项目。由于DirectX SDK提供了很多Filter的例子项目(位于DXSDK\samples\Multimedia\DirectShow\ Filters目录下),最简单的方法就是拷贝一个,然后再在此基础上修改。但如果你是Filter开发的初学者,笔者并不赞成这么做。

  自己新建一个Filter项目也很简单。使用VC++的向导,建立一个空的”Win32 Dynamic-link Library”项目。注意,几个文件是必须有的:.def文件,定义四个导出函数;定义Filter类的.cpp文件和.h文件,并在.cpp文件中定义Filter的注册信息以及两个Filter的注册函数:DllRegisterServer和DllUnregisterServer。(注: Filter的注册信息是Filter在注册时写到注册表里的内容,格式可以参考SDK的示例代码,Filter相关的GUID务必使用 GuidGen.exe产生。)接下去进行项目的设置(Project->Settings…)。此时,你可以打开一个SDK的例子项目进行对比,有些宏定义完全可以照抄,最后注意将输出文件的扩展名改为.ax。

  上一讲曾经提到过,在写Filter之前,选择一个合适的Filter基类是至关重要的。为此,你必须对几个Filter的基类有相当的了解。在实际应用中,Filter的基类并不总是选择CBaseFilter的。相反,因为我们绝大部分写的都是中间的传输Filter(Transform Filter),所以基类选择CTransformFilter和CTransInPlaceFilter的居多。如果我们写的是源Filter,我们可以选择CSource作为基类;如果是Renderer Filter,可以选择CBaseRenderer或CBaseVideoRenderer等。

  总之,选择好Filter的基类是很重要的。当然,选择Filter的基类也是很灵活的,没有绝对的标准。能够通过CTransformFilter实现的Filter当然也能从CBaseFilter一步一步实现。下面,笔者就从本人的实际经验出发,对Filter基类的选择提出几点建议供大家参考。

  首先,你必须明确这个Filter要完成什么样的功能,即要对Filter项目进行需求分析。请尽量保持Filter实现的功能的单一性。如果必要的话,你可以将需求分解,由两个(或者更多的)功能单一的Filter去实现总的功能需求。

  其次,你应该明确这个Filter大致在整个Filter Graph的位置,这个Filter的输入是什么数据,输出是什么数据,有几个输入Pin、几个输出Pin等等。你可以画出这个Filter的草图。弄清这一点十分重要,这将直接决定你使用哪种“模型”的Filter。比如,如果Filter仅有一个输入Pin和一个输出Pin,而且一进一处的媒体类型相同,则一般采用CTransInPlaceFilter作为Filter的基类;如果媒体类型不一样,则一般选择CTransformFilter作为基类。

  再者,考虑一些数据传输、处理的特殊性要求。比如Filter的输入和输出的Sample并不是一一对应的,这就一般要在输入 Pin上进行数据的缓存,而在输出Pin上使用专门的线程进行数据处理。这种情况下,Filter的基类选择CSource为宜(虽然这个Filter并不是源Filter)。

  当Filter的基类选定了之后,Pin的基类也就相应选定了。接下去,就是Filter和Pin上的代码实现了。有一点需要注意的是,从软件设计的角度上来说,应该将你的逻辑类代码同Filter的代码分开。下面,我们一起来看一下输入Pin的实现。你需要实现基类所有的纯虚函数,比如CheckMediaType等。在CheckMediaType内,你可以对媒体类型进行检验,看是否是你期望的那种。因为大部分Filter采用的是推模式传输数据,所以在输入Pin上一般都实现了Receive方法。有的基类里面已经实现了Receive,而在 Filter类上留一个纯虚函数供用户重载进行数据处理。这种情况下一般是无需重载Receive方法的,除非基类的实现不符合你的实际要求。而如果你重载了Receive方法,一般会同时重载以下三个函数EndOfStream、BeginFlush和EndFlush。我们再来看一下输出Pin的实现。一般情况下,你要实现基类所有的纯虚函数,除了CheckMediaType进行媒体类型检查外,一般还有DecideBufferSize以决定 Sample使用内存的大小,GetMediaType提供支持的媒体类型。最后,我们看一下Filter类的实现。首先当然也要实现基类的所有纯虚函数。除此之外,Filter还要实现CreateInstance以提供COM的入口,实现NonDelegatingQueryInterface以暴露支持的接口。如果我们创建了自定义的输入、输出Pin,一般我们还要重载GetPinCount和GetPin两个函数。

   Filter框架的实现大致就是这样。你或许还想知道怎样在Filter上实现一个自定义的接口,以及怎么实现Filter的属性页等等。限于篇幅,笔者就不展开阐述了。其实,这些问题都能在SDK的示例项目中找到答案。其他的,关于在实际编程中应该注意的一些问题,笔者整理了一下,供大家参考。

  1. 锁(Lock)问题

  DirectShow应用程序至少包含有两条线程:一条主线程和一条数据传输线程。既然是多线程,肯定会碰到线程同步的问题。Filter有两种锁: Filter对象锁和数据流锁。Filter对象锁用于Filter级别的如Filter状态转换、BeginFlush、EndFlush等;数据流锁用于数据处理线程内,比如Receive、EndOfStream等。如果这两种锁没有搞清楚,很容易产生程序的死锁,这一点特别需要提醒。

  2. EndOfStream问题

  当Filter接收到这个“消息”,意味着上一级Filter的数据都已经发送完毕。在这之后,如果Receive再有数据接收,也不应该去理睬它。如果Filter对输入Pin上的数据进行了缓存,在接收到EndOfStream后应确保所有缓存的数据都已经处理过了才能返回。

  3. Media Seeking问题

  一般情况下,你只需要在Filter的输出Pin上实现NonDelegatingQueryInterface方法,当用户申请得到 IID_ImediaPosition接口或IID_IMediaSeeking接口时将请求往上一级Filter的输出Pin上传递。当Filter Graph进行Mediaseeking的时候,一般会调用Filter上的BeginFlush、EndFlush和NewSegment。如果你的 Filter对数据进行了缓存,你就要重载它们,并做出相应的处理。如果你的Filter负责给发送出去的Sample打时间戳,那么,在 Mediaseeking之后应该重新从零开始打起。

  4. 关于使用专门的线程

  如果你使用了专门的线程进行数据的处理和发送,你需要特别小心,不要让线程进行死循环,并且要让线程处理函数能够去时时检查线程命令。应该确保在Filter结束工作的时候,线程也能正常地结束。有时候,你把GraphEdit程序关掉,但GraphEdit进程仍在内存中,往往就是因为数据线程没有安全关闭这个原因。

  5. 如何从媒体类型中获取信息

  比如,你想在输入Pin连接的媒体类型中,获取视频图像的宽、高等信息,你应该在输入Pin的CompleteConnect方法中实现,而不要在SetMediaType中。

  DirectX媒体对象(DirectX Media Objects,简称DMOs),是微软提供的另一种流数据处理COM组件。与DirectShow filter相比,DMO有很多相似之处。对filter原理的熟悉,将会大大帮助你对DMO的学习。另外,DMO也因其结构简单、易于创建和使用而倍受微软推崇。
我来回答
回答0个
时间排序
认可量排序
易百纳技术社区暂无数据
或将文件直接拖到这里
悬赏:
E币
网盘
* 网盘链接:
* 提取码:
悬赏:
E币

Markdown 语法

  • 加粗**内容**
  • 斜体*内容*
  • 删除线~~内容~~
  • 引用> 引用内容
  • 代码`代码`
  • 代码块```编程语言↵代码```
  • 链接[链接标题](url)
  • 无序列表- 内容
  • 有序列表1. 内容
  • 缩进内容
  • 图片![alt](url)
+ 添加网盘链接/附件

Markdown 语法

  • 加粗**内容**
  • 斜体*内容*
  • 删除线~~内容~~
  • 引用> 引用内容
  • 代码`代码`
  • 代码块```编程语言↵代码```
  • 链接[链接标题](url)
  • 无序列表- 内容
  • 有序列表1. 内容
  • 缩进内容
  • 图片![alt](url)
相关问答
无更多相似问答 去提问
举报反馈

举报类型

  • 内容涉黄/赌/毒
  • 内容侵权/抄袭
  • 政治相关
  • 涉嫌广告
  • 侮辱谩骂
  • 其他

详细说明

易百纳技术社区