Microsoft DirectX 8.0

Visual Basic を使用したフィルタ グラフの制御方法

ここでは、Microsoft® DirectShow® のダイナミック リンク ライブラリである Quartz.dll によって公開されているメソッド、イベント、およびプロパティを使用して、Microsoft® Visual Basic® ベースのアプリケーションでタイム スタンプ付きのビデオ データのストリームをレンダリングする方法を説明する。この内容は、Microsoft® Windows® ベースのアプリケーション プログラミング、Windows ベースのマルチメディア プログラミング、および Visual Basic プログラミング システム バージョン 5.x の Automation 機能について既に理解している開発者が対象である。

ここでは次の内容について説明する。

DirectShow のフィルタとフィルタ グラフ

アプリケーションで Quartz.dll を使用してマルチメディアを表示するには、フィルタと呼ばれるオブジェクトのコレクションを使用する。このコレクションはフィルタ グラフとも呼ばれる。次の図は、AVI (Audio-Video Interleaved) ファイルをレンダリングするフィルタ グラフを示している。

AVI フィルタ グラフ

この図では、AVI ソース フィルタがディスクからファイルを読み取る。AVI デコンプレッサ フィルタ (CODEC) は、ソース フィルタから渡されたビデオ データを圧縮解除する。次に、CODEC フィルタはこのデータをビデオ レンダラに渡す。その次に、ビデオ レンダラはデバイスが認識できるフォーマットのデータをデバイスに渡す。AVI ソース フィルタはオーディオ レンダラに直接オーディオ データを渡し、オーディオ レンダラはオーディオ デバイスにデータを渡す。

DirectShow は、フィルタのほかにも、フィルタ グラフ マネージャと呼ばれる Automation オブジェクトをサポートしている。このオブジェクトは、利用可能なフィルタについて知っている。また、どのファイル フォーマットをレンダリングするためにどのフィルタ タイプが必要かを認識している。フィルタ グラフ マネージャは、特定のグラフ内のフィルタがサポートしているメソッド、イベント、およびプロパティを公開する。さらに、独自のメソッド、イベント、およびプロパティのセットを、インターフェイスを使用して公開する。インターフェイスは、関連したメソッド、イベント、およびプロパティのコレクションである。

次の表では、Visual Basic ベースのアプリケーションで使用する、Quartz.dll に提供されている DirectShow のインターフェイスを示し、各インターフェイスの目的を説明する。
インターフェイス説明
IAMCollection ピン コレクションおよびフィルタ コレクションにアクセスする。
IBasicAudio 現在のボリューム設定を制御し、取得する。
IBasicVideo 汎用ビデオ レンダラを制御する。
IFilterInfo フィルタに関する情報、およびフィルタ内のピン オブジェクトに関する情報を取得する。
IMediaControl フィルタ グラフをインスタンス化し、メディア フロー (実行、ポーズ、停止) を制御する。
IMediaEvent 再ペイント、ユーザー終了、完了などのイベントに対するカスタマイズしたイベント処理を可能にする。
IMediaPosition 開始タイム、終了タイム、レート、および現在位置を制御し、取得する。
IMediaTypeInfo メディア タイプとサブタイプを取得する。
IPinInfo ピンの方向やメディア タイプなどのピン情報にアクセスし、ピンの接続、切断、およびレンダリングを制御する。
IRegFilterInfo 登録済みの (変換およびレンダリング) フィルタに関する情報を含む。
IVideoWindow ビデオ レンダラのウィンドウ アスペクトを制御する。

DirectShow インターフェイスにアクセスするために Quartz.dll を登録する方法

Microsoft Visual Basic ベースのアプリケーションで DirectShow のインターフェイスを使用するには、Visual Basic プロジェクトで Microsoft® ActiveMovie® コントロール タイプ ライブラリを登録する必要がある。そのためには、[プロジェクト] メニューの [参照設定] をクリックし、次に [ActiveMovie control type library] の左のチェック ボックスをオンにする。

Visual Basic の [参照設定] ダイアログ ボックスを使用して ActiveMovie コントロール タイプ ライブラリを登録することによって、Visual Basic に必要な Automation 情報を含むタイプ ライブラリを特定する。次の図に [参照設定] ダイアログ ボックスを示す。

Visual Basic の [参照設定] ダイアログ ボックス

タイプ ライブラリを登録した後、[オブジェクト ブラウザ] ダイアログ ボックスを使用して、特定のインターフェイスに関連したメソッド、イベント、およびプロパティの一覧を表示できる。[表示] メニューの [オブジェクト ブラウザ] をクリックし、次に、[オブジェクト ブラウザ] ダイアログ ボックスの左上にあるライブラリのドロップダウン リストから [QuartzTypeLib] を選択する。

注 :  QuartzTypeLib 内のタイプ情報は、オブジェクト別ではなくインターフェイス別に編成されている。

Visual Basic でのフィルタ グラフの制御

ここでは次の内容について説明する。

ファイルのインストール

Visual Basic ベースのアプリケーションで DirectShow オブジェクトを使用するには、Windows\System ディレクトリに Quartz.dll をインストールし、システムのレジストリ データベースに適切な項目が作成されたことを確認する必要がある。現在、このプロセスは Microsoft® DirectX® Software Development Kit (SDK) セットアップ プログラムによって自動化されている。インストールするには、Setup.exe を起動し、Runtime オプションを選択する。ダイナミック リンク ライブラリ (DLL) が正しい場所にコピーされ、レジストリが自動的に更新される。

Visual Basic への Quartz.dll の登録

ファイルが正しくインストールされたことを確認するには、Visual Basic アプリケーションを開き、[表示] メニューの [参照設定] コマンドをクリックする。起動時に Visual Basic によってレジストリ データベースの登録済み Automation コントロールが確認され、このダイアログ ボックスに表示される一覧にコントロールの名前が追加される。フィルタ グラフ マネージャを使用するには、[ActiveMovie control type library] をクリックする。

Visual Basic にタイプ情報が登録されると、アプリケーションでフィルタ グラフ マネージャおよび関連するインターフェイスを使用できる。

DirectShow のオブジェクトを使用するための準備

Visual Basic は、FilgraphManager オブジェクトを使用してすべてのオブジェクトを初期化する。FilgraphManager オブジェクトは次のインターフェイスを実装する。

各インターフェイスには、そのインターフェイス タイプとして定義した Visual Basic のプログラム可能なオブジェクトからアクセスする。オブジェクトは、次の例に示すように、汎用宣言セクションでグローバル変数として定義できる。

Dim g_objVideoWindow As IVideoWindow            ' VideoWindow オブジェクト
Dim g_objMediaControl As IMediaControl          ' MediaControl オブジェクト
Dim g_objMediaPosition As IMediaPosition        ' MediaPosition オブジェクト
Dim g_objBasicAudio  As IBasicAudio             ' Basic Audio オブジェクト
Dim g_objBasicVideo As IBasicVideo              ' Basic Video オブジェクト

次の例に示すように、FilgraphManager を使用してすべてのプログラム可能なオブジェクトを初期化する。

Set g_objMediaControl = New FilgraphManager
g_objMediaControl.RenderFile (g_strFileName)    ' 入力ファイルの名前
...
Set g_objBasicAudio = g_objMediaControl
Set g_objVideoWindow = g_objMediaControl
Set g_objMediaEvent = g_objMediaControl
Set g_objMediaPosition = g_objMediaControl

目的のインターフェイスを明示的に返すメソッドを呼び出すことによって、ほかのインターフェイスを取得する。次の表は、これらのインターフェイスの取得方法を示している。
インターフェイスインターフェイス ポインタを返すメソッド
IAMCollection IPinInfo.MediaTypesIFilterInfo.PinsIMediaControl.FilterCollectionIMediaControl.RegFilterCollection
IFilterInfo 最初に IMediaControl.FilterCollection、次に IAMCollection.Item または IPinInfo.FilterInfo
IMediaTypeInfo IPinInfo.ConnectionMediaType
IPinInfo IFilterInfo.FindPinIAMCollection.Item
IRegFilterInfo 最初に IMediaControl.RegFilterCollection、次に IAMCollection.Item

これらのフィルタ インターフェイスおよびピン インターフェイスの操作方法を示す例については、「Visual Basic を使用したフィルタ グラフの作成」を参照すること。

フィルタ グラフのインスタンス化

フィルタ グラフ マネージャを使用して、次のタイプの既存ファイルをレンダリングできる。

さらに、フィルタ グラフ マネージャを使用して既存のフィルタ グラフをレンダリングできる。そのためには、そのグラフを含むファイルを RenderFile メソッドのパラメータとして指定する。

フィルタ グラフ内のフィルタはレンダリングするファイルのタイプに依存するため、ユーザーがファイルを選択してからフィルタ グラフをインスタンス化すること。フィルタ グラフ マネージャは、Visual Basic のキーワード New を使用して AUTOMATION オブジェクトを作成するときにインスタンス化される。フィルタ グラフ オブジェクトは、次の例に示すように、IMediaControl::RenderFile メソッドを呼び出したときに作成される。

    '要求されたファイル フォーマットのフィルタ グラフを
    'インスタンス化する
    
    Set g_objMediaControl = New FileGraphManager
    g_objMediaControl.RenderFile (g_strFileName)

ビデオのレンダリング

IMediaControl インターフェイスは 3 つのメソッドをサポートしている (RunPause、および Stop)。アプリケーションでは、これらのメソッドを呼び出してビデオ ストリームをレンダリング、ポーズ、または停止することができる。フィルタ グラフ オブジェクトがインスタンス化された後、アプリケーションでこれらのメソッドを呼び出すことができる。

次のコード例は、ユーザーがボタンをクリックしたとき、それに応答して RunPause、および Stop メソッドを起動する。

Private Sub Toolbar1_ButtonClick(ByVal Button As Button)
' ツール バーのボタンを処理する

    ' オブジェクトが定義されていない場合はエラーを回避する
    If g_objMediaControl Is Nothing Then
Exit Sub
End If 
    
    If Button.Index = 1 Then 'PLAY
        'MediaControl Run() メソッドを呼び出して
        'ビデオを再生する (あらかじめ定義された
        'フィルタ グラフを使用)
    
        g_objMediaControl.Run
        g_fVideoRun = True
            
    ElseIf Button.Index = 2 Then 'PAUSE
        'MediaControl Pause() メソッドを呼び出して
        '表示中のビデオをポーズする (ビデオの表示には
        'あらかじめ定義されたフィルタ グラフを使用)
    
        g_objMediaControl.Pause
        g_fVideoRun = False
    
    ElseIf Button.Index = 3 Then 'STOP
    
        'MediaControl Stop() メソッドを呼び出して
        '表示中のビデオを停止する (ビデオの表示には
        'あらかじめ定義されたフィルタ グラフを使用)
    
        g_objMediaControl.Stop
        g_fVideoRun = False
        ' ビデオの先頭にリセットする
        g_objMediaPosition.CurrentPosition = 0
        txtElapsed.Text = "0.0"

オーディオの制御

IBasicAudio インターフェイスは、Volume プロパティと Balance プロパティという 2 つのプロパティをサポートしている。Volume プロパティはボリュームを取得または設定する。サンプル アプリケーションでは、このプロパティはスライダ コントロール slVolume にバインドされている。Balance プロパティはステレオのバランスを取得または設定する。サンプル アプリケーションでは、このプロパティはスライダ コントロール slBalance にバインドされている。

注 :  ボリュームはリニア ボリューム スケールであるため、有用なのはスライダの右端だけである。

次の例では、g_objBasicAudio.Volume プロパティを設定してボリュームを調整している。

Private Sub slVolume_Change()
'スライダのボリュームを設定する

    If Not g_objMediaControl Is Nothing Then
    'g_objMediaControl が割り当てられている場合

       g_objBasicAudio.Volume = slVolume.Value

End If 
    
End Sub

ビデオ出力のスケーリングと移動

IVideoWindow インターフェイスは、転送先ウィンドウのサイズ、状態、所有者、パレット、可視性などを変更するメソッドとプロパティをサポートしている。転送先ウィンドウの位置または外観を考慮する必要がない場合は、これらのメソッドとプロパティを呼び出さず、デフォルトのウィンドウ (デスクトップの左上に表示される) に出力をレンダリングすることができる。

キャプション、境界、およびダイアログ ボックスの枠を移動してウィンドウのスタイルを変更することもできる。そのためには、g_objVideoWindow.WindowStyle プロパティを 0x06000000 に設定する。これは、値 WS_DLGFRAME (0x04000000) と WS_VSCROLL (0x02000000) の 論理 OR に相当する。ウィンドウのスタイルおよび対応する値すべての一覧については、Microsoft® Platform SDK の Winuser.h ファイルを参照すること。

転送先ウィンドウをフォームの上に移動する場合、新しい位置を指定するには、g_objVideoWindow の Top および Left プロパティを設定する。Top および Left プロパティは、矩形をした空のコントロールの左上隅に対応するように設定する。これはフォームに表示されるある種のプレースホルダである。フォームの ScaleMode プロパティは 3 に設定されている。これはピクセルの単位を指定する。これでフォームのプロパティと DirectShow オブジェクトのプロパティを変換することなく使用できる。DirectShow オブジェクトのプロパティもピクセルで表される。Visual Basic フォームのデフォルトの単位は twip である。

ソース ビデオの幅と高さを取得して必要な矩形のサイズを決定する。これらの値は、IBasicVideo オブジェクトの VideoWidth および VideoHeight プロパティに対応する。

Top および Left プロパティを設定することに加えて、アプリケーションのフォームを新しい親ウィンドウとして識別する必要がある。そのためには、フォームのウィンドウ ハンドルである hWnd をオブジェクトの Owner プロパティに渡す。ハンドルを渡さない場合、転送先ウィンドウはフォームではなくデスクトップに対して相対的な位置に表示される。

次に例は、これらのタスクを示している。

    Set g_objVideoWindow = g_objMediaControl
    g_objVideoWindow.WindowStyle = CLng(&H6000000)   ' WS_DLGFRAME | WS_VSCROLL
    g_objVideoWindow.Left = CLng(Shape1.Left)   ' shape はフォームのプレースホルダ
    g_objVideoWindow.Top = CLng(Shape1.Top)
    Shape1.Width = g_objVideoWindow.Width       ' 入力ビデオに応じて shape をサイズ変更する
    Shape1.Height = g_objVideoWindow.Height
    g_objVideoWindow.Owner = frmMain.hWnd       ' フォームを親として設定する

次の例は、ScaleMode プロパティを初期化する方法を示している。

' ...
    frmMain.ScaleMode = 3    ' ピクセル
' ...

パフォーマンスに大きく影響するため、IVideoWindow オブジェクトの Width および Height プロパティを設定して転送先ウィンドウのスケールを変更しないこと。

状態の追跡

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
    txtRate.Text = CStr(g_dblRate)

開始位置の取得と設定

IMediaPosition.CurrentPosition プロパティを使用すると、ユーザーがビデオのレンダリング開始位置を調整できる。次のコード例では、ユーザーがキーを押すと、それに応じて現在の位置を変更する。

Private Sub txtStart_KeyDown(KeyCode As Integer, Shift As Integer)
' ユーザー入力を処理して開始位置を変更する
If KeyCode = vbKeyReturn Then
If g_objMediaPosition Is Nothing Then
Exit Sub
    ElseIf CDbl(txtStart.Text) > g_dblRunLength Then
MsgBox "Specified position invalid:re-enter new position."
    ElseIf CDbl(txtStart.Text) < 0 Then
MsgBox "Specified position invalid:re-enter new position."
    ElseIf CDbl(txtStart.Text) <> "" Then
        g_dblStartPosition = CDbl(txtStart.Text)
        g_objMediaPosition.CurrentPosition = g_dblStartPosition
End If 
End If 
End Sub

レートの取得と設定

IMediaPosition.Rate プロパティを使用すると、ユーザーがビデオのレンダリング レートを調整できる。このレートは、標準再生速度を基準にしている。たとえば、レートが 0.5 の場合、ビデオは標準速度の 2 分の 1 の速度でレンダリングされ、レートが 2.0 の場合は標準レートの 2 倍の速度でレンダリングされる。

CurrentPosition プロパティはビデオのレンダリング中に設定できるが、Rate プロパティはレンダリングの前にあらかじめ設定しておく必要がある。

注 :  レートが 1.0 未満のときはサウンド トラックを無効にできるビデオもある。

次のコード例では、ユーザーがキーを押すと、それに応じてレートを変更する。

Private Sub txtRate_KeyDown(KeyCode As Integer, Shift As Integer)
' DirectShow VB サンプル
' Rate 値に対するユーザーによる更新を処理する
If KeyCode = vbKeyReturn Then
If g_objMediaPosition Is Nothing Then
Exit Sub
    ElseIf CDbl(txtRate.Text) < 0# Then
        MsgBox "Negative values invalid: re-enter value between 0 and 2.0"
    ElseIf CStr(txtRate.Text) <> "" Then
        g_dblRate = CDbl(txtRate.Text)
        g_objMediaPosition.Rate = g_dblRate
End If 
End If 
End Sub

クリーン アップ

アプリケーションでは、Visual Basic の Set ステートメントを使用して新しい DirectShow オブジェクトのインスタンスを作成するたびに、次のコード例に示すように、対応する Set ステートメントでそのオブジェクト (および関連するリソース) をメモリから削除してからシャットダウンする必要がある。

Set g_objBasicAudio = Nothing