Capturando vídeo em um arquivo AVI

[O recurso associado a esta página, DirectShow, é um recurso herdado. Foi substituído por MediaPlayer, IMFMediaEngine e Audio/Video Capture in 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 Audio/Video Capture in 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 ilustração a seguir mostra o grafo mais simples possível para capturar vídeo em um arquivo AVI.

avi video capture graph

O filtro AVI Mux usa o fluxo de vídeo do pino de captura e o empacota em um fluxo AVI. Um fluxo de áudio também pode ser conectado ao filtro AVI Mux; nesse caso, o mux intercalaria os dois fluxos. O filtro Gravador de Arquivos grava o fluxo AVI no disco.

Para criar o grafo, comece chamando o método ICaptureGraphBuilder2::SetOutputFileName , da seguinte maneira:

IBaseFilter *pMux;
hr = pBuild->SetOutputFileName(
    &MEDIASUBTYPE_Avi,  // Specifies AVI for the target file.
    L"C:\\Example.avi", // File name.
    &pMux,              // Receives a pointer to the mux.
    NULL);              // (Optional) Receives a pointer to the file sink.

O primeiro parâmetro especifica o tipo de arquivo — nesse caso, AVI. O segundo parâmetro fornece o nome do arquivo. Para a AVI, o método SetOutputFileName cocria o filtro AVI Mux e o filtro Gravador de Arquivos e os adiciona ao grafo. Ele também define o nome do arquivo no filtro Gravador de Arquivos chamando o método IFileSinkFilter::SetFileName e conecta os dois filtros. O método retorna um ponteiro para o AVI Mux no terceiro parâmetro. Opcionalmente, ele retorna um ponteiro para a interface IFileSinkFilter no quarto parâmetro. Se você não precisar dessa interface, poderá definir esse parâmetro como NULL, conforme mostrado no exemplo anterior.

Em seguida, chame o método ICaptureGraphBuilder2::RenderStream para conectar o filtro de captura ao AVI Mux, da seguinte maneira:

hr = pBuild->RenderStream(
    &PIN_CATEGORY_CAPTURE, // Pin category.
    &MEDIATYPE_Video,      // Media type.
    pCap,                  // Capture filter.
    NULL,                  // Intermediate filter (optional).
    pMux);                 // Mux or file sink filter.

// Release the mux filter.
pMux->Release();

O primeiro parâmetro fornece a categoria de pino, que é PIN_CATEGORY_CAPTURE para captura. O segundo parâmetro fornece o tipo de mídia. O terceiro parâmetro é um ponteiro para a interface IBaseFilter do filtro de captura. O quarto parâmetro é opcional; ele permite rotear o fluxo de vídeo por meio de um filtro intermediário, como um codificador, antes de passá-lo para o filtro mux. Caso contrário, defina esse parâmetro como NULL, conforme mostrado no exemplo anterior. O quinto parâmetro é o ponteiro para o filtro mux. Esse ponteiro é obtido chamando o método SetOutputFileName.

Para capturar áudio, chame RenderStream com o tipo de mídia MEDIATYPE_Audio. Se você estiver capturando áudio e vídeo de dois dispositivos separados, é uma boa ideia fazer do fluxo de áudio o fluxo de master. Isso ajuda a evitar o descompasso entre os dois fluxos, pois o filtro AVI Mux ajusta a taxa de reprodução no fluxo de vídeo para corresponder ao fluxo de áudio. Para definir o fluxo de master, chame o método IConfigAviMux::SetMasterStream no filtro AVI Mux:

IConfigAviMux *pConfigMux = NULL;
hr = pMux->QueryInterface(IID_IConfigAviMux, (void**)&pConfigMux);
if (SUCCEEDED(hr))
{
    pConfigMux->SetMasterStream(1);
    pConfigMux->Release();
}

O parâmetro para SetMasterStream é o número de fluxo, que é determinado pela ordem em que você chama RenderStream. Por exemplo, se você chamar RenderStream primeiro para vídeo e depois para áudio, o vídeo será transmitido 0 e o áudio será transmitido 1.

Talvez você também queira definir como o filtro AVI Mux intercala os fluxos de áudio e vídeo chamando o método IConfigInterleaving::p ut_Mode .

IConfigInterleaving *pInterleave = NULL;
hr = pMux->QueryInterface(IID_IConfigInterleaving, (void**)&pInterleave);
if (SUCCEEDED(hr))
{
    pInterleave->put_Mode(INTERLEAVE_CAPTURE);
    pInterleave->Release();
}

Com o sinalizador INTERLEAVE_CAPTURE, o AVI Mux executa a intercalação a uma taxa adequada para captura de vídeo. Você também pode usar INTERLEAVE_NONE, o que significa que não há intercalação — o AVI Mux simplesmente gravará os dados na ordem em que chegar. O sinalizador INTERLEAVE_FULL significa que o AVI Mux executa a intercalação completa; no entanto, esse modo é menos adequado para captura de vídeo porque requer o mais ouvido.

Codificando o fluxo de vídeo

Você pode codificar o fluxo de vídeo inserindo um filtro de codificador entre o filtro de captura e o filtro AVI Mux. Use o Enumerador de Dispositivo do Sistema ou o Mapeador de Filtro para selecionar um filtro de codificador. (Para obter mais informações, consulte Enumerando dispositivos e filtros.)

Especifique o filtro de codificador como o quarto parâmetro para RenderStream, mostrado em negrito no exemplo a seguir:

IBaseFilter *pEncoder;
/* Create the encoder filter (not shown). */
// Add it to the filter graph.
pGraph->AddFilter(pEncoder, L"Encoder");

/* Call SetOutputFileName as shown previously. */

// Render the stream.
hr = pBuild->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, 
    pCap, 
pEncoder, pMux);
pEncoder->Release();

O filtro do codificador pode dar suporte a IAMVideoCompression ou a outras interfaces para definir os parâmetros de codificação. Para obter uma lista de interfaces possíveis, consulte Interfaces de codificação e decodificação de arquivos.

Capturando vídeo em um arquivo