DirectShow 过滤链
过滤器链是满足以下条件的过滤器序列:
- 链中的每个过滤器最多有一个连接的输入引脚和一个连接的输出引脚。
- 可以遍历链中的每个过滤器,而不遍历链外的过滤器。
例如,在下图中,过滤器A–B、C–D和F–G–H是过滤器链。F–G–H(F–G和G–H)中的每个子链也是一个过滤链。滤波器链可以由单个滤波器组成,因此滤波器A、B、C、D、F、G和H也是不同的滤波器链。过滤器E有两个输入连接,因此任何包含过滤器E的过滤器序列都不是过滤器链。
IFilterChain接口提供了以下控制过滤器链的方法:
- IFilterChain::StartChain启动一个链。
- IFilterChain::StopChain停止链。
- IFilterChain::PauseChain暂停链。
- IFilterChain::RemoveChain从图中删除链。
没有添加链的特定方法。要添加链,请使用IFilterGraph::AddFilter方法插入新筛选器。然后通过调用IGraphBuilder::connect、IGraphBuilder::Render或类似方法连接过滤器。
当图形运行时,过滤器链可以在运行和停止之间切换。当图形暂停时,它可以在暂停和停止之间切换。这些是过滤器链中唯一可能的状态转换。
过滤链指南
使用IFilterChain方法时,确保图中的筛选器可以支持筛选器链接操作非常重要。否则,可能会导致死锁或图形错误。连接到链的筛选器必须在链更改状态后正常工作。
使用IFilterChain的最佳方法是使用一组专门为链接设计的过滤器。使用以下指导原则,以确保您的过滤器对过滤器链操作是安全的。这些点参考下图。
- 在筛选器链的状态更改之前,必须完成筛选器链边界处的所有数据处理调用。此规则适用于IMemInputPin::Receive、IPin::NewSegment和IPin::EndOfStream方法。链中的筛选器必须从链外的筛选器对这些方法的调用返回;链外的筛选器必须从链内的筛选器对这些方法的调用返回。
例如,在上一个图中,筛选器B必须完成来自筛选器A的所有数据处理调用,筛选器E必须完成来自筛选器D的所有调用。如果管脚公开了IPinFlowControl和IPinConnection接口,则可以通过调用IPinFlowControl::Block和IGraphConfig::PushThroughData方法将数据推送到图中,如动态重连中所述。过滤器还可能支持用于推送数据的私有方法。
上游过滤器必须期望链的状态改变。例如,在上一个图中,假设链已停止,但filter A调用IMemInputPin::Receive。调用失败,过滤器A的响应是停止流式传输。当应用程序重新启动链时,它没有效果,因为过滤器A不再流式传输数据。
下游过滤器还必须期望链的状态发生变化。否则,下游过滤器可能会在等待永远不会到达的样本时阻塞。例如,多路复用器(MUX)滤波器通常需要来自其所有输入管脚的数据。停止来自一个输入管脚的数据流可能会阻止其他流的处理。这可能导致图形死锁。
从链外的筛选器到链内的筛选器的每个pin连接都应该有自己的分配器,而不是由其他连接共享。当链改变状态或从图中移除时,分配器可能会被解除委托。如果其他连接正在使用同一分配器,则它们将无法再处理样本。
除非连接到链条的过滤器支持动态断开,否则不要拆下链条。通常,连接的过滤器将支持IPinConnection或IPinFlowControl接口,但可能支持专用接口。