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.
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.
Tópicos relacionados