刷新数据

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

以下伪代码演示如何实现 IPin::BeginFlush 方法:

HRESULT CMyInputPin::BeginFlush()
{
    CAutoLock lock_it(m_pLock);
   
    // First, make sure the Receive method will fail from now on.
    HRESULT hr = CBaseInputPin::BeginFlush();
    
    // Force downstream filters to release samples. If our Receive method
    // is blocked in GetBuffer or Deliver, this will unblock it.
    for (each output pin)
    {
        hr = pOutputPin->DeliverBeginFlush();
    }

    // Unblock our Receive method if it is waiting on an event.
    SetEvent(m_hSomeEventThatReceiveNeedsToWaitOn);

    // At this point, the Receive method can't be blocked. Make sure 
    // it finishes, by taking the streaming lock. (Not necessary if this 
    // is the last step.)
    { 
        CAutoLock lock_2(&m_csReceive);

        /* Now it's safe to do anything that would crash or hang 
           if Receive were executing. */
    }
    return hr;
}

刷新开始时, BeginFlush 方法采用筛选器锁,该锁将序列化状态更改。 使用流式处理锁尚不安全,因为刷新发生在应用程序线程上,并且流式处理线程可能正在 接收 调用中。 引脚需要保证 Receive 不会被阻止,并且对 Receive 的任何后续调用都将失败。 CBaseInputPin::BeginFlush 方法设置内部标志 CBaseInputPin::m_bFlushing。 当标志为 TRUE 时, Receive 方法将失败。

通过向下游传递 BeginFlush 调用,引脚可以保证所有下游筛选器释放其示例并从 接收 调用返回。 这反过来又保证不会阻止输入引脚等待 GetBufferReceive。 例如,如果固定的 Receive 方法曾经等待事件 (获取资源) , 则 BeginFlush 方法应通过设置事件来强制等待终止。 此时, Receive 方法保证返回, 并且 m_bFlushing 标志会阻止新的 Receive 调用执行任何工作。

对于某些筛选器,这只需 BeginFlush 即可完成。 EndFlush 方法将向筛选器发出信号,表明它可以再次开始接收样本。 其他筛选器可能需要在 BeginFlush 中使用也在 Receive 中使用的变量或资源。 在这种情况下,筛选器应首先保留流式处理锁。 请确保不要在上述任何步骤之前执行此操作,因为可能会导致死锁。

EndFlush 方法保留筛选器锁,并将调用传播到下游:

HRESULT CMyInputPin::EndFlush()
{
    CAutoLock lock_it(m_pLock);
    for (each output pin)
        hr = pOutputPin->DeliverEndFlush();
    return CBaseInputPin::EndFlush();
}

CBaseInputPin::EndFlush 方法将m_bFlushing标志重置为 FALSE,这允许 Receive 方法再次开始接收样本。 这应该是 EndFlush 中的最后一步,因为引脚在刷新完成并通知所有下游筛选器之前不得接收任何样本。

线程和关键部分