メディア タイプについて

DirectShow はモジュール化されているので、フィルタ グラフ内の各ポイントでデータのフォーマットを記述する方法が必要である。たとえば、AVI の再生を考えてみる。データは RIFF チャンクのストリームとしてグラフに入力される。このストリームはビデオ ストリームとオーディオ ストリームに解析される。ビデオ ストリームはビデオ フレームで構成され、通常は圧縮されている。デコード後、ビデオ ストリームは一連の非圧縮ビットマップになる。オーディオ ストリームについても同様の処理が行われる。

メディア タイプ :DirectShow によるフォーマットの表現方法

"メディア タイプ" は、デジタル メディア フォーマットを記述するための汎用的で拡張性の高い方法である。2 つのフィルタが接続したとき、フィルタはメディア タイプについて合意する。メディア タイプは、アップストリーム フィルタがダウンストリーム フィルタに送るデータの種類、およびデータの物理的なレイアウトを識別する。2 つフィルタがメディア タイプについて合意できない場合、接続はできない。

一部のアプリケーションでは、メディア タイプについて意識する必要はない。たとえば、ファイルの再生では、DirectShow がすべての処理を行う。ある種のアプリケーションでは、直接メディア タイプを処理しなければならない場合もある。

メディア タイプは、AM_MEDIA_TYPE 構造体を使って定義する。この構造体には次の情報が含まれる。

  • メジャー タイプ :メジャー タイプはデータのカテゴリ全体を定義する GUID である。メジャー タイプには、ビデオ、オーディオ、解析されていないバイト ストリーム、MIDI データなどがある。

  • サブタイプ :サブタイプは、フォーマットをさらに細かく定義する別の GUID である。たとえば、ビデオ メジャー タイプには、RGB-24、RGB-32、UYVY などのサブタイプがある。オーディオの場合は、PCM オーディオ、MPEG-1 ペイロードなどがある。サブタイプはメジャー タイプよりも詳しい情報を提供するが、フォーマットに関するすべてを定義しているわけではない。たとえば、ビデオのサブタイプでは、イメージ サイズやフレーム レートを定義しない。これらは次に説明するフォーマット ブロックで定義される。

  • フォーマット ブロック :フォーマット ブロックは、フォーマットを詳細に記述するデータのブロックである。フォーマット ブロックは、AM_MEDIA_TYPE 構造体とは別に割り当てられる。AM_MEDIA_TYPE 構造体の pbFormat メンバがフォーマット ブロックを指す。

    フォーマット ブロックのレイアウトはメディア タイプによって変わるので、pbFormat メンバは void* 型である。たとえば、PCM オーディオでは WAVEFORMATEX 構造体を使う。ビデオでは、VIDEOINFOHEADERVIDEOINFOHEADER2 など、さまざまな構造体を使う。AM_MEDIA_TYPE 構造体の formattype メンバは、フォーマット ブロックに格納される構造体を指定する。各フォーマット構造体には GUID が割り当てられる。cbFormat メンバはフォーマット ブロックのサイズを指定する。pbFormat ポインタの参照を解除する前に、常にこれらの値をチェックすること。

フォーマット ブロックに情報が格納されている場合、メジャー タイプとサブタイプには冗長な情報が含まれていることになる。しかし、メジャー タイプとサブタイプは、詳細なフォーマット ブロックを使わずに、フォーマットを識別するときに便利である。たとえば、イメージ サイズやフレーム レートなど、VIDEOINFOHEADER 構造体で必要なすべての情報がわからなくても、一般的な 24 ビット RGB フォーマット (MEDIASUBTYPE_RGB24) を指定できる。

たとえば、フィルタでは次のコードを使って、メディア タイプをチェックできる。

HRESULT CheckMediaType(AM_MEDIA_TYPE *pmt)
{
    if (pmt == NULL) return E_POINTER;

    // メジャー タイプをチェックする。 ここでは、ビデオを検索している。
    if (pmt->majortype != MEDIATYPE_Video)
    {
        return VFW_E_INVALIDMEDIATYPE;
    }

    // サブタイプをチェックする。 ここでは、24 ビット RGB を検索している。
    if (pmt->subtype != MEDIASUBTYPE_RGB24)
    {
        return VFW_E_INVALIDMEDIATYPE;
    }

    // フォーマット タイプおよびフォーマット ブロックのサイズをチェックする。
    if ((pmt->formattype == FORMAT_VideoInfo) &&
         (pmt->cbFormat >= sizeof(VIDEOINFOHEADER) &&
         (pmt->pbFormat != NULL))
    {
        // これで、フォーマット ブロック ポインタを、フォーマットタイプ GUID で定義された
        // 正しい構造体に強制しても安全である。
        VIDEOINFOHEADER *pVIH = (VIDEOINFOHEADER*)pmt->pbFormat;
    
        // pVIH (省略されている) を調べる。 問題がない場合は、S_OK を返す。
        return S_OK;
    }

    return VFW_E_INVALIDMEDIATYPE;
}

AM_MEDIA_TYPE 構造体には、いくつかのオプション フィールドも格納される。これらのフィールドを使って追加情報を提供できるが、フィルタでこれらのフィールドを使う必要はない。

  • lSampleSize。このフィールドが 0 以外の場合、各サンプルのサイズを定義する。0 の場合は、サンプル サイズはサンプルごとに変更される場合がある。
  • bFixedSizeSamples。このブール型フラグが TRUE の場合は、lSampleSize の値が有効であることを意味する。それ以外の場合は、lSampleSize を無視するべきである。
  • bTemporalCompression。このブール型フラグが FALSE の場合は、すべてのフレームがキー フレームであることを意味する。