Deinterlace の基本設定の設定

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

Video Mixing Renderer (VMR) では、ハードウェアアクセラレータによるデインターレースがサポートされています。これにより、インターレースされたビデオのレンダリング品質が向上します。 使用できる正確な機能は、基になるハードウェアによって異なります。 アプリケーションは、ハードウェアのインターレース解除機能を照会し、 IVMRDeinterlaceControl インターフェイス (VMR-7) または IVMRDeinterlaceControl9 インターフェイス (VMR-9) を使用して、インターレース解除の基本設定を設定できます。 インターレース解除は、ストリームごとに実行されます。

VMR-7 と VMR-9 の間のインターレース動作には重要な違いが 1 つあります。 グラフィックス ハードウェアが高度なインターレース解除をサポートしていないシステムでは、VMR-7 はハードウェア オーバーレイにフォールバックし、BOB スタイルのデインターレースを使用するように指示できます。 この場合、VMR は 30fps を報告していますが、ビデオは実際には 1 秒あたり 60 フリップでレンダリングされています。

ハードウェア オーバーレイを使用する VMR-7 の場合を除き、インターレース解除は VMR のミキサーによって実行されます。 ミキサーは、DirectX ビデオ アクセラレーション (DXVA) デインターレース デバイス ドライバー インターフェイス (DDI) を使用して、デインターレースを実行します。 この DDI はアプリケーションで呼び出すことができません。また、アプリケーションは VMR のインターレース解除機能を置き換えることはできません。 ただし、アプリケーションでは、このセクションで説明するように、目的のインターレース解除モードを選択できます。

注意

このセクションでは 、IVMRDeinterlaceControl9 メソッドについて説明しますが、VMR-7 のバージョンはほぼ同じです。

 

ビデオ ストリームのインターレース解除機能を取得するには、次の操作を行います。

  1. VMR9VideoDesc 構造体にビデオ ストリームの説明を入力します。 この構造を入力する方法の詳細については、後で説明します。
  2. 構造体を IVMRDeinterlaceControl9::GetNumberOfDeinterlaceModes メソッドに渡します。 メソッドを 2 回呼び出します。 最初の呼び出しは、ハードウェアが指定した形式でサポートするデインターレース モードの数を返します。 このサイズの GUID の配列を割り当て、もう一度 メソッドを呼び出して、配列のアドレスを渡します。 2 番目の呼び出しでは、配列に GUID が入力されます。 各 GUID は、1 つのインターレース解除モードを識別します。
  3. 特定のモードの上限を取得するには、 IVMRDeinterlaceControl9::GetDeinterlaceModeCaps メソッドを呼び出します。 配列の GUID の 1 つと共に、同じ VMR9VideoDesc 構造体を渡します。 メソッドは 、VMR9DeinterlaceCaps 構造体にモード機能を設定します。

これらの手順を示すコードは次のようになります。

VMR9VideoDesc VideoDesc; 
DWORD dwNumModes = 0;
// Fill in the VideoDesc structure (not shown).
hr = pDeinterlace->GetNumberOfDeinterlaceModes(&VideoDesc, 
    &dwNumModes, NULL);
if (SUCCEEDED(hr) && (dwNumModes != 0))
{
    // Allocate an array for the GUIDs that identify the modes.
    GUID *pModes = new GUID[dwNumModes];
    if (pModes)
    {
        // Fill the array.
        hr = pDeinterlace->GetNumberOfDeinterlaceModes(&VideoDesc, 
            &dwNumModes, pModes);
        if (SUCCEEDED(hr))
        {
            // Loop through each item and get the capabilities.
            for (int i = 0; i < dwNumModes; i++)
            {
                VMR9DeinterlaceCaps Caps;
                hr = pDeinterlace->GetDeinterlaceModeCaps(pModes + i, 
                    &VideoDesc, &Caps);
                if (SUCCEEDED(hr))
                {
                    // Examine the Caps structure.
                }
            }
        }
        delete [] pModes;
    }
}

次のメソッドを使用して、アプリケーションでストリームのインターレース解除モードを設定できるようになりました。

  • SetDeinterlaceMode メソッドは優先モードを設定します。 GUID_NULLを使用して、インターレース解除をオフにします。
  • SetDeinterlacePrefs メソッドは、要求されたモードが使用できない場合の動作を指定します。
  • GetDeinterlaceMode メソッドは、設定した優先モードを返します。
  • GetActualDeinterlaceMode メソッドは、使用されている実際のモードを返します。優先モードが使用できない場合はフォールバック モードである可能性があります。

