Compartilhar via


Implementando um pin de visualização (opcional)

[O recurso associado a esta página, DirectShow, é um recurso herdado. Foi substituído por MediaPlayer, IMFMediaEngine e Audio/Video Capture in Media Foundation. Esses recursos foram otimizados para Windows 10 e Windows 11. A Microsoft recomenda fortemente que o novo código use MediaPlayer, IMFMediaEngine e Audio/Video Capture in Media Foundation em vez de DirectShow, quando possível. A Microsoft sugere que o código existente que usa as APIs herdadas seja reescrito para usar as novas APIs, se possível.]

Este tópico descreve como implementar um pin de visualização em um filtro de captura do DirectShow.

Se o filtro tiver um pin de visualização, o pin de visualização deverá enviar uma cópia dos dados entregues pelo pino de captura. Somente enviar dados do pino de visualização ao fazer isso não fará com que o pino de captura solte quadros. O pino de captura sempre tem prioridade sobre o pino de visualização.

O pino de captura e o pin de visualização devem enviar dados com o mesmo formato. Portanto, eles devem se conectar usando tipos de mídia idênticos. Se o pino de captura se conectar primeiro, o pin de visualização deverá oferecer o mesmo tipo de mídia e rejeitar qualquer outro tipo. Se o pino de visualização se conectar primeiro e o pino de captura se conectar a um tipo de mídia diferente, o pino de visualização deverá se reconectar usando o novo tipo de mídia. Se o filtro downstream do pino de visualização rejeitar o novo tipo, o pin de captura também deverá rejeitar o tipo. Use o método IPin::QueryAccept para consultar o filtro downstream do pino de visualização e use o método IFilterGraph::Reconnect para reconectar o pino. Essas regras também se aplicam se o Gerenciador do Gráfico de Filtro reconecta o pino de captura.

O exemplo a seguir mostra uma estrutura de tópicos desse 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);
}

Como os filtros se conectam

Escrevendo filtros de captura