と言うわけで、日曜日の後編側です。
後編ではサンプルで作ったCSurfaceRendererを実際に組み込んで使ってみる処理をやってみます。
一応かな~り昔の記事ですが、この記事にあるDirectShowの処理に割り込ませる形で組み込みを行います。
割り込むコードは
//lpwFileNameには有効なファイル名が代入されているものとする //IGraphBuliderを生成する hr = CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER,IID_IGraphBuilder,(void **)&m_lpGraphBuilder); //ファイル名を指定してグラフを生成する hr = m_lpGraphBuilder->RenderFile(lpwFileName,NULL);
の間になります。なお、CBaseVideoRendererを使って描画するときはIVideoWindowは使用できませんのでご注意を。
フィルタを作成して初期化
CSurfaceRenderer *m_lpSurfaceRenderer; hr = S_OK; m_lpSurfaceRenderer = new CSurfaceRenderer(NULL,&hr); if(hr != S_OK){ delete m_lpSurfaceRenderer; throw; } m_lpSurfaceRenderer->AddRef();
フィルタのメモリ確保そのものはnewをつかいます。ただのクラス初期化です。
基本的に第一引数のlpOwnerはNULLで問題ありません。第二引数は初期化時のエラーチェック用なのでhrのアドレスを渡します。
初期化に問題があったときはhrがS_OK以外の値になる(という仕様な)ので、そのときはdeleteでクラスメモリを解放してエラー処理をします。
フィルタの登録
IBaseFilter *lpBaseFilter; hr = m_lpSurfaceRenderer->QueryInterface(IID_IBaseFilter,(void **)&lpBaseFilter); hr = m_lpGraphBuilder->AddFilter(lpBaseFilter,L"Surface Renderer"); lpBaseFilter->Release(); lpBaseFilter = NULL;
ちなみに、QueryInterfaceの処理をなしにしてAddFilterの第一引数に直接lpSurfaceRendererと書いても間違いではありません。COM的な書き方だとこれが正しいのでこう書いているだけです。
この処理でGraphBuilderにレンダラフィルタを登録して描画が可能ならこちらに描画させるようにします。
フィルタの解放
フィルタ使用後(m_lpGraphBuilderを解放する前)に
m_lpSurfaceRenderer->Release();
があればメモリリークは起こりませんので。
なお、AddFilter後、グラフ外からm_lpSurfaceRendererにアクセスしないというのでしたらAddFilter直後に書いて解放してもかまいません。
AddFilterの時点でグラフ内で参照カウントがある状態になっていますので、所有権がプログラムと共有している状態からグラフのみに変わるだけです。
これでビデオラインがある動画であればだいたいはCSurfaceRenderer経由で描画ができると思います。