Controlando um grafo de captura

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

A interface IMediaControl do Gerenciador de Grafo de Filtro tem métodos para executar, parar e pausar todo o grafo. No entanto, se o grafo de filtro tiver fluxos de captura e visualização, você provavelmente deseja controlar os dois fluxos de forma independente. Por exemplo, talvez você queira visualizar o vídeo sem capturá-lo. Você pode fazer isso por meio do método ICaptureGraphBuilder2::ControlStream .

Observação

Esse método não funciona ao capturar em um arquivo ASF (Advanced Systems Format).

 

Controlando o fluxo de captura

O código a seguir define o fluxo de captura de vídeo a ser executado por quatro segundos, iniciando um segundo após a execução do grafo:

// Control the video capture stream. 
REFERENCE_TIME rtStart = 10000000, rtStop = 50000000;
const WORD wStartCookie = 1, wStopCookie = 2;  // Arbitrary values.
hr = pBuild->ControlStream(
    &PIN_CATEGORY_CAPTURE, // Pin category.
    &MEDIATYPE_Video,      // Media type.
    pCap,                 // Capture filter.
    &rtStart, &rtStop,     // Start and stop times.
    wStartCookie, wStopCookie  // Values for the start and stop events.
);
pControl->Run();

O primeiro parâmetro especifica qual fluxo controlar, como um GUID de categoria de pino. O segundo parâmetro fornece o tipo de mídia. O terceiro parâmetro é um ponteiro para o filtro de captura. Para controlar todos os fluxos de captura no grafo, defina o segundo e o terceiro parâmetros como NULL.

Os próximos dois parâmetros definem os horários em que o fluxo será iniciado e interrompido, em relação à hora em que o grafo começa a ser executado. Chame IMediaControl::Run para executar o grafo. Até que você execute o grafo, o método ControlStream não terá efeito. Se o grafo já estiver em execução, as configurações entrarão em vigor imediatamente.

Os dois últimos parâmetros são usados para obter notificações de evento quando o fluxo é iniciado e interrompido. Para cada fluxo que você controla usando esse método, o grafo de filtro envia um par de eventos: EC_STREAM_CONTROL_STARTED quando o fluxo é iniciado e EC_STREAM_CONTROL_STOPPED quando o fluxo é interrompido. Os valores de wStartCookie e wStopCookie são usados como o segundo parâmetro de evento. Assim, lParam2 no evento inicial é igual a wStartCookie e lParam2 no evento stop é igual a wStopCookie. O código a seguir mostra como obter esses eventos:

while (hr = pEvent->GetEvent(&evCode, &param1, &param2, 0), SUCCEEDED(hr))
{
    switch (evCode)
    {
    case EC_STREAM_CONTROL_STARTED: 
    // param2 == wStartCookie
    break;

    case EC_STREAM_CONTROL_STOPPED: 
    // param2 == wStopCookie
    break;
    
    } 
    pEvent->FreeEventParams(evCode, param1, param2);
}

O método ControlStream define alguns valores especiais para os horários de início e parada.

Valor Iniciar Stop
MAXLONGLONG Nunca inicie esse fluxo. Não pare até que o grafo pare.
NULL Comece imediatamente quando o grafo for executado. Pare imediatamente.

 

Por exemplo, o código a seguir interrompe o fluxo de captura imediatamente:

pBuild->ControlStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, pCap,
    0, 0,     // Start and stop times.
    wStartCookie, wStopCookie); 

Embora você possa interromper o fluxo de captura e reiniciá-lo mais tarde, isso criará uma lacuna nos carimbos de data/hora. Na reprodução, o vídeo aparecerá parado durante a lacuna (dependendo do formato do arquivo).

Controlando o fluxo de visualização

Para controlar o pin de visualização, chame ControlStream , mas defina o primeiro parâmetro como PIN_CATEGORY_PREVIEW. Isso funciona da mesma forma que funciona para PIN_CATEGORY_CAPTURE, exceto que você não pode usar tempos de referência para especificar o início e a parada, pois os quadros de visualização não têm carimbos de data/hora. Portanto, você deve usar NULL ou MAXLONGLONG. Use NULL para iniciar o fluxo de visualização:

pBuild->ControlStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, pCap,
    NULL,    // Start now.
    0,       // (Don't care.)
    wStartCookie, wStopCookie); 

Use MAXLONGLONG para interromper o fluxo de visualização:

pBuild->ControlStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, pCap,
    0,               // (Don't care.)
    MAXLONGLONG,     // Stop now.
    wStartCookie, wStopCookie); 

Não importa se o fluxo de visualização vem de um pino de visualização no filtro de captura ou do filtro Smart Tee. O método ControlStream funciona de qualquer maneira.

No entanto, para pinos de porta de vídeo, o método falhará. Nesse caso, outra abordagem é ocultar a janela de vídeo. Consulte o grafo para IVideoWindow e use o método IVideoWindow::p ut_Visible para mostrar ou ocultar a janela.

// Hide the video window.
IVideoWindow *pVidWin = 0;
hr = pGraph->QueryInterface(IID_IVideoWindow, (void**)&pVidWin);
if (SUCCEEDED(hr))
{
    pVidWin->put_Visible(OAFALSE);
    pVidWin->Release();
}

Além disso, se você chamar IVideoWindow::p ut_AutoShow com o valor OAFALSE antes de executar o grafo, o filtro Renderizador de Vídeo ocultará a janela até que você especifique o contrário. Por padrão, o Renderizador de Vídeo mostra a janela quando você executa o grafo.

Comentários sobre o Controle de Fluxo

O comportamento padrão de um pin é fornecer amostras quando o grafo é executado. Por exemplo, suponha que você chame ControlStream com PIN_CATEGORY_CAPTURE mas não com PIN_CATEGORY_PREVIEW. Quando você executar o grafo, o fluxo de visualização será executado imediatamente, enquanto o fluxo de captura será executado em qualquer momento especificado em ControlStream.

Se você estiver capturando mais de um fluxo e enviando-os para um filtro mux , por exemplo, se você estiver capturando áudio e vídeo em um arquivo AVI, deverá controlar ambos os fluxos em conjunto. Caso contrário, o filtro mux pode bloquear a espera de um fluxo, pois ele tenta intercalar os dois fluxos. Defina os mesmos horários de início e parada em todos os fluxos de captura antes de executar o grafo:

pBuild->ControlStream(&PIN_CATEGORY_CAPTURE, 
    
NULL, NULL,       // All capture streams.
    &rtStart, rtStop, 
    wStartCookie, wStopCookie); 

Internamente, o método ControlStream usa a interface IAMStreamControl , que é exposta nos pinos do filtro de captura, no filtro Smart Tee (se estiver presente) e possivelmente no filtro mux. Você pode usar essa interface diretamente, em vez de chamar ControlStream, embora não haja nenhuma vantagem específica para fazer isso.

Captura de vídeo