Date

通常、EVR Custom Presenter (カスタムプレゼンタ)はcoclassとして実装し、DLL としてコンパイルする。この方法はバージョンアップが容易であったり、コンパイル無しに複数のアプリケーションで再利用できたりするメリットがある。しかし、配布ファイル数が多くなる、他のアプリケーションから参照されるといったデメリットもあり、プライベートで使用するのであれば DLL ではなく実行ファイル(.EXE)に内蔵することを検討したい。

Media Foundation ではActivation Object (アクティベーションオブジェクト) を実装することにより、実行ファイルに EVR Custom Presenter を内蔵することができる。

Activation Object を実装する

Activation Object とはCOMにおけるクラスファクトリに似ている。IMFActivateインターフェイスを実装したクラスであり、coclass のインスタンスを作成したり、シャットダウンする役割がある。

もっとも重要なのは IMFActivate::ActivateObjectCoCreateInstanceのような役割がある。インスタンスを作成し、そのインターフェイスのポインタを返すメソッドである。

EVR Custom Presenter のクラスをCEvrPresとすると、このインスタンスを作成するためのIMFActivate::ActivateObjectは以下のように実装できる。

```c++ IMFActivate::ActivateObject CComPtr m_CustomPres; // メンバ変数 STDMETHODIMP ActivateObject(REFIID riid, void ppv) { if (riid != __uuidof(IMFVideoPresenter)) { return MF_E_CANNOT_CREATE_SINK; } if (ppv == NULL) { return E_POINTER; } if (m_CustomPres != NULL) { CComQIPtr mfvp(m_CustomPres); ppv = mfvp; mfvp.p->AddRef(); return S_OK; } CComObject * object; CComObject::CreateInstance(&object); m_CustomPres.Attach(object); m_CustomPres.p->AddRef(); CComQIPtr mfvp(object); if (mfvp == NULL) { return MF_E_CANNOT_CREATE_SINK; } ppv = mfvp; mfvp.p->AddRef(); return S_OK; }

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
このコードの流れをざっと説明すると、はじめに、引数`riid`が`__uuidof(IMFVideoPresenter)`かどうか確認する。EVR Custom Presenter の Activation Object に対してこのメソッドが呼ばれるとき `IMFVideoPresenter` インターフェイスが要求される。そして、`CEvrPres`クラスのインスタンスを作成し、`IMFVideoPresenter`インターフェイスを問い合わせる(`QueryInterface`)。最後に、戻り値`ppv`に代入して完了。

`CoCreateInstance`と`IMFActivate::ActivateObject`の違いは、作成したインスタンスを Activation Object が記憶していることだ。これは`IMFActivate::ActivateObject`を再度呼び出したとき、`IMFActivate::Shutdown`と`IMFActivate::DetachObject`のいずれかが呼ばれるまで同じインスタンスを示すポインタを返す必要があるからだ。

>After the first call to ActivateObject, subsequent calls return a pointer to the same instance, until the client calls either ShutdownObject or IMFActivate::DetachObject.

[IMFActivate::ActivateObject Method](http://msdn.microsoft.com/en-us/library/ms694292%28V=VS.85%29.aspx)

## EVR Custom Presenter の Activation Object を EVR に設定する

EVR の Activation Object を作成するAPIは<a href="http://msdn.microsoft.com/en-us/library/ms693543(VS.85).aspx">`MFCreateVideoRendererActivate`</a>である。これで作成した Activation Object の `MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_ACTIVATE` 属性に EVR Custom Presenter の Activation Object を設定する。

```c++ Activation Object を設定
CComPtr<IMFActivate> &activate;
hr = MFCreateVideoRendererActivate(m_hWnd, &activate);
CComObject<CMyActivateObj> * my_activate_obj;
CComObject<CMyActivateObj>::CreateInstance(&my_activate_obj);
CComPtr<IUnknown> unk(my_activate_obj);
hr = activate->SetUnknown(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_ACTIVATE, unk);

あとはTopologyのノードに、この Activation Object を追加すれば、内蔵した EVR Custom Presenter が使われるようになる。


Comments

comments powered by Disqus