`
从此醉
  • 浏览: 1123712 次
  • 性别: Icon_minigender_1
  • 来自: US
社区版块
存档分类
最新评论

DirectShow系列讲座之二——Filter原理

 
阅读更多

在上一讲中,笔者介绍了DirectShow的总体系统框架。从这一讲开始,我们要从程序员的角度,进一步深入探讨一下DirectShow的应用以及Filter的开发。
在这之前,笔者首先要特别提一下微软提供的一个Filter测试工具——GraphEdit,它的路径在DXSDK/bin/DXUtils/GraphEdit.exe。(如果您还没有安装DirectX SDK,请到微软的网站上去下载。)通过这个工具,我们可以很直观地看到Filter Graph的运行及处理流程,方便我们进行程序调试。(如果您手边就有电脑,还等什么,马上体验一下吧:运行GraphEdit,执行File->Render Media File…选择一个媒体文件;当Filter Graph构建成功后,按下工具栏的运行按钮;您就能看到刚才选择的媒体文件被回放出来了!看到了吧,写一个媒体播放器也就这么回事!)
接下去,我们开讲Filter的开发。
学习DirectShow Filter的开发,不外乎以下几种方法:看帮助文档、看示例代码和看SDK基类源代码。看帮助文档,应着重于总体概念上的理解;看示例代码应与基类源代码的研究同步进行,因为自己写Filter,关键的第一步是选择一个合适的Filter基类和Pin的基类。对于Filter的把握,一般认为要掌握以下三方面的内容:Filter之间Pin的连接、Filter之间的数据传输以及流媒体的随机访问(或者说流的定位)。下面就开始分别进行阐述。
所谓的Filter Pin之间的连接,实际上是Pin之间Media Type(媒体类型)的一个协商过程。连接总是从输出Pin指向输入Pin的。要想深入了解具体的连接过程,就必须认真研读SDK的基类源代码(位于DXSDK/samples/Multimedia/DirectShow/BaseClasses/amfilter.cpp,类CBasePin的Connect方法)。连接的大致过程为,枚举欲连接的输入Pin上所有的媒体类型,逐一用这些媒体类型与输出Pin进行连接,如果输出Pin也接受这种媒体类型,则Pin之间的连接宣告成功;如果所有输入Pin上枚举的媒体类型输出Pin都不支持,则枚举输出Pin上的所有媒体类型,并逐一用这些媒体类型与输入Pin进行连接。如果输入Pin接受其中的一种媒体类型,则Pin之间的连接到此也宣告成功;如果输出Pin上的所有媒体类型,输入Pin都不支持,则这两个Pin之间的连接过程宣告失败。
有一点需要注意的是,上述的输入Pin与输出Pin一般不属于同一个Filter,典型的是上一级Filter(也叫Upstream Filter)的输出Pin连向下一级Filter(也叫Downstream Filter)的输入Pin。如下图所示:



当Filter的Pin之间连接完成,也就是说,连接双方通过协商取得了一种大家都支持的媒体类型之后,即开始为数据传输做准备。这些准备工作中,最重要的是Pin上的内存分配器的协商,一般也是由输出Pin发起。在DirectShow Filter之间,数据是通过一个一个数据包传送的,这个数据包叫做Sample。Sample本身是一个COM对象,拥有一段内存用以装载数据,Sample就由内存分配器(Allocator)来统一管理。已成功连接的一对输出、输入Pin使用同一个内存分配器,所以数据从输出Pin传送到输入Pin上是无需内存拷贝的。而典型的数据拷贝,一般发生在Filter内部,从Filter的输入Pin上读取数据后,进行一定意图的处理,然后在Filter的输出Pin上填充数据,然后继续往下传输。下面,我们就具体阐述一下Filter之间的数据传送。
首先,大家要区分一下Filter的两种主要的数据传输模式:推模式(Push Model)和拉模式(Pull Model)。参考图如下:



所谓推模式,即源Filter(Source Filter)自己能够产生数据,并且一般在它的输出Pin上有独立的子线程负责将数据发送出去,常见的情况如代表WDM模型的采集卡的Live Source Filter;而所谓拉模式,即源Filter不具有把自己的数据送出去的能力,这种情况下,一般源Filter后紧跟着接一个Parser Filter或Splitter Filter,这种Filter一般在输入Pin上有个独立的子线程,负责不断地从源Filter索取数据,然后经过处理后将数据传送下去,常见的情况如文件源。推模式下,源Filter是主动的;拉模式下,源Filter是被动的。而事实上,如果将上图拉模式中的源Filter和Splitter Filter看成另一个虚拟的源Filter,则后面的Filter之间的数据传输也与推模式完全相同。
那么,数据到底是怎么通过连接着的Pin传输的呢?首先来看推模式。在源Filter后面的Filter输入Pin上,一定实现了一个IMemInputPin接口,数据正是通过上一级Filter调用这个接口的Receive方法进行传输的。值得注意的是(上面已经提到过),数据从输出Pin通过Receive方法调用传输到输入Pin上,并没有进行内存拷贝,它只是一个相当于数据到达的“通知”。再看一下拉模式。拉模式下的源Filter的输出Pin上,一定实现了一个IAsyncReader接口;其后面的Splitter Filter,就是通过调用这个接口的Request方法或者SyncRead方法来获得数据。Splitter Filter然后像推模式一样,调用下一级Filter输入Pin上的IMemInputPin接口Receive方法实现数据的往下传送。深入了解这部分内容,请认真研读SDK的基类源代码(位于DXSDK/samples/Multimedia/DirectShow/BaseClasses/source.cpp和pullpin.cpp)。
下面,我们来讲一下流的定位(Media Seeking)。在GraphEdit中,当我们成功构建了一个Filter Graph之后,我们就可以播放它。在播放中,我们可以看到进度条也在相应地前进。当然,我们也可以通过拖动进度条,实现随机访问。要做到这一点,在应用程序级别应该可以知道Filter Graph总共要播放多长时间,当前播放到什么位置等等。那么,在Filter级别,这一点是怎么实现的呢?
我们知道,若干个Filter通过Pin的相互连接组成了Filter Graph。而这个Filter Graph是由另一个COM对象Filter Graph Manager来管理的。通过Filter Graph Manager,我们就可以得到一个IMediaSeeking的接口来实现对流媒体的定位。在Filter级别,我们可以看到,Filter Graph Manager首先从最后一个Filter(Renderer Filter)开始,询问上一级Filter的输出Pin是否支持IMediaSeeking接口。如果支持,则返回这个接口;如果不支持,则继续往上一级Filter询问,直到源Filter。一般在源Filter的输出Pin上实现IMediaSeeking接口,它告诉调用者总共有多长时间的媒体内容,当前播放位置等信息。(如果是文件源,一般在Parser Filter或Splitter Filter实现这个接口。)对于Filter开发者来说,如果我们写的是源Filter,我们就要在Filter的输出Pin上实现IMediaSeeking这个接口;如果写的是中间的传输Filter,只需要在输出Pin上将用户的获得接口请求往上传递给上一级Filter的输出Pin;如果写的是Renderer Filter,需要在Filter上将用户的获得接口请求往上传递给上一级Filter的输出Pin。进一步的了解,请认真研读SDK的基类源代码(位于DXSDK/samples/Multimedia/DirectShow/BaseClasses/transfrm.cpp的类方法CTransformOutputPin::NonDelegatingQueryInterface实现和ctlutil.cpp中类CPosPassThru的实现)。
以上我们介绍了一下如何学习DirectShow Filter开发,以及一些开始写自己的Filter之前的预备知识。下一讲,笔者将根据自己开发Filter的经验,手把手教你如何写自己的Filter。

分享到:
评论

相关推荐

    基于directShow,打造全能播放器系列之二——简易播放器的补充 源码

    基于directShow,打造全能播放器系列之二——简易播放器的补充 源码 对应博客地址: http://blog.csdn.net/harvic880925/article/details/7987798# 此博文仅供交流,转载请标明出处,谢谢

    基于directshow的基础应用——图像翻转

    DirectShow 是微软开发的一个强大的多媒体框架,用于处理视频和音频流。它提供了一种标准的接口和组件模型,使得开发者可以...通过这个项目,开发者不仅可以掌握图像翻转技术,还能深入理解DirectShow的内部工作原理。

    Directshow filter编写例程(二)读取文件

    在我们的"Directshow filter编写例程(二)读取文件"中,我们将创建一个自定义Filter,即AsyncReadFilter,它的主要任务是从文件中异步地读取数据并将其推送到Filter Graph中。 AsyncReadFilter是基于SDK自带的...

    基于directShow,打造全能播放器系列之一——简易播放器源码

    这是我系统博文《基于directShow,打造全能播放器系列》第一篇“简易播放器的实现”源码,有兴趣的可以下载 博客地址: http://blog.csdn.net/harvic880925/article/details/7978566

    在自己的DirectShow程序中连接Pushsource Filter

    刚接触DirectShow的时候看代码无从下手,看SDK里面的例子也看不懂,网上也很少有适合初学者的资料,这是我用DirectShow连接的第一个filter,功能是把一组图片播放在指定的窗体上,控件是用MFC对话框中的图形控件做的

    DirectShow调用手动Lav Filter建立Filter Graph播放视频

    在DirectShow中,Filter Graph是核心概念,它定义了数据流从源到目的地的路径,由多个过滤器(Filter)通过连接(Pin)构成。每个过滤器都有特定的功能,如捕获、解码、渲染等。 Lav Filter是一个开源的DirectShow...

    DirectShow入门讲座

    这是陆老师的DirectShow入门讲座

    用DirectShow封装DirectSound的RenderFilter

    它由一系列Filter组成,每个Filter都有特定的功能,如解码、渲染、捕获等。RenderFilter是DirectShow中的一种,它的主要任务是将数据呈现到设备,如扬声器或耳机。 DirectSound是Windows平台上的一个高级音频服务,...

    Directshow的filter开发

    Directshow的Filter开发简要步骤-C++技术文章-C++-程序设计-技术资料

    文件系统驱动编程基础篇之6——DirectShow.pdf

    阅读这些材料可以帮助开发者逐步积累知识,从基础到高级,深入理解DirectShow的工作原理。 总的来说,虽然DirectShow不是驱动编程的基础,但它与操作系统和硬件交互的方式对理解底层系统操作有重要的启示作用。通过...

    directshow filter 工具

    DirectShow Filter工具是一种用于开发和调试DirectShow过滤器的强大资源,它为用户提供了全面的DirectShow滤镜集合,以及一个方便的查看工具,以便更好地理解和管理这些滤镜。DirectShow是微软开发的一个多媒体处理...

    C#媒体播放器——基于directshow

    本项目名为"C#媒体播放器——基于DirectShow",它为开发者提供了一个简单的平台,来理解和实践如何利用DirectShow框架在C#中实现多媒体播放功能。DirectShow是微软开发的一个强大的多媒体处理框架,广泛应用于视频和...

    利用 DirectShow 开发自己的 Filter_源码.rar_Directshow Filter_Directshow_f

    在本压缩包中,"利用 DirectShow 开发自己的 Filter_源码.rar" 提供了关于如何自定义 DirectShow Filter 的源代码,这对于理解 DirectShow 工作原理以及进行多媒体应用程序开发非常有帮助。 一个 DirectShow Filter...

    DirectShow Filter

    通过实践编写Filter,解决实际问题,能够深入理解DirectShow Filter的工作原理和应用场景。对于多媒体应用程序的开发者来说,精通DirectShow Filter不仅可以提升开发效率,还能创造出更加高效和定制化的多媒体解决...

    Custom DirectShow SampleGrabber Filter for Windows Mobile

    在移动设备开发领域,Windows Mobile操作系统提供了一套强大的多媒体处理框架——DirectShow。DirectShow是Microsoft为Windows平台设计的一种媒体处理架构,它允许开发者高效地处理音频和视频流。在Windows Mobile上...

    做一个directshow的filter,把RGB视频流变成黑白的

    在 Transform Filter 的核心——TransformSample 或 ProcessInput 方法中,我们会接收RGB像素数据,应用灰度转换算法,然后将结果输出。这里需要特别注意线程安全问题,因为DirectShow可能会在多个线程上同时调用...

    DirectShow-Filter 最简单的示例代码

    DirectShow Filter是微软DirectX框架的一部分,用于视频和音频处理。它是一个强大的API,允许开发者构建复杂的多媒体应用程序,包括播放器、捕获设备和流媒体系统。本示例代码将帮助我们理解如何在DirectShow中创建...

    DirectShow务实精选第二章代码

    2. **过滤器和过滤器图**:在DirectShow中,媒体数据的处理是通过一系列的过滤器完成的,如源过滤器、解码过滤器、渲染过滤器等。这些过滤器通过连接形成一个过滤器图,描述了数据流的处理路径。Chapter02的代码可能...

    DirectShow Filter 最简单的示例+两个 PIN 的实现

    DirectShow Filter技术是微软开发的一种多媒体处理框架,用于在Windows平台上进行音频和视频的捕获、处理和播放。在这个最简单的示例中,我们将探讨如何实现一个包含两个PIN(Pin)的DirectShow Filter,分别代表...

Global site tag (gtag.js) - Google Analytics