Criando o grafo de recompactação
[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.]
Um grafo de filtro típico para recompactação de arquivo AVI é semelhante ao seguinte:
O Filtro divisor AVI extrai dados do Filtro de Fonte de Arquivo (Assíncrono) e os analisa em fluxos de áudio e vídeo. O descompactador de vídeo decodifica o vídeo compactado, em que ele é recompactado pelo compressor de vídeo. A escolha dos descompactadores depende do arquivo de origem; ele será tratado automaticamente pelo Intelligent Connect. O aplicativo deve escolher o compressor, normalmente apresentando uma lista ao usuário. (Consulte Escolhendo um filtro de compactação.)
Em seguida, o vídeo compactado vai para o Filtro AVI Mux. O fluxo de áudio neste exemplo não é compactado, portanto, ele vai diretamente do Divisor AVI para o AVI Mux. O AVI Mux intercala os dois fluxos e o Filtro do Gravador de Arquivos grava a saída no disco. Observe que o AVI Mux é necessário mesmo que o arquivo original não tenha um fluxo de áudio.
A maneira mais fácil de criar esse grafo de filtro é usar o Capture Graph Builder, que é um componente directShow para criar grafos de captura e outros grafos de filtro personalizados.
Comece chamando CoCreateInstance para criar o Construtor de Grafo de Captura:
ICaptureGraphBuilder2 *pBuild = NULL;
hr = CoCreateInstance(CLSID_CaptureGraphBuilder2,
NULL, CLSCTX_INPROC_SERVER,
IID_ICaptureGraphBuilder2, (void **)&pBuild);
Em seguida, use o Capture Graph Builder para criar o grafo de filtro:
- Crie a seção de renderização do grafo, que inclui o filtro AVI Mux e o Gravador de Arquivos.
- Adicione o filtro de origem e o filtro de compactação ao grafo.
- Conecte o filtro de origem ao filtro MUX. O construtor de grafo de captura insere todos os filtros de divisor e decodificador necessários para analisar o arquivo de origem. Ele também pode rotear os fluxos de vídeo e áudio por meio de filtros de compactação.
As seções a seguir explicam cada uma dessas etapas.
Criar a seção renderização
Para criar a seção de renderização do grafo, chame o método ICaptureGraphBuilder2::SetOutputFileName . Esse método usa parâmetros de entrada que especificam o subtipo de mídia para a saída e o nome do arquivo de saída. Ele retorna ponteiros para o filtro MUX e o gravador de arquivos. O filtro MUX é necessário para o próximo estágio da criação de grafo. O ponteiro para o gravador de arquivos não é necessário para este exemplo, portanto, esse parâmetro pode ser NULL:
IBaseFilter *pMux = NULL;
hr = pBuild->SetOutputFileName(
&MEDIASUBTYPE_Avi, // File type.
wszOutputFile, // File name, as a wide-character string.
&pMux, // Receives a pointer to the multiplexer.
NULL); // Receives a pointer to the file writer.
Quando o método retorna, o filtro MUX tem uma contagem de referência pendente, portanto, certifique-se de liberar o ponteiro mais tarde.
O diagrama a seguir mostra o grafo de filtro neste ponto.
O filtro MUX expõe duas interfaces para controlar o formato AVI:
- Interface IConfigInterleaving: define o modo de intercalação.
- Interface IConfigAviMux: define o fluxo de master e o índice de compatibilidade AVI.
Adicionar os filtros de origem e compactação
A próxima etapa é adicionar os filtros de origem e compactação ao grafo de filtro. O Capture Graph Builder cria automaticamente uma instância do Gerenciador de Grafo de Filtro quando você chama SetOutputFileName. Obtenha um ponteiro para ele chamando o método ICaptureGraphBuilder2::GetFiltergraph :
IGraphBuilder *pGraph = NULL;
hr = pBuild->GetFiltergraph(&pGraph);
Agora chame o método IGraphBuilder::AddSourceFilter para adicionar o filtro Fonte de Arquivo Assíncrono e o método IFilterGraph::AddFilter para adicionar o compressor de vídeo:
IBaseFilter *pSrc = NULL;
hr = pGraph->AddSourceFilter(wszInputFile, L"Source Filter", &pSrc);
hr = pGraph->AddFilter(pVComp, L"Compressor");
Neste ponto, o filtro de origem e o filtro de compactação não estão conectados a mais nada no grafo, conforme mostrado na ilustração a seguir:
Conectar a origem ao Mux
A etapa final é conectar o filtro de origem ao filtro AVI Mux por meio do compressor de vídeo. Use o método ICaptureGraphBuilder2::RenderStream , que conecta um pino de saída no filtro de origem a um filtro de coletor especificado, opcionalmente por meio de um filtro de compactação.
Os dois primeiros parâmetros especificam quais dos pinos do filtro de origem se conectar, designando uma categoria de pino e um tipo de mídia. O filtro Origem do Arquivo Assíncrono tem apenas um pino de saída, portanto, esses parâmetros devem ser NULL. Os próximos três parâmetros especificam o filtro de origem, o filtro de compactação (se houver) e o filtro Mux.
O exemplo de código a seguir renderiza o fluxo de vídeo por meio do compressor de vídeo:
hr = pBuild->RenderStream(
NULL, // Output pin category
NULL, // Media type
pSrc, // Source filter
pVComp, // Compression filter
pMux); // Sink filter (the AVI Mux)
O diagrama a seguir mostra o grafo de filtro até o momento.
Supondo que o arquivo de origem tenha um fluxo de áudio, o filtro AVI Splitter criou um pino de saída para o áudio. Para conectar esse pino, chame RenderStream novamente:
hr = pBuild->RenderStream(NULL, NULL, pSrc, NULL, pMux);
Aqui, nenhum filtro de compactação é especificado. O pino de saída do filtro de origem já está conectado, portanto, o método RenderStream procura um pino de saída não conectado no filtro de divisor. Ele localiza o pino de áudio e o conecta diretamente ao filtro MUX. Se o arquivo de origem não tiver um fluxo de áudio, a segunda chamada para RenderStream falhará. Este comportamento é esperado. O grafo é concluído após a primeira chamada para RenderStream, portanto, a falha na segunda chamada é inofensiva.
Neste exemplo, a ordem das duas chamadas renderstream é importante. Como a segunda chamada não especifica um compressor, ela conectará qualquer pino não conectado do Divisor AVI. Se você fizer essa chamada antes da outra, ela poderá conectar o fluxo de vídeo ao AVI Mux, sem o compressor de vídeo. Portanto, a chamada mais específica (com o filtro de compactação) deve ocorrer primeiro.
A discussão anterior assumiu que o arquivo de origem é um arquivo AVI. No entanto, essa técnica também funciona com outros tipos de arquivo, como arquivos MPEG. O grafo de filtro resultante será um pouco diferente.
Tópicos relacionados