科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件DirectShow学习指南之数据流结束通知

DirectShow学习指南之数据流结束通知

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

当一个源filter结束发送数据流时,它调用和它连接的filter的输入pin的IPin::EndOfStream,然后下游的filter再依次通知与之相连的filter。

作者:智慧的鱼 来源:天极开发 2007年10月16日

关键字: DirectShow 数据流 结束通知

  • 评论
  • 分享微博
  • 分享邮件
当一个源filter结束发送数据流时,它调用和它连接的filter的输入pin的IPin::EndOfStream,然后下游的filter再依次通知与之相连的filter。当EndOfStream方法一直调用到renderer filter的时候,最后的一个filter就给filter图表管理器发送一个EC_COMPLETE事件通知。如果renderer有多个输入pin,当所有的输入pin都接收到end of stream通知的时候,它才会给filter图表管理器发送一个EC_COMPLETE事件通知。

  Filter必须在其他函数调用之后调用EndOfStream函数,比如IMemInputPin::Receive.。

  在一些情况下,下游的filter可能比源filter更早的发现数据流的结束。在这种情况下,下游filter发送 结束stream的通知,同时, IMemInputPin::Receive函数返回S_FALSE直到图表管理器停止。这个返回值提示源filter停止发送数据。

  对EC_COMPLETE事件的缺省处理

  缺省的情况下,filter图表管理器并不将EC_COMPLETE事件通知发送给应用程序,当所有的数据流都发送了EC_COMPLETE事件通知后,它才给应用程序发送一个EC_COMPLETE事件通知。所以,应用程序只有在所有的数据流停止的时候才能接收到这个通知。

  filter图表管理器通过计算支持seeking接口的filter,并且具有一个renderer pin,没有相应的输出pin,就可以确定数据流的数目。Filter图表管理器通过下面的方法来决定一个pin是否是个renderer 。

  1、pin的IPin::QueryInternalConnections方法通过nPin参数返回0;

  2、filter保露一个IAMFilterMiscFlags接口,并且返回一个AM_FILTER_MISC_FLAGS_IS_RENDERER标志。

  在拉模式下的数据流结束通知

  在IAsyncReader连接中,源filter并不发送数据流结束的通知,相应的发送数据流结束的通知是有renderer filter发出的。

  New Segments

  一个段就是一组media samples,这些sample具有共同的开始时间,结束时间,播放速率。

  The IPin::NewSegment 方法用来通知一个new segments的开始。源filter通过这种方法来通知下游的filter segment的开始时间和播放速率。例如,如果源filter在数据流中改变了新的开始点,它就用新的时间做参数来通知下游的filter。

  下游的filter在处理sample的时候需要segment。例如,在桢间压缩的时候,if the stop time falls on a delta frame, the source filter may need to send additional samples after the stop time. This enables the decoder to decode the final delta frame.为了确定正确的结束桢,解码器指向色gement的停止时间。另外一个例子,在音频播放的过程中,播放filter利用segment的速度和音频sample速度来产生正确的输出。

  在推模式中,源filter 产生一个新的segment,并初始化。在拉模式,这个工作是由剖析器(parser)来完成的。两种情况下,filter都调用下游filter的输入pin上的NewSegment,一直到达renderfilter。当filters调用数据流时候,必须序列化NewSegment。

  当每一个新的segment,数据流的时间都被重新设置为零,当segment从零开始的时候,samples 重新贴上了time标签。

  Flushing

  当graph运行的时候,在整个graph中会有大量的数据流动。同时也有一些数据排在队列里等到传递。当graph移动这些未决的数据,并在该内存块中写入新的数据是需要一定的时间的。例如,在seek命令后,源filter在生成新的sample,这些是需要一定时间的。为了减小延迟,下游的filter在seek命令必须丢掉以前的sample。这个抛弃sample的过程就叫flushing。

  当事件改变了数据的流向时,这可以使garph响应的更及时一些。

  推模式和拉模式在处理flushing的时候有点不同。我们先讨论一下推模式,然后再讨论拉模式。

  下面两种情况下发生flushing

  1、源filter调用下游filter输入pin的IPin::BeginFlush方法,然后下游的filter就开始拒绝从上游filter接收数据流。然后它开始抛弃它正在处理的samples,继续调用下游filter的IPin::BeginFlush方法。

  2、当源filter准备好新的数据时,它调用输入pin的IPin::EndFlush方法,这就告诉下游的filter可以接收新的samples,然后继续调用下游的filter的IPin::EndFlush。

  在BeginFlush方法中,输入pin进行了下列工作:

  1、首先调用下游filter的输入pin上的Calls BeginFlush方法

  2、拒绝处理数据流,包括Receive和endofstream方法

  3、取消那些正在阻塞等待filter释放allocator的等待,

  4、如果filter正处于阻塞数据状态,那么filter就退出阻塞。例如当停止的时候Renderer filter就阻塞,此时,filter就要取消阻塞。

  在EndFlush方法中,输入pin做了下列工作:

  1、等待所有正在队列中的samples被抛弃

  2、释放存放数据的buffer,这一步也可能在BeginFlush方法里,但是,beginflush方法streaming 线程是不同步的。Filter在BeginFlush和EndFlush方法之间不能够处理如何数据

  3、清除所有的EC_COMPLETE通知

  4、调用下游filter的EndFlush方法

  此时,filter可以再次接收sample。

  在拉模式中,parser Filter初始化flushing,而不是由source filter,它不仅调用了下游filterIPin::BeginFlush and IPin::EndFlush方法,它又调用了源filter输出pin上的IAsyncReader::BeginFlush and IAsyncReader::EndFlush,如果此时,源filter有未决的read请求,它就抛弃

  Seeking
 
  Filter通过IMediaSeeking接口支持seeking。应用程序从filter 图表管理器请求IMediaSeeking接口,然后通过这个接口,执行seek命令。Filter图表管理器传递到graph里所有的renderer filter。每个renderer 通过上游filter的输出pin来传递seek命令,直到某一个filter可以执行这个seek命令。一般来说,源filter,或者parser filter可以执行seek 命令。

  当一个filter执行seek命令的时候,它就flushes所有的未决的数据,这是为了减少seek命令的迟延。当一个seek命令后,stream time设置为零。

  下面的图表演示了seek过程


图1

  如果一个parser filter 的输出pin不止一个的话,它就指定一个pin来接收seek commands,其他的pin当接收到seek 命令时,就拒绝或者忽略seek 命令。这样,parser就保持了所有的数据流同步。

  pin连接时数据格式的动态改变

  当两个filter连接的时候,他们会就某种媒体类型达成协议。这种数据类型用来描述上游filter将传递什么格式的数据。大多数情况下,在连接的持续过程中,这个媒体类型是不变的,但是,directshow也支持动态改变媒体类型。

  Directshow定义了一些机制来支持动态改变媒体类型。关键在于filter graph的状态和将要改变的类型。

  如果graph处于停止状态,pin可以重新连接,重新就某个媒体类型达成协议。

  一些filter还支持动态的连接,

  当graph处于活动状态,并且不支持动态的重新连接的时候,有三种机制支持媒体类型的改变。

  QueryAccept (Downstream) 适用于输出pin向下游的filter提出改变媒体类型,并且新的媒体格式的大小不超过原来的buffer。

  QueryAccept (Upstream) 适用于输入pin首先向上游的filter提出媒体类型的改变,新的媒体类型格式可以和原来的大小一致,也可以大于。

  ReceiveConnection适用于输出pin首先提出改变媒体类型,但是新的媒体类型的格式大于原来的buffer。

查看本文源

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章