Como reproduzir um arquivo
[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.]
Este artigo destina-se a fornecer a você o tipo de programação directShow. Ele apresenta um aplicativo de console simples que reproduz um arquivo de áudio ou vídeo. O programa tem apenas algumas linhas, mas demonstra parte do poder da programação do DirectShow.
Como descreve o artigo Introdução à Programação de Aplicativos do DirectShow , um aplicativo DirectShow sempre executa as mesmas etapas básicas:
- Crie uma instância do Gerenciador de Grafo de Filtro.
- Use o Gerenciador de Grafo de Filtro para criar um grafo de filtro.
- Execute o grafo, fazendo com que os dados se movam pelos filtros.
Para compilar e vincular o código neste tópico, inclua o arquivo de cabeçalho Dshow.h e o link para o arquivo de biblioteca estática strmiids.lib. Para obter mais informações, consulte Criando aplicativos DirectShow.
Comece chamando CoInitialize ou CoInitializeEx para inicializar a biblioteca COM:
HRESULT hr = CoInitialize(NULL);
if (FAILED(hr))
{
// Add error-handling code here. (Omitted for clarity.)
}
Para manter as coisas simples, este exemplo ignora o valor retornado, mas você sempre deve marcar o valor HRESULT de qualquer chamada de método.
Em seguida, chame CoCreateInstance para criar o Gerenciador de Grafo de Filtro:
IGraphBuilder *pGraph;
HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL,
CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph);
Conforme mostrado, o CLSID (identificador de classe) é CLSID_FilterGraph. O Gerenciador de Grafo de Filtro é fornecido por uma DLL em processo, portanto, o contexto de execução é CLSCTX_INPROC_SERVER. O DirectShow dá suporte ao modelo de threading livre, portanto, você também pode chamar CoInitializeEx com o sinalizador COINIT_MULTITHREADED .
A chamada para CoCreateInstance retorna a interface IGraphBuilder , que contém principalmente métodos para criar o grafo de filtro. Duas outras interfaces são necessárias para este exemplo:
- IMediaControl controla o streaming. Ele contém métodos para interromper e iniciar o grafo.
- IMediaEvent tem métodos para obter eventos do Gerenciador de Grafo de Filtro. Neste exemplo, a interface é usada para aguardar a conclusão da reprodução.
Ambas as interfaces são expostas pelo Gerenciador de Grafo de Filtro. Use o ponteiro IGraphBuilder retornado para consultá-los:
IMediaControl *pControl;
IMediaEvent *pEvent;
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
Agora você pode criar o grafo de filtro. Para reprodução de arquivo, isso é feito por uma única chamada de método:
hr = pGraph->RenderFile(L"C:\\Example.avi", NULL);
O método IGraphBuilder::RenderFile cria um grafo de filtro que pode reproduzir o arquivo especificado. O primeiro parâmetro é o nome do arquivo, representado como uma cadeia de caracteres largos (2 bytes). O segundo parâmetro é reservado e deve ser igual a NULL.
Esse método poderá falhar se o arquivo especificado não existir ou se o formato de arquivo não for reconhecido. Supondo que o método seja bem-sucedido, no entanto, o grafo de filtro agora está pronto para reprodução. Para executar o grafo, chame o método IMediaControl::Run :
hr = pControl->Run();
Quando o grafo de filtro é executado, os dados se movem pelos filtros e são renderizados como vídeo e áudio. A reprodução ocorre em um thread separado. Você pode aguardar a conclusão da reprodução chamando o método IMediaEvent::WaitForCompletion :
long evCode = 0;
pEvent->WaitForCompletion(INFINITE, &evCode);
Esse método é bloqueado até que o arquivo termine de ser reproduzido ou até que o intervalo de tempo limite especificado se especifique. O valor INFINITE significa que o aplicativo é bloqueado indefinidamente até que o arquivo termine de ser reproduzido. Para obter um exemplo mais realista de manipulação de eventos, consulte Respondendo a eventos.
Quando o aplicativo for concluído, solte os ponteiros da interface e feche a biblioteca COM:
pControl->Release();
pEvent->Release();
pGraph->Release();
CoUninitialize();
Código de exemplo
Este é o código completo para o exemplo descrito neste artigo:
#include <dshow.h>
void main(void)
{
IGraphBuilder *pGraph = NULL;
IMediaControl *pControl = NULL;
IMediaEvent *pEvent = NULL;
// Initialize the COM library.
HRESULT hr = CoInitialize(NULL);
if (FAILED(hr))
{
printf("ERROR - Could not initialize COM library");
return;
}
// Create the filter graph manager and query for interfaces.
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void **)&pGraph);
if (FAILED(hr))
{
printf("ERROR - Could not create the Filter Graph Manager.");
return;
}
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
// Build the graph. IMPORTANT: Change this string to a file on your system.
hr = pGraph->RenderFile(L"C:\\Example.avi", NULL);
if (SUCCEEDED(hr))
{
// Run the graph.
hr = pControl->Run();
if (SUCCEEDED(hr))
{
// Wait for completion.
long evCode;
pEvent->WaitForCompletion(INFINITE, &evCode);
// Note: Do not use INFINITE in a real application, because it
// can block indefinitely.
}
}
pControl->Release();
pEvent->Release();
pGraph->Release();
CoUninitialize();
}
Tópicos relacionados