实现预览固定 (可选)

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

本主题介绍如何在 DirectShow 捕获筛选器上实现预览固定。

如果筛选器具有预览引脚,则预览引脚必须发送捕获引脚传递的数据的副本。 执行此操作时,仅从预览引脚发送数据不会导致捕获引脚丢弃帧。 捕获引脚始终优先于预览引脚。

捕获引脚和预览引脚必须使用相同的格式发送数据。 因此,它们必须使用相同的媒体类型进行连接。 如果捕获引脚首先连接,则预览引脚应提供相同的媒体类型,并拒绝任何其他类型。 如果预览引脚首先连接,并且捕获引脚连接到其他媒体类型,则预览引脚应使用新媒体类型重新连接。 如果预览引脚下游的筛选器拒绝新类型,捕获引脚还应拒绝该类型。 使用 IPin::QueryAccept 方法从预览引脚向下游查询筛选器,并使用 IFilterGraph::Reconnect 方法重新连接引脚。 如果筛选器关系图管理器重新连接捕获引脚,则这些规则也适用。

以下示例演示此过程的概述:

// Override CBasePin::CheckMediaType.
CCapturePin::CheckMediaType(CMediaType *pmt)
{
    if (m_pMyPreviewPin->IsConnected()) 
    {
        // The preview pin is already connected, so query the pin it is
        // connected to. If the other pin rejects it, so do we.
        hr = m_pMyPreviewPin->GetConnected()->QueryAccept(pmt);
        if (hr != S_OK) 
        {
            // The preview pin cannot reconnect with this media type.
            return E_INVALIDARG;
        }
        // The preview pin will reconnect when SetMediaType is called.
    }
    // Decide whether the capture pin accepts the format. 
    BOOL fAcceptThisType = ...  // (Not shown.)
    return (fAcceptThisType? S_OK : E_FAIL);
}

// Override CBasePin::SetMediaType.
CCapturePin::SetMediaType(CMediaType *pmt);
{
    if (m_pMyPreviewPin->IsConnected()) 
    {
        // The preview pin is already connected, so it must reconnect.
        if (m_pMyPreviewPin->GetConnected()->QueryAccept(pmt) == S_OK)
        {
            // The downstream pin will accept the new type, so it's safe
            // to reconnect. 
            m_pFilter->m_pGraph->Reconnect(m_pMyPreviewPin);
        }
        else
        {
            return VFW_E_INVALIDMEDIATYPE;
        }
    }
    // Now do anything that the capture pin needs to set the type.
    hr = MyInternalSetMediaType(pmt);

    // And finally, call the base-class method.
    return CBasePin::SetMediaType(pmt);
}

CPreviewPin::CheckMediaType(CMediaType *pmt)
{
    if (m_pMyCapturePin->IsConnected())
    {
       // The preview pin must connect with the same type.
       CMediaType cmt = m_pMyCapturePin->m_mt;
       return (*pmt == cmt ? S_OK : VFW_E_INVALIDMEDIATYPE);
    }
    // Decide whether the preview pin accepts the format. You can use your 
    // knowledge of which types the capture pin will accept. Regardless,
    // when the capture pin connects, the preview pin will reconnect.
    return (fAcceptThisType? S_OK : E_FAIL);
}

筛选器连接方式

编写捕获筛选器