メソッドの参照ページには、詳細が表示されます。

VMR9VideoDesc 構造体の使用

前に示した手順では、最初の手順として、 VMR9VideoDesc 構造体にビデオ ストリームの説明を入力します。 まず、ビデオ ストリームのメディアの種類を取得します。 これを行うには、VMR フィルターの入力ピンで IPin::ConnectionMediaType を呼び出します。 次に、ビデオ ストリームがインターレースされているかどうかを確認します。 インターレースできるのは VIDEOINFOHEADER2 形式のみです。 書式の種類がFORMAT_VideoInfoの場合は、プログレッシブ フレームである必要があります。 書式の種類がFORMAT_VideoInfo2の場合は、AMINTERLACE_IsInterlaced フラグの dwInterlaceFlags フィールドをチェックします。 このフラグが存在すると、ビデオがインターレースされていることを示します。

変数 pBMI が format ブロック内の BITMAPINFOHEADER 構造体へのポインターであるとします。 VMR9VideoDesc 構造体に次の値を設定します。

  • dwSize: このフィールドを に sizeof(VMR9VideoDesc)設定します。

  • dwSampleWidth: このフィールドを に pBMI->biWidth設定します。

  • dwSampleHeight: このフィールドを に abs(pBMI->biHeight)設定します。

  • SampleFormat: このフィールドは、メディアタイプのインターレース特性を記述します。 VIDEOINFOHEADER2 構造体の dwInterlaceFlags フィールドを確認し、SampleFormat を同等の VMR9_SampleFormat フラグに設定します。 これを行うためのヘルパー関数を以下に示します。

  • InputSampleFreq: このフィールドは、VIDEOINFOHEADER2 構造体の AvgTimePerFrame フィールドから計算できる入力頻度を示します。 一般的なケースでは、 dwNumerator を 10000000 に設定し、 dwDenominatorAvgTimePerFrame に設定します。 ただし、一部の既知のフレーム レートをチェックすることもできます。

    フレームあたりの平均時間 フレーム レート (fps) 分子 分母
    166833 59.94 (NTSC) 60000 1001
    333667 29.97 (NTSC) 30000 1001
    417188 23.97 (NTSC) 24000 1001
    200000 50.00 (PAL) 50 1
    400000 25.00 (PAL) 25 1
    416667 24.00 (フィルム) 24 1

     

  • OutputFrameFreq: このフィールドは、 InputSampleFreq 値と入力ストリームのインターリーブ特性から計算できる出力周波数を示します。

    • OutputFrameFreq.dwDenominatorInputSampleFreq.dwDenominator に設定します。
    • 入力ビデオがインターリーブされている場合は、 OutputFrameFreq.dwNumerator を 2 x InputSampleFreq.dwNumerator に設定します。 (インターレース解除後、フレーム レートは 2 倍になります)。それ以外の場合は、値を InputSampleFreq.dwNumerator に設定します。
  • dwFourCC: このフィールドを に pBMI->biCompression設定します。

次のヘルパー関数は、AMINTERLACE_X フラグを VMR9_SampleFormat 値に変換します。

#define IsInterlaced(x) ((x) & AMINTERLACE_IsInterlaced)
#define IsSingleField(x) ((x) & AMINTERLACE_1FieldPerSample)
#define IsField1First(x) ((x) & AMINTERLACE_Field1First)

VMR9_SampleFormat ConvertInterlaceFlags(DWORD dwInterlaceFlags)
{
    if (IsInterlaced(dwInterlaceFlags)) {
        if (IsSingleField(dwInterlaceFlags)) {
            if (IsField1First(dwInterlaceFlags)) {
                return VMR9_SampleFieldSingleEven;
            }
            else {
                return VMR9_SampleFieldSingleOdd;
            }
        }
        else {
            if (IsField1First(dwInterlaceFlags)) {
                return VMR9_SampleFieldInterleavedEvenFirst;
             }
            else {
                return VMR9_SampleFieldInterleavedOddFirst;
            }
        }
    }
    else {
        return VMR9_SampleProgressiveFrame;  // Not interlaced.
    }
}