DirectShow DirectShow 의 사용법 Video Mixing Renderer 의 사용법 DirectShow 필터 개발자전용 VMR 의 사용법 MPEG 디코더의 사전 처리 변환   [목차열람] [주소복사] [슬롯비우기]
MPEG 디코더의 사전 처리 변환
 
Microsoft DirectX 9.0

MPEG 디코더의 사전 처리 변환

레터박스와 팬-스캔

4x3 이미지를 생성 하려면 , 이미지의 상하를 패딩 하는지 (레터박스 이미지라고 부른다), 이미지의 4x3 부분을 추출한다 (팬-스캔 이미지라고 부른다). 메뉴와 서브 픽쳐 스트림은 최종 비디오 이미지 위에 오버레이 된다. 16x9 어스펙트비(가로세로 비율)의 이미지는 4x3 변형 포맷으로 보존된다. 변형 4x3 어스펙트비(가로세로 비율)의 720x480 소스 비디오를 16x9 어스펙트비(가로세로 비율)에 지연시키면 원의 16x9 어스펙트비(가로세로 비율)의 이미지가 된다.

다음에, 각 모드와 그 하이라이트 영역을 올바르게 표시하는 방법에 대해 기술한다.

DVD 네비게이터와 VMR 를 사용한 MPEG 사전 처리

현재, 디코더에는 FORMAT_MPEG2_VIDEO 미디어 타입 (포맷 블록은 MPEG2VIDEOINFO 구조체를 가리킨다)이 건네받는다. 출력 핀에 디코더는 FORMAT_VideoInfo2 미디어 타입을 생성한다. 그 포맷 블록은 VIDEOINFOHEADER2 구조체를 가리킨다. VIDEOINFOHEADER2 의 dwReserved 필드는 dwControls 플래그로 이름이 변경된다. 새로운 정의 (dvdmedia.h 내)는 다음과 같이 된다.

typedef struct tagVIDEOINFOHEADER2 {
  RECT     rcSource;
  RECT     rcTarget;
  DWORD    dwBitRate;
  DWORD    dwBitErrorRate;
  REFERENCE_TIME   AvgTimePerFrame;
  DWORD   dwInterlaceFlags;   // AMINTERLACE_* 정의를 사용한다.
                             // 미정도리 비트가 0 이 아닌 경우, 접속을 거부한다.
  DWORD   dwCopyProtectFlags; // AMCOPYPROTECT_* 정의를 사용한다.
                             // 미정도리 비트가 0 이 아닌 경우, 접속을 거부한다.
  DWORD   dwPictAspectRatioX; // 화면의 어스펙트비(가로세로 비율)의 X 넓이.
                              // 예를 들어 16x9 표시의 16.
  DWORD   dwPictAspectRatioY; // 화면의 어스펙트비(가로세로 비율)의 Y 넓이.
                              // 예를 들어 16x9 표시의 9.
  union {
      DWORD dwControlFlags;   // AMCONTROL_* 정의를 사용한다.
                              // 이후는 이 값을 사용한다.
      DWORD dwReserved1;    // 하위 호환성이기 때문에.
                            //(반드시 0 으로 한다. 그 이외의 경우,
                            // 접속은 거부된다. )
    };
  DWORD     dwReserved2;  // 반드시 0 으로 한다. 그 이외의 경우, 접속은 거부된다.
  BITMAPINFOHEADER    bmiHeader;
} VIDEOINFOHEADER2;

VIDEOINFOHEADER2.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 에는, 컨텐츠의 표시 방법을 제어하는 3 개의 플래그를 포함되어 있다.

대부분의 디코더는 GetMediaType 를 사용해, 입력 핀의 미디어의 변경을 검출해,VIDEOINFOHEADER2 의 컨텐츠 (MPEG2INFOHEADER 에 포함된다)를 출력 핀에 복사 한다. 팬-스캔 비트만을 처리하는 것이 많다.

다음 샘플 코드는,VIDEOINFOHEADER2 의 컨텐츠를 입력 핀으로부터 출력 핀에 복사 하는 방법을 나타내고 있다.

#include <dvdmedia.h>
HRESULT CopyMPeg2ToVideoInfoHeader2(CMediaSample* pInSample, CMediaSample* pOutSample)
{
    HRESULT hr = S_OK;
    // 입력 샘플의 미디어 타입을 조사한다.
    AM_MEDIA_TYPE* pInType;
    if (pInSample->GetMediaType(&pInType) == S_OK) 
    {
        // MPEG2 비디오 포맷인 것을 확인한다.
        if ((pInType->formattype == FORMAT_MPEG2_VIDEO) &&
            (pInType->cbFormat >= sizeof(MPEG2VIDEOINFO)))
        {
            hr = S_OK; // CMediaType 생성자의 hr 를 초기화한다.
            CMediaType outType(*pInType, &hr);
            if (FAILED(hr))
            {
                DeleteMediaType( pInType );
                return hr;
            }

            // 포맷 타입 GUID 를 설정한다.
            outType.SetFormatType(&FORMAT_VideoInfo2);
                
            // VIDEOINFOHEADER 부분만을 포함하도록(듯이) 포맷 블록을 절약한다.
            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); // MPEG2 헤더는 아니다.
            hr = VFW_E_INVALIDMEDIATYPE;
        }
        DeleteMediaType( pInType );
    } 

    return hr;
}
↑TOP