Vidage des données

[La fonctionnalité associée à cette page, DirectShow, est une fonctionnalité héritée. Il a été remplacé par MediaPlayer, IMFMediaEngine et Audio/Video Capture dans Media Foundation. Ces fonctionnalités ont été optimisées pour Windows 10 et Windows 11. Microsoft recommande vivement au nouveau code d’utiliser MediaPlayer, IMFMediaEngine et La capture audio/vidéo dans Media Foundation au lieu de DirectShow, lorsque cela est 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.]

Le pseudocode suivant montre comment implémenter la méthode IPin::BeginFlush :

HRESULT CMyInputPin::BeginFlush()
{
    CAutoLock lock_it(m_pLock);
   
    // First, make sure the Receive method will fail from now on.
    HRESULT hr = CBaseInputPin::BeginFlush();
    
    // Force downstream filters to release samples. If our Receive method
    // is blocked in GetBuffer or Deliver, this will unblock it.
    for (each output pin)
    {
        hr = pOutputPin->DeliverBeginFlush();
    }

    // Unblock our Receive method if it is waiting on an event.
    SetEvent(m_hSomeEventThatReceiveNeedsToWaitOn);

    // At this point, the Receive method can't be blocked. Make sure 
    // it finishes, by taking the streaming lock. (Not necessary if this 
    // is the last step.)
    { 
        CAutoLock lock_2(&m_csReceive);

        /* Now it's safe to do anything that would crash or hang 
           if Receive were executing. */
    }
    return hr;
}

Lorsque le vidage démarre, la méthode BeginFlush prend le verrou de filtre, qui sérialise le changement d’état. Il n’est pas encore sûr de prendre le verrou de diffusion en continu, car le vidage se produit sur le thread d’application et le thread de streaming peut se trouver au milieu d’un appel de réception . Le code pin doit garantir que la réception n’est pas bloquée et que tous les appels ultérieurs à Receive échouent. La méthode CBaseInputPin::BeginFlush définit un indicateur interne, CBaseInputPin::m_bFlushing. Lorsque l’indicateur a la valeur TRUE, la méthode Receive échoue.

En remettant l’appel BeginFlush en aval, la broche garantit que tous les filtres en aval libèrent leurs échantillons et retournent à partir des appels de réception . Cela garantit à son tour que la broche d’entrée n’est pas bloquée en attendant GetBuffer ou Receive. Si la méthode Receive de votre code pin attend sur un événement (par exemple, pour obtenir des ressources), la méthode BeginFlush doit forcer l’arrêt de l’attente en définissant l’événement. À ce stade, la méthode Receive est garantie de retourner, et l’indicateur m_bFlushing empêche les nouveaux appels de réception d’effectuer tout travail.

Pour certains filtres, c’est tout ce que BeginFlush doit faire. La méthode EndFlush signale au filtre qu’elle peut recommencer à recevoir des exemples. D’autres filtres peuvent avoir besoin d’utiliser des variables ou des ressources dans BeginFlush qui sont également utilisées dans Réception. Dans ce cas, le filtre doit d’abord contenir le verrou de diffusion en continu. Veillez à ne pas le faire avant l’une des étapes précédentes, car vous risquez de provoquer un blocage.

La méthode EndFlush contient le verrou de filtre et propage l’appel en aval :

HRESULT CMyInputPin::EndFlush()
{
    CAutoLock lock_it(m_pLock);
    for (each output pin)
        hr = pOutputPin->DeliverEndFlush();
    return CBaseInputPin::EndFlush();
}

La méthode CBaseInputPin::EndFlush réinitialise l’indicateur m_bFlushing sur FALSE, ce qui permet à la méthode Receive de recommencer à recevoir des exemples. Il doit s’agir de la dernière étape dans EndFlush, car la broche ne doit pas recevoir d’échantillons tant que le vidage n’est pas terminé et que tous les filtres en aval sont notifiés.

Threads et sections critiques