动态重新连接

[与此页面关联的功能 DirectShow 是旧版功能。 它已被 MediaPlayerIMFMediaEngineMedia Foundation 中的音频/视频捕获所取代。 这些功能已针对Windows 10和Windows 11进行了优化。 Microsoft 强烈建议新代码尽可能在 Media Foundation 中使用 MediaPlayerIMFMediaEngine音频/视频捕获 ,而不是 DirectShow。 如果可能,Microsoft 建议重写使用旧 API 的现有代码以使用新 API。]

在大多数 DirectShow 筛选器中,当图形主动流式传输数据时,无法重新连接图钉。 应用程序必须在重新连接引脚之前停止图形。 但是,某些筛选器在图形运行时支持引脚重新连接,此过程称为动态重新连接。 这可以通过应用程序或图形中的筛选器来完成。

例如,请考虑下图中的图。

动态图形生成图

动态重新连接的一种方案可能是在图形正在运行时从图形中删除筛选器 2,并将其替换为另一个筛选器。 若要使此方案正常工作,必须满足以下条件:

  • 筛选器 3 (引脚 D) 上的输入引脚必须支持 IPinConnection 接口。 此接口允许在不停止筛选器的情况下重新连接引脚。
  • 筛选器 1 上的输出引脚 (引脚 A) 必须能够在重新连接发生时阻止媒体数据流。 在重新连接期间,任何数据都不能在引脚 A 和引脚 D 之间传输。 通常,这意味着输出引脚必须支持 IPinFlowControl 接口。 但是,如果筛选器 1 是启动重新连接的筛选器,则它可能有一些内部机制来阻止其自己的数据流。

动态重新连接将涉及以下步骤:

  1. 阻止来自引脚 A 的数据流。
  2. 重新连接引脚 A 到引脚 D,可能通过新的中间筛选器。
  3. 取消阻止固定 A,以便数据再次开始流动。

步骤 1。 阻止数据流

若要阻止数据流,请在引脚 A 上调用 IPinFlowControl::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);
    }
}

若要 同步调用 方法,只需传递值 NULL 而不是事件句柄。 现在, 方法将阻止,直到操作完成。 在引脚准备好提供新示例之前,可能不会发生这种情况。 如果筛选器已暂停,则可能需要任意时间长度。 因此,不要从main应用程序线程进行同步调用。 使用工作线程,或者异步调用 方法。

步骤 2。 重新连接引脚

若要重新连接引脚,请查询 IGraphConfig 接口的 Filter Graph 管理器,并调用 IGraphConfig::ReconnectIGraphConfig::Reconfigure重新连接方法更易于使用;它执行以下操作:

  • 停止示例) 中 (筛选器 2 的中间筛选器,并将其从图中删除。
  • 根据需要添加新的中间筛选器。
  • 连接所有引脚。
  • 暂停或运行任何新筛选器,以匹配图形的状态。

重新连接方法有多个可选参数,可用于指定引脚连接的媒体类型和要使用的中间筛选器。 例如:

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);     

有关详细信息,请参阅参考页。 如果 重新连接 方法不够灵活,可以使用 Reconfigure 方法,该方法调用应用程序定义的回调方法来重新连接引脚。 若要使用此方法,请在应用程序中实现 IGraphConfigCallback 接口。

在调用 重新配置之前,请阻止来自输出引脚的数据流,如前所述。 然后推送正在重新连接的关系图部分仍处于挂起状态的任何数据,如下所示:

  1. 在示例) 中,在重新连接链中最远下游的输入引脚上调用 IPinConnection::NotifyEndOfStream (引脚 D。 将句柄传递到 Win32 事件。
  2. 在从阻止数据流的输出引脚直接下游的输入引脚上调用 IPin::EndOfStream 。 (在此示例中,数据流在引脚 A 处被阻止,因此可以在引脚 B.)
  3. 等待事件发出信号。 输入引脚 (引脚 D) 接收流结束通知时向事件发出信号。 这表示没有数据在引脚之间传输,并且调用方可以安全地重新连接引脚。

请注意, IGraphConfig::重新连接 方法会自动处理前面的步骤。 仅当使用 Reconfigure 方法时,才需要执行这些步骤。

通过图形推送数据后,调用 重新配置 并将指针传递到 IGraphConfigCallback 回调接口。 Filter Graph 管理器将调用你提供的 IGraphConfigCallback::Reconfigure 方法。

步骤 3: 取消阻止数据流

重新连接引脚后,请为第一个参数调用值为零的 IPinFlowControl::Block 来取消阻止数据流。

备注

如果动态重新连接由筛选器执行,则必须注意一些线程问题。 如果 Filter Graph 管理器尝试停止筛选器,它可能会死锁,因为图形等待筛选器停止,同时筛选器可能正在等待数据通过图形推送。 为了防止可能出现的死锁,本部分所述的某些方法会处理 Win32 事件。 如果 Filter Graph 管理器尝试停止筛选器,筛选器应发出事件信号。 有关详细信息,请参阅 IGraphConfigIPinConnection

 

动态图形生成