MPEGファイルを再生する
ここでは、DirectShowプログラミングの第一歩として、DirectShowを使ってMPEGを再生する最も単純な方法の説明をしたいと思います。 (注意)ここの例では、サンプルを簡潔にするためにエラー処理を書いていません。
とりあえず、コードを書いてみる
まず、何も考えずに以下のコードを書いてみましょう。 「C:\DXSDK\Samples\media\butterfly.mpg」というMPEGファイルを再生します。
#include <stdio.h>
#include <dshow.h>
#define FILENAME L"c:\\DXSDK\\Samples\\Media\\butterfly.mpg"
int
main()
{
IGraphBuilder *pGraphBuilder;
IMediaControl *pMediaControl;
// COMを初期化
CoInitialize(NULL);
// FilterGraphを生成
CoCreateInstance(CLSID_FilterGraph,
NULL,
CLSCTX_INPROC,
IID_IGraphBuilder,
(LPVOID *)&pGraphBuilder);
// MediaControlインターフェース取得
pGraphBuilder->QueryInterface(IID_IMediaControl,
(LPVOID *)&pMediaControl);
// Graphを生成
pMediaControl->RenderFile(FILENAME);
// 再生開始
pMediaControl->Run();
// 再生中にプログラムが終わってしまわないように
MessageBox(NULL,
"Block Execution",
"Block",
MB_OK);
// 資源を解放
pMediaControl->Release();
pGraphBuilder->Release();
// COM終了
CoUninitialize();
return 0;
}
このコードが行っている事は、GraphEditの説明で行ったMPEGファイル再生と全く同じ事を行います。
このサンプルコードでは、MessageBoxを使って処理を止めています。 サンプルコードを実行してみるとMessageBoxが出現して、OKボタンを押すとプログラムが終了します。 何故、このような事が起こるのでしょうか? 直感的にはRunは再生が終了するまでブロッキングしてくれるように思えるかもしれません。 何故、Runは一瞬で抜けて返って来てしまうのでしょうか?
IMediaControlのRunが一瞬で返って来てしまうのは映像の再生が別スレッドで行われているからです。 Directshowでは、IMediaControlのRunが行われると別スレッドを利用して再生のための処理を行っています。 映像再生プログラムを書いていると、任意のタイミングでStopやPauseなどを行いたくなります。 プログラマがそのような事を任意のタイミングで行ったりするには再生自体は別スレッドである方が有利です。 また、デコードや再生を出来るだけ集中して行い、音声や映像の跡切れを出来るだけ発生させないためにも別スレッドである方が良いのです。
以上の理由によりRunは一瞬で返ってきてしまうのですが、次は、「何故MessageBoxを使っているのか」を説明したいと思います。 上記サンプルコード中のRunは一瞬で返ってきてしまいます。 もしもMessageBoxが無ければ、そのままReleaseを行ってCoUninitializeを行い、main関数は終了してしまいます。 main関数が終了してしまうとプログラム全体が終わってしまうので結果として映像は全く再生されずに終了してしまうことになります。 これを防ぐためにMessageBoxで処理をとどめています。 MessageBoxをSleepなどと置き換えても似たような効果が得られます。 ただし、Sleepを利用した場合には一定時間が経つとmainが終了してしまいます。
MessageBoxによるブロッキング処理の意味を説明しましたが、MessageBoxを使って処理をとめる事は見栄えの面からもあまり現実的ではありません。 MessageBox以外の方法により再生時間を調整する方法は後述したいと思います。
ここでは「MPEGファイルを再生する」という説明にしていますが、RenderFileはMPEGに限定したものではありません。 例えば、FILENAMEでdefineしている部分をMPEGのファイルではなく、aviやwmvのファイルにしてもそのまま再生できます。 また、映像でなくmp3やwavやwmaなどのファイルもRenderFileで再生できてしまいます。 もし、よろしければ試してみてください。