DirectShowのリファレンスを読み解く!(第二部) | ゲームプログラマ志望が福岡で叫ぶ 『絶望』

ゲームプログラマ志望が福岡で叫ぶ 『絶望』

プログラマーになりたい!!!!! あ、風のうわさで聞いた最近若者で流行っているトゥイッターなるものを始めてみました (・ト・) @toshi_desu_yo

はい。

第二部のスタートです。



今回は
【ファイルの再生法】というところを読んでいくので

コンソールで簡単なビデオ再生までをやっていこうと思います。


ここ にかいてあるのは
 くっっっっっそ簡略化してるので、今の環境では実行までいけない。


色々保管しながらやっていこうと思います(`・ω・´)





*********************************
*********************************



まずは DirectShowDirectXから消えさってしまったので
別のライブラリを新たに入れなければなりません。

Vista 以前は Platform SDK に入っていましたが、
以降は .NET Framework SDK と統合し、 WIndows SDK という名前で爆誕しやがりました。



で、そのWindowsSDKをインストールし、
DirectXと同じように Include と Lib を参照してやれば問題なく実行できます。


ここから どうぞ ↓

【 ( URL ) Windows SDK 6.1



なんで 6.1 ?(´・ω・`)


最初 windows 8 SDK を入れてやってたのですが、8 では


graphedt .exe というDirectShow の フィルタをGUI的に繋げてその結果を
視覚的に確認できるツールが入ってなかったので 6.1 を入れてみました。




↓ こんなやつ




取り敢えず、コンソールで再生してみます。



VisualStdioのコンソールでプロジェクトを作成。

DirectX など基本的なライブラリはリンカ設定、インクルードして、


新しく Strmiids.lib をリンカに追加。
そして以下のインクルードも追加。

・objbase, show, Vmr9




適当にこんなかんじに。



#pragma comment( lib, "winmm.lib" ) 
#pragma comment( lib, "d3d9.lib" )
#pragma comment( lib, "d3dx9.lib" )
#pragma comment( lib, "Strmiids.lib" )


#include <tchar.h>
#include <stdio.h>
#include <d3d9.h>
#include <d3dx9.h>

#include <objbase.h>
#include <dshow.h>
#include <Vmr9.h>


int main( void )
{
    return 0;
}



まずは
DIrectShowはDirectXと違い、

 COM を使うために初期化をしなければいけないらしい。
それを行うのが


『 CoInitialize 関数 』 こいつを呼び出すだけでおk。
 
HRESULT hr; 

//** COMを使うときのお約束!

hr = CoInitialize( NULL );
if ( FAILED( hr ) )
{
// エラー・・・ 本当は処理コード入れてね
}




これでCOMを使う準備が完了しました。


次に、
フィルタグラフマネージャーを作成。

フィルタグラフマネージャーが持つ関数でフィルタ同士の接続や作成を行えます。



作成するためには、
『CoCreateInstance』 メソッドに引数で

「フィルタグラフマネージャー を作成してくれ」とします。




CoCreateInstance(
    REFCLSID rclsid, /** オブジェクト識別ID **/
    LPUNKNOWN pUnkOuter, /** 既存のCOMを利用する? **/
DWORD dwClsContext, /** オブジェクトがローカルか別の実行空間にあるのか **/
REFIID riid, /** インターフェイスの識別ID **/
LPVOID* ppv ); /** インターフェイスのポインタ **/



重要となるのは 作成するオブジェクトを指定するIDインターフェイスを識別するID です

インターフェイスIDを見て IGraphBuilder を見つけ、
オブジェクトID を見て フィルターグラフマネージャーのポインタを IGraphBuilder に入れます。




これで IGraphBuilder インターフェイス型にフィルタグラフマネージャーが入ってきます。




//** フィルタグラフマネージャーを作成する 
IGraphBuilder* pGraph;

hr = CoCreateInstance( CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, ( void** )&pGraph );
if ( FAILED( hr ) )
{
// エラー
}



フィルタグラフマネージャーはフィルタの接続を内部でしてくれる関数を
実装しているので

開発側は関数を呼び出すだけでフィルタ同士の接続を行なってくれる。



フィルタグラフを作成するクラスの生成は完了。

しかし、この他にも2つのオブジェクトが必要。



========================
・IMediaControl 
・IMediaEvent

========================


IMediaControl はその名の通りメディアの様々なコントロールをしてくれるもので、
完成したフィルタグラフの再生、停止、一時停止を行なってくれる。

IMediaEvent は「~が再生されました」や「停止しました」などの
フィルタグラフ内で発生するイベントを取得することが出来る。



今回はIMediaEventを使って再生が終わるまで待機します。

これらはフィルタグラフマネージャーの QueryInterface によって作成できます。
これも識別子を第一引数にいれて作成します。




//** IMediaControlとIMediaEventを作成する 
IMediaControl* pControl;
IMediaEvent* pEvent;

hr = pGraph->QueryInterface( IID_IMediaControl, ( void** )&pControl );
if ( FAILED( hr ) )
{
// エラー
}

hr = pGraph->QueryInterface( IID_IMediaEvent, ( void** )&pEvent );
if ( FAILED( hr ) )
{
// エラー
}



この2つの生成終わったらフィルタグラフの作成が可能になります。



今回は再生するだけです。


RenderFile関数

指定されたファイルを読み込み、再生をするフィルタグラフを作成します。

あらかじめ再生するファイルはプロジェクトの直下に置いておきましょ!



//** ファイルの読み出しと再生準備完了 
hr = pGraph->RenderFile( L"test.avi", NULL );
if ( FAILED( hr ) )
{

    // エラー
}



これで完了です。
後は IMediaControl Run関数を呼び出すだけで再生されます。


しかし、
Run しても再生は別のスレッドで行われるので
 プログラムは一瞬で終了します。





なので IMediaEvent
  WaitForCompletion 関数再生が終わるまで待機させます。



第一引数で待機時間を指定します。

ここで実際の再生時間よりも多く指定しても
ファイルの再生が終わると同時に待機が終了する便利なものになっています。


しかし、待機するので他の処理ができなくなります。
こんな時は IMediaEvent の GetState 関数を使います。 これはまた今度。。




//** 再生
hr = pControl->Run();

if ( SUCCEEDED( hr ) )
{
//** このまま再生したら一瞬で終わるので、待機状態にする
//** 今回は無限待機( 実際は INIFINITEを使わないこと。待機が無期限する恐れがある )
long evCode;
pEvent->WaitForCompletion( INFINITE, &evCode );
}




で、最後はいらないものを開放してCOMを閉じたら終了。


//** 解放 
pControl->Release();
pEvent->Release();
pGraph->Release();

// COMの終了
CoUninitialize();




簡単ですな!! 

後はフルスクリーンに対応すればゲームに組み込めるようになるのではないでしょうか?


しかし、DirectShowの利点のイベント取得やテクスチャに動画を貼り付けて再生する
という高度な技が出来ていないので

ココらへんが出来るように読み進めていこうと思います!(`・ω・´)




----------------------------------------------------------------------------------------

今回のプロジェクト  ( VisualStdio C++ 2012 ) とテキスト

【 ( URL)
DirectShow_コンソール

【 ( URL) ソースコード