Skip to main content.

Tuesday, June 05, 2007

DirectShow C#からの呼び出し

DirectShowでのC#からの呼び出しのサンプルプログラムです。DirectShowはCOMベースなので、VC++でアプリケーションを作成するのが妥当だとは思いますが、もちろんC#からも利用可能です。一般的なテーマとしては、.NETへのCOMの公開、.NETからのCOMの呼び出し方法ということになるかと思います。(※そのあたりの全般的なことは参考サイトあたりを参考にして下さい。)ここでは、こちらのページを見ながら、以下のようにC#で簡単なアプリケーションを作成してみました。

ランタイム呼び出し可能ラッパー ( RCW ) の作成
以下のようにコマンドプロンプトで、tlbimp.exeを使用して、QuartzTypeLib.dllを作成します。tlbimp.exeは(Visual Studioディレクトリ)¥SDK¥v2.0¥Bin 配下にあるかと思います。また、quartsz.dllは、WindowsディレクトリのSystem32ディレクトリにあるかと思います。
> tlbimp.exe C:¥WINDOWS¥system32¥quartz.dll

QuartzTypeLib.dllの参照設定
まずは、C#でアプリケーションのためのプロジェクトを作成します。今回作成したのはWindowsアプリケーションのプロジェクトです。そのプロジェクトに上で作成したQuartzTypeLib.dllを参照設定に追加します。

アプリケーションの作成
今回作成したアプリケーションは、DirectShow基礎(その2)動画ファイル再生とほぼ同じようなアプリケーションで、メニューから選択した動画ファイルを再生します。ファイルを選択して再生する部分のプログラムは以下のようになりました。VC++のソースと比較していただければ同じような処理だということがお分かり頂けるかと思います。(※ソース全体が必要な場合は、お手数ですが、プロジェクト全体をダウンロードして下さい。)
//
// メニューからファイルを選択して再生までの処理
//
private void openOToolStripMenuItem_Click(object sender, EventArgs e)
{
    //初期化処理
    CleanUp();

    //ファイルを選択
    OpenFileDialog openFileDialog = new OpenFileDialog();
    openFileDialog.Filter = "Media Files|*.avi;*.wma|All Files|*.*";

    //ファイルの再生
    if(DialogResult.OK == openFileDialog.ShowDialog())
    {
        //初期化
        CleanUp();

        try
        {
            //フィルタ グラフ マネージャを生成
            m_filterGraph = new FilgraphManager();

            //各インターフェースを取得
            m_BasicVideo = (IBasicVideo)m_filterGraph;
            m_MediaControl = (IMediaControl)m_filterGraph;
            m_MediaEventEx = (IMediaEventEx)m_filterGraph;
            m_VideoWindow = (IVideoWindow)m_filterGraph;
            m_MediaPosition = (IMediaPosition)m_filterGraph;

            //グラフを構築
            m_filterGraph.RenderFile(openFileDialog.FileName);

            //動画のサイズの取得
            int height = 0;
            int width = 0;

            m_BasicVideo.GetVideoSize(out width, out height);

            //VideoWindowをメインWindowにアタッチして、子ウィンドウに設定
            m_VideoWindow.Owner = (int)this.Handle;
            m_VideoWindow.WindowStyle = WS_CHILD | WS_CLIPSIBLINGS;

            //親Windowをビデオのサイズに設定(+8、+55+25は縦と横がうまく表示されるように適当に設定)
            SetDisplayRectLocation(width + 8, height + 55 + 25);

            //VideWindowを動画のサイズに設定 
            m_VideoWindow.SetWindowPosition(0, 25, width, height);

            //イベント通知を受け取るように所有者ウィンドウを設定
            m_MediaEventEx.SetNotifyWindow((int)this.Handle, WM_GRAPHNOTIFY, 0);

            //グラフを実行
            m_MediaControl.Run();
                
        }catch(Exception ex){
            //エラーメッセージ
            String msg = @"動画ファイル再生に失敗しました。 ";
            MessageBox.Show(msg+ex.Message,@ "エラー",MessageBoxButtons.OK,MessageBoxIcon.Exclamation);

            //初期化
            m_BasicVideo = null;
            m_MediaControl = null;
            m_MediaEventEx = null;
            m_VideoWindow = null;
            m_filterGraph = null;
        }
    }
}

C#(.NET)からDirectShowを呼び出してアプリケーションを作成する場合、気になるポイントとしてはやはりパフォーマンスでしょうか。パフォーマンスが要求されるアプリケーションではやはりVC++で全て作成した方が無難でしょうか。(※実際にC#で実務レベルのDirectShowのアプリケーションは今のところ開発したことはないので私からは何とも言えません。すいません。)逆にC#で開発するメリットは、GUIの開発の容易さ、豊富な.NETのクラスライブラリを利用出来るということでしょうか。

プロジェクトファイル一式(Visual C# 2005 Express Editionで作成)


参考リンク
[Win32SDK].NET プログラムで DirectShow を使用する
MSDN アンマネージコードとの相互運用
DirectShow MediaPlayer in C#

Windowsプログラミング関連記事