DirectShow基礎(その2)動画ファイル再生
ベースとなるプログラム(スケルトン)は単純なWin32アプリケーションです。Visual C++ 2005 Express EditionでWindowsアプリケーションのプロジェクトを生成してそのプログラムにDirectShowのプログラムを追加しました。(※開発環境については、こちらを参照して下さい。)全体としては単純な関数ベースのプログラムです。
プログラムでは、以下のDirectShowのインターフェースを利用して動画のWindowに関するプログラミングを行っています。
IVideoWindow:Windowのオーナ、位置等のVideoWindowのプロパティの設定
IBasicVideo:Videoプロパティの設定、今回は動画ファイルの画面サイズを取得するために利用
IMediaEventEx:イベント通知を取得するメソッド等を提供、今回は動画再生の終了を取得するために利用
(※詳細は、参考サイト等を参照して下さい。)
プログラムの流れとしては以下のようになります。
メニューから動画ファイル再生を実行
↓
PlayFile()関数呼び出し
(動画サイズの取得、VideoWindow生成、メインWindowに割り当て、イベント通知の設定)
↓
再生開始
↓
再生終了待ち
↓
再生終了
↓
イベント発生、CleanUp()関数呼び出し
(後処理、メモリ解放)
以上のDirectShowのプログラムの部分は以下になります。全体を参照する場合は、お手数ですが、ファイルをダウンロードして御覧下さい。エラー処理(※戻り値の判定等)は行っていませんので御注意、御了承下さい。
//
// 動画の再生
//
void PlayFile(void)
{
// フィルタ グラフ マネージャを生成
CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC,
IID_IGraphBuilder, (void **)&pGraph);
// 各インターフェースを取得
pGraph->QueryInterface(IID_IMediaControl, (void **)&pMediaControl);
pGraph->QueryInterface(IID_IVideoWindow, (void **)&pVidWin);
pGraph->QueryInterface(IID_IBasicVideo, (void **)&pBasicVideo);
pGraph->QueryInterface(IID_IMediaEventEx, (void **)&pEvent);
// グラフを構築
pGraph->RenderFile(L"c:\\Ruby.avi", NULL);
// 動画のサイズの取得
long height=0;
long width=0;
pBasicVideo->get_VideoHeight(&height);
pBasicVideo->get_VideoWidth(&width);
// VideoWindowをメインWindowにアタッチして、子ウィンドウに設定
pVidWin->put_Owner((OAHWND)g_hwnd);
pVidWin->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS);
// 親Windowの位置を取得
RECT lpRect;
GetWindowRect(g_hwnd,&lpRect);
// 親Windowをビデオのサイズに設定(+8、+55は縦と横がうまく表示されるように適当に設定)
SetWindowPos(g_hwnd,NULL,lpRect.left,lpRect.top,width+8,height+55,SWP_SHOWWINDOW);
// VideWindowを動画のサイズに設定
pVidWin->SetWindowPosition(0, 0, width, height);
// イベント通知を受け取るように所有者ウィンドウを設定
pEvent->SetNotifyWindow((OAHWND)g_hwnd, WM_GRAPHNOTIFY, 0);
// グラフを実行
pMediaControl->Run();
}
//
// 終了処理
//
void CleanUp(void)
{
//グラフを停止する。
pMediaControl->Stop();
//リソースの解放
pMediaControl->Release();
pBasicVideo->Release();
pVidWin->Release();
pEvent->Release();
pGraph->Release();
}
//
// イベントの処理
//
void HandleEvent()
{
long evCode, param1, param2;
HRESULT hr;
//イベントをキューから取得する
//ここでは、一応、while文でキューから全てのイベントを取得する
while (hr = pEvent->GetEvent(&evCode, ¶m1, ¶m2, 0), SUCCEEDED(hr)){
//イベントの引数に関連付けられたリソースを解放する
hr = pEvent->FreeEventParams(evCode, param1, param2);
//ストリーム終了または中断でCleanUp()の呼び出し
if((evCode == EC_COMPLETE) || (evCode == EC_USERABORT)){
CleanUp();
break;
}
}
}
ソースファイル
プロジェクトファイル一式(Visual C++ 2005 Express Editionで作成)
参考リンク
DirectShow(※Microsoft DirectX 9.0のドキュメント)
Windowsプログラミング関連記事
Posted by nishida at 14:00:38


