ファイルの再生法
ここでは、DirectShow プログラミングの一例を示す。オーディオまたはビデオ ファイルを再生する簡単なコンソール アプリケーションが示されている。このプログラムはほんの数行であるが、DirectShow プログラミングの可能性の一端を顕著に示している。
「DirectShow アプリケーション プログラミングの概要」で説明しているように、DirectShow アプリケーションが実行する基本的な手順は常に同じである。
- フィルタ グラフ マネージャのインスタンスを作成する。
- フィルタ グラフ マネージャを使ってフィルタ グラフを作成する。
- グラフを実行し、データをフィルタで処理する。
まず最初に、CoInitialize を呼び出して COM ライブラリを初期化する。
HRESULT hr = CoInitialize(NULL);
if (FAILED(hr))
{
// ここにエラー処理コードを追加する。 この例ではわかりやすくするために省略している。
}
説明を簡単にするために、この例では戻り値を無視しているが、通常はメソッドの呼び出しからの HRESULT 値をチェックする必要がある。
次に、CoCreateInstance を呼び出してフィルタ グラフ マネージャを作成する。
IGraphBuilder *pGraph;
HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL,
CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph);
ここに示されているように、クラス識別子 (CLSID) は CLSID_FilterGraph である。フィルタ グラフ マネージャはインプロセス DLL として提供されるので、実行コンテキストは CLSCTX_INPROC_SERVER である。DirectShow ではフリースレッド モデルをサポートしているので、COINIT_MULTITHREADED フラグを指定して CoInitializeEx を呼び出すこともできる。
CoCreateInstance を呼び出すと IGraphBuilder インターフェイスが返される。このインターフェイスにフィルタ グラフを作成するためのほとんどのメソッドが含まれている。この例では、これ以外に 2 つのインターフェイスが必要である。
- IMediaControl はストリーミングを制御する。このインターフェイスには、グラフを停止および開始するメソッドが含まれている。
- IMediaEvent には、フィルタ グラフ マネージャからイベントを取得するためのメソッドがある。この例では、このインターフェイスを使って、再生が完了するまで待機する。
これらのインターフェイスはいずれもフィルタ グラフ マネージャによって公開される。これらのインターフェイスを照会するには、返された IGraphBuilder ポインタを使う。
IMediaControl *pControl;
IMediaEvent *pEvent;
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
これで、フィルタ グラフを作成できる。ファイルの再生については、単一のメソッドの呼び出しで行われる。
hr = pGraph->RenderFile(L"C:\\Example.avi", NULL);
IGraphBuilder::RenderFile メソッドは、指定されたファイルを再生できるフィルタ グラフを作成する。最初のパラメータは、ワイド文字 (2 バイト) の文字列で表されたファイル名である。2 つ目のパラメータは予約済みで、NULL でなければならない。
このメソッドは、指定されたファイルが存在しない場合、またはファイル フォーマットが認識されない場合、失敗することがある。ここでは、メソッドが成功したと仮定して、フィルタ グラフで再生の準備ができたとする。グラフを実行するには、IMediaControl::Run メソッドを呼び出す。
hr = pControl->Run();
フィルタ グラフを実行すると、データはフィルタ内で処理され、ビデオおよびオーディオとしてレンダリングされる。再生は別のスレッドで続けられる。IMediaEvent::WaitForCompletion メソッドを呼び出して、再生が完了するまで待機できる。
long evCode = 0;
pEvent->WaitForCompletion(INFINITE, &evCode);
このメソッドは、ファイルの再生が終了するまで、または指定されたタイムアウト間隔が経過するまで、ブロック状態となる。値 INFINITE は、ファイルの再生が完了するまで、アプリケーションが無期限にブロック状態となることを意味する。より現実的なイベント処理の例については、「イベントへの応答」を参照すること。
アプリケーションが終了したら、インターフェイスのポインタを解放し、COM ライブラリを閉じる。
pControl->Release();
pEvent->Release();
pGraph->Release();
CoUninitialize();
サンプル コード
以下は、ここで説明した例のコード全体である。
#include <dshow.h>
void main(void)
{
IGraphBuilder *pGraph = NULL;
IMediaControl *pControl = NULL;
IMediaEvent *pEvent = NULL;
// COM ライブラリを初期化する。
HRESULT hr = CoInitialize(NULL);
if (FAILED(hr))
{
printf("ERROR - Could not initialize COM library");
return;
}
// フィルタ グラフ マネージャを作成し、インターフェイスを問い合わせる。
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void **)&pGraph);
if (FAILED(hr))
{
printf("ERROR - Could not create the Filter Graph Manager.");
return;
}
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
// グラフを作成する。 重要 : この文字列をシステム上のファイルに置き換える。
hr = pGraph->RenderFile(L"C:\\Example.avi", NULL);
if (SUCCEEDED(hr))
{
// グラフを実行する。
hr = pControl->Run();
if (SUCCEEDED(hr))
{
// 完了するまで待機する。
long evCode;
pEvent->WaitForCompletion(INFINITE, &evCode);
// 注 : 実際のアプリケーションでは INFINITE を使用しないこと。
// 無期限にブロックする場合がある。
}
}
pControl->Release();
pEvent->Release();
pGraph->Release();
CoUninitialize();
}
参照