メディア タイプについて
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 構造体を使う。ビデオでは、VIDEOINFOHEADER や VIDEOINFOHEADER2 など、さまざまな構造体を使う。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 の場合は、すべてのフレームがキー フレームであることを意味する。