DirectShow项目开发经验

 
DirectShow 项目开发经验
一、              开发环境
开发平台:PPC/SP MicrosoftR Windows Mobile 5.0、MicrosoftR Windows Mobile 6.0;开发工具:Visual Studio 2005;开发文档:magneto documentation may 18, 2006.chm,directshow.chm,Windows Media Player SDK。
二、              Windows Media Player
Microsoft公司的WMP(Windows Media Player)对文件的播放提供了一套基于DirectShow的框架,而对于开发者而言,可以基于该原理来实现对本地、网络数据的不同处理。
DirectShow主要包括三大功能模块,Source Filter负责解决数据来源,Transform Filter一般指各种Decoder Filter,实现数据的解码,Renderer Filter负责解码后数据的显示与呈现,即负责数据的“去向”。
三、              LocalSource Filter(跳帧的实现原理)
LocalSource Filter一般包括推模式和拉模式,为了减少开发的工作量我们采取推模式,即该LocalSource Filter一边从文件中读取数据,一边实现Audio、Video数据的分离,然后分别推送给各自的Decoder Filter,数据经过A/V分离后,在各自的线程中解码、显示,哪它们怎么达到A/V同步的呢?
DirectShow确保A/V同步,主要是依赖于Sample(数据包)上的TimeStamp(时间戳),Video Renderer根据其TimeStamp来安排何时进行显示,或者丢弃一些sample。由于我们的开放平台是Windows Mobile,其CPU的性能不高,一般在200~500Mhz左右,因此当播放一些high performance文件时,仅仅依靠Video Renderer丢包处理是远远不够的,而必须需要Source Filter“早早”地进行数据丢包——跳帧。
又由于Video Renderer依赖于流时间Stream Time 并比较TimeStamp来进行决策的,所以我们的Source Filter也必须参考Stream Time(T s)这个“桥梁”进行跳帧处理。此外LocalSource Filter需要给将发送的sample打上时间戳,而该时间戳一般是从文件层(File Layer)获取的,这里不妨命名为T f,另外跳帧后为了不引起花屏现像,我们必须选择keyframe位置进行跳帧。这样一来需要综合考虑文件层keyframe的分布情况:
1.Keyframe间隔不大,且分布比较均匀
这种keyframe分布是最为理想的,因为基本上任意点都可以作为跳帧点,这样LocalSource Filter随时可以在文件层获取一个与T s匹配的T f,这样发送出去的Samples很好地符合了Video Renderer的要求,也很好达到了A/V同步。
2.Keyframe间隔大,且分布不均匀
这种情况较差,因为LocalSource Filter较难在文件层获取一个与T s匹配的T f,同时考虑到Video Renderer对Sample的处理,我们选择的跳帧点(T f)不能偏离T s太远,否则如果T f>>T s,那么Video Renderer将Hold住该Sample,画面表现为停滞一段时间;如果T f<<T s,那么Video Renderer将丢弃一些Sample或者极快的进行显示,这样画面看起来滚动飞快。根据经验我们选择那些满足T s<T f<T s+500ms的keyframe点作为LocalSource Filter的跳帧点。这样A/V同步是暂时的,不同步是动态的,但总体说来基本能够满足A/V同步的要求,毕竟这类文件是比较少的。一种最差的情况是整个文件就一个keyframe,对于该类型的文件只能是不同步播放了。
另外Seek之后的Sample也需要作些特殊处理。Seek之后由于Sample的时间戳进行了突变,DirectShow的流时间也会有一个动态调整来确保Stream Time与新起始的Sample时间戳相吻合。但由于Video Seek要求文件的keyframe点,这样与实际得到的位置有一个偏差,一般我们采取超前请求点Seek 关键帧。这样得到的Samples对于Video Renderer而言是“迟到”的。所以LocalSource Filter需要对这些Samples作特殊处理以“决定”是否丢弃(比如处理后的TimeStamp < 0就应该直接丢弃,以免图像过快播放)。
四、              网络接收NetSource Filter
目前我们的项目采用rtsp协议进行网络数据的接收,由于客户端采用WMP,这就涉及WMP基于rtsp://的url来Load NetSource Filter,以及当网络Buffer数据时怎样与WMP进行“对话”的问题。
首先通过查阅Windows Media Player SDK,我们可以修改注册表如下:
       [ HKEY_LOCAL_MACHINE/Microsoft/MediaPlayer/Player/Schemes/rtsp]
       Runtime = 7             // Render using Microsoft DirectShow.
       Permission = 31     
              这样我们的 NetSource Filter 就可以被 WMP 通过 rtsp:// url load 了。
下面看看当 NetSource Filter Buffer 数据时,怎么“通知” WMP 的。我们知道 WMP 是通过创建 FilterGraph 来管理各种 Filters ,这样当 Buffer 数据时, NetSource Filter 必须向 FilterGraph 发送 EC_STARVATION 消息,即“告知“ FilerGraph 当前的 Filter 转换到了一种新的状态,要求上层应用程序等待该转换过程。同时 WMP 接收到 EC_STARVATION 消息后会不断调用 NetSource Filter GetState 接口来查询其状态是否转换完成。这就要求我们虚继承该函数,当 Buffer 数据时,直接返回 VFW_S_STATE_INTERMEDIATE The state transition has not completed )否则返回 S_OK 表明转换完毕。从而在用户看来当网络 Buffer 数据时,其进度条是暂停的,当数据足够时,进度条又继续前进了。
LiveSource Pause/Resume 问题的解决。当 NetSource Filter 接收广播数据时,我们碰到最棘手的就是播放过程中怎么解决用户的 Pause/Resume 问题。由于底层库没有提供针对 LiveSource 源的 Pause 功能,即用户 Pause 一段时间后,继续播放时,其图像应该是同步于服务器的。所以我们只好在 Pause 时“人为”地断开 RTSP 的连接,继续播放时重新建立连接,采取这种绕的方式来达到 LiveSource 中的 Pause/Resume 功能。由于这种“ Pause ”的实现违背了 DirectShow 的基本原理,即 Pause 时数据线程被强行 Stop 掉了。因此在深入研究 DirectShow Push Source 框架和多次试验后,我们做出了这样的特殊处理:当用户 Pause 时,我们一方面 Stop RTSP 的数据连接,同时确保 Audio/Video Pin 中各自线程的正常运行,当用户执行 Resume 操作时,我们在 Audio 或者 Video Pin 的线程中进行 RTSP Reset 重连接操作,最后由于 RTSP Reset Video/Audio Sample 的时间戳复位了,为了保证画面的连贯性,我们必须给 Reset Resume )后的 Video/Audio Sample 加上 Pause 时各自的时间戳(作为偏移量)。
 
 
五、              Decoder Filter
Decoder Filter的开发比较简单,一般都是跟踪调试一些解码Crash的问题。比如:内存越界、解码容错处理、Seek或者Flush后对头信息的解析处理等等。
六、              Video Renderer
Video Renderer在我接手开发时已经比较完善了,我主要解决了一些刷新问题。比如全屏后不能返回到正常模式,Stop后WMP又Repeat播放起来等等问题。
七、              Muxer Filter
Muxer Filter实现时,也时碰到了类似LiveSource的Pause/Resume的问题。当时由于Muxer Filter接收的Sample只有Audio打上了绝对时间戳,Video的是相对的。如果用户执行了Pause/Resume操作,就给我们Dump文件时带来了一定的困难,因为Resume后这些Sample需要减去Pause->Resume段内时间戳的累积,否则播放该文件时要么黑屏,要么A/V不同步。因此Resume后Dump Video时必须参考Audio来计算Pause->Resume的时间段了,这里不妨记为DeltT a 这样需要考虑以下几种情况:
1.Resume后Video Sample先到达Muxer
如果Video Sample先于Audio到达Muxer,由于这时我们没法从Audio中得到正确的DeltT a,因此我们只好在Pause时刻的基础上加上一个默认值(比如100ms)作为Resume后那些先于Audio的Video Sample的起始时间戳。
2.Resume后Audio Sample先到达Muxer
如果Resume后有太多的Audio Sample先于Video到达Muer,我们需要给Resume后第一帧的Video Sample的时间戳进行调整,否则播放该文件时会出现某处被卡住的现象。Resume后接收到的第一帧Video Sample经由DeltT a的偏移调整后,还比Pause的时刻滞后许多(比如大于1秒),我们需要对其作特殊处理,确保与Pause的时刻点连贯起来——在Pause时刻基础上加上500ms的偏移作为新的起始时间戳。
八、              小结
我们这个DirectShow项目的开发是在既定的框架下,所以需要做好的工作往往是一些细节方面的处理,以及探索、熟知Windows Media Player应用层如何通过Graph这个桥梁与各种Filter进行交互的,还包括熟知一些注册表信息的特殊功能。而涉及到Filter本身功能的开发一般都比较顺利,项目往往是卡在Filter与Windows Media Player打交道的处理上。WMP应用层对于DirectShow的处理并没有详细的官方资料,所以我们往往是通过两头“凑”的方法来进行探索的,即一方面查阅DirectShow的资料,一方面查阅WMP SDK,同时进行许多试验和经验总结,来积累一些它们之间相互处理的一些具体细节过程。
 
/---------------------------------------------------------------------\ * 书 名:《DirectShow开发指南》 * 作 者: 陆其明(著) 金邦飞(审校) * 内容提要: 本书以DirectX SDK 9.0版为蓝本,涉及的内容几乎涵盖了在Windows平台上使 用DirectShow进行C++编码的方方面面。全书共分4个部分。第1部分详细介绍了 DirectShow的基础知识。第2部分重点讨论了Filter开发,以及DirectShow 应用程序的开发,包括目前非常流行的如音视频采集、数码摄像机的支持、非线性 编辑等应用。第3部深入分析了DirectShow SDK提供的部分典型源代码例子。第 4部分结合作者个人的一些开发实践,通过案例和开放源码分析,进一步介绍 DirectShow的实务应用。 本书完全忠实于DirectX SDK 9.0的帮助文档以及基类源代码,并结合作者多年 的实践,经过提炼而成。内容丰富,条理清晰,实用性强。适合广大的流媒体应用 开发人员,以及对Windows平台上多媒体处理感兴趣的编程爱好者、学生学习和参 考。 * 下载内容说明: readme.txt:本说明文件。 Chapter04:第4章用到的代码,其中AppIPTransform为MFC Filter的例子, DsDemo是一些演示代码,FilterTitleOverlay是字符叠加Filter的源代码。 Chapter05:第5章用到的代码,其中GraphBuilding为Filter Graph构建技术 的一些代码,SimplePlayer为一个简单的播放器例子。 Chapter07:第7章用到的代码,其中DsDemo是一些演示代码。 Chapter09:第9章用到的代码,其中DESCallback演示了控制DirectShow智能 连接的方法。 Chapter18:第18章用到的代码,其中MpegNetwork为“MPEG流的网络客户端播放” 实现的所有源代码(请打开Daisy.dsw浏览各项目)。 Chapter19:第19章用到的代码,其中DVD2AVI_1.77.3_SRC.zip为开放源码, FilterMpeg2VD为此开放源码基础上开发的MPEG-2 Video Decoder Filter例子。 除上述代码外,本书各章用到的其他代码均在DirectX SDK安装目录的Samples 子目录下可以找到。 * 备注: DirectX SDK 9.0以及DirectX 9.0运行时库可以到微软的网站上下载。 请访问微软的网站首页http://www.microsoft.com,然后输入DirectX进行搜 索;或者直接访问http://www.microsoft.com/directx下载运行时库,或者 http://www.microsoft.com/downloads/details.aspx?FamilyId=9216652F-51E0-402E-B7B5-FEB68D00F298&displaylang=en * 技术支持网站:http://hqtech.nease.net \---------------------------------------------------------------------/
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值