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 フィルタとフィルタ グラフ

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」 をチェックする必要はありません。

vbdemo

Quartz.dll のインターフェイス

関数名 機能
IAMCollection ピンとフィルタ群へのコントロール
IbasicAudio カレントのボリューム設定を取得・コントロール
IbascVideo 基本ビデオレンダラ
IfilterInfo フィルタ内のフィルタとピン オブジェクトの情報を取得
ImediaControl フィルタ グラフのインスタンス化とメディア フローのコントロール
ImediaEvent イベント ハンドリングのカスタマイズ、リピートやユーザーによる停止
ImediaPosion スタート・ストップ・レート等の取得とコントロール
ImediaTypeInfo メディアタイプとサブタイプの取得
IpinInfo Pin 情報へのアクセス
IregFilterInfo 登録されているフィルタについての情報を含む
IvideoWindow ビデオレンダラのウィンドウ アスペクト比をコントロール

VBDemo サンプル アプリケーション

ActiveMovie VB Sample

この 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 を使ったビデオ再生にトライしてみてください。