共用方式為


實作預覽釘選 (選擇性)

[與此頁面相關的功能 DirectShow是舊版功能。 它已被 MediaPlayerIMFMediaEngineMedia Foundation 中的音訊/視訊擷取取代。 這些功能已針對Windows 10和Windows 11進行優化。 Microsoft 強烈建議新程式碼盡可能使用 MediaPlayerIMFMediaEngine音訊/視訊擷取 ,而不是 DirectShow。 Microsoft 建議使用舊版 API 的現有程式碼盡可能重寫為使用新的 API。

本主題描述如何在 DirectShow 擷取篩選上實作預覽釘選。

如果您的篩選有預覽釘選,預覽釘選必須傳送擷取釘選所傳遞資料的複本。 只有在執行此動作時,才會從預覽釘選傳送資料,不會造成擷取釘選卸載畫面格。 擷取針腳一律優先于預覽釘選。

擷取釘選和預覽針腳必須傳送具有相同格式的資料。 因此,它們必須使用相同的媒體類型進行連線。 如果擷取針腳先連線,預覽釘選應該提供相同的媒體類型,並拒絕任何其他類型。 如果預覽針腳先連線,而擷取針腳會以不同的媒體類型連線,則預覽釘選應該使用新的媒體類型重新連線。 如果預覽針腳的下游篩選拒絕新的類型,擷取針腳也應該拒絕該類型。 使用 IPin::QueryAccept 方法來查詢預覽釘選的下游篩選,並使用 IFilterGraph::Reconnect 方法來重新連接針腳。 如果 Filter Graph Manager 重新連接擷取針腳,這些規則也會適用。

下列範例顯示此程式的大綱:

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

篩選連線的方式

撰寫擷取篩選