MPEG 디코더 전처리 변환

[이 페이지와 연결된 기능인 DirectShow는 레거시 기능입니다. MediaPlayer, IMFMediaEngineMedia Foundation의 오디오/비디오 캡처로 대체되었습니다. 이러한 기능은 Windows 10 및 Windows 11 최적화되었습니다. 가능한 경우 새 코드에서 DirectShow 대신 MediaPlayer, IMFMediaEngine오디오/비디오 캡처를 사용하는 것이 좋습니다. 가능한 경우 레거시 API를 사용하는 기존 코드를 다시 작성하여 새 API를 사용하도록 제안합니다.]

Letterbox 및 PanScan

4x3 이미지는 이미지의 위쪽과 아래쪽(Letterbox 이미지라고 함)을 패딩하거나 이미지의 4x3 부분(PanScan 이미지라고 함)을 추출하여 형성할 수 있습니다. 메뉴 및 하위 사진 스트림은 최종 비디오 이미지 위에 오버레이됩니다. 16x9 비율 이미지는 4x3 단형 형식으로 저장됩니다. 아나모픽 4x3 가로 세로 비율 720x480 원본 비디오를 16x9 가로 세로 비율로 늘이면 원래 16x9 가로 세로 이미지가 형성됩니다.

다음은 각 모드와 해당 하이라이트를 올바르게 표시하는 방법에 대한 설명입니다.

  • 와이드 스크린: 원본 비디오는 출력 창에서 가장 큰 16x9 영역으로 확장되었습니다. 하이라이트는 16x9 영역의 내부를 기준으로 합니다. 16x9 영역을 유지하려면 위쪽과 아래쪽 또는 측면에 검은색 막대를 추가해야 합니다.
  • Pan Scan: 16x9 비디오에서 MPEG2 스트림에 제공된 가로 오프셋을 사용하여 4x3 하위window를 추출합니다. 4x3 하위 창을 출력 클라이언트 창의 가장 큰 4x3 영역에 배치합니다. 강조 표시의 좌표는 4x3 출력 창을 기준으로 하며 원본 16x9 비디오와 아무런 관계가 없습니다. 4x3 영역을 유지하려면 위쪽과 아래쪽 또는 측면에 검은색 막대를 추가해야 합니다.
  • 레터 박스: 출력 창에서 가장 큰 4x3 영역을 계산합니다. 4x3 영역을 유지하려면 위쪽과 아래쪽 또는 측면에 검은색 막대를 추가해야 합니다. 원본 아나모픽 4x3 비디오(16x9 이미지를 나타낸)는 4x3 영역 내에서 가장 큰 16x9 하위 창에 배치됩니다. 16x9 영역을 유지하려면 하위 창의 위쪽과 아래쪽에 검은색 막대를 추가해야 합니다. 강조 표시의 좌표는 4x3 영역을 기준으로 하며 원본 16x9 비디오와 아무런 관계가 없습니다. 디스크에서 16x9 영역 외부에 있는 강조 표시를 지정할 수 있습니다(하지만 여전히 4x3 창에 있음). 4x3 비디오의 경우 비디오는 출력 클라이언트 창에서 가장 큰 4x3 출력 영역에 배치됩니다. 4x3 영역을 유지하려면 위쪽과 아래쪽 또는 측면에 검은색 막대를 추가해야 합니다.

DVD 탐색기 및 VMR을 사용하여 MPEG 전처리

현재 디코더는 FORMAT_MPEG2_VIDEO 미디어 형식(형식 블록이 MPEG2VIDEOINFO 구조를 가리킵니다)으로 전달됩니다. 출력 핀에서 디코더는 videoINFOHEADER2 구조를 가리키는 형식 블록의 FORMAT_VideoInfo2 미디어 형식을 생성합니다. 구조체의 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 샘플을 받지 않아야 합니다. 간단한 구현은 원본 사각형을 변경하여 왼쪽 가장자리가 picture_display_extension 표시 오프셋과 같은 540 광원 영역을 나타낼 수 있습니다.

  • AMMPEG2_LetterboxAnalogOut (0x00000020): 하드웨어 디코더가 이 스트림을 비디오 출력(일반적으로 카드 SVIDEO 커넥터)에 표시하는 경우 4x3 디스플레이에 16x9 샘플을 표시하는 규칙을 적용해야 합니다.

    소프트웨어 디코더(또는 VMR로 전송된 출력을 생성하는 하드웨어 디코더)에는 이미지를 처리할 때 두 가지 옵션이 있습니다.

    1. 이 플래그를 무시하고 VideoInfoHeader2 콘텐츠를 VMR에 전달합니다(샘플의 DVD 탐색기 에서 AMCONTROL_PAD_TO_4x3 플래그가 이미 설정됨). VMR은 AMCONTROL_PAD_TO_4x3 플래그 집합과 4x3 하위픽처 스트림이 있는 16x9 비디오 샘플이 발생합니다. 애플리케이션은 두 스트림의 정규화된 출력 대상 사각형을 동일한 너비로 설정해야 합니다.
    2. 이미지의 위쪽과 아래쪽을 패딩하고 이미지 가로 세로 비율을 4x3으로 설정하고(위의 Letterbox 참조) VIDEOINFOHEADER2에서 AMCONTROL_PAD_TO_4x3 비트를 제거하여 아나모픽 스트림을 4x3 이미지로 변환합니다.

    비디오 및 하위픽처 스트림을 혼합하는 DirectXVA 디코더는 이 플래그를 처리해야 합니다. 하드웨어가 혼합된 하위 구성의 크기를 조정할 수 없는 경우 디코더는 VMR이 비디오와 혼합되도록 별도의 하위픽처 스트림을 생성해야 합니다.

  • AMMPEG2_WidescreenAnalogOut (0x00000200): 하드웨어 디코더가 이 스트림을 비디오 출력(일반적으로 카드 SVIDEO 커넥터)에 표시하는 경우 16x9(아나모픽) 디스플레이를 가정해야 합니다.

    소프트웨어 디코더(또는 VMR로 전송된 출력을 생성하는 하드웨어 디코더)에는 아나모픽 이미지를 처리할 때 두 가지 옵션이 있습니다.

    1. 이 플래그를 무시하고 VideoInfoHeader2 콘텐츠를 VMR에 복사합니다. VMR은 AMCONTROL_PAD_TO_16x9 설정된 경우 4x3 이미지를 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;
}