Date

Media Foundation においても DirectShow と同様にストリームの内容が画像なのか音なのかといった区別をするために「メディアタイプ」がある。

メディアタイプは Major Type(メジャータイプ)、Subtype(サブタイプ)という2つの要素がある。メジャータイプはそれがビデオなのかオーディオなのかという大まかな内容を、サブタイプはビデオであればRGB32なのかYV12なのか、オーディオであればPCMなのかAACなのかといった形式を示す。更に、フレームサイズや周波数といった詳細な情報も扱う。

DirectShowと大きく異なる点として、DirectShowではメジャータイプ、サブタイプ、詳細な情報をメディアタイプに応じた構造体(VIDENINFOHEADERWAVEFORMATEXなど)で取得するためのメソッドがあった。Media Foundationではキー/値ペアをいくつか組み合わせた「属性」で表すようになった。これにより、今後、メディアタイプが拡張された場合でも柔軟に対応できる。しかも、従来通り構造体として取得するメソッドや、属性に変換するメソッドも実装されている。

本ブログで作成した動画プレイヤーサンプルにちょっと手を加えてメディアタイプを見てみよう。

CMyWindow::CreateMediaSinkActivateにあるhr=stream_desc->GetMediaTypeHandler(&handler);に注目してほしい。メディアタイプハンドラからメディアタイプを取得するメソッドGetMajorTypeを呼び出してメジャータイプの取得までは済んでいる。これに加えてサブタイプを取得してみる。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
HRESULT CreateMediaSinkActivate(
       CComPtr<IMFStreamDescriptor> stream_desc,
       CComPtr<IMFActivate> &activate)
{
       CComPtr<IMFMediaTypeHandler> handler;
       GUID guidMajorType=GUID_NULL;
       CHResult hr;
       hr=stream_desc->GetMediaTypeHandler(&handler);
       hr=handler->GetMajorType(&guidMajorType);
       /* 追加個所(1) */
       CComPtr<IMFMediaType> mt;
       handler->GetCurrentMediaType(&mt);
       GUID sub_type;
       mt->GetGUID(MF_MT_SUBTYPE, &sub_type);
       if(guidMajorType==MFMediaType_Audio) {
               hr=MFCreateAudioRendererActivate(&activate);
       }else if(guidMajorType==MFMediaType_Video) {
               hr=MFCreateVideoRendererActivate(m_Static.m_hWnd, &activate);
               /* 追加個所(2) */
       }else {
               hr=MF_E_INVALIDMEDIATYPE;
       }
       return hr;
}

サブタイプを取得するにはIMFMediaTypeインターフェイスをメディアタイプハンドラから取得する。それからIMFMediaType::GetGUIDMF_MT_SUBTYPEとともに呼び出す。(追加個所(1))ちなみにメジャータイプはMF_MT_MAJOR_TYPEというキーである。

ビデオについてより詳細な情報を取得してみよう。まずはインターレースかどうか取得してみる。追加個所(2)というところに次のコードを追加する。

1
2
UINT32 im;
mt->GetUINT32(MF_MT_INTERLACE_MODE, &im);

MF_MT_INTERLACE_MODEというのはビデオのインターレースモードのキーである。

次に、フレームサイズを取得してみよう。フレームサイズはMF_MT_FRAME_SIZEというキーである。ここではMFGetAttributeSizeというAPI を使う。この API はサイズの属性を取得して、UINT32型の2つの変数に幅と高さを代入する。

1
2
UINT32 w, h;
MFGetAttributeSize(mt, MF_MT_FRAME_SIZE, &w, &h);

最後にMFCreateMFVideoFormatFromMFMediaTypeMFCreateWaveFormatExFromMFMediaTypeという API を紹介する。MFCreateMFVideoFormatFromMFMediaTypeはメディアタイプの内容をMFVIDEOFORMAT構造体として、MFCreateWaveFormatExFromMFMediaTypeWAVEFORMATEX構造体として取得する API である。値を個別に問い合わせるのは手間がかかるので、こういった便利なものが定義されている。

1
2
3
4
5
6
7
8
MFVIDEOFORMAT *mfvf;
UINT32 mfvf_size;
MFCreateMFVideoFormatFromMFMediaType(mt, &mfvf, &mfvf_size);
CoTaskMemFree(mfvf);
WAVEFORMATEX *wf;
UINT32 wf_size;
MFCreateWaveFormatExFromMFMediaType(mt, &wf, &wf_size);
CoTaskMemFree(wf);

必ずCoTaskMemFreeで解放すること。


Comments

comments powered by Disqus