ビデオ キャプチャの方法

Webカメラなどの画像を読み込み、ウィンドウ上に表示する方法について解説します。

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using DirectShowLib;

public class VideoCaptureForm : System.Windows.Forms.Form
{
}

フィールド

/// <summary>
/// フィルタ グラフ構築用のインターフェイス
/// </summary>
IGraphBuilder graphBuilder = null;

/// <summary>
/// ビデオキャプチャ用のフィルタ グラフ構築用のインターフェイス
/// </summary>
ICaptureGraphBuilder2 captureGraphBuilder = null;

初期処理

/// <summary>
/// コンストラクタ
/// </summary>
private VideoCaptureForm()
{
    this.graphBuilder = ( IGraphBuilder )new FilterGraph();
    this.captureGraphBuilder = ( ICaptureGraphBuilder2 )new CaptureGraphBuilder2();


    // フィルタグラフを構築する
    SetupFilterGraph( this.graphBuilder, this.captureGraphBuilder );

    // ビデオ ウィンドウを構築する
    SetupVideoWindow( this.graphBuilder, this );


    // ビデオデータのプレビューを開始する
    int hr = ( ( IMediaControl )this.graphBuilder ).Run();
    DsError.ThrowExceptionForHR( hr );
}

終了処理

/// <summary>
/// リソースの解放
/// </summary>
/// <param name="disposing"></param>
protected override void Dispose( bool disposing )
{
    if( disposing )
    {
        // DirectShowのインターフェイスを解放する
        Marshal.ReleaseComObject( this.graphBuilder );
        Marshal.ReleaseComObject( this.captureGraphBuilder );

        this.graphBuilder = null;
        this.captureGraphBuilder = null;
    }

    base.Dispose( disposing );
}

フィルタ グラフの構築

/// <summary>
/// フィルタ グラフの構築
/// </summary>
/// <param name="graphBuilder"></param>
/// <param name="captureGraphBuilder"></param>
private void SetupFilterGraph( IGraphBuilder graphBuilder, ICaptureGraphBuilder2 captureGraphBuilder )
{
    int hr = 0;

    // キャプチャ グラフが使用するフィルタ グラフを指定する
    hr = captureGraphBuilder.SetFiltergraph( graphBuilder );
    DsError.ThrowExceptionForHR( hr );


    // ビデオキャプチャ フィルタを取得する
    IBaseFilter videoCaptureFilter = GetCaptureDevice( 0 );

    // フィルタ グラフにビデオキャプチャ フィルタを追加する
    hr = graphBuilder.AddFilter( videoCaptureFilter, "Video Capture" );
    DsError.ThrowExceptionForHR( hr );


    // ビデオキャプチャ フィルタをレンダリング フィルタに接続する
    hr = captureGraphBuilder.RenderStream(
        PinCategory.Preview,
        MediaType.Video,
        videoCaptureFilter,
        null,
        null );
    DsError.ThrowExceptionForHR( hr );

    // ビデオキャプチャ フィルタを解放する
    Marshal.ReleaseComObject( videoCaptureFilter );
}

キャプチャ デバイスの取得

/// <summary>
/// キャプチャ デバイスの取得
/// </summary>
/// <param name="deviceIndex">キャプチャ デバイスのインデックス</param>
/// <returns></returns>
private IBaseFilter GetCaptureDevice( int deviceIndex )
{
    // ビデオ デバイスのリストを取得する
    DsDevice[] devices = DsDevice.GetDevicesOfCat( FilterCategory.VideoInputDevice );

    if( devices.Length <= deviceIndex )
    {
        throw new Exception( "指定インデックスのビデオ キャプチャ デバイスは存在しない。" );
    }
    else
    {
        DsDevice device = devices[ deviceIndex ];

        object source;
        Guid filterId = typeof( IBaseFilter ).GUID;

        // モニカ (Moniker) を使用して、デバイスをフィルタ オブジェクトに結びつける
        device.Mon.BindToObject( null, null, ref filterId, out source );

        return ( IBaseFilter )source;
    }
}

ビデオ ウィンドウの構築

/// <summary>
/// ビデオ ウィンドウの構築
/// <param name="graphBuilder"></param>
/// <param name="owner"></param>
/// </summary>
private void SetupVideoWindow( IGraphBuilder graphBuilder, Control owner )
{
    int hr = 0;
    IVideoWindow videoWindow = ( IVideoWindow )graphBuilder;

    // ビデオ ウィンドウのオーナーに このウィンドウを設定する
    hr = videoWindow.put_Owner( owner.Handle );
    DsError.ThrowExceptionForHR( hr );

    // ウィンドウのスタイルを設定する
    hr = videoWindow.put_WindowStyle( WindowStyle.Child | WindowStyle.ClipChildren );
    DsError.ThrowExceptionForHR( hr );


    // ビデオ ウィンドウを親ウィンドウのサイズに一致させる
    hr = videoWindow.SetWindowPosition(
        0,
        0,
        owner.ClientSize.Width,
        owner.ClientSize.Height
        );
}

アプリケーションのエントリ ポイント

/// <summary>
/// アプリケーションのエントリ ポイント
/// </summary>
[STAThread]
static void Main()
{
    Application.Run( new VideoCaptureForm() );
}