次の方法で共有


MPEG デコーダーの前処理変換

[このページに関連付けられている機能 DirectShow は、従来の機能です。 MediaPlayerIMFMediaEngine、および Media Foundation のオーディオ/ビデオ キャプチャに置き換わりました。 これらの機能は、Windows 10とWindows 11用に最適化されています。 新しいコードでは、可能であれば、DirectShow ではなく Media Foundation で MediaPlayerIMFMediaEngineAudio/Video Capture を使用することを強くお勧めします。 Microsoft は、従来の API を使用する既存のコードを、可能であれば新しい API を使用するように書き直すよう提案しています。]

レターボックスと PanScan

4x3 イメージは、画像の上下を埋め込む (Letterbox イメージと呼ばれます) か、画像の 4x3 部分 (PanScan イメージと呼ばれます) を抽出することによって形成できます。 メニューとサブ画像ストリームは、最終的なビデオ画像の上にオーバーレイされます。 16 x 9 の比率の画像は、4x3 アナモーフィック形式で格納されます。 アナモーフィックな4x3アスペクト比720x480ソースビデオを16x9アスペクト比にストレッチすると、元の16x9アスペクトイメージが形成されます。

各モードとそのハイライトを正しく表示する方法を次に示します。

  • ワイド スクリーン: ソース ビデオは、出力ウィンドウの最大の 16 x 9 領域に拡張されました。 ハイライトは、16x9 領域の内側を基準にしています。 16x9 の領域を維持するには、黒いバーを上下または側面に追加する必要があります。
  • パン スキャン: 16x9 ビデオから、MPEG2 ストリームに提供される水平オフセットを使用して、4x3 サブウィンドウを抽出します。 4x3 サブウィンドウを出力クライアント ウィンドウの最大 4 x 3 領域に配置します。 ハイライトの座標は 4x3 出力ウィンドウを基準にしており、ソース 16x9 ビデオとは関係がありません。 黒い棒は、4x3 の領域を維持するために、上下または側面に追加する必要があります。
  • レター: 出力ウィンドウの最大 4 x 3 領域を計算します。 黒い棒は、4x3 の領域を維持するために、上下または側面に追加する必要があります。 ソースアナモーフィック 4x3 ビデオ (16x9 画像を表す) は、4x3 領域内の最大の 16x9 サブウィンドウに配置されます。 16 x 9 の領域を維持するには、サブウィンドウの上部と下部に黒いバーを追加する必要があります。 ハイライトの座標は 4x3 領域を基準にしており、ソース 16x9 ビデオとは関係がありません。 ディスクでは、16 x 9 領域の外側にある強調表示を指定できます (ただし、4x3 ウィンドウに残ります)。 4x3 ビデオの場合、ビデオは出力クライアント ウィンドウの最大 4x3 出力領域に配置されます。 黒い棒は、4x3 の領域を維持するために、上下または側面に追加する必要があります。

DVD ナビゲーターと VMR を使用した MPEG 前処理

現在、デコーダーには、FORMAT_MPEG2_VIDEOメディアの種類 (形式ブロックが MPEG2VIDEOINFO 構造体を指す) が渡されています。 出力ピンでは、デコーダーは、フォーマット ブロックが VIDEOINFOHEADER2 構造体を指すFORMAT_VideoInfo2メディア タイプを生成します。 構造体の dwReserved フィールドの名前が dwControls フラグに変更されました。

dwControlFlags メンバーに新しいビットが含まれるようになりました。

Label
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は、画像を 16 x 9 の領域に埋め込んで表示する必要があることを示します。

デコーダーは、ビットを盲目的にコピーまたは処理する必要があります。 デコーダーがレターボックス化自体を実行する場合は、ピクセルの縦横比を変更し、画像を埋め込み、対応するAMCONTROL_* ビットを削除する必要があります。

MPEG2VIDEOINFO.dwFlags には、コンテンツの表示方法を制御するための制御用の 3 つのフラグが含まれるようになりました。

  • AMMPEG2_DoPanScan (0x00000001): このフラグが設定されている場合、MPEG-2 ビデオ デコーダーは、picture_display_extensionのパン スキャン ベクトルに基づいて出力イメージをトリミングし、画像の縦横比を 4x3 に変更する必要があります。 VMR は、このフラグを持つ 16x9 サンプルを受け取るべきではありません。 単純な実装では、ソース四角形を変更して、picture_display_extensionの表示オフセットと等しい左端を持つ 540 のワイド ソース領域を示す場合があります。

  • AMMPEG2_LetterboxAnalogOut (0x00000020): ハードウェア デコーダーがこのストリームをビデオ出力 (通常はカードの SVIDEO コネクタ) に表示する場合は、4x3 ディスプレイに 16x9 サンプルを表示するための規則を適用する必要があります。

    ソフトウェア デコーダー (または VMR に送信される出力を生成するハードウェア デコーダー) には、イメージを処理するときに次の 2 つのオプションがあります。

    1. このフラグを無視し、VideoInfoHeader2 の内容を VMR に渡します (AMCONTROL_PAD_TO_4x3 フラグは、サンプルの DVD ナビゲーター によって既に設定されています)。 VMR では、AMCONTROL_PAD_TO_4x3 フラグが設定された 16x9 ビデオ サンプルと 4x3 サブ画像ストリームが検出されます。 アプリケーションでは、2 つのストリームの出力正規化された変換先の四角形を同じ幅に設定する必要があります。
    2. 画像の上下を埋め込み、画像の縦横比を 4x3 に設定し (上記のレターボックスを参照)、VIDEOINFOHEADER2 からAMCONTROL_PAD_TO_4x3 ビットを削除して、アナモーフィック ストリームを 4x3 イメージに変換します。

    ビデオストリームとサブ画像ストリームをブレンドする DirectXVA デコーダーは、このフラグを処理する必要があります。 ハードウェアがブレンドされたサブPICTUREをスケーリングできない場合、デコーダーは、VMR がビデオとブレンドするための別のサブ画像ストリームを生成する必要があります。

  • AMMPEG2_WidescreenAnalogOut (0x00000200): ハードウェア デコーダーがこのストリームをビデオ出力 (通常はカード上の SVIDEO コネクタ) に表示する場合は、16x9 (アナモーフィック) ディスプレイを想定する必要があります。

    ソフトウェア デコーダー (または VMR に送信される出力を生成するハードウェア デコーダー) には、アナモーフィック イメージを処理する場合に 2 つのオプションがあります。

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