Compartilhar via


Liberando dados

[O recurso associado a esta página, DirectShow, é um recurso herdado. Ele foi substituído por MediaPlayer, IMFMediaEngine e Captura de Áudio/Vídeo na 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 Captura de Áudio/Vídeo no 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.]

O pseudocódigo a seguir mostra como implementar o método 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;
}

Quando a liberação é iniciada, o método BeginFlush usa o bloqueio de filtro, que serializa a alteração de estado. Ainda não é seguro pegar o bloqueio de streaming, pois a liberação acontece no thread do aplicativo e o thread de streaming pode estar no meio de uma chamada de Recebimento . O pin precisa garantir que Receive não está bloqueado e que todas as chamadas subsequentes para Receber falharão. O método CBaseInputPin::BeginFlush define um sinalizador interno, CBaseInputPin::m_bFlushing. Quando o sinalizador for TRUE, o método Receive falhará.

Ao entregar a chamada BeginFlush downstream, o pino garante que todos os filtros downstream liberem seus exemplos e retornem de Receber chamadas. Isso, por sua vez, garante que o pino de entrada não esteja bloqueado aguardando GetBuffer ou Receive. Se o método Receive do pin aguardar um evento (por exemplo, para obter recursos), o método BeginFlush deverá forçar a espera para terminar definindo o evento. Neste ponto, o método Receive tem a garantia de retornar e o sinalizador m_bFlushing impede que novas chamadas de Recebimento executem qualquer trabalho.

Para alguns filtros, isso é tudo o que BeginFlush precisa fazer. O método EndFlush sinalizará ao filtro que ele pode começar a receber amostras novamente. Outros filtros podem precisar usar variáveis ou recursos no BeginFlush que também são usados em Receive. Nesse caso, o filtro deve manter o bloqueio de streaming primeiro. Certifique-se de não fazer isso antes de nenhuma das etapas anteriores, pois você pode causar um deadlock.

O método EndFlush mantém o bloqueio de filtro e propaga a chamada downstream:

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

O método CBaseInputPin::EndFlush redefine o sinalizador m_bFlushing para FALSE, o que permite que o método Receive comece a receber amostras novamente. Essa deve ser a última etapa no EndFlush, pois o pino não deve receber amostras até que a liberação seja concluída e todos os filtros downstream sejam notificados.

Threads e seções críticas