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


Шаг 6. Обработка событий Graph

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

Этот раздел является шагом 6 руководства По воспроизведению звука и видео в DirectShow. Полный код показан в разделе Пример воспроизведения DirectShow.

Когда приложение создает новый экземпляр диспетчера фильтров graph, приложение вызывает IMediaEventEx::SetNotifyWindow. Этот метод регистрирует окно приложения для получения событий из графа фильтра.

    hr = m_pGraph->QueryInterface(IID_PPV_ARGS(&m_pEvent));
    if (FAILED(hr))
    {
        goto done;
    }

    // Set up event notification.
    hr = m_pEvent->SetNotifyWindow((OAHWND)m_hwnd, WM_GRAPH_EVENT, NULL);
    if (FAILED(hr))
    {
        goto done;
    }

Значение WM_GRAPH_EVENT является сообщением частного окна. Всякий раз, когда приложение получает это сообщение, оно вызывает DShowPlayer::HandleGraphEvent метод .

    case WM_GRAPH_EVENT:
       g_pPlayer->HandleGraphEvent(OnGraphEvent);
       return 0;

Метод DShowPlayer::HandleGraphEvent выполняет следующие действия:

  1. Вызывает IMediaEvent::GetEvent в цикле, чтобы получить все события в очереди.
  2. Вызывает функцию обратного вызова (pfnOnGraphEvent).
  3. Вызывает IMediaEvent::FreeEventParams , чтобы освободить данные, связанные с каждым событием.
// Respond to a graph event.
//
// The owning window should call this method when it receives the window
// message that the application specified when it called SetEventWindow.
//
// Caution: Do not tear down the graph from inside the callback.

HRESULT DShowPlayer::HandleGraphEvent(GraphEventFN pfnOnGraphEvent)
{
    if (!m_pEvent)
    {
        return E_UNEXPECTED;
    }

    long evCode = 0;
    LONG_PTR param1 = 0, param2 = 0;

    HRESULT hr = S_OK;

    // Get the events from the queue.
    while (SUCCEEDED(m_pEvent->GetEvent(&evCode, &param1, &param2, 0)))
    {
        // Invoke the callback.
        pfnOnGraphEvent(m_hwnd, evCode, param1, param2);

        // Free the event data.
        hr = m_pEvent->FreeEventParams(evCode, param1, param2);
        if (FAILED(hr))
        {
            break;
        }
    }
    return hr;
}

В следующем коде показана функция обратного вызова, передаваемая в DShowPlayer::HandleGraphEvent. Функция обрабатывает минимальное количество событий графа (EC_COMPLETE, EC_ERRORABORT и EC_USERABORT); Можно развернуть функцию для обработки дополнительных событий.

void CALLBACK OnGraphEvent(HWND hwnd, long evCode, LONG_PTR param1, LONG_PTR param2)
{
    switch (evCode)
    {
    case EC_COMPLETE:
    case EC_USERABORT:
        g_pPlayer->Stop();
        break;

    case EC_ERRORABORT:
        NotifyError(hwnd, L"Playback error.");
        g_pPlayer->Stop();
        break;
    }
}

Воспроизведение звука и видео в DirectShow

Пример воспроизведения DirectShow

Уведомление о событиях в DirectShow

Реагирование на события