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:

  1. Crie uma instância do Gerenciador de Grafo de Filtro.
  2. Use o Gerenciador de Grafo de Filtro para criar um grafo de filtro.
  3. 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();
}

Tarefas básicas do DirectShow