コールバック関数を使用する

ここではコールバック関数を使用して画像処理をするために、 FrameQueueSinkListenerクラスライブラリリファレンス>クラス>FrameQueueSinkListenerFrameQueueSinkクラスライブラリリファレンス>クラス>FrameQueueSinkで使用する方法を示します。
このプログラムはディレクトリ%TOPLEVEL%\Samples\VC\Callbackにあります。
プログラムを実行するには、 ソリューションファイルCallback.slnを開きメニューからビルド -> ビルド Callbackと選択します。
そこからデバッグ -> スタートと選択することでプログラムを実行することができます。

概要

この例ではsetupDeviceFromFileという関数を使用します。ソースコードは%TOPLEVEL%\Samples\VC\Common\CmdHelper.h内にあります。この関数はユーザーにデバイス、ビデオ規格、ビデオフォーマット、入力チャンネルの選択を求めるものです。選択された設定は保存できるため、プログラムを実行するたびに選択をする必要はありません。
次のコードはキャプチャされた画像を毎回受け取るためにCallbackを取得よう、FrameQueueSinkクラスライブラリリファレンス>クラス>FrameQueueSinkを設定する方法を示しています。

sink_listener listener_instance;
// 利用可能なカラーフォーマットを表すFrameTypeInfoArray構造体を作成
FrameTypeInfoArray acceptedTypes = FrameTypeInfoArray::createRGBArray();
// Frame Sinkを作成
tFrameQueueSinkPtr pSink = FrameQueueSink::create( listener_instance, acceptedTypes );
// sinkをgrabberに適用
grabber.setSinkType( pSink );

プログラムはFrameQueueSinkListenerから、sink_listenerとされるクラスを派生しています。

Sinkの入力キュー用のバッファ数を指定するために、FrameQueueSink::allocAndQueueBuffersクラスライブラリリファレンス>クラス>FrameQueueSink>FrameQueueSink::allocAndQueueBuffers Methodを使用します。

virtual void sink Connected( FrameQueueSink& sink, const FrameTypeInfo& frameType )
{
    UNREFERENCED_PARAMETER( frameType );
    sink.allocAndQueueBuffers( 10 );
}

FrameQueueSinkListener::frameQueuedクラスライブラリリファレンス>クラス>FrameQueueSinkListener>FrameQueueSinkListener::framesQueued Methodの中で、 FrameQueueSink::popOutputQueueBufferクラスライブラリリファレンス>クラス>FrameQueueSink>FrameQueueSink::popOutputQueueBuffer Methodをコールすることで最も古いバッファから取得されていきます。

このバッファはsaveImageメソッドによりBMPファイルに保存されます。

// イメージをストレージに保存するために、saveImageメソッドをコールします。
virtual void framesQueued( FrameQueueSink& sink )
{
    tFrameQueueBufferPtr buffer = sink.popOutputQueueBuffer();
    unsigned int frame number = buffer->getFrameMetaData() .mediaSampleDesc.FrameNumber;
    std::cout << "Buffer " << frame_number << " processed in sink_listener::framesQueued()." << std::endl;
    saveImage( buffer, frame_number );
    Sleep( 250 );
}

この例では、高負荷な処理をシミュレートするためにSleep( 250 )を入れています。この場合も連続したフレームが Sinkの出力キューに蓄積され、逐次処理することができます。

全ての入力バッファが満たされると、main()関数内で、イメージの取得を終了します。Sleep( 100 )は、処理遅延があった場合をシミュレートしています。この後で残ったバッファを処理します。

grabber.startLive();
// 設定したSinkのキューバッファ(先ほど10フレームを設定した)がいっぱいになるまで待ちます。
while( pSink->getInputQueueSize() != 0 )
{
    Sleep( 100 );
}
grabber.stopLive();

FrameQueueSink::popAllOutputQueueBuffersクラスライブラリリファレンス>クラス>FrameQueueSink>FrameQueueSink::popAllOutputQueueBuffers Methodを使って、まだframesQueuedでコールされていない全てのバッファを、保存します。

// まだCListener::frameReady()がコールされていないバッファを保存します
tFrameQueueBufferList remaining_buffers = pSink->popAllOutputQueueBuffers();
for( size_t i = 0; i < remaining_buffers.size(); i++ )
{
    unsigned int frame_number = remaining_buffers[i]->getFrameMetaData() .mediaSampleDesc.FrameNumber;
    std::cout << "Buffer " << frame_number << " processed in main()." << std::endl;
    listener_instance.saveImage( remaining_buffers[i], frame_number );
}