Date

フィルタグラフを構築する方法

フィルタグラフを構築するメソッドはいくつかある。 1. IGraphBuilder::RenderFileを使う。インテリジェント接続によりデフォルトのレンダラーフィルタが使われるため、構築する自由度は最も低い。 2. IGraphBuilder::Connectなどピン同士を接続するメソッドを使う。ピン同士を一つ一つ繋いでいくため自由度は高い。但しステップが多い。 3. ICaptureGraphBuilder2::RenderStreamを使う。カテゴリ、接続開始フィルタ(または出力ピン)、中間フィルタ、終端フィルタを指定して接続できる。自由度は1よりは高い。 このエントリでは1の方法を紹介する。

簡単な動画再生アプリケーションの作成

簡単な動画再生アプリケーションを作成してフィルタグラフの構築・制御を行う。することは以下の通り。

  1. COMを初期化する。
  2. フィルタグラフのインスタンスを作成する。
  3. フィルタグラフを制御するためのインターフェイス取得する。
  4. フィルタグラフを構築する。
  5. フィルタグラフを実行し、再生終了するまで待機する。
  6. 解放する。

下準備

プロジェクトを「コンソールアプリケーション」で新規作成する。名前は test1 とでもしておく。

stdafx.h に DirectShow アプリケーションを作るために必要なライブラリをリンクするように宣言する。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#pragma once
#define WIN32_LEAN_AND_MEAN
#define _WIN32_DCOM
#pragma comment(lib, "strmiids.lib")
#pragma comment(lib, "ole32.lib")
#include <tchar.h>
#include <windows.h>
#include <objbase.h>
#include <dshow.h>
#include <atlbase.h>

COMの初期化

_tmain関数にCOMの初期化・解放を行うコードを入力する。

1
2
3
4
5
6
int _tmain(int argc, _TCHAR* argv[]) {
    CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
    Play();
    CoUninitialize();
    return 0;
}

フィルタグラフのインスタンス作成、およびインターフェイスを取得

CoCreateInstanceでフィルタグラフのインスタンスを作成する。クラスIDはCLSID_FilterGraphで、インターフェイスはグラフビルダであるIGraphBuilderである。

IGraphBuilderIMediaControlインターフェイスを問い合わせる。これはグラフの開始・停止を制御する。さらに再生の終了を検出するために IMediaEventを取得する。

1
2
3
4
5
6
7
8
9
void Play() {
    CComPtr<IGraphBuilder> graph;
    CComPtr<IMediaControl> control;
    CComPtr<IMediaEvent> media_event;
    // フィルタグラフのインスタンス作成と、
    // 構築・制御のためのインターフェイスの取得
    graph.CoCreateInstance(CLSID_FilterGraph);
    graph.QueryInterface<IMediaControl>(&control);
    graph.QueryInterface<IMediaEvent>(&media_event);

フィルタグラフを作成する

IGraphBuilder::RenderFileメソッドでフィルタグラフを作成する。このメソッドはフィルタを一つ一つ作成し繋がなくても、インテリジェント接続を使ってデフォルトのレンダラーフィルタで再生を行うフィルタグラフを作成してくれる。

1
2
// フィルタグラフを構築する
graph->RenderFile(MovieFile, NULL);

フィルタグラフを実行する。 IMediaControl::Runを使う。再生は異なるスレッドで行われるため、すぐに処理が戻ってくる。そこでフィルタグラフのイベントを待つIMediaEvent::WaitForCompletionを呼び出し、実行完了まで待つ。

1
2
3
// 再生が完了するまで待機
long evCode;
media_event->WaitForCompletion(INFINITE, &evCode);

実行結果

ActiveMovie Windowが開いてムービーが再生される。音付きの場合は音も再生される。

![実行結果][/img/20081003-fig1.jpg]

再生が終わると自動的にウィンドウが閉じられてアプリケーションが終了する。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include "stdafx.h"
LPCWSTR MovieFile=
 L"C:\\Users\\Public\\Videos\\Sample Videos\\Bear.wmv";
 // (任意のファイル)
void Play() {
    CComPtr<IGraphBuilder> graph;
    CComPtr<IMediaControl> control;
    CComPtr<IMediaEvent> media_event;
    // フィルタグラフのインスタンス作成と、
    // 構築・制御のためのインターフェイスの取得
    graph.CoCreateInstance(CLSID_FilterGraph);
    graph.QueryInterface<IMediaControl>(&control);
    graph.QueryInterface<IMediaEvent>(&media_event);
    // フィルタグラフを構築する
    graph->RenderFile(MovieFile, NULL);
    // フィルタグラフを実行する
    control->Run();
    // 再生が完了するまで待機
    long evCode;
    media_event->WaitForCompletion(INFINITE, &evCode);
}
int _tmain(int argc, _TCHAR* argv[]) {
    CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
    Play();
    CoUninitialize();
    return 0;
}

https://github.com/mahorigahama/DShowPlay1


Comments

comments powered by Disqus