Microsoft DirectX 9.0

MPEG Decoder Preprocessing Transformations

Letterbox and PanScan

The 4x3 image can be formed by either padding the top and bottom of the image (referred to as a Letterbox image) or by extracting a 4x3 portion of the image (referred to as a PanScan image). The menus and subpicture streams are overlaid on top of the final video image. The 16x9 ratio images are stored in a 4x3 anamorphic format. Stretching the anamorphic 4x3 aspect ratio 720x480 source video to a 16x9 aspect ratio forms the original 16x9 aspect image.

Below is a description of how to correctly display each of the modes and their highlights:

MPEG preprocessing with the DVD Navigator and VMR

Currently, the decoder is passed a FORMAT_MPEG2_VIDEO media type (whose format block points to a MPEG2VIDEOINFO structure). On the output pins, the decoder produces a FORMAT_VideoInfo2 media type, whose format block points to a VIDEOINFOHEADER2 structure. The VIDEOINFOHEADER2's dwReserved field has been renamed to dwControls flags. Its new definition (in dvdmedia.h) is:

typedef struct tagVIDEOINFOHEADER2 {
  RECT     rcSource;
  RECT     rcTarget;
  DWORD    dwBitRate;
  DWORD    dwBitErrorRate;
  REFERENCE_TIME   AvgTimePerFrame;
  DWORD   dwInterlaceFlags;   // Use AMINTERLACE_* defines.
                             // Reject connection if undef'd bits are not 0.
  DWORD   dwCopyProtectFlags; // Use AMCOPYPROTECT_* defines. 
                             // Reject connection if undef'd bits are not 0.
  DWORD   dwPictAspectRatioX; // X dimension of picture aspect ratio,
                              // for example, 16 for 16x9 display.
  DWORD   dwPictAspectRatioY; // Y dimension of picture aspect ratio,
                              // for example  9 for 16x9 display.
  union {
      DWORD dwControlFlags;   // Use AMCONTROL_* defines,
                              // use this from now on
      DWORD dwReserved1;    // for backward compatibility 
                            //(must be 0;connection 
                            // rejected otherwise).
    };
  DWORD     dwReserved2;  // Must be 0; reject connection otherwise.
  BITMAPINFOHEADER    bmiHeader;
} VIDEOINFOHEADER2;

The VIDEOINFOHEADER2.dwControlFlags will now contain the new bits.

AMCONTROL_USED 0x00000001
AMCONTROL_PAD_TO_4x3 0x00000002
AMCONTROL_PAD_TO_16x9 0x00000004

AMCONTROL_USED is used to test whether these new flags are supported. A source filter should set the AMCONTROL_USED flag and see if QueryAccept(MediaType) succeeds on the downstream pin. If it is rejected, then the AMCONTROL flags cannot be used and dwReserved1 must be set to 0.

AMCONTROL_PAD_TO_4x3 indicates that the image should be padded and displayed in a 4x3 area.

AMCONTROL_PAD_TO_16x9 indicates that the image should be padded and displayed in a 16x9 area.

The decoder should either blindly copy or process the bits. If the decoder performs letterboxing itself, then it must alter the pixel aspect ratio, pad the image and remove the corresponding AMCONTROL_* bits.

The MPEG2VIDEOINFO.dwFlags now contains three flags for controlling for controlling how the content should be displayed:

Most decoders should use GetMediaType to detect a media change on the input pin and copy the VIDEOINFOHEADER2 contents (contained in the MPEG2INFOHEADER) to the output pin. They will probably only process the PanScan bit.

The following example code shows how to copy the VIDEOINFOHEADER2 contents from an input pin to an output pin.

#include <dvdmedia.h>
HRESULT CopyMPeg2ToVideoInfoHeader2(CMediaSample* pInSample, CMediaSample* pOutSample)
{
    HRESULT hr = S_OK;
    // Check for a media type on the input sample.
    AM_MEDIA_TYPE* pInType;
    if (pInSample->GetMediaType(&pInType) == S_OK) 
    {
        // Make sure it's an MPEG2 Video format.
        if ((pInType->formattype == FORMAT_MPEG2_VIDEO) &&
            (pInType->cbFormat >= sizeof(MPEG2VIDEOINFO)))
        {
            hr = S_OK; // Initialize hr for the CMediaType constructor.
            CMediaType outType(*pInType, &hr);
            if (FAILED(hr))
            {
                DeleteMediaType( pInType );
                return hr;
            }

            // Set the format type GUID.
            outType.SetFormatType(&FORMAT_VideoInfo2);
                
            // Truncate the format block to include just the VIDEOINFOHEADER part.
            MPEG2VIDEOINFO *pMPeg2Header = (MPEG2VIDEOINFO*)pInType->pbFormat;
            BYTE *pVIH = (BYTE*)&pMPeg2Header->hdr;
            hr = (outType.SetFormat(pVIH, sizeof(VIDEOINFOHEADER2)) ? S_OK : E_OUTOFMEMORY);
            if (SUCCEEDED(hr))
            {
                hr = pOutSample->SetMediaType(&outType);
            }
        } 
        else 
        {
            ASSERT(FALSE); // Not a MPEG2 header.
            hr = VFW_E_INVALIDMEDIATYPE;
        }
        DeleteMediaType( pInType );
    } 

    return hr;
}