Поделиться через


Воспроизведение файла

[Функция, связанная с этой страницей DirectShow, является устаревшей функцией. Он был заменен MediaPlayer, IMFMediaEngine, и аудио/ видео захвата в Media Foundation. Эти функции оптимизированы для Windows 10 и Windows 11. Корпорация Майкрософт настоятельно рекомендует, чтобы новый код использовал MediaPlayer, IMFMediaEngine и аудио- и видеозахват в Media Foundation вместо DirectShow, когда это возможно. Корпорация Майкрософт предлагает переписать существующий код, использующий устаревшие API, чтобы по возможности использовать новые API.]

Эта статья предназначена для того, чтобы дать вам вкус программирования DirectShow. Она представляет собой простое консольное приложение, которое воспроизводит звуковой или видеофайл. Программа длиной всего в несколько строк, но она демонстрирует некоторые возможности программирования DirectShow.

Как описано в статье Введение в программирование приложений DirectShow , приложение DirectShow всегда выполняет те же основные действия:

  1. Создайте экземпляр диспетчера графов фильтров.
  2. Используйте диспетчер графов фильтров для создания графа фильтра.
  3. Запустите граф, в результате чего данные будут перемещаться по фильтрам.

Чтобы скомпилировать и связать код в этом разделе, добавьте файл заголовка Dshow.h и ссылку на файл статической библиотеки strmiids.lib. Дополнительные сведения см. в разделе Создание приложений DirectShow.

Начните с вызова CoInitialize или CoInitializeEx для инициализации библиотеки COM:

HRESULT hr = CoInitialize(NULL);
if (FAILED(hr))
{
    // Add error-handling code here. (Omitted for clarity.)
}

Чтобы упростить все, в этом примере не учитывается возвращаемое значение, но всегда следует проверка значение HRESULT из любого вызова метода.

Затем вызовите CoCreateInstance , чтобы создать диспетчер графов фильтров:

IGraphBuilder *pGraph;
HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL, 
    CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph);

Как показано, идентификатор класса (CLSID) CLSID_FilterGraph. Диспетчер графов фильтров предоставляется внутрипроцессной библиотекой DLL, поэтому контекст выполнения CLSCTX_INPROC_SERVER. DirectShow поддерживает модель свободного потока, поэтому вы также можете вызвать CoInitializeEx с флагом COINIT_MULTITHREADED .

Вызов CoCreateInstance возвращает интерфейс IGraphBuilder , который в основном содержит методы для построения графа фильтра. Для этого примера требуются два других интерфейса:

  • IMediaControl управляет потоковой передачей. Он содержит методы для остановки и запуска графа.
  • IMediaEvent содержит методы для получения событий из диспетчера фильтров Graph. В этом примере интерфейс используется для ожидания завершения воспроизведения.

Оба этих интерфейса предоставляются диспетчером фильтров Graph. Используйте возвращенный указатель IGraphBuilder , чтобы запросить их:

IMediaControl *pControl;
IMediaEvent   *pEvent;
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);

Теперь можно создать граф фильтра. Для воспроизведения файлов это выполняется одним вызовом метода:

hr = pGraph->RenderFile(L"C:\\Example.avi", NULL);

Метод IGraphBuilder::RenderFile создает граф фильтра, который может воспроизводить указанный файл. Первый параметр — это имя файла, представленное в виде широкой символьной (2-байтовой) строки. Второй параметр зарезервирован и должен иметь значение NULL.

Этот метод может завершиться ошибкой, если указанный файл не существует или формат файла не распознается. При условии, что метод выполнен успешно, граф фильтра теперь готов к воспроизведению. Чтобы запустить граф, вызовите метод IMediaControl::Run :

hr = pControl->Run();

При выполнении графа фильтров данные перемещаются по фильтрам и отображаются в виде видео и аудио. Воспроизведение выполняется в отдельном потоке. Вы можете дождаться завершения воспроизведения, вызвав метод IMediaEvent::WaitForCompletion :

long evCode = 0;
pEvent->WaitForCompletion(INFINITE, &evCode);

Этот метод блокируется до завершения воспроизведения файла или до истечения указанного интервала времени ожидания. Значение INFINITE означает, что приложение блокируется на неопределенный срок, пока не будет завершено воспроизведение файла. Более реалистичный пример обработки событий см. в разделе Реагирование на события.

После завершения работы приложения отпустите указатели интерфейса и закройте библиотеку COM:

pControl->Release();
pEvent->Release();
pGraph->Release();
CoUninitialize();

Пример кода

Ниже приведен полный код для примера, описанного в этой статье:

#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();
}

Основные задачи DirectShow