Filter Graph的动态构建

原创 2005年05月25日 16:29:00

 

 

1动态的重新连接

在进行pin连接的时候,应用程序一般都要讲graph停掉。但是,一些filter支持pin的动态连接。

         1

如上图,我们想将Filter 2动态移走。有两个必要条件:

1Filter 3 (pin D)必须支持IPinConnection接口(这个接口能够保证Filter在非Stopped状态下也能进行Pin的重连);

2Filter1上的输出pin,也就是pin A,在重新连接的过程中必须要将发送数据的线程阻塞,在重连的时候,pin Apin D中不允许数据的传输, 如果“重连”是由Filter 1发起的(在Filter内部完成),那么Filter 1要有内部机制来阻塞数据发送线程;如果“重连”由应用程序来完成,则要求Filter 1 (pin A)实现IPinFlowControl接口。

动态重连的一般步骤如下:

1)在Filter 1(pin A)上阻塞数据流线程。

2)重连Pin APin D,必要时插入新的Filter

3)再次启动Filter 1(pin A)上的数据发送线程。

下面先来看看第一步;
1)在Filter 1(pin A)上阻塞数据流线程。

IPinFlowControl::Block可以工作在同步和异步两种模式下。

如果在异步方式下使用Block函数,要首先创建一个win32事件,然后将这个事件句柄作为参数传递给block函数,这个函数会立即返回,然后调用WaitForSingleObject方法等待事件被触发。如下:
// Create an event
HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (hEvent != NULL)
{
    // Block the data flow.
    hr = pFlowControl->Block(AM_PIN_FLOW_CONTROL_BLOCK, hEvent);
    if (SUCCEEDED(hr))
    {
        // Wait for the pin to finish.
        DWORD dwRes = WaitForSingleObject(hEvent, dwMilliseconds);
    }
}

如何用同步的方式调用Block函数,只需给它传递一个NULL的参数即可。这样这个函数就会一直阻塞下去,直到pin完全做好准备可以传递sample,阻塞停止。如果filter处于paused状态,阻塞时间也许会无限延长,因此,不要在你的主线程中采用同步的方式调用这个函数,可以新开一个线程或者采用异步的方式。
2)重连Pin APin D,必要时插入新的Filter

这里Pin的重连可以使用IGraphConfig::ReconnectIGraphConfig::ReconfigureIGraphConfig接口可以从Filter Graph Manager上获得)。ReconnectReconfigure使用起来要简单,它主要作如下几件事:

1Filter 2置于Stopped状态,然后将其移走;

2如果需要,可以在filter graph中增加新的Filter

3重新连接相关的各个Pin

4将新加入的Filter置于PausedRunning状态,以使其与Filter Graph同步。示例如下:
pGraph->AddFilter(pNewFilter, L"New Filter for the Graph");
pConfig->Reconnect(
    pPinA,      // Reconnect this output pin...
    pPinD,      // ... to this input pin.
    pMediaType, // Use this media type.
    pNewFilter, // Connect them through this filter.
    NULL,
    0);    
 
实际应用中,如果你觉得Reconnect不够灵活,还可以改用Reconfigure方法。这个方法可以通过应用程序中的回调函数来重新连接pin。使用Reconfigure方法,你必须在你的应用程序里实现IGraphConfigCallback接口;

Reconfigure调用之前,还要如前所述,阻塞数据发送线程,然后通过以下步骤将海没有处理得数据发送下去:

1调用filter最末端的输入pin上的IPinConnection::NotifyEndOfStream。在这个例子里就是pin D。给这个pin传递一个win32事件

2然后在和上游需要阻塞发送数据的filter的输出pin相连的输入pin上调用IPin::EndOfStream方法,这个例子,上游最远端得数据输出pinpin A,那么和它相连的输入pin就是pin B了,就调用pin B上的IPin::EndOfStream方法。

3等待触发事件。当Pin D接收到一个end of stream通知的时候,表明graph中已经没有数据流在传递了,可以安全的进行pin的重新连接了。

这些处理IGraphConfig::Reconnect会自动给我们完成
3)再次启动Filter 1(pin A)上的数据发送线程。

只需调用IPinFlowControl::Block,如下:pFlowControl->Block(0, NULL);  
过滤器链(Filter Chains

首先要弄明白什么是Filter Chain。见下图:

2
1 Filter Chain
是相互连接着的一条Filter链路,并且链路中的每个Filter至多有一个Input pin,至多有一个Output pin

2 这条Filter链路中的数据流不依赖于链路外的其他Filter

如上图中,ABCDFGHFGGH都是Filter Chain,同时Filter链也可以只包括一个filter,因此A,B,C,D,E,F,G也都是独立的链,因为E含有两个输入pin,因此任何含有E的都不是Filter Chain
Filter Chain
通过IFilterChain接口来操作的,该接口可以从Filter Graph Manager上获得。

IFilterChain提供了下面的方法用来操作filter链。

IFilterChain::StartChain      开始一个链条

IFilterChain::StopChain       停止一个链条

IFilterChain::PauseChain      暂停一个链条

IFilterChain::RemoveChain    将一个链条从graph中删除

并没有一个特殊的方法用来添加一个chain,它和正常的添加filter的方法一样,首先用IFilterGraph::AddFilter graph中添加一个filter,然后就是IGraphBuilder::Connect, IGraphBuilder::Render等诸如此类的方法。    

Graph在运行的时候,Filter Chain可以在RunningStopped状态之间切换;当Graph在暂停状态下,Filter Chain可以在PausedStopper状态之间切换。以上是Filter Chain仅有的两种状态转换。

Filter Chain的使用规则

当你使用IFilterChain的方法时,你一定要确保graph中的filter都支持这个接口,否则的话你也可能会造成死锁和graph错误。

下面将教给你如何正确使用filter chain

           3

1 在链条的状态改变之前,在链条边界的数据处理必须完成。下面的函数可以完成这些事情:IMemInputPin::Receive, IPin::NewSegment, and IPin::EndOfStream

Filters in the chain must return from calls to these methods made by filters outside the chain; and filters outside the chain must return from calls made by filters within the chain.

例如:上面图中,filter B必须将从filter A中请求的数据处理完毕,filter E必须完成对filter D请求的数据的处理。

2 上游的filter必须能够察觉filter 链表的状态改变。例如,在上图中,假如chain停止,但是filter A却调用B上的输入pin上的IMemInputPin::Receive方法,调用肯定是失败的,并且返回的信息是stream 停止。如果当应用程序重新启动chain的时候,filter A就没有数据流了。

3chain下游的filter也应该能够察觉链表状态的改变。如果不能够察觉的话,如果E阻塞等待上游的D传递sample,但是上游的chain的状态已经改变成停止状态,容易造成死锁。

4所有和链表内的filter 相连的filter都应该有自己独立的allocator,因为如果chain的状态改变或者被删除,它的allocator就会被销毁,和它们相连的filter就没法处理sample了。

5只有链表支持动态断开才能将一个链表从graph中移走。

 

 

 

 

构建Filter Graph

构建Filter Graph 3.3.1. 用于构建Graph的组件     DirectShow提供了一系列用于构建filter graph的组件,包括:     *Filte...

DirectShow编程(3.3)- 关于DirectShow - 构建Filter Graph

3.3. 构建Filter Graph3.3.1. 用于构建Graph的组件     DirectShow提供了一系列用于构建filter graph的组件,包括:    *Filter Graph ...

amcap sample code 分析初步 --学习通用filter graph的构建技术

以代码为例说明amcap在 direct sample 中的使用
  • titer1
  • titer1
  • 2014年06月11日 16:31
  • 2545

DSpy.dll 偵測graph使用的filter

  • 2011年04月25日 15:00
  • 226KB
  • 下载

Building a Simple Camera DirectShow Filter graph Application in WEC7

Many of you might have noted that your WinCE 6.0 DirectShow camera application was not working with ...

添加DMO到directshow filter graph中

这里我主要是碰上了一个   要添加进我的graph的问题。(DMO不同于,Filter,但是可以通过IWrapperFilter 来使用DMO --象Filter一样使用 但是有局限性) 这里截...
  • lanhxg
  • lanhxg
  • 2012年04月04日 20:32
  • 1394

全手动连接Filter Graph

昨天努了一天,终于搞完了一个全手动连接的filter graph 程序,虽然很简单,但是还是费了老大的劲。不扯了,上菜……开发环境:Vista+VS2008+DX9.0,控制台应用程序(便于调试)第一...
  • cg_csu
  • cg_csu
  • 2011年03月27日 10:13
  • 1473

获得filter的CLSID并加入到graph中

一、获得filter的CLSID 获得filter的CLSID有三种方法: 1、通过注册表中记录的值获得。 HKEY_CURRENT_USER/Software/Microsoft/Active...

获得filter的CLSID并加入到graph中

获得filter的CLSID并加入到graph中   一、获得filter的CLSID 获得filter的CLSID有三种方法: 1、通过注册表中记录的值获得。 HKEY_CURRENT_U...

DirectShow编程(3.2)- 关于DirectShow - Filter Graph和它的组件

3.2. Filter Graph和它的组件     这一节描述了DirectShow的主要组件,为DirectShow应用程序和DirectShow Filter开发者提供一个介绍。应用程序开发者可...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Filter Graph的动态构建
举报原因:
原因补充:

(最多只允许输入30个字)