VCDプロパティ
VCDプロパティを使うことでビデオキャプチャデバイスの設定を包括的でハードウェア非依存、そして拡張可能な形で行えます。
概要
DirectShowはビデオキャプチャデバイス用に2つのサブセットプロパティを定義しています。
VideoProcAmpとCameraControlです。それらの プロパティ値を表すためのスカラーデータとして唯一long型のデータが定義されています。このコンセプトによりデバイス非依存のコードを記述することが可能になりますが、問題が2つでてきます。
- デバイスの中にはDirectShowが定義する以上のプロパティを備えているものがある。
- 例えば"exposure (露光時間)"のようなプロパティ値を"long"で設定したとすると、その値が意味を失ってしまいます。 どの値が1/20.000 sec に対応するのでしょう? DirectShowではこの問題に対処するために負の値を使用するという方法があります。 例えば -2という値は2のマイナス2乗を意味する為 1/4 秒となります。これらの負の値は 物理的に意味を持つ(このケースでは秒を表す) ことから"物理値" と呼ばれます。ただこの方法では正確性に問題がでてきます。物理値によって1/3 秒の露光時間を設定することは不可能です。同じような問題が "iris(絞り)"や "zoom(ズーム)"の設定時にもあてはまります。
新しい VCDプロパティは秒などの物理的な単位をもちいてプロパティ値を調整できるインターフェースを提供しながらも、高い正確性を備えています。ある程度の制限はありますがGrabber::setPropertyクラスライブラリリファレンス>クラス>Grabber>Grabber::setProperty Method や Grabber::getPropertyクラスライブラリリファレンス>クラス>Grabber>Grabber::getProperty Methodメソッドでプロパティにアクセスする方法がシンプルでお好みだというのであれば、CSimplePropertyAccessクラスライブラリリファレンス>ヘルパークラス>CSimplePropertyAccessというヘルパークラスがあり、setPropertyやgetPropertyを使用する古いコードもなんなく移植することが可能です。ただしこのクラスを使用する場合、新しい VCD プロパティの恩恵は受けることができません。
基本コンセプト
VCDプロパティの基本的な概念は構造化された組織といえます。それを理解するにはプロパティを構成する要素について考える必要があります。はじめに、プロパティは"exposure(露光時間)"というような名前を持っており、さらにそこには値や自動設定という要素(エレメント)が含まれています。よってプロパティは名前といくつかの要素を持つオブジェクトといえるでしょう。このオブジェクトはIVCDPropertyItemクラスライブラリリファレンス>クラス>IVCDPropertyItemと呼ばれ、IVCDPropertyElementクラスライブラリリファレンス>クラス>IVCDPropertyElementという要素はそれをコントロールするための一連のインターフェースを持っています。それらのインターフェースはプロパティへ様々なアクセスメソッドを提供します。たとえばIVCDRangePropertyクラスライブラリリファレンス>クラス>IVCDRangePropertyというインターフェースはDirectShowと同様のプロパティへのアクセスを提供します。IVCDAbsoluteValuePropertyクラスライブラリリファレンス>クラス>IVCDAbsoluteValuePropertyは物理値を使ったプロパティへのアクセスで精度の高い調整を可能にします。このことから、VCD propertyの構造が見えてきます。プロパティ項目がプロパティ要素を持ち、そしてそれが複数のインターフェースを含んでいます。プロパティの調整を行うには適切な項目、要素、インターフェースを取得する必要があります。スタートメニューから"VCD Property Inspector"を開き、 VCDプロパティがどのように構成されているかをご覧になってください。
プロパティオブジェクトを見つける
プロパティオブジェクトを見つけるにはまず最初にプロパティ項目、要素、あるいはインターフェースを指定する手段が必要となります。定義されている全てのプロパティ項目、要素、インターフェースにはGUIDs (Global Unique Identifiers) という識別子が割り当てられており、定数クラスライブラリリファレンス>クラス>定数のところにて一覧できます。これらのGUIDはVCDプロパティ内でメソッドの検出に使用されます。接続中のデバイスがサポートするプロパティ項目はIVCDPropertyItemsクラスライブラリリファレンス>クラス>IVCDPropertyItemsコレクションに格納されます。このコレクションがプロパティ項目、要素、インターフェースを取得するためのメソッドを提供されます。それぞれIVCDPropertyItems::findItemクラスライブラリリファレンス>クラス>IVCDPropertyItems>IVCDPropertyItems::findItem Method, IVCDPropertyItems::findElementクラスライブラリリファレンス>クラス>IVCDPropertyItems>IVCDPropertyItems::findElement Method,IVCDPropertyItems::findInterfaceクラスライブラリリファレンス>クラス>IVCDPropertyItems>IVCDPropertyItems::findInterface Methodと呼ばれるものです。取得されるオブジェクトはfindItemのために一つのGUIDか2つの組み合わされたGUIDによって指定する必要があります。以後、 プロパティオブジェクトを指定したGUIDや組み合わされたGUIDの事をGUIDパスと呼びます。
インターフェースを見つける
前述の通り、インターフェースとはプロパティからデータを読み取り、またデータをプロパティに書き込むものでもあります。
必要なインターフェースを呼び出すためにはそのインターフェース用のGUIDパスをIVCDPropertyItems::findInterfaceクラスライブラリリファレンス>クラス>IVCDPropertyItems>IVCDPropertyItems::findInterface Methodへのパラメータとして使用しますが、それを行う前にどのインターフェースを使用するかを決める必要があります。 自動項目の場合(IVCDPropertyElementクラスライブラリリファレンス>クラス>IVCDPropertyElement, GUID:VCDElement_Auto) はスイッチインターフェース ( IVCDSwitchPropertyクラスライブラリリファレンス>クラス>IVCDSwitchProperty, GUID: IID_IVCDSwitchProperty)を取得します。値項目( 実際のプロパティ値)を使う場合は最適なインターフェースを探さなければなりません。最適、あるいはもっとも高度なインターフェースは絶対値(absolute value) インターフェースとなります。 ( 詳細についてはIVCDAbsoluteValuePropertyクラスライブラリリファレンス>クラス>IVCDAbsoluteValuePropertyをご参照ください)
最初に説明したように、絶対値インターフェースは高精度で、値がその通りの意味を持つことになります。次のコードは露光時間のプロパティ項目の要素値のための絶対値インターフェースを取得しています。
// サポートしているプロパティ項目の取得
tIVCDPropertyItemsPtr pItems = m_Grabber.getAvailableVCDProperties();
// 露光時間の設定用に絶対値インターフェースを取得
tIVCDAbsoluteValuePropertyPtr pAbsVal = 0;
if( pItems->findInterfacePtr( VCDID_Exposure, VCDElement_Value, pAbsVal ) != 0 )
{
// インターフェースの取得成功
}
else
{
// 露光時間プロパティ項目の値エレメントの絶対値インターフェースはありません。
}
絶対値インターフェースがこのプロパティに存在しない場合、マップストリング(map string)インターフェースを取得します。 ( IVCDMapStringsPropertyクラスライブラリリファレンス>クラス>IVCDMapStringsProperty, GUID: IID_IVCDMapStringsProperty)。絶対値インターフェースほどの正確性はありませんが、値に意味はあります。次のコードは露光時間のプロパティ項目の値エレメントのためのマップストリングインターフェースを取得しています。
// サポートしているプロパティ項目の取得
tIVCDPropertyItemsPtr pItems = m_Grabber.getAvailableVCDProperties();
// 露光時間の設定用にレンジインターフェースを取得
tIVCDRangePropertyPtr pRange = 0;
if( pItems->findInterfacePtr( VCDID_Exposure, VCDElement_Value, pRange ) != 0 )
{
// インターフェースの取得成功
}
else
{
// 露光時間プロパティ項目の値エレメントのレンジインターフェースはありません。
}
マップストリングインターフェースがこのプロパティに存在しない場合、レンジ(range)インターフェースを呼び出します。( IVCDRangePropertyクラスライブラリリファレンス>クラス>IVCDRangeProperty, GUID: VCDInterface_Range) このインターフェースは値に意味を持たせるものではありませんが、マップストリングよりも多くの値を提供することも可能です。 次のコードは露光時間のプロパティ項目の要素値のためのレンジインターフェースを呼び出しています。
// サポートしているプロパティ項目の取得
tIVCDPropertyItemsPtr pItems = m_Grabber.getAvailableVCDProperties();
// 露光時間の設定用にレンジインターフェースを取得
tIVCDRangePropertyPtr pRange = 0;
if( pItems->findInterfacePtr( VCDID_Exposure, VCDElement_Value, pRange ) != 0 )
{
// インターフェースの取得成功
}
else
{
// 露光時間プロパティ項目の値エレメントのレンジインターフェースはありません。
}
インターフェースを使用する
さきほどはインターフェースの取得について説明しました。ここではそれを使ってプロパティの情報を取得し、値を調整する方法について説明します。全てのインターフェースが以下のプロパティを提供します。
- Available: インターフェースが利用可能であるかを示します。例えば、トリガープロパティ項目のインターフェースはライブ画像を流している間は利用できない可能性があります。
- ReadOnly: インターフェースの値を設定できるかどうかを示します
- Default: デフォルトの値
- Value: インターフェースの値
絶対値インターフェースとレンジインターフェースは実際値に設定できる最小と最大の値についての情報を得るためのプロパティを提供します。絶対値インターフェースは追加として値の物理単位の情報を提供し、 マップストリングインターフェースは文字列コレクションを提供し、これが実際値に設定できる可能性のある値の集まりを構成します。
絶対値インターフェースが呼び出せる場合、インターフェースにアクセスするためのコードは次のようになります。
// pAbsValItfは露光時間の有効な絶対値インターフェースである
if( pAbsVal->getAvailable() )
{
// 現在の値を平均値とする
pAbsVal->setValue( ( pAbsVal->getRangeMin() + pAbsVal->getRangeMax() ) / 2 );
}
マップストリングインターフェースが呼び出せる場合、インターフェースにアクセスするためのコードは次のようになります。
// pMapStringsは 露光時間の有効なマップストリングインターフェースである
if( pMapStrings->getAvailable() )
{
// 現在の値を平均値とする
pMapStrings->setValue( ( pMapStrings->getRangeMin() + pMapStrings->getRangeMax() ) / 2 );
}
レンジインターフェースのみが取得可能な場合、インターフェースにアクセスするためのコードは次のようになります。
// pRangeは露光時間の有効なレンジインターフェースである
if( pRange->getAvailable() )
{
// 現在の値を平均値とする
pRange->setValue( ( pRange->getRangeMin() + pRange->getRangeMax() ) / 2 );
}
プロパティ値のシリアライズ
IVCDPropertyItemsクラスライブラリリファレンス>クラス>IVCDPropertyItemsというコレクション はIVCDPropertyItems::saveクラスライブラリリファレンス>クラス>IVCDPropertyItems>IVCDPropertyItems::save Methodというメソッドを提供し、それによって接続されているデバイスの全VCDプロパティ設定を文字列にシリアライズします。プロパティ値はXMLフォーマットで保存されます。よって後に復元する時のためにその文字列をレジストリやファイルに保存したりというのが簡単にできます。XMLへの対応は公式に明記されておらず 予告なく変更される場合がありますのでご了承ください。全てのプロパティ値を保存するのにはIVCDPropertyItems::loadクラスライブラリリファレンス>クラス>IVCDPropertyItems>IVCDPropertyItems::load Methodが呼び出されます。