Microsoft DirectX 9.0

Setting Deinterlace Preferences

The Video Mixing Renderer (VMR) supports hardware-accelerated deinterlacing, which improves rendering quality for interlaced video. The exact features that are available depend on the underlying hardware. The application can query for the hardware deinterlacing capabilities and set deinterlacing preferences through the IVMRDeinterlaceControl interface (VMR-7) or IVMRDeinterlaceControl9 interface (VMR-9). Deinterlacing is performed on a per-stream basis.

Note   This section describes the IVMRDeinterlaceControl9 methods, but the VMR-7 versions are almost identical.

To get the deinterlacing capabilities for a video stream, do the following:

  1. Fill in a VMR9VideoDesc structure with a description of the video stream. Details of how to fill in this structure are given later.
  2. Pass the structure to the IVMRDeinterlaceControl9::GetNumberOfDeinterlaceModes method. Call the method twice. The first call returns the number of deinterlace modes the hardware supports for the specified format. Allocate an array of GUIDs of this size, and call the method again, passing in the address of the array. The second call fills the array with GUIDs. Each GUID identifies one deinterlacing mode.
  3. To get the capabiltiies of a particular mode, call the IVMRDeinterlaceControl9::GetDeinterlaceModeCaps method. Pass in the same VMR9VideoDesc structure, along with one of the GUIDs from the array. The method fills a VMR9DeinterlaceCaps structure with the mode capabilities.

The following code shows these steps:

VMR9VideoDesc VideoDesc; 
DWORD dwNumModes = 0;
// Fill in the VideoDesc structure (not shown).
hr = pDeinterlace->GetNumberOfDeinterlaceModes(&VideoDesc, 
    &dwNumModes, NULL);
if (SUCCEEDED(hr) && (dwNumModes != 0))
{
    // Allocate an array for the GUIDs that identify the modes.
    GUID *pModes = new GUID[dwNumModes];
    if (pModes)
    {
        // Fill the array.
        hr = pDeinterlace->GetNumberOfDeinterlaceModes(&VideoDesc, 
            &dwNumModes, pModes);
        if (SUCCEEDED(hr))
        {
            // Loop through each item and get the capabilities.
            for (int i = 0; i < dwNumModes; i++)
            {
                VMR9DeinterlaceCaps Caps;
                hr = pDeinterlace->GetDeinterlaceModeCaps(pModes + i, 
                    &VideoDesc, &Caps);
                if (SUCCEEDED(hr))
                {
                    // Examine the Caps structure.
                }
            }
        }
        delete [] pModes;
    }
}

Now the application can set the deinterlacing mode for the stream, using the following methods:

The method reference pages give more information.

Using the VMR9VideoDesc Structure

In the procedure given previously, the first step is to fill in a VMR9VideoDesc structure with a description of the video stream. Start by getting the media type of the video stream. You can do this by calling IPin::ConnectionMediaType on the VMR filter's input pin. Then confirm whether the video stream is interlaced. Only VIDEOINFOHEADER2 formats can be interlaced. If the format type is FORMAT_VideoInfo, it must be a progressive frame. If the format type is FORMAT_VideoInfo2, check the dwInterlaceFlags field for the AMINTERLACE_IsInterlaced flag. The presence of this flag indicates the video is interlaced.

Assume that the variable pBMI is a pointer to the BITMAPINFOHEADER structure in the format block. Set the following values in the VMR9VideoDesc structure:

The following helper function converts AMINTERLACE_X flags to VMR9_SampleFormat values:

#define IsInterlaced(x) ((x) & AMINTERLACE_IsInterlaced)
#define IsSingleField(x) ((x) & AMINTERLACE_1FieldPerSample)
#define IsField1First(x) ((x) & AMINTERLACE_Field1First)

VMR9_SampleFormat ConvertInterlaceFlags(DWORD dwInterlaceFlags)
{
    if (IsInterlaced(dwInterlaceFlags)) {
        if (IsSingleField(dwInterlaceFlags)) {
            if (IsField1First(dwInterlaceFlags)) {
                return VMR9_SampleFieldSingleEven;
            }
            else {
                return VMR9_SampleFieldSingleOdd;
            }
        }
        else {
            if (IsField1First(dwInterlaceFlags)) {
                return VMR9_SampleFieldInterleavedEvenFirst;
             }
            else {
                return VMR9_SampleFieldInterleavedOddFirst;
            }
        }
    }
    else {
        return VMR9_SampleProgressiveFrame;  // Not interlaced.
    }
}