如何开发视频播放Filter[1]

[入库:2005年8月19日] [更新:2007年3月24日]

本文简介:选择自 aoosang 的 blog

摘要:这篇文章讨论了一个播放filter需要处理的一些消息通知。只要正确的处理这些消息通知,才能够正确地设置directshow播放视频的画面。

1 开发一个可选择的视频播放filter
directshow提供了一个基于窗口的视频播放filter,它也提供了一个全屏幕实时播放的filter。你可以利用directshow的基类开发自己的可选择的视频播放filter。你可以利用cbaserenderer and cbasevideorenderer类根据下面的一些经验指南就可以开发一个可选择的视频播放filter。
在directshow中主要有三种消息通知。
1数据流的通知,
这是数据流在graph图中传递的过程中,从一个filter到另一个filter的过程中发生的事件通知。例如,begin-flushing, end-flushing or end-of-stream事件通知,这些事件通知都是通过上游fitlter调用的下游filter的输入pin来通知下游filter的。比如ipin::beginflush。
2 filter图表管理器发送的消息通知,
这些都是filter给图表管理器发送的事件通知,比如ec_complete,这种消息一般都是通过图表管理器的imediaeventsink::notify发送或接收的。
3 应用程序发送的消息通知
应用程序通过调用图表管理器上的imediaevent::getevent方法就可以获得这些事件消息。一般来说,图表管理经常讲得到的消息传递给应用程序处理。
2对end-of-stream and flushing消息的处理
当源filter发现没有数据传送的时候,它就会向下游发送一个end-of-stream通知,这个通知会沿着graph图表中的filter一个一个的往下传递,最后到达render filter。这就导致graph图表产生一个ec_complete消息。
当renderer的输入pin上的ipin::endofstream被上游的filter调用的时候,render filter就会接收到一个end-of-stream消息通知。render filter应该标记下这个消息通知,然后将已经接收到的数据处理完毕。当所有剩余的数据接收完毕,render filter就会给graph图表管理器发送一个ec_complete消息。当render filter在处理完毕所有的数据时,你应该给graph图表管理器发送一次ec_complete消息。只有当render filter处于运行状态时才能给图表管理器发送ec_complete消息。如果一个render 正处于paused状态时接收到源filter 发送的end-of-stream通知,只有当filter graph结束的时候render 才能给图表管理器发送ec_complete消息。
end-of-stream通知发出以后,如果上游filter再次调用render filter上的输入pin上的imeminputpin::receive or imeminputpin::receivemultiple方法时,render就要拒绝它,此时就返回一个e_unexpected错误消息。
当filter 图表管理器停止的时候,render应该将捕捉到的任何end-of-stream通知都应该被清除,当图表管理器再次启动的时候,render不应该再给管理器发送任何通知。因为图表管理器在启动以前会paused所有的filter,这就会导致发生flushing。例如,如果filter graph处于pause状态收到一个end-of-stream通知,然后filter graph就停止了,当filter graph再次运行的时候,render 就不应该给管理器发送ec_complete消息了。如果没有发生seek,源filter会自动地在发生pause时给下游的filter发送一个end-of-stream通知,如果在filter graph图表stop的时候发生seek,此时源filter也许正有数据要发送,所以它不会发送end-of-stream通知。
render filter经常依靠end-of-stream通知来发送ec_complete通知。例如,如果一个数据流已经结束发送(也就是end-of-stream消息已经发送出来),另一个窗口已经覆盖到视频窗口上,也产生了一系列的wm_paint消息。但是,当end-of-stream消息发出以后,render就处于等待状态,但是render也明白它不会再接收任何数据了,视频播放窗口就会出现黑屏幕。
flushing是render应该处理的另外一种复杂的事件。flushing消息是通过ipin上的两个方法beginflush and endflush.触发的。源filter在没有调用endflush,而仅仅调用了beginflush方法是不合法的,所以此时flushing的状态是短暂和不连续的。但是在flushing状态下,render要处理好数据以及接收的消息。
在beginflush方法被调用之后所有接收到的数据都要立即被rejected,并且返回一个s_fasle。并且捕捉到的end-of-stream也要立即清除。当render接收到seek消息后,就立即处于flush状态。flush确保在重新发送数据之前从filter graph中清除所有的旧的数据。
3如何处理状态的改变handling state changes and pause completion
当一个renderer filter的状态改变的时候,它的行为和其他的filter是一样的,但是也有以下的区别,当filter的状态变为pause的时候,render filter 的数据就排成队列,等待下次播放,当一个video 播放filter 停止的时候,它也会保留这些队列中的数据,这就是一个例外,因为dshow规定,当一个graph停止的时候,它不应该保留任何资源。
造成这种例外的原因是如果render filter保持资源,这样,当这个filter接收到一个wm_paint 消息时可以通过这个资源来重绘窗口。同样保持这个资源也可以满足一些方法的调用,比如cbasecontrolvideo::getstaticimage,,这个方法用来返回当前图像的一份拷贝。保持资源的另一个原因是,在资源保持的过程中,它所占用的内存块不会被回收,这样,再次开始数据传输时速度会比较快一点,因为不用分配内存了。
在graph运行的期间,sample中的内容会被随时地提交sample内存也随时地被释放,但是,在停止运行的状态中,sample只能被提交,不能被释放,例如,在窗口绘制一幅静态的图画。音频流在停止的状态没法被提交,但是他们可以进行其他的动作,比如准备wave设备。sample被提交的时间由sample的stream time和imediacontrol::run方法调用时传递的参考时间综合以后得到的。当开始时间小于等于结束时间时,sample就应该被丢弃。
当应用程序调用imediacontrol::pause方法准备停止一个graph图时,只有当提交过滤器中有一个数据队列时才能够返回。为了确保此点,当一个render filter 没有等待提交的数据时,该方法就返回s_false,如果有数据等待提交,返回s_ok。
未来确保render filter 有一个等待提交的数据,filter图表管理器在停止一个graph时会检查方法的返回值,如果一个或者几个filter 还没有准备好,filter 图表管理器就会调用getstate方法来polls filter。getstate方法带有一个超时的参数,当getstate函数的等待的时间到期返回之前,如果filter还在等待数据的到来时,那么该函数返回vfw_s_state_intermediate,如果filter已经有等到数据的时候,getstate返回s_ok。
当一个filter在等待数据的时候,源filter会发送一个end of stream的通知,此时状态的转变完成。
当一个graph中的所有的filter都有了等待提交的数据,那么整个graph就成为了pause状态。

4如何处理终止态(handling termination)
视频提交过滤器必须能够正确处理来自用户的终止数据流的事件。这就意味着要正确地隐藏窗口,并且知道当窗口重新显示的时候该怎么做。同时,当窗口销毁的时候,提交过滤器也要能够通知filter 图表管理器来正确的释放资源。
当用户关闭了视频窗口时,或者(用户按alt+f4),一般的做法是将视频窗口隐藏同时给filter 图表管理器发送一个ec_userabort通知,这个通知最终会被发送到应用程序,然后应用程序就会停止播放视频。当发出ec_userabort通知后,所有发送给提交filter的数据都会被拒绝。
当一个视频正在在播放的时候,如果用户此时按下atl +f4,视频窗口就会暂时的隐藏起来,然后所有送往窗口的数据都会被拒绝。当窗口重新显示的时候,不会产生ec_repaint通知。
当一个视频提交filter终止的时候,它要给filter图表管理器发送一个ec_window_destroyed消息通知。事实上,最好的处理这个消息的时机是在ibasefilter::joinfiltergraph方法调用时,而不是等到实际的窗口销毁时。sending this notification enables the plug-in distributor in the filter graph manager to pass on resources that depend on window focus to other filters (such as audio devices).

本文关键:如何开发视频播放Filter
  相关方案
Google
 

本站最佳浏览方式为 分辨率 1024x768 IE 6.0(或更高版本的 IE浏览器)

go top