DirectShow for Visual Basic
Hiroyuki Kawanishi (川西 裕幸)
マイクロソフト株式会社
テクニカル エバンジェリスト
May 11, 2000
DirectShow はビデオなどのストリーミングデータを扱う API です。DirectShow を使うには DirectX Media SDK をインストールする必要があり、DirectX Media SDK は DirectX 7 SDK CD の DXMedia フォルダにあります。
ここでは AVI ファイルなどを読み込み、再生するシンプルなアプリケーションを紹介します。シンプルではありますが、サウンドボリュームの変更やカレントポジションの表示など結構細かなことも行っています。このサンプルはデフォルトで DXMedia\sanples\Multimedia\dshow\src\vb\vbdemo にインストールされます。
目次
- DirectShow フィルタとフィルタ グラフ
- DirectShow にアクセスするためのコントロール Quarts.dll
- VBDemo サンプル アプリケーション
DirectShow フィルタとフィルタ グラフ
DiretShow はフィルタと呼ばれるオブジェクトと、それらを接続するフィルタ グラフというアーキテクチャを持っています。ソースフィルタはデータを読み込み、データは CODEC フィルタを経て、レンダラに渡されます。レンダラはデバイスが認識できるフォーマットでデータをデバイスに渡すフィルタです。この時のデータ受け渡し口をピンと呼びます。このフィルタ グラフでは、AVI ソース フィルタがオーディオ データをオーディオ レンダラに渡し、オーディオ レンダラがそのオーディオ データを再生します。ビデオ データについては AVI CODEC で伸張し、ビデオ レンダラが描画します。フィルタグラフ マネージャはこのフィルタグラフを管理し、その目的に合わせてフィルタグラフを構築します。
DirectShow にアクセスするためのコントロール Quarts.dll
DirectShow にアクセスするためのコントロールが用意されています、それが Quarts.dll です。これを使う際には Visual Basic の [プロジェクト] → [参照設定…] で 「ActiveMovie control type library」 をチェックしてください。DirectX 7 で DirectShow を使う場合は、「DirectX 7 for Visual Basic Type Library」 をチェックする必要はありません。
Quartz.dll のインターフェイス
関数名 | 機能 |
---|---|
IAMCollection | ピンとフィルタ群へのコントロール |
IbasicAudio | カレントのボリューム設定を取得・コントロール |
IbascVideo | 基本ビデオレンダラ |
IfilterInfo | フィルタ内のフィルタとピン オブジェクトの情報を取得 |
ImediaControl | フィルタ グラフのインスタンス化とメディア フローのコントロール |
ImediaEvent | イベント ハンドリングのカスタマイズ、リピートやユーザーによる停止 |
ImediaPosion | スタート・ストップ・レート等の取得とコントロール |
ImediaTypeInfo | メディアタイプとサブタイプの取得 |
IpinInfo | Pin 情報へのアクセス |
IregFilterInfo | 登録されているフィルタについての情報を含む |
IvideoWindow | ビデオレンダラのウィンドウ アスペクト比をコントロール |
VBDemo サンプル アプリケーション
この DirectShow のサンプル VBDemo は、File で avi ファイル等を読み込み、下の白いフレーム内に表示するビデオプレーヤーです。
ステップ バイ ステップでアプリケーション コードを説明していきます。
- DirectShow オブジェクトの準備
- フィルタグラフのインスタンス化
- ビデオのレンダリング
- オーディオ コントロール
- ビデオ出力のスケール
- スケールモード
- ステータスのトラッキング
- クリーンアップ
DirectShow オブジェクトの準備
このアプリケーションではビデオとオーディオの再生と、再生ポジションデータの表示やポーズ、ストップなどの制御を行うので、まずこれらをハンドリングするための 5 つのオブジェクトを準備します。
' ビデオウィンドウ オブジェクト
Dim g_objVideoWindow As IVideoWindow
' メディアコントロール オブジェクト
Dim g_objMediaControl As IMediaControl
' メディアポジション オブジェクト
Dim g_objMediaPosition As IMediaPosition
' 基本オーディオ オブジェクト
Dim g_objBasicAudio As IBasicAudio
' 基本ビデオ オブジェクト
Dim g_objBasicVideo As IBasicVideo
フィルタグラフのインスタンス化
フィルタグラフ マネージャは .avi、.mov、.mpg を再生できますが、フィルタグラフをインスタンス化する際にそのフォーマットを明示する必要があります。フィルタグラフ マネージャはそれぞれのフォーマットに依存した CODEC フィルタを用意するからです。
'要求されたファイル フォーマットにしたがってフィルタグラフをインスタンス化
Set g_objMediaControl = New FilgraphManager
g_objMediaControl.RenderFile (g_strFileName)
ビデオのレンダリング
IMediaControl インターフェイスは Run、Pause、Stop の 3 つのメソッドを用意しています、フィルタグラフをインスタンス化すると、これらのメソッドを使って再生のコントロールができます。フォーマットさえ決まってしまえば、非常にシンプルに Run メソッドをコールするだけで再生が始まります。
If Button.Index = 1 Then ' プレイ
' MediaControl の Run メソッドを使って事前に定義してある
'フィルタグラフを通してビデオをプレイ
' 指定されたスタート位置を使用
If g_objMediaPosition.CurrentPosition < g_dblStartPosition Then
g_objMediaPosition.CurrentPosition = g_dblStartPosition
End If
g_objMediaControl.Run
g_fVideoRun = True
ElseIf Button.Index = 3 Then ' ポーズ
' MediaControl の Pause メソッドを使って事前に
' 定義してあるフィルタグラフを通してビデオをポーズ
g_objMediaControl.Pause
g_fVideoRun = False
ElseIf Button.Index = 5 Then ' ストップ
' MediaControl の Stop メソッドを使って事前に
' 定義してあるフィルタグラフを通してビデオをストップ
g_objMediaControl.Stop
g_fVideoRun = False
' ビデオの開始位置をリセット
g_objMediaPosition.CurrentPosition = 0
txtElapsed.Text = "0.0"
End If
オーディオのコントロール
ビデオだけではなく音も流さなければなりません、IBasicControl インターフェイスは Volume と Balance のプロパティをサポートします。このアプリケーションではスライダ コントロール slVolume からボリュームをコントロールします。
Private Sub slVolume_Change()
' スライダの値をボリュームにセット
If Not g_objMediaControl Is Nothing Then
On Error Resume Next ' オーディオのない場合g_objBasicAudio.Volume = slVolume.Value
End If
End Sub
ビデオ出力のスケール
もしデフォルトウィンドウにビデオを流すだけなら、IVideoWindow インターフェイスがサポートするメソッドやプロパティは使う必要はありません。このインターフェイスを使うと対象ウィンドウに合わせて、サイズやパレット、見え方などを操作することができます。このサンプルではターゲットであるshape1 オブジェクトの左上にビデオ出力をあわせ、Shape1 の高さと幅をビデオのサイズに合わせています。Top や Left のプロパティをセットするためには、ビデオ オブジェクトのオーナーを フォームの hWnd に設定する必要があります。
' IVideoWindow オブジェクトをセットアップ
Set g_objVideoWindow = g_objMediaControl
' キャプション、ボーダー、ダイアログフレーム、
' スクロールバーをデフォルトウィンドウから削除
g_objVideoWindow.WindowStyle = CLng(&H6000000)
' ウィンドウを配置
g_objVideoWindow.Left = CLng(Shape1.Left)
g_objVideoWindow.Top = CLng(Shape1.Top)
Shape1.Width = g_objVideoWindow.Width
Shape1.Height = g_objVideoWindow.Height
' アプリケーションのフォームをペアレントに設定
g_objVideoWindow.Owner = frmMain.hWnd
スケールモード
スケール モードを Visual Basic のデフォルトである Twips からピクセルに変更します。これは非常に重要です、これをしないと前述のサイズ変更などはとんでもない結果になります。
Private Sub Form_Load()
' スケールモードを twips からピクセルに変更
frmMain.ScaleMode = 3 ' ピクセル
End Sub
ここまでで、基本的な再生のための手順は終わりです、残りはカレント ポジション等を取得し表示することです。
ステータスのトラッキング
IMediaPositionObject を使うと、カレント ポジションや、停止ポジション、時間幅、再生レート等の情報を取得あるいは設定できます。このサンプルではファイルを選択すると、時間幅、スタートポジション、再生レートが右上に表示されます。プレイが開始されると、カレント ポジションが更新されていきます。
まずファイルオープン時の初期状態です、Duration プロパティでそのメディアの時間幅を取得し、表示します。
' トータル時間幅とカレント タイムを表示するために
' IMediaPosition オブジェクトをセットアップ
Set g_objMediaPosition = g_objMediaControl
g_dblRunLength = g_objMediaPosition.Duration
txtDuration.Text = CStr(g_dblRunLength)
' スタート位置をゼロにリセット
g_dblStartPosition = 0.0
txtStart.Text = CDbl(g_dblStartPosition)
' ユーザーが指定した再生レートを使用
g_dblRate = g_objMediaPosition.Rate
'タイマーでトラッキングし、CurrentPosition
' メソッドを使用して、カレントポジションを更新します。
Private Sub Timer1_Timer()
' カレント タイムを取得してテキストボックスに表示
Dim Dbl As Double
If g_fVideoRun = True Then
Dbl = g_objMediaPosition.CurrentPosition
If Dbl < g_dblRunLength Then
txtElapsed.Text = CStr(Dbl)
Else
txtElapsed.Text = CStr(g_dblRunLength)
End If
End If
End Sub
クリーンアップ
最後は取得したオブジェクトのクリアです、オーナーも忘れず NULL にセットします。
Private Sub cleanup()
' メモリーのクリーンアップ
g_fVideoRun = False
DoEvents
If Not g_objMediaControl Is Nothing Then
g_objMediaControl.Stop
Debug.Print "Setting owner to NULL" + Chr(13)
On Error Resume Next
g_objVideoWindow.Owner = 0 ' オーナーを NULL にセット
End If
Set g_objVideoWindow = Nothing
Set g_objMediaControl = Nothing
Set g_objMediaPosition = Nothing
Set g_objBasicAudio = Nothing
Set g_objBasicVideo = Nothing
End Sub
まとめ
DirectShow を使ったビデオのハンドリングは非常にシンプルです、にもかかわらず DirectShow のインターフェイスが持つメソッドやプロパティを使えば、かなり細かにコントロールすることができます。このサンプルをベースに Visual Basic を使ったビデオ再生にトライしてみてください。