Преобразования препроцессинга для декодера MPEG

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

Леттербокс и ПанСкан

Изображение 4x3 может быть сформировано путем заполнения верхней и нижней части изображения (называемого изображением Letterbox) или извлечением части изображения 4x3 (называемой изображением PanScan). Меню и потоки подпиктуры наложены на финальное изображение видео. Изображения с коэффициентом 16x9 хранятся в анаморфном формате 4x3. Растяжение анаморфного видео с исходными пропорциями 4x3 (720x480) до формата 16x9 создаёт оригинальное изображение в формате 16x9.

Ниже приведено описание правильного отображения каждого из режимов и их выделений:

  • Widescreen: исходное видео растянуто до максимально возможного размера 16x9 на экране. Выделенные элементы относятся к внутренней части области формата 16x9. Черные полосы следует добавить либо в верхнюю и нижнюю части, либо по бокам, чтобы сохранить область 16x9.
  • Пан скан: Из видео 16x9 используйте горизонтальное смещение, указанное в потоке MPEG2, чтобы выделить 4x3 подокно. Поместите подокно 4x3 в самую большую область 4x3 в окно клиента вывода. Координаты подсветки определяются относительно выходного окна с соотношением сторон 4x3 и не связаны с размерами исходного видео 16x9. Черные полосы следует добавить либо в верхней и нижней части, либо по бокам, чтобы сохранить область 4x3.
  • Letterbox: Вычислить самую большую область размером 4x3 в окне вывода. Черные полосы следует добавить либо в верхней и нижней части, либо по бокам, чтобы сохранить область 4x3. Исходное анаморфное видео 4x3 (представляющее изображение 16x9) располагается в самое большое подокно 16x9 внутри области 4x3. Черные полосы следует добавить в верхнюю и нижнюю часть подмножества, чтобы сохранить область 16x9. Координаты выделения относятся к области 4x3 и не имеют связи с исходным видео 16x9. Диск может указать выделение, которое находится за пределами области 16x9 (но по-прежнему в окне 4x3). Для видео формата 4x3 видео помещается в самую большую часть области отображения 4x3 в окне выходного клиента. Черные полосы следует добавить либо сверху и снизу, либо по бокам, чтобы сохранить область 4x3.

MPEG-предобработка с помощью DVD-Навигатора и VMR

В настоящее время декодатору передается тип мультимедиа FORMAT_MPEG2_VIDEO (блок формата которого указывает на структуру MPEG2VIDEOINFO). На выходных контактах декодатор создает мультимедиа тип FORMAT_VideoInfo2, блок форматирования которого указывает на структуру VIDEOINFOHEADER2. Поле dwReserved структуры было переименовано в флаги dwControls.

Элемент dwControlFlags теперь будет содержать новые биты.

Ярлык Ценность
AMCONTROL_USED 0x00000001
AMCONTROL_PAD_TO_4x3 0x00000002
AMCONTROL_PAD_TO_16x9 0x00000004

 

AMCONTROL_USED используется для проверки того, поддерживаются ли эти новые флаги. Исходный фильтр должен установить флаг AMCONTROL_USED и выяснить, успешно ли выполняется QueryAccept(MediaType) на потребляющем выводе. Если это отклонено, то флаги AMCONTROL нельзя использовать, а dwReserved1 должен иметь значение 0.

AMCONTROL_PAD_TO_4x3 указывает, что изображение должно быть дополнено и отображено в области с соотношением сторон 4x3.

AMCONTROL_PAD_TO_16x9 указывает, что изображение должно быть заполнено и отображено в области 16x9.

Декодатор должен либо слепо копировать, либо обрабатывать биты. Если декодировщик сам выполняет добавление полей (оконное форматирование), он должен изменить соотношение сторон пикселей, добавить поля к изображению и удалить соответствующие биты AMCONTROL_*.

Теперь MPEG2VIDEOINFO.dwFlags содержит три флага для управления, контролирующего, как следует отображать содержимое.

  • AMMPEG2_DoPanScan (0x00000001): если этот флаг задан, декодатор видео MPEG-2 должен обрезать выходной образ на основе векторов панорамирования в picture_display_extension и изменить соотношение сторон изображения на 4x3. VMR не должен получать образец 16x9 с этим флагом. Простая реализация может изменить исходный прямоугольник, чтобы указать исходный регион шириной 540 с левым краем, равным смещению отображения в picture_display_extension.

  • AMMPEG2_LetterboxAnalogOut (0x00000020). Если аппаратный декодировщик отображает этот поток на видеовыход (обычно соединитель SVIDEO на карте), он должен применять правила для отображения примера 16x9 на дисплее 4x3.

    Программный декодер (или аппаратный декодер, который отправляет выходные данные в VMR) имеет два варианта при обработке изображений:

    1. Пропустите этот флаг и передайте содержимое VideoInfoHeader2 в VMR (флаг AMCONTROL_PAD_TO_4x3 уже будет задан DVD-навигатором в примере). VMR столкнется с видеосемплом 16x9 с установленным флагом AMCONTROL_PAD_TO_4x3 и субкартинным потоком 4x3. Приложение должно задать нормализованные прямоугольники назначения выходных данных двух потоков одинаковой ширины.
    2. Преобразуйте анаморфный поток в изображение 4x3, добавив полосы сверху и снизу изображения и установив соотношение сторон изображения 4x3 (см. Леттербокс выше), а также удалив бит AMCONTROL_PAD_TO_4x3 из VIDEOINFOHEADER2.

    Декодировщики DirectXVA, которые объединяют видеопотоки и субтитры, должны обработать этот флаг. Если оборудование не может масштабировать смешанную подпиктуру, декодировщик должен создать отдельный поток подпиктуры, чтобы видеомикшер мог смешивать его с видео.

  • AMMPEG2_WidescreenAnalogOut (0x00000200). Когда аппаратный декодатор выводит этот поток на видеовыход (обычно разъем SVIDEO на карте), следует предусматривать дисплей 16x9 (анаморфный).

    Программный декодер (или аппаратный декодер, передающий выходные данные в VMR) имеет два варианта при обработке анаморфного изображения:

    1. Игнорируйте этот флаг и скопируйте содержимое VideoInfoHeader2 в VMR. VmR будет заполнять 4x3 изображения до 16x9, если они имеют набор AMCONTROL_PAD_TO_16x9.
    2. Поместите выходное изображение на изображение 16x9 и удалите AMCONTROL_PAD_TO_16x9 бит.

Большинство декодаторов должны использовать GetMediaType для обнаружения изменения носителя на входном пин-коде и копирования содержимого VIDEOINFOHEADER2 (содержащегося в MPEG2INFOHEADER) в выходной пин-код. Вероятно, они будут заниматься обработкой только бита PanScan.

В следующем примере кода показано, как скопировать содержимое VIDEOINFOHEADER2 из входного пин-кода в выходной пин-код.

#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;
}