続・PS3eye.axの問題?

PS3eye.axの不具合?の続き。
今回はコードから問題点を見つけます。

videoInputでの処理

videoInputを利用した初期化からキャプチャ画像取得までの流れは次のような感じです。

// videoInut インスタンス作成
videoInput *vi = new videoInput();

// デバイスを列挙し、デバイス数を取得
int n = vi->listDevices();

// デバイスを初期化(ここでは末尾に列挙されたデバイスを使用する)
vi->setupDevice(n-1, capW, capH);

// キャプチャした画像データへのポインタを取得
char *img;
if( vi->isFrameNew(n-1) ) {
	img = (char *)vi->getPixels(n-1,false);
}


setupDevice()の中では、指定されたカメラ(具体的にはカメラに対応したDirectShowフィルタ?)がサポートする機能を取得(http://msdn.microsoft.com/ja-jp/library/cc355061.aspx)し、指定した解像度のフォーマットでカメラを初期化しています。
ただし、指定した解像度をカメラがサポートしていない場合も想定して(だと思うのですが)、カメラがサポートする最小解像度、最大解像度、細分度というパラメータを用いて適切な解像度でカメラを初期化するようです。
細分度については、MSDNで以下のように説明されています。

使用しているキャプチャ カードが、160 x 120 ピクセルから 320 x 240 ピクセルの間のすべての解像度で JPEG フォーマットをサポートしているとする。この場合、サポートされている解像度間の違いは 1 である。なぜなら、サポートされている各解像度に対して 1 ピクセル加算または減算することによって、次のサポートされている解像度を得ているからである。サポートされている解像度間におけるこの差は、細分度と呼ばれる。

ビデオ能力


videoInputの実装では、だいたい次のようにして解像度を決めています。

int tempW = 999999;
int attemptWidth  = capW;
bool exactMatchX = false;

if(scc.OutputGranularityX >= 1)
{
    for(int x = scc.MinOutputSize.cx; x <= scc.MaxOutputSize.cx; x+= scc.OutputGranularityX)
    {               
        //If we find an exact match
        if( attemptWidth == x ){
            exactMatchX = true;
            tempW = x;                              
        }

        //Otherwise lets find the closest match based on width
        else if( abs(attemptWidth-x) < abs(attemptWidth-tempW) ){
            tempW = x;                              
        }
    }
}


値を最小解像度から最大解像度の範囲内で細分度の分ずつ増加させて、完全一致する、もしくは近い値を調べています。
この後、exactMatchXがtrueならattemptWidthを、falseならtempWをキャプチャ幅として設定するといった感じです。
上記はX軸のみですが、Y軸でも同様に処理しています。

PS3eyeの設定に問題?

PS3eyeでは最小解像度、最大解像度、細分度が次のように設定されています。

scc.MinOutputSize.cx : 640
scc.MinOutputSize.cy : 480
scc.MaxOutputSize.cx : 640
scc.MaxOutputSize.cy : 480
scc.OutputGranularityX : 0
scc.OutputGranularityY : 0

どうやら、解像度640x480のみサポートするようです。
前述のコードから行けば、細分度が0なので最初のif文に引っかかることなく先へ進んでしまうため、tempWの初期値999999がキャプチャ幅として設定されることになります。

ちょいと試してみたところ細分度が1以上あれば期待通りに設定できるので、当初は「細分度0を指定しているPS3eyeのDirectShowフィルタであるPS3eye.axの問題」と思っていたのですが、MSDNに次のような記述があります。

GetStreamCaps を使って次に公開するペアは、最小能力 640 x 480、最大能力 640 x 480、細分度 0 を組み合わせた 640 x 480 JPEG のメディア タイプとなる。

ビデオ能力

細分度0というのは、解像度を640x480に限定するといった意味のようですね。
と、いうことは・・・

本当の問題と対策

問題はPS3eye.axではなく、細分度0に正しく対応していない(と思われる)videoInputにあるようです。
対策としては、

1.videoInputを修正して今後も使用する
2.PS3eyeSDKを利用する

といった感じでしょうか。
videoInputは昨年の4月から更新が途絶えているようなので、絶賛更新中のPS3eyeSDKを利用するべきですかね。

あ、あれ?

videoInput、更新されてる・・・Jan 2009ってめっちゃ最近・・・

Fixes:

  • some non freed memory issues.
  • a bug with closest device matching.
  • a potential bug from not setting the lSampleSize of the media type. Thanks Peter!
  • restartDevice remembers all your settings now.
videoInput Library


この問題も今回の更新で直っているっぽいですね。
問題のあった箇所も、「とりあえず希望の解像度を設定してみる→エラーならこれまでと同様に最適なサイズをサーチ、設定する」という流れになっているので
大丈夫そうです。
自作のアプリにも適用してみましたが、特に問題はありません。


ファイルのタイムスタンプが2/2になってるので、多分昨日UPされたんだろーなぁ・・・






というわけで皆さん、PS3eyeとvideoInput(最新のやつね!)は使える子でしたよ!!!(なんつーオチだ)