这段时间一直在学习陆其明老师的《DirectShow开发指南》一书,书中对DirectShow的很多细节讲解清晰,但是却容易让人缺少对全局的把握。在学习过程中,整理了关于DirectShow程序运行过程的内容,希望会对上手学习DirectShow的人有所帮助。

DirectShow是微软公司提供的一套在Windows平台上进行流媒体处理的开发包,与DirectX开发包一起发布。对于DirectShow的使用除妖是为了对多媒体流的捕捉和回放提供支持,以及对获取的数据进行后期的处理和存储。

在介绍DirectShow程序运行过程之前,需要先说明几个概念。

Filter:有些资料中翻译为过滤器,用于参与数据处理的功能模块。根据功能的不同,可以分为Source Filters、Transform Filters和Rendering Filters,分别用于对数据的获取,处理和分发。

Pin:Filter对外提供的接口,分为输入Pin和输出Pin,作为Filter之间的连接通道用于数据传输。

Filter Graph:用于管理Filter的模型,展示整个数据流的处理过程。在Filter Graph中,每个Filter按一定的顺序进行连接,数据在Filter之间进行传递。微软提供的GraphEdit工具是用于对Filter的测试,在这个工具中可以很直观的看到Filter Graph的运行和处理。

Filter Graph Manager:用于管理Filter Graph,控制数据处理过程。

DirectShow程序的运行过程就是以上提到的对象之间协作的过程。由于DirectShow应用程序实际上是一种COM组件的客户程序,所以涉及到COM组件的创建,对象接口的调用等问题。

(1)DirectShow应用程序运行的第一步就是初始化COM库。

    HRESULT hr = Colnitialize(NULL);  // 调用 Colnitialize来初始化COM库

(2)创建Filter Graph Manager实例

    HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL,
CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph);

(3)创建Filter Graph Manager之后,根据实际应用,创建完整的Filter链路。此处的Filter可以是调用已有的Filter,或者是调用由用户自行实现的Filter。在Filter之间连接链路的过程就是将对应的Pin进行连接的过程,即为媒体类型的协商过程。无论是输入Pin还是输出Pin,支持的媒体类型都是有限的,需要选择两端都支持的媒体类型,才能实现Pin之间的连接。需要提出的是,连接的过程总是从输出Pin指向输入Pin。

①首先,枚举欲连接的输入Pin上所有的媒体类型,用这些媒体类型与输出Pin进行连接,如果输出Pin也支持某种媒体类型,那么该连接即成功,若在输入Pin上支持的媒体类型都不能被支持,就会转而从输出Pin方进行枚举,如果输出方Pin支持的媒体类型同时也被输入方Pin支持,那么也使该连接成功。如果两次枚举过程都不能成功建立连接,则这两个Pin之间不能进行连接。

    HRESULT CBasePin::AttempConnection(IPin*,const CMediaType*) 

②在建立连接之后,还不能立刻进行数据传输,还需要针对Pin上的内存分配器进行协商。连接双方的Pin之间进行传输的数据单元叫做Sample,Sample是由分配器(Allocator)来管理的。连接两个Filter的Pin必须使用同一个分配器,而具体需要由哪个Pin来创建是需要协商的。

   HRESULT CBaseOutputPin::DecideAllocator(IMemlnputPin*,IMemAllocator)    

(4)在成功构建了一个Filter Graph之后,就可以进行播放了。此时,使用Filter Graph Manager控制Filter graph及在其中的数据流。在这个过程中,应用程序会收到Filter Graph Manager发送的事件,并对这些事件进行响应。

以上就是一个DirectShow应用程序运行的基本过程,在此过程中还牵涉到很多细节,例如在推模式和拉模式两种不同的数据传送模式下,Pin之间数据如何传送的问题等,在本文中没有进行详细说明。

最新文章

  1. Q
  2. ListView与GridView异步加载图片
  3. win7重新安装win7
  4. NetFlow学习笔记
  5. UWP 使用Telerik Chart控件
  6. Laravel——安装Laravel-admin
  7. 记录7: office 2016 Mac不能使用的解决过程
  8. docker日志清理
  9. emqtt日志、证书、集群状态等位置
  10. oracle(sql)基础篇系列(五)——PLSQL、游标、存储过程、触发器
  11. 二本毕业,我是如何逆袭成为BAT年薪40W的Java工程师的?
  12. 加载properties文件的三种方法
  13. verilog的移位运算符(存在不公平现象)
  14. hdu1573-X问题-(扩展欧几里得定理+中国剩余定理)
  15. python ros 使用launch文件启动脚本
  16. 让cxGrid像Excel那样高亮显示选区的行号列标
  17. Sharepoint 安装部署Project Server
  18. 8.在XamarinAndroid上进一步控制包的大小
  19. Shell脚本传递带有空格的参数[摘录自网络]
  20. 总结day24 ---- socket ,struct 的学习

热门文章

  1. JAVA中关于数组的定义
  2. Linux下MySQL不能远程访问
  3. 130 个你需要了解的 vim 命令
  4. MarkDown写blog(测试)
  5. WebApp MVC,“不一样”的轻量级互联网应用程序开发框架
  6. Maven更新子模块的版本号
  7. Linux下grep显示前后几行信息
  8. C# 5.0 新特性——Async和Await使异步编程更简单
  9. 加快MySQL逻辑恢复速度的方法和参数总结
  10. 斜堆(二)之 C++的实现