ホーム < ゲームつくろー! < DirectX技術編 < 音声付き動画をフルスクリーンで再生する


その5 音声付き動画をフルスクリーンで再生する:サンプルプログラム

  DirectX技術編「音声付き動画をフルスクリーンで再生する」で説明した内容を踏まえたサンプルプログラムです。実行するとフルスクリーンモードになり、指定した動画が再生されます。動画ファイルの指定はプログラム上でグローバル変数として与えたWCHAR wFileName[] = L"OP.AVI"を変える事で行えます(パスの指定をお忘れなく)。AVIでもMPEGでも、お使いのWindowsのMedia Playerが再生できる動画であれば大抵このプログラムでも再生できます!(オーディオのみは不可です)。


画面は「おてもとプロダクション」作成のノベルスゲーム「ふゆのき」のオープニングムービー(作者は私と友人です)

 再生中にEscapeキーを押すとキャンセルされてアプリケーションが終了します。


 以下のプログラムは空のプロジェクトにコピペすることで完全に動きます。上からデバッグしていくと、何をしているか良くわかるように1つのソースで完結させています。とは言うもののフルスクリーンなのでデバッグは難しいですけど(^-^;。Direct3Dの初期化の部分をウィンドウモードに直すとデバッグしていけます。今回のポイントになりそうなところは太文字で示されています。

 「d3dx9_26.dllがありません」という類のリンカエラーが発生した場合、必要なコンポーネントが完全にインストールされていません。マイクロソフトのホームページからdxwebsetup.exeをダウンロードして実行すると、必要なコンポーネントを自動ダウンロードしてくれます。

(もしうまく動かないようでしたら掲示板にてご連絡下さい)

// フルスクリーン動画再生サンプルプログラム

#pragma comment(lib, "dxguid.lib")
#pragma comment(lib, "d3d9.lib")

#pragma comment(lib, "Strmiids.lib")

#define _WIN32_DCOM     // CoInitializeEx関数の呼び出しに必要

#include <windows.h>
#include <objbase.h>
#include <tchar.h>
#include <d3d9.h>
#include <dshow.h>
#include <Vmr9.h>

TCHAR gName[100] = _T("フルスクリーン動画再生サンプルプログラム");
WCHAR wFileName[] = L"OP.AVI";  // 描画する動画ファイル


// ウィンドウプロシージャ
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){
   if(msg == WM_DESTROY) {PostQuitMessage(0); return 0;}
   if(msg == WM_CHAR) if(wParam == VK_ESCAPE){ PostQuitMessage(0); return 0; }
   return DefWindowProc(hWnd, msg, wParam, lParam);
}


int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
   // アプリケーションの初期化
   MSG msg; HWND hWnd;
   WNDCLASSEX wcex ={sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW, WndProc, 0, 0, hInstance, NULL, NULL,
                                    (HBRUSH)(COLOR_WINDOW+1), NULL, (TCHAR*)gName, NULL};
   if(!RegisterClassEx(&wcex))
      return 0;

   // フルスクリーン用にポップアップウィンドウを作成
   if(!(hWnd = CreateWindow(gName, gName, WS_POPUPWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
                                    NULL, NULL, hInstance, NULL)))
      return 0;

   // Direct3Dの初期化
   LPDIRECT3D9 g_pD3D;
   LPDIRECT3DDEVICE9 g_pD3DDev;
   if( !(g_pD3D = Direct3DCreate9( D3D_SDK_VERSION )) ) return 0;

   // フルスクリーン用に初期化パラメータを設定
   D3DPRESENT_PARAMETERS d3dpp = {640,480,D3DFMT_A8R8G8B8,0,D3DMULTISAMPLE_NONE,0,
                                                      D3DSWAPEFFECT_DISCARD,hWnd,FALSE,0,D3DFMT_UNKNOWN,D3DPRESENT_RATE_DEFAULT,0}; 

   if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &g_pD3DDev ) ) )
   if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pD3DDev ) ) )
   {
      g_pD3D->Release();
      return 0;
   }

        HRESULT hr;

        // COMの初期化
        hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 
        if(FAILED(hr)) {g_pD3DDev->Release(); g_pD3D->Release(); return 0;}

        // フィルタグラフマネージャの作成
        IGraphBuilder *pGB = NULL;
        hr = CoCreateInstance( CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&pGB);
        if(FAILED(hr)) {g_pD3DDev->Release(); g_pD3D->Release(); CoUninitialize(); return 0;}

        // VRM9フィルタの作成と登録
        IBaseFilter *pVMR9 = NULL;
        hr = CoCreateInstance( CLSID_VideoMixingRenderer9, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pVMR9);
        if(FAILED(hr)) {g_pD3DDev->Release(); g_pD3D->Release(); pGB->Release(); CoUninitialize(); return 0;}
        pGB->AddFilter( pVMR9, L"VMR9" );       // フィルタグラフに登録

        // VRM9をウィンドウレスモードにする
        IVMRFilterConfig *pVMRCfg = NULL;
        hr = pVMR9->QueryInterface( IID_IVMRFilterConfig9, (void**)&pVMRCfg );
        if(FAILED(hr)) {g_pD3DDev->Release(); g_pD3D->Release(); pGB->Release(); CoUninitialize(); return 0;}
        pVMRCfg->SetRenderingMode( VMRMode_Windowless );
        pVMRCfg->Release();     // IVMRFilterConfigはもう必要ない

        // 描画ウィンドウの指定
        IVMRWindowlessControl9 *pVMRWndCont = NULL;
        hr = pVMR9->QueryInterface( IID_IVMRWindowlessControl9, (void**)&pVMRWndCont );
        if(FAILED(hr)) {g_pD3DDev->Release(); g_pD3D->Release(); pGB->Release(); CoUninitialize(); return 0;}
        hr = pVMRWndCont->SetVideoClippingWindow( hWnd );

        // ソースフィルタの生成と登録
        IBaseFilter *pSource = NULL;
        pGB->AddSourceFilter(wFileName, wFileName, &pSource); 

        // CaptureGraphBuilder2インターフェイスの取得
        ICaptureGraphBuilder2 *pCGB2 = NULL;
        hr = CoCreateInstance( CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void**)&pCGB2);
        if(FAILED(hr)) {g_pD3DDev->Release(); g_pD3D->Release(); pGB->Release(); CoUninitialize(); return 0;}
        pCGB2->SetFiltergraph( pGB ); 

        // フィルタの接続
        hr = pCGB2->RenderStream(0, 0, pSource, 0, pVMR9);
        if(FAILED(hr)) {g_pD3DDev->Release(); g_pD3D->Release(); pCGB2->Release(); pGB->Release(); CoUninitialize(); return 0;}
        hr = pCGB2->RenderStream(0, &MEDIATYPE_Audio, pSource, 0, 0);

        // 描画領域の設定(接続後でないとエラーになる)
        LONG W,H;
        RECT SrcR, DestR;
        hr = pVMRWndCont->GetNativeVideoSize(&W, &H, NULL, NULL);
        SetRect(&SrcR, 0, 0, W, H);
        GetClientRect(hWnd, &DestR);
        hr = pVMRWndCont->SetVideoPosition(&SrcR, &DestR);
        pVMRWndCont->Release();         // ウィンドウレスコントロールはもう必要ない

        // メディアコントロールインターフェイスの取得
        IMediaControl *pMediaCont = NULL;
        hr = pGB->QueryInterface( IID_IMediaControl, (void**)&pMediaCont );
        if(FAILED(hr)) {g_pD3DDev->Release(); g_pD3D->Release(); pCGB2->Release(); pGB->Release(); CoUninitialize(); return 0;}

        ShowWindow(hWnd, nCmdShow);

        // 動画再生
        pMediaCont->Run();

   // メッセージ ループ
        do{
                Sleep(1);
                if( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) ){
                        TranslateMessage(&msg);
                        DispatchMessage(&msg);
                }
        }while(msg.message != WM_QUIT);

        // 動画停止
        pMediaCont->Stop();
        Sleep(1000);    // 1秒くらい待ってみる(念のため)

        pMediaCont->Release();
        pVMR9->Release();
        pCGB2->Release();
        pGB->Release();
        CoUninitialize();

        g_pD3DDev->Release();
        g_pD3D->Release();

   return 0;
}