步骤 5:添加视频功能

[与此页面关联的功能 DirectShow 是一项旧功能。 它已被 MediaPlayerIMFMediaEngine媒体基金会中的音频/视频捕获取代。 这些功能已针对Windows 10和Windows 11进行了优化。 Microsoft 强烈建议新代码尽可能使用 MediaPlayerIMFMediaEngineMedia Foundation 中的音频/视频捕获 ,而不是 DirectShow。 如果可能,Microsoft 建议重写使用旧 API 的现有代码以使用新 API。]

本主题是 教程 DirectShow 中的音频/视频播放的步骤 5。 主题 DirectShow 播放示例中显示了完整的代码。

为了确保视频正确显示,应用程序必须响应 WM_PAINTWM_SIZEWM_DISPLAYCHANGE 消息,如下所示。

处理WM_PAINT消息

当应用程序收到 WM_PAINT 消息时,视频呈现器可能需要重绘最后一个视频帧。 对于 增强的视频呈现器 (EVR) 筛选器,请调用 IMFVideoDisplayControl::RepaintVideo

HRESULT CEVR::Repaint(HWND hwnd, HDC hdc)
{
    if (m_pVideoDisplay)
    {
        return m_pVideoDisplay->RepaintVideo();
    }
    else
    {
        return S_OK;
    }
}

对于 视频混合呈现器筛选器 9 (VMR-9) ,请调用 IVMRWindowlessControl9::RepaintVideo

HRESULT CVMR9::Repaint(HWND hwnd, HDC hdc)
{
    if (m_pWindowless)
    {
        return m_pWindowless->RepaintVideo(hwnd, hdc);
    }
    else
    {
        return S_OK;
    }
}

对于 视频混合呈现器筛选器 7 (VMR-7) ,请调用 IVMRWindowlessControl::RepaintVideo

HRESULT CVMR7::Repaint(HWND hwnd, HDC hdc)
{
    if (m_pWindowless)
    {
        return m_pWindowless->RepaintVideo(hwnd, hdc);
    }
    else
    {
        return S_OK;
    }
}

处理WM_SIZE消息

如果视频窗口的大小发生更改,请通知视频呈现器调整视频大小。 对于 EVR,请调用 IMFVideoDisplayControl::SetVideoPosition

HRESULT CEVR::UpdateVideoWindow(HWND hwnd, const LPRECT prc)
{
    if (m_pVideoDisplay == NULL)
    {
        return S_OK; // no-op
    }

    if (prc)
    {
        return m_pVideoDisplay->SetVideoPosition(NULL, prc);
    }
    else
    {

        RECT rc;
        GetClientRect(hwnd, &rc);
        return m_pVideoDisplay->SetVideoPosition(NULL, &rc);
    }
}

对于 VMR-9,请调用 IVMRWindowlessControl9::SetVideoPosition

HRESULT CVMR9::UpdateVideoWindow(HWND hwnd, const LPRECT prc)
{
    if (m_pWindowless == NULL)
    {
        return S_OK; // no-op
    }

    if (prc)
    {
        return m_pWindowless->SetVideoPosition(NULL, prc);
    }
    else
    {

        RECT rc;
        GetClientRect(hwnd, &rc);
        return m_pWindowless->SetVideoPosition(NULL, &rc);
    }
}

对于 VMR-7,请调用 IVMRWindowlessControl::SetVideoPosition

HRESULT CVMR7::UpdateVideoWindow(HWND hwnd, const LPRECT prc)
{
    if (m_pWindowless == NULL)
    {
        return S_OK; // no-op
    }

    if (prc)
    {
        return m_pWindowless->SetVideoPosition(NULL, prc);
    }
    else
    {
        RECT rc;
        GetClientRect(hwnd, &rc);
        return m_pWindowless->SetVideoPosition(NULL, &rc);
    }
}

处理WM_DISPLAYCHANGE消息

如果显示模式发生更改,则必须通知 VMR-9 或 VMR-7 筛选器。 对于 VMR-9,请调用 IVMRWindowlessControl9::D isplayModeChanged

HRESULT CVMR9::DisplayModeChanged()
{
    if (m_pWindowless)
    {
        return m_pWindowless->DisplayModeChanged();
    }
    else
    {
        return S_OK;
    }
}

对于 VMR-7,请调用 IVMRWindowlessControl::D isplayModeChanged

HRESULT CVMR7::DisplayModeChanged()
{
    if (m_pWindowless)
    {
        return m_pWindowless->DisplayModeChanged();
    }
    else
    {
        return S_OK;
    }
}

当显示模式更改时,无需通知 EVR。

下一 步:步骤 6:处理图形事件

DirectShow 中的音频/视频播放

DirectShow 播放示例

使用 DirectShow EVR 筛选器

使用视频混合呈现器