Implémentation d’une broche d’aperçu (facultatif)

[La fonctionnalité associée à cette page, DirectShow, est une fonctionnalité héritée. Il a été remplacé par MediaPlayer, IMFMediaEngine et Audio/Video Capture in Media Foundation. Ces fonctionnalités ont été optimisées pour Windows 10 et Windows 11. Microsoft recommande vivement que le nouveau code utilise MediaPlayer, IMFMediaEngine et Audio/Video Capture dans Media Foundation au lieu de DirectShow, si possible. Microsoft suggère que le code existant qui utilise les API héritées soit réécrit pour utiliser les nouvelles API si possible.]

Cette rubrique explique comment implémenter une broche d’aperçu sur un filtre de capture DirectShow.

Si votre filtre a une épingle d’aperçu, l’épingle d’aperçu doit envoyer une copie des données fournies par l’épingle de capture. L’envoi de données uniquement à partir de l’aperçu n’entraîne pas la suppression d’images par l’épingle de capture. L’épingle de capture a toujours la priorité sur l’épingle d’aperçu.

La broche de capture et l’épingle d’aperçu doivent envoyer des données au même format. Par conséquent, ils doivent se connecter à l’aide de types de média identiques. Si la broche de capture se connecte en premier, la broche d’aperçu doit offrir le même type de média et rejeter tous les autres types. Si l’épingle d’aperçu se connecte en premier et que la broche de capture se connecte avec un autre type de média, l’épingle d’aperçu doit se reconnecter à l’aide du nouveau type de média. Si le filtre en aval de la broche d’aperçu rejette le nouveau type, la broche de capture doit également rejeter le type. Utilisez la méthode IPin::QueryAccept pour interroger le filtre en aval à partir de l’épingle d’aperçu et utilisez la méthode IFilterGraph::Reconnect pour reconnecter l’épingle. Ces règles s’appliquent également si le Gestionnaire de graphe de filtre reconnecte la broche de capture.

L’exemple suivant montre un plan de ce processus :

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

Connexion des filtres

Écriture de filtres de capture