Step 5: Add Video Functionality

[The feature associated with this page, DirectShow, is a legacy feature. It has been superseded by MediaPlayer, IMFMediaEngine, and Audio/Video Capture in Media Foundation. Those features have been optimized for Windows 10 and Windows 11. Microsoft strongly recommends that new code use MediaPlayer, IMFMediaEngine and Audio/Video Capture in Media Foundation instead of DirectShow, when possible. Microsoft suggests that existing code that uses the legacy APIs be rewritten to use the new APIs if possible.]

This topic is step 5 of the tutorial Audio/Video Playback in DirectShow. The complete code is shown in the topic DirectShow Playback Example.

To ensure that video displays correctly, the application must respond to WM_PAINT, WM_SIZE, and WM_DISPLAYCHANGE messages as follows.

Handle WM_PAINT Messages

When the application receives a WM_PAINT message, the video renderer might need to redraw the last video frame. For the Enhanced Video Renderer (EVR) filter, call IMFVideoDisplayControl::RepaintVideo.

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

For the Video Mixing Renderer Filter 9 (VMR-9), call IVMRWindowlessControl9::RepaintVideo.

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

For the Video Mixing Renderer Filter 7 (VMR-7), call IVMRWindowlessControl::RepaintVideo.

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

Handle WM_SIZE Messages

If the size of the video window changes, notify the video renderer to resize the video. For the EVR, call 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);
    }
}

For the VMR-9, call 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);
    }
}

For the VMR-7, call 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);
    }
}

Handle WM_DISPLAYCHANGE Messages

If the display mode changes, you must notify the VMR-9 or VMR-7 filter. For the VMR-9, call IVMRWindowlessControl9::DisplayModeChanged.

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

For the VMR-7, call IVMRWindowlessControl::DisplayModeChanged.

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

The EVR does not need to be notified when the display mode changes.

Next: Step 6: Handle Graph Events.

Audio/Video Playback in DirectShow

DirectShow Playback Example

Using the DirectShow EVR Filter

Using the Video Mixing Renderer