Partilhar via


Reconexão dinâmica

[O recurso associado a esta página, DirectShow, é um recurso herdado. Foi substituído por MediaPlayer, IMFMediaEnginee Audio/Video Capture in Media Foundation. Esses recursos foram otimizados para Windows 10 e Windows 11. A Microsoft recomenda vivamente que o novo código utilize 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 DirectShow, os pinos não podem ser reconectados enquanto o gráfico estiver transmitindo dados ativamente. O aplicativo deve parar o gráfico antes de reconectar os pinos. No entanto, alguns filtros suportam reconexões de pinos enquanto o gráfico está em execução, um processo conhecido como reconexão dinâmica. Isso pode ser feito tanto pelo aplicativo, quanto por um filtro no gráfico.

Como exemplo, considere o gráfico na ilustração a seguir.

diagrama dinâmico de construção de gráficos

Um cenário para reconexão dinâmica pode ser remover o Filtro 2 do gráfico, enquanto o gráfico está 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 (pino D) deve suportar o interface IPinConnection. Essa interface permite que o pino seja reconectado sem parar 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. Geralmente, isso significa que o pino de saída deve suportar a interfaceIPinFlowControl. No entanto, se o Filtro 1 for o filtro que inicia a reconexão, ele pode 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 ao pino D, possivelmente através de um novo filtro intermediário.
  3. Desbloqueie o pino A para que os dados comecem a fluir novamente.

Passo 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 uma nova amostra. Se o filtro estiver pausado, isso pode levar um período de tempo arbitrário. Portanto, não faça a chamada síncrona do thread principal do aplicativo. Use um thread de trabalho ou chame o método de forma assíncrona.

Passo 2. Reconecte os pinos

Para reconectar os pinos, consulte o Gerenciador de Gráficos 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:

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

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 mais informações, 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 o IGraphConfigCallback interface 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 gráfico que você está reconectando, da seguinte maneira:

  1. Chame IPinConnection::NotifyEndOfStream no pino de entrada mais a jusante na cadeia de reconexão (pino D no exemplo). Passe uma alça para um evento Win32.
  2. Chame IPin::EndOfStream no pino de entrada que está imediatamente a jusante do pino de saída onde você bloqueou o fluxo de dados. (Neste exemplo, o fluxo de dados foi bloqueado no pino A, então você chamaria EndOfStream no pino B.)
  3. Aguarde até que o evento seja sinalizado. O pino de entrada (pino D) sinaliza o evento quando recebe a notificação de fim de fluxo. Isso indica que nenhum dado está viajando entre os pinos e que o chamador pode reconectá-los 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 Reconfigure.

Depois que os dados forem enviados por push através do gráfico, chame Reconfigure e passe um ponteiro para o seu IGraphConfigCallback interface de retorno de chamada. O Filter Graph Manager chamará o IGraphConfigCallback::Reconfigure método que você forneceu.

Passo 3. Desbloqueie o fluxo de dados

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

Observação

Se uma reconexão dinâmica for executada por um filtro, há alguns problemas de threading que você deve estar ciente. Se o Gerenciador de Gráficos de Filtro tentar parar o filtro, ele poderá travar, porque o gráfico aguarda que o filtro pare, enquanto ao mesmo tempo o filtro pode estar aguardando que os dados sejam enviados por push através do gráfico. 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 Gráficos de Filtros tentar parar o filtro. Para obter mais informações, consulte IGraphConfig e IPinConnection.

 

Dynamic Graph Building