Reconexão dinâmica

[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.]

Na maioria dos filtros do DirectShow, os pinos não podem ser reconectados enquanto o grafo está transmitindo dados ativamente. O aplicativo deve interromper o grafo antes de reconectar os pinos. No entanto, alguns filtros dão suporte a reconexões de pino enquanto o grafo está em execução, um processo conhecido como reconexão dinâmica. Isso pode ser feito pelo aplicativo ou por um filtro no grafo.

Por exemplo, considere o grafo na ilustração a seguir.

diagrama de criação dinâmica de grafo

Um cenário para reconexão dinâmica pode ser remover o Filtro 2 do grafo, enquanto o grafo estiver em execução e substituí-lo por outro filtro. Para que esse cenário funcione, o seguinte deve ser verdadeiro:

  • O pino de entrada no Filtro 3 (pin D) deve dar suporte à interface IPinConnection . Essa interface permite que o pino seja reconectado sem interromper o filtro.
  • O pino de saída no Filtro 1 (pino A) deve ser capaz de bloquear o fluxo de dados de mídia enquanto a reconexão ocorre. Nenhum dado pode viajar entre o pino A e o pino D durante a reconexão. Em geral, isso significa que o pino de saída deve dar suporte à interface IPinFlowControl . No entanto, se Filter 1 for o filtro que inicia a reconexão, ele poderá ter algum mecanismo interno para bloquear seu próprio fluxo de dados.

A reconexão dinâmica envolverá as seguintes etapas:

  1. Bloqueie o fluxo de dados do pino A.
  2. Reconecte o pino A para fixar D, possivelmente por meio de um novo filtro intermediário.
  3. Desbloqueie o pino A para que os dados comece a fluir novamente.

Etapa 1. Bloquear o fluxo de dados

Para bloquear o fluxo de dados, chame IPinFlowControl::Block no pino A. Esse método pode ser chamado de forma assíncrona ou síncrona. Para chamar o método de forma assíncrona, crie um objeto de evento Win32 e passe o identificador de evento para o método Block . O método retornará imediatamente. Aguarde até que o evento seja sinalizado, usando uma função como WaitForSingleObject. O pino sinaliza o evento quando ele bloqueou o fluxo de dados. Por exemplo:

// Create an event
HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (hEvent != NULL)
{
    // Block the data flow.
    hr = pFlowControl->Block(AM_PIN_FLOW_CONTROL_BLOCK, hEvent); 
    if (SUCCEEDED(hr))
    {
        // Wait for the pin to finish.
        DWORD dwRes = WaitForSingleObject(hEvent, dwMilliseconds);
    }
}

Para chamar o método de forma síncrona, basta passar o valor NULL em vez do identificador de evento. Agora, o método será bloqueado até que a operação seja concluída. Isso pode não acontecer até que o pino esteja pronto para entregar um novo exemplo. Se o filtro estiver em pausa, isso poderá levar um período arbitrário. Portanto, não faça a chamada síncrona do thread do aplicativo main. Use um thread de trabalho ou chame o método de forma assíncrona.

Etapa 2. Reconectar os pinos

Para reconectar os pinos, consulte o Gerenciador de Grafo de Filtro para a interface IGraphConfig e chame IGraphConfig::Reconnect ou IGraphConfig::Reconfigure. O método Reconnect é mais simples de usar; ele faz o seguinte:

  • Interrompe os filtros intermediários (Filtro 2 no exemplo) e os remove do grafo.
  • Adiciona novos filtros intermediários, se necessário.
  • Conecta todos os pinos.
  • Pausa ou executa novos filtros para corresponder ao estado do grafo.

O método Reconnect tem vários parâmetros opcionais que podem ser usados para especificar o tipo de mídia para a conexão de pino e o filtro intermediário a ser usado. Por exemplo:

pGraph->AddFilter(pNewFilter, L"New Filter for the Graph");
pConfig->Reconnect(
    pPinA,      // Reconnect this output pin...
    pPinD,      // ... to this input pin.
    pMediaType, // Use this media type.
    pNewFilter, // Connect them through this filter.
    NULL, 
    0);     

Para obter detalhes, consulte a página de referência. Se o método Reconnect não for flexível o suficiente, você poderá usar o método Reconfigure , que chama um método de retorno de chamada definido pelo aplicativo para reconectar os pinos. Para usar esse método, implemente a interface IGraphConfigCallback em seu aplicativo.

Antes de chamar Reconfigurar, bloqueie o fluxo de dados do pino de saída, conforme descrito anteriormente. Em seguida, envie por push todos os dados que ainda estão pendentes na seção do grafo que você está reconectando, da seguinte maneira:

  1. Chame IPinConnection::NotifyEndOfStream no pin de entrada mais distante downstream na cadeia de reconexão (fixar D no exemplo). Passe um identificador para um evento Win32.
  2. Chame IPin::EndOfStream no pino de entrada que é imediatamente downstream do pino de saída em que você bloqueou o fluxo de dados. (Neste exemplo, o fluxo de dados foi bloqueado no pino A, portanto, você chamaria EndOfStream no pino B.)
  3. Aguarde até que o evento seja sinalizado. O pino de entrada (pin D) sinaliza o evento quando ele recebe a notificação de fim do fluxo. Isso indica que nenhum dado está viajando entre os pinos e que o chamador pode reconectar os pinos com segurança.

Observe que o método IGraphConfig::Reconnect manipula automaticamente as etapas anteriores. Você só precisará executar essas etapas se estiver usando o método Reconfigurar .

Depois que os dados forem enviados por push pelo grafo, chame Reconfigurar e passe um ponteiro para a interface de retorno de chamada IGraphConfigCallback . O Gerenciador de Grafo de Filtro chamará o método IGraphConfigCallback::Reconfigure que você forneceu.

Etapa 3. Desbloquear o Fluxo de Dados

Depois de reconectar os pinos, desbloqueie o fluxo de dados chamando IPinFlowControl::Block com um valor igual a zero para o primeiro parâmetro.

Observação

Se uma reconexão dinâmica for executada por um filtro, haverá alguns problemas de threading que você deve estar ciente. Se o Gerenciador de Grafo de Filtro tentar interromper o filtro, ele poderá ficar em deadlock, pois o grafo aguardará a interrupção do filtro, enquanto, ao mesmo tempo, o filtro pode estar aguardando que os dados sejam enviados por push pelo grafo. Para evitar o possível deadlock, alguns dos métodos descritos nesta seção levam um identificador para um evento Win32. O filtro deve sinalizar o evento se o Gerenciador de Grafo de Filtro tentar interromper o filtro. Para obter mais informações, consulte IGraphConfig e IPinConnection.

 

Criação dinâmica de grafo