• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:DirectShowを用いたmpgファイルの再生が上手くいかないのですが)

DirectShowを用いたmpgファイルの再生が上手くいかないのですが

このQ&Aのポイント
  • 趣味でゲームを作っているものです。ゲームのオープニングムービーでmpgファイルを再生したいのですが上手くいきません。
  • mpgファイルの再生中にウインドウが再描画されたとき(他のウインドウに隠されてた後、再びアクティブにしたり、最小化後最大化など)ムービーの一部あるいは全部が黒い画面になってしまいます。再描画されなければ上手くいきます。また、aviファイルであれば、問題なく動作します。
  • 使用しているライブラリはDirectX9.0bで、ビデオボードはGeForce7900GTです。ドライバは最新のものを使用しています。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.2

 すんません。フラグの照会でSW_RESTOREを無視していました。  此方へ修正した方が良いかもしれません。 //追加 //フラグ照会用のタグ typedef struct __flag_t { WORD fwSizeType;//WM_SIZE側のフラグ int iCmdType;//DirectShowに渡す int iOAFlag;//DirectShowに渡す } flag_t; //修正 //フラグの照会 static const flag_t _S_convert_flag(WORD fwSizeType) { const flag_t aflags[] = { {SIZE_MAXHIDE, SW_HIDE, OAFALSE}, {SIZE_MAXIMIZED, SW_MAXIMIZE, OATRUE}, {SIZE_MINIMIZED, SW_MINIMIZE, OATRUE}, {SIZE_RESTORED, SW_RESTORE, OATRUE}, {SIZE_MAXSHOW, SW_SHOW, OATRUE} }; for(int i = 0; i < 5; ++i) { if(aflags[i].fwSizeType == fwSizeType) return aflags[i]; } return aflags[0]; } プロシージャの中 +----------------------------------------------------------------------- case WM_SIZE://修正 { if(!pVideoWindow)break; //パラメータの分解 const WORD fwSizeType = wParam; const int nWidth = LOWORD(lParam); const int nHeight = HIWORD(lParam); const flag_t flag = ::_S_convert_flag(fwSizeType);//修正 //ビデオウィンドウのサイズ pVideoWindow->SetWindowPosition(0, 0, nWidth, nHeight); //ビデオウィンドウの表示ステートを外側のウィンドウの表示ステートと照会する pVideoWindow->put_WindowState(flag.iCmdType); //ビデオウィンドウを表示 pVideoWindow->put_Visible(flag.iOAFlag); break; } -----------------------------------------------------------------------+

cyacya2000
質問者

お礼

非常に丁寧なご回答ありがとうございます。 おかげさまで上手く行きそうです。 本当にありがとうございました。

その他の回答 (1)

回答No.1

 こんにちは。  確認出来ました。確かに表示がおかしくなります。  リサイズされた時の為に、WM_SIZEを処理して、pVideoWindow->put_Visible(OATRUE)を呼び出して対応すれば良いようです。  欠けた領域に関しては、DirectShowのビデオウィンドウにInvalidateRect()APIを使用して強引に解決出来るようです。  一通り出来ましたので、以下参考程度に。 #include<windows.h> #include<dshow.h> #pragma comment(lib, "strmbasd.lib") static IGraphBuilder* pBuilder; static IVideoWindow* pVideoWindow; static IMediaControl* pMediaControl; static IMediaEvent *pMediaEvent; static IMediaEventEx *pMediaEventEx; bool GameStartFlag = false; const UINT WM_GRAPHNOTIFY = 0x00008001; //関数プロトタイプ LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); //DirectShowの初期化 static HRESULT _S_init(HWND hwnd) { 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; } return 0; } //フラグの照会 static int _S_convert_flag(WORD fwSizeType) { switch(fwSizeType) { case SIZE_MAXHIDE : return SW_HIDE; case SIZE_MAXIMIZED : return SW_MAXIMIZE; case SIZE_MINIMIZED : return SW_MINIMIZE; case SIZE_RESTORED : case SIZE_MAXSHOW : return SW_SHOW; } return SW_SHOW; } //ウィンドウの作成 static HWND _S_create() { WNDCLASSEX w = {sizeof(w)}; const char* pszClass = "DirectShowTest"; w.lpfnWndProc = (WNDPROC)WndProc; w.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); w.lpszClassName = pszClass; RegisterClassEx(&w); HWND h = CreateWindow(pszClass,pszClass,WS_OVERLAPPEDWINDOW, 0,0,640,480,NULL,NULL,NULL,NULL); return h; } //見ての通り LRESULT CALLBACK WndProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { 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; } //此処を処理する case WM_SIZE: { if(!pVideoWindow)break; //パラメータの分解 const WORD fwSizeType = wParam; const int nWidth = LOWORD(lParam); const int nHeight = HIWORD(lParam); //ビデオウィンドウのサイズ pVideoWindow->SetWindowPosition(0, 0, nWidth, nHeight); //ビデオウィンドウの表示ステートを外側のウィンドウの表示ステートと照会する pVideoWindow->put_WindowState(::_S_convert_flag(fwSizeType)); //ビデオウィンドウを表示 pVideoWindow->put_Visible(OATRUE); break; } //再描画 case WM_PAINT : //DirectShowのビデオウィンドウを再描画させる ::InvalidateRect(::GetWindow(hWnd, GW_CHILD), NULL, TRUE); break; // DirectShow用 case WM_GRAPHNOTIFY: while(SUCCEEDED(pMediaEventEx->GetEvent(&ecode,&param1,&param2,0))) { //此れを呼ばないといけない pMediaEventEx->FreeEventParams(ecode, param1, param2); 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); } //見ての通り int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int) { MSG msg; //ウィンドウの作成 HWND hWnd = ::_S_create(); //DirectShowの初期化 ::_S_init(hWnd); //再生 pMediaControl->Run(); //ビデオを表示する pVideoWindow->put_Visible(OATRUE); //ウィンドウを表示する ::ShowWindow(hWnd, SW_SHOW); while(::GetMessage(&msg, NULL, 0, 0)) { ::TranslateMessage(&msg); ::DispatchMessage(&msg); } return msg.wParam; }

cyacya2000
質問者

お礼

ありがとうございました。 助かりました。

関連するQ&A