Implementazione di un pin di anteprima (facoltativo)

[La funzionalità associata a questa pagina, DirectShow, è una funzionalità legacy. È stata sostituita da MediaPlayer, FMMediaEngine e Audio/Video Capture in Media Foundation. Queste funzionalità sono state ottimizzate per Windows 10 e Windows 11. Microsoft consiglia vivamente che il nuovo codice usi MediaPlayer, FMMediaEngine e Audio/Video Capture in Media Foundation anziché DirectShow, quando possibile. Microsoft suggerisce che il codice esistente che usa le API legacy venga riscritto per usare le nuove API, se possibile.

Questo argomento descrive come implementare un pin di anteprima in un filtro di acquisizione DirectShow.

Se il filtro ha un pin di anteprima, il pin di anteprima deve inviare una copia dei dati recapitati dal pin di acquisizione. Solo inviare dati dal pin di anteprima quando si esegue questa operazione non causerà l'eliminazione dei fotogrammi del pin di acquisizione. Il pin di acquisizione ha sempre la priorità sul pin di anteprima.

Il pin di acquisizione e il pin di anteprima devono inviare dati con lo stesso formato. Pertanto, devono connettersi usando tipi di supporti identici. Se il pin di acquisizione si connette per primo, il pin di anteprima deve offrire lo stesso tipo di supporto e rifiutare eventuali altri tipi. Se il pin di anteprima si connette prima e il pin di acquisizione si connette con un tipo di supporto diverso, il pin di anteprima deve riconnettersi usando il nuovo tipo di supporto. Se il filtro downstream dal pin di anteprima rifiuta il nuovo tipo, il pin di acquisizione deve anche rifiutare il tipo. Usare il metodo IPin::QueryAccept per eseguire una query sul filtro downstream dal pin di anteprima e usare il metodo IFilterGraph::Reconnect per riconnettere il pin. Queste regole si applicano anche se Filter Graph Manager riconnette il pin di acquisizione.

Nell'esempio seguente viene illustrata una struttura di questo processo:

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

Modalità di connessione dei filtri

Scrittura di filtri di acquisizione