DirectShowを用いたmpgファイルの再生が上手くいかないのですが
趣味でゲームを作っているものです。ゲームのオープニングムービーでmpgファイルを再生したいのですが上手くいきません。詳細は以下の通りです。よろしくお願いします。
ゲームはウインドウモードで作成
ゲームウインドウ内にmpgファイルを再生
DirectXのバージョン DirectX9.0b
ビデオボード GeForce7900GT (ドライバは最新のものを使用)
不具合点
mpgファイルの再生中にウインドウが再描画されたとき(他のウインドウに隠されて
た後、再びアクティブにしたり、最小化後最大化など)ムービーの一部あるいは全部
が黒い画面になってしまいます。再描画されなければ上手くいきます。
また、aviファイルであれば、問題なく動作します。
具体的コード
<初期処理部>
RECT rc;
long w,h;
//COMライブラリの初期化
CoInitialize(NULL);
//GraphBuilder オブジェクトの作成
if(FAILED(CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER,IID_IGraphBuilder,(void **)&pBuilder))){
MessageBox(NULL, "GraphBuilder オブジェクトの作成に失敗しました", NULL, MB_OK);
return E_FAIL;
}
//フィルタ・グラフの作成
if(FAILED(pBuilder->RenderFile(L"sample.mpg",NULL))){
MessageBox(NULL, "フィルタ・グラフの作成に失敗しました", NULL, MB_OK);
return E_FAIL;
}
// AVI描画用ウインドウを作成し...
if(FAILED(pBuilder->QueryInterface(IID_IVideoWindow,(void **)&pVideoWindow))){
MessageBox(0,"AVI描画用ウインドウの作成に失敗しました",NULL,MB_OK);
return E_FAIL;
}
// メインウインドウの子ウインドウに設定する
// ウインドウハンドルの設定
if(FAILED(pVideoWindow->put_Owner((OAHWND)hwnd))){
MessageBox(0,"AVI描画用ウインドウを子ウインドウにすることに失敗しました",NULL,MB_OK);
return E_FAIL;
}
// ウインドウスタイルの設定
if(FAILED(pVideoWindow->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS ))){
MessageBox(0,"AVI描画用ウインドウを子ウインドウにすることに失敗しました",NULL,MB_OK);
return E_FAIL;
}
// ウインドウサイズの設定(メインウインドウに合わせる)
GetClientRect(hwnd,&rc);
w=rc.right;
h=rc.bottom;
if(FAILED(pVideoWindow->SetWindowPosition(0,0,w,h))){
MessageBox(0,"ウインドサイズの変更に失敗しました",NULL,MB_OK);
return E_FAIL;
}
// メディアコントロールの取得
if(FAILED(pBuilder->QueryInterface(IID_IMediaControl,(void **)&pMediaControl))){
MessageBox(0,"メディアコントロールの取得に失敗しました",NULL,MB_OK);
return 0;
}
// メディアイベントの取得
if(FAILED(pBuilder->QueryInterface(IID_IMediaEvent,(void **)&pMediaEvent))){
MessageBox(0,"メディアイベントの取得に失敗しました",NULL,MB_OK);
return 0;
}
//ウインドウメッセージの受け取り準備
if(FAILED(pBuilder->QueryInterface(IID_IMediaEventEx,(void **)&pMediaEventEx))){
MessageBox(0,"メディアイベントの作成に失敗しました",NULL,MB_OK);
return E_FAIL;
}
if(FAILED(pMediaEventEx->SetNotifyWindow((OAHWND)hwnd,WM_GRAPHNOTIFY,0))){
MessageBox(0,"メッセージの設定に失敗しました",NULL,MB_OK);
return E_FAIL;
}
<コールバック関数にて>
long ecode,param1,param2; //DirectShow用
switch(iMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_KEYDOWN:
switch((CHAR)wParam)
{
case VK_ESCAPE:
PostQuitMessage(0);
return 0;
}
// DirectShow用
case WM_GRAPHNOTIFY:
while(SUCCEEDED(pMediaEventEx->GetEvent(&ecode,¶m1,¶m2,0))){
switch(ecode){
case EC_COMPLETE:
case EC_END_OF_SEGMENT:
case EC_WINDOW_DESTROYED:
if(FAILED(pMediaControl->Stop())){
MessageBox(0,"停止に失敗しました",NULL,MB_OK);
return 0;
}
GameStartFlag=true;
}
}
break;
}
return DefWindowProc (hWnd, iMsg, wParam, lParam) ;
お礼
実は私の勘違いで、例外が発生しているのは MessageBoxの方だったんです。それが何故かはわからないんですが… 一応その1行を消せば動くようにはなりました。 でもtry catchの方がいいみたいですね。 どうもありがとうございました。