「覚え間違い」を教えてください!

現在、USB複数カメラのプログラムを開発して居ます。
問題は複数カメラを使用するとPICバスの帯域を越えてしまうので、フレームレートを低くしようとしていますが、うまく行って居ません。

調べた所、フレームレートを取得するのはAvgTimePerFrameがあり、こちらは実装出来てテストも終了して居ます。ただ、これは読み取り専用で書き込みが出来ません。
もう一つはGetOutputFPSで、これに対して書き込みにPutOutputFPSがあります。
この2つを実装したいと思っています。実装自体はLongSecret様のご助言で
一応出来ました。

下記のプログラムはフレームレートを読み出すプログラムで、前半はAvgTimePerFrameのものです。
関数の引数、Indexは現在使用しているカメラ、ロジクールC905Mの解像度23個のどれを選択しているかで、0から22が入って来ます。
AvgTimePerFrameの方はこのパラメーターに従って、選択した解像度のフレームレートを返して来ます。
(実際はレートでは無く、100nS単位のインターバル時間値ですが・・)

これに対して、後半のGetOutputFPSはどの解像度でも15FPSしか返しません。
もっとも、後半のプログラムはどの解像度を選択されているか関数に伝わって居ないと思われるので当然でしょうけど。
実はこのプログラムは先人が作成し、私が少しずつ分かる範囲で今回の様に改造を加えて来たもので、現在は相談する人も無く困っております。
AvgTimePerFrameの追加は何とか私でも出来たのですが、GetOutputFPSから選択した解像度に従ったフレームレートを出させる事は出来ないでしょうか。
若しくは他の方法で選択された解像度のフレームレートの入手、変更は出来ないでしょうか。

宜しくお願い致します。

int __fastcall TWebCam::RedFPS( int Index )
{
int iFrmSpd;
//分解能コントロール
IAMStreamConfig *pStreamConfig;
//キャプチャピンに対してストリームコングィグをセット
FCapture->FindInterface(&PIN_CATEGORY_CAPTURE, //キャプチャピン
0,//すべてのメディアタイプ
FVideoCap, IID_IAMStreamConfig, (void **)&pStreamConfig );

AM_MEDIA_TYPE *pmt;
VIDEO_STREAM_CONFIG_CAPS scc;
//フォーマットリストの取得
HRESULT hr;
// フォーマット機能の取得 機能番号はIndexに設定
hr=pStreamConfig->GetStreamCaps(Index,&pmt,(BYTE*)&scc);
if(hr!=S_OK){
ShowMessage("Format change error(1).");
return 0;
}
// フォーマットの設定
hr = pStreamConfig->SetFormat(pmt);
if(hr!=S_OK){
ShowMessage("Format change error(2).");
return 0;
}
VIDEOINFOHEADER *pVideoHeader = (VIDEOINFOHEADER*)pmt->pbFormat;
// ビットマップ情報を BITMAPINFO 構造体にコピーする

// これはテスト用、今の所、選択されたカメラ、解像度番号のタイミングが入手出来ている様だ。
// 一方GetOutputFPSはどの解像度でも15が返ってくる。アクセス箇所位置が違う?
iFrmSpd = pVideoHeader->AvgTimePerFrame; // フレームタイミング入手

// ここからGetOutputFPS用のプログラム
IAMTimelineObj* pVideoGroupObj;
IAMTimeline* pTimeLine;

CoCreateInstance(CLSID_AMTimeline, NULL, CLSCTX_INPROC_SERVER,
IID_IAMTimeline, (void**)&pTimeLine);
pTimeLine->CreateEmptyNode(&pVideoGroupObj, TIMELINE_MAJOR_TYPE_GROUP);

IAMTimelineGroup* pVideoGroup;
pVideoGroupObj->QueryInterface(IID_IAMTimelineGroup, (void**)&pVideoGroup);
double dTmp;

pVideoGroup->GetOutputFPS(&dTmp); // 読み出しフレーム/秒
// pVideoGroup->GetOutputFPS(dTmp); // 書き込みフレーム/秒
pTimeLine->AddGroup( pVideoGroupObj );
pStreamConfig->Release();
return( (int) dTmp );

A 回答 (5件)

>ところでLongSecretさん、Builderやdirectxの質問サイトご存知ありませんか?




私はC++関連については専らVisual C++ を使ってきたので、Builderについては分かりません。
ただ、C++についての質問サイトということであれば

Visual C++サイドのそれを利用しても、一応問題はないはずです。(C++ Builder使いながらMSDNのVC++のフォーラムで質問する、となると、ちょっとどうなのか分かりませんが…w ただ、そう言う点を除けばMSDNのVC++フォーラムとかは有力だとは思います。)


また、DirectXはBuilderでも対応してるのは間違いないと思いますが
Microsoft DirectXという名の通りMicrosoftが作ったAPIで、(全部は未確認ですが、おそらくManaged DirectXとか以外ネイティブな)C++で書かれているので

情報が充実している
といえば、その中でもC++コードを非常に簡単に扱える
同じくMicrosoftが作ったVisual C++関連のサイトに、必然的に落ち着いてくると思います。


単純に、C++の基本的なクラスの仕様を煮詰めたい場合であれば
C++関係の質問の場なら、ここでもMSDNのフォーラムでもYahoo知恵袋でも…
大抵の場所でなら教えてもらえるはずです。


あとは調べるときの「勘」とか「検索技術」は
実はかなり重要なポイントだったりするかもしれません。
    • good
    • 0
この回答へのお礼

色々ありがとうございました。
本日も色々試行錯誤していましたが、フレームレートの設定には至りませんでした。
とりあえずこちらの質問を締め切らせて頂きます。
もう一つの方は、今日の帰りがけにやって見たい事が出来てしまったので。来年、それを確認してから締め切ります。

お礼日時:2011/12/28 21:09

>私としてはDirectShowもクラスの事もわからず、先人の物を引き継がされてしまっていますが、うちの部にはソフト屋さんは他に居ないので思い付いた事はやって見るだけです。




なかなか不憫な事でございますね。
とりあえず、私もちょろっとではありますが調べたことですので
下記内容を試してみて、出来るか出来ないかは教えていただけるとすっきりします(笑)

出来ないとしても各関数の戻り値などから活路が分かるかもしれませんし


DirectShow等も結局「誰かが作ったもの」で、型や関数の意味だけ知ってればいいし、実装部は見えない(或いは見る必要がない)という扱いになってるので
それぞれについて細かいことについて調べようとすれば、そのライブラリを作った人以外は、誰であっても

・ネットや書籍で調べる
・自分で実験してみる
・人に教わる

といった方法しかないはずです。

とはいえ、C++のclassの詳細が分かっていれば、見た目が見慣れない型名や関数名などで、ぱっと見「うわぁ」と思う事はあったりはしても、丁寧に見たり実験していくことで、それぞれの意味を必ず理解出来るようになるはずです。


時間が全くないならひとまずおいとくとしても
今後C++に触る可能性が0でないなら、classの仕様について、ある程度把握しておくとかなり良い、かもしれません。

深いところに突っ込みだすとキリがないですが、基本的にはCのstructが拡張されたものだとお考えください。


・Cのstructは、(表記上)変数だけで構成されていますが、C++のclassは、変数だけでなく関数もメンバに持っています。

・C++ではstructもclassも「継承」が可能です。

・Cのstructは、メンバに対して無制限にどこからでもアクセスできる(ため、意図しないところで書き換えられたりする危険がある)のですが、C++のclassやstructはアクセス修飾子、publicやprivate、あるいは継承先からのみ使用protectedを指定でき、どこからアクセスされるかを細かくコントロールできます。

・C++のstructとC++のclassは、なにもアクセス修飾子を書かない時のデフォルトが、前者はpublic、後者はprivateになっていて、それ以外は前方宣言の時にしっかり

class A;
struct B;

と、区別して書かないといけないといった細かいこと以外同じものです。


などなど。
    • good
    • 0
この回答へのお礼

>なかなか不憫な事でございますね。

そうなんですよね。カメラのIOは動くものとして、アプリケーションを組んで居たのに、カメラのIOの部分が仕様を満足しないから改造しないといけなく成るなんて。
私はクラスも分かりませんが、継承も漠然としか理解して居ないので大変です。

ところでLongSecretさん、Builderやdirectxの質問サイトご存知ありませんか?
もっともMSDNのフォーラム追いかけていったら英語のサイトに繋がってしまって、おまけに2008年辺りで交信が切れていたり。
ゲーム作成のサイトはにぎやかそうですが、やっている内容が全然分かりませんでした。
私レベルだとこのサイト位が一番いいんでしょうかね。

何度か画像処理は辞めたいと申告したんですが、却下されてしまい、今はやるしか無い状態です。
まぁ、今回の件は今までUSBカメラのキャプチャーに1~2秒かかって居たのが100mS程度でキャプチャー出来るので、現場が遅いプログラムでも何とか待つて居てくれていますが、原因が判ったので早く実装させたい機能です。

ぼやいてすみません。

お礼日時:2011/12/23 19:11

いやまてよ



>問題は複数カメラを使用するとPICバスの帯域を越えてしまうので、フレームレートを低くしようとしていますが、うまく行って居ません。


ここなんですよね?

改めて名前と解説から考えると
IAMStreamConfig が気になります。

pStreamConfig->GetStreamCaps(Index,&pmt,(BYTE*)&scc);

で得たAM_MEDIA_TYPEを

hr = pStreamConfig->SetFormat(pmt);

するまえに

((VIDEOINFOHEADER*)pmt->pbFormat)->AvgTimePerFrame = 数値;

的なことをするとどうなるのでしょうか?
(関係ないかな?)
    • good
    • 0
この回答へのお礼

私としてはDirectShowもクラスの事もわからず、先人の物を引き継がされてしまっていますが、うちの部にはソフト屋さんは他に居ないので思い付いた事はやって見るだけです。

ありがとうございました。

お礼日時:2011/12/22 23:23

あ、もちろん



No1のコードはテストコードなので戻り値チェックとかはしていませんが
実際にはご質問のコードのようにそれぞれの場所で

hr = pStreamConfig->GetStreamCaps(Index,&pmt,(BYTE*)&scc);
if ( hr != S_OK ){

等々のチェックをちゃんと行ってください。
    • good
    • 0
この回答へのお礼

はい、とりあえず動作出来たらその後で追加致します。

ありがとうございます。

お礼日時:2011/12/22 23:20

こんばんは。



ハードが関連しそうなことはモノ(この場合Webカメラ)がないと把握が難しいので
相変わらず詳しいところは全く分かっていませんが


PutOutputFPSではなくSetOutputFPSではないでしょうか?
http://msdn.microsoft.com/ja-jp/library/cc355147 …


>もっとも、後半のプログラムはどの解像度を選択されているか関数に伝わって居ないと思われるので当然でしょうけど。


おっしゃるとおり、たぶん下の方は単純に、タイムラインってやつを生成したり
生成直後の状態をGetしたりしてる(?)
感じのコードに思いますし


// ここからGetOutputFPS用のプログラム

以降

pStreamConfig->Release();

の手前まで
上の部分で使った変数名が一個も出てこないのですが


とりあえず、下のほうの部分についてだけ

てきとーなコードでSetOutputFPSがS_OKを返してくる(成功する)ことは確認できました。


Debug::f(引数);
は単に、デバッグ簡単にするために使ってる自作関数です。
上述の通りS_OKを表示してくれました



IAMTimelineObj* obj;
IAMTimeline* tline;

CoCreateInstance(CLSID_AMTimeline, NULL, CLSCTX_INPROC_SERVER,
IID_IAMTimeline, (void**)&tline);
tline->CreateEmptyNode( &obj, TIMELINE_MAJOR_TYPE_GROUP );

IAMTimelineGroup* group;
obj->QueryInterface(IID_IAMTimelineGroup, (void**)&group);
double dTmp;

Debug::f( group->SetOutputFPS( 60.0 ) ); //現状よく分かってないので数値は適当です
tline->AddGroup( obj );

///つくったものは1対1の対応で全て解放をお忘れなく(DirectX(やCOM?)関連のインターフェースはRelease関数で解放というのが多いです。)///
obj->Release();
tline->Release();
group->Release();


///CoInitializeを呼び出したら、いつかはCoUninitializeするのをお忘れなく///
CoUninitialize();



あとは、AvgTimePerFrameのやつで、一致させられる
…ということでいいのかどうかは、ご確認ください。
    • good
    • 0
この回答へのお礼

こちらの問題もご回答頂いてありがとうございます。

>PutOutputFPSではなくSetOutputFPSではないでしょうか?

打ち間違いです。すみません。

>///CoInitializeを呼び出したら、いつかはCoUninitializeするのをお忘れなく///

はい、プログラムの開始と終了の所でやっています。

>上の部分で使った変数名が一個も出てこないのですが

そうなんです、どうやって関連付けて良いかわからなくて、今日半日MSDS等を見ていましたが、結局判りませんでした。

明日、家のPCで出来るかやってみます。そうで無ければ月曜までまって、会社のpCでやらざるを得ないのですが。

ここの所が解決すると、かなり処理が速く成るので何とかしたい所です。
自分のPCで出来て、何で現場のPCで出来ないのか長い間疑問でしたが、PCIバスの帯域らしい事が判ったら、今度は先人の作成したプログラムにはフレームレートの制御部分が無くて、八方ふさがりです。

兎に角、知識が無いので色々やって見るしかありません。

ありがとうございました。

お礼日時:2011/12/22 23:17

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


おすすめ情報