DirectShowと戦うスレ Part 2
■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん
2006/11/08(水) 00:25:56http://pc8.2ch.net/test/read.cgi/tech/1026666092/
0232213
2007/03/02(金) 21:13:20色々調べて試したみたところ、IKsPropertySetが使えそうなのは判りました。
ただ、これでVideoProcAmpのプロパティへアクセスしてみたところ、
旧来のKSPROPERTY_VIDEOPROCAMP_BRIGHTNESSのようなFilterベースの
プロパティアクセスをサポートしているものはうまく動作しますが、
KSPROPERTY_VIDEOPROCAMP_WHITEBALANCE_COMPONENTのような
ノードベースのアクセスしかサポートされていないパラメータへはアクセス出来ないようです。
入力インスタンス構造体のFlagsにKSPROPERTY_TYPE_TOPOLOGYをつけて
Get()を使ってみてますが、正常終了するものの中身が0です。
旧来のパラメータもノードベースでアクセス出来るようなので試したみたところ、
入力インスタンス構造体をノードベース(KSP_NODE)ではなくフィルタベース(KSPROPERTY)で
見ているようです。
どうもIKsPropertySetはフィルタベースのアクセスしかサポートしていないのでは、と
推測してるのですがどうなんでしょうか。
IKsControlを使うべきなのかと思い試してますが、こっちはnot supportedのえらーコードが返ります。
0233デフォルトの名無しさん
2007/03/02(金) 21:25:17今でもわかんないこと多いけど。
サンプルと手助けがないとつらいね。
0234デフォルトの名無しさん
2007/03/02(金) 22:02:35勘で書いてるんだけど、IKsTopologyInfo:, CreateNodeInstanceでノードを作って、
ノードの方から IKsProperty を QueryInterface で取得して、IKsPropertySet::Setで
プロパティをセットするんじゃないだろうか。
0235デフォルトの名無しさん
2007/03/02(金) 23:55:00DirectShowは設計がマズイと思う。
フィルタグラフマネージャは自前でスレッドをもってユーザスレッドストリームスレッドとの切り離しをすべきだ。
いつの間にかメインスレッドから呼び出されていたりしてデッドロックとか多い。
0236デフォルトの名無しさん
2007/03/03(土) 11:14:01ほんとそのとおりだね。
IBasedPin::Reciver内で別スレッド立ててアロケータ確保すると
うまくやらないとアボーンする。。
0237215
2007/03/03(土) 23:03:00ありがとうございます。
そうしてみます。
C++の入門書を一通り読みましたが、新しいことがいっぱいで疲れました・・・。
次はMSDNのリファレンスを読みます。
早くキャプチャソフト作りたいです。
0238デフォルトの名無しさん
2007/03/04(日) 00:56:51切り離すモードと切り離さないモードがある。
0239213
2007/03/05(月) 22:24:32DDKやPlatformSDKの情報からみて、まさに指摘されてるようなことなんじゃないかと
思って試してみてますが、IKsTopologyInfo::CreateNodeInstance自体がエラーになるんですよね。
色々調べてみると、どうもWindowsXPでCreateNodeInstance自体が完全にサポート
されていない雰囲気がするのですよ。UVC extensionを調べててこんな情報がありました。
ttp://www.codecomments.com/archive421-2005-11-657282.html
自分のやり方が間違ってるかもとも思うんで、しばらく頭を冷やしてもう一度
試してみるつもりです。
0240デフォルトの名無しさん
2007/03/05(月) 22:27:24キャプチャ(640×480出力)→ビデオレンダラ
というふうに繋いでいます。
ビデオレンダラでフルスクリーンにすると、4:3のアスペクト比を守りながら拡大してくれるのは
うれしいのですが、16:9ソースの表示にも対応するために、フルスクリーンの状態で
16:9にしたいです。
しかし、どうしてもできません。
描画されるビデオウィンドウはウィンドウズアプリのメインウィンドウに貼り付けているカタチです。
ソースは640×480を保ったまま、16:9にリサイズしてフルスクリーンにしたいです。
ご助言、よろしくお願いします。
0241デフォルトの名無しさん
2007/03/05(月) 22:40:46ビデオレンダラーから(フィルタグラフからでもいいのか?)
IVMRAspectRatioControl、IVMRAspectRatioControl9 や IVMRWindowlessControl を取得して、
SetAspectRatioModeでアスペクトレシオを無視するようにする。
レンダラのサイズは自前で16:9にしておく。
0242デフォルトの名無しさん
2007/03/05(月) 22:57:06再接続することなく対応したいのですが、レンダラへ新しい縦横サイズは教えてやれたのですが、
バッファサイズを変更できませんでした。
マニュアルには現在より大きなバッファサイズが必要な場合は、ReceiveConnectionを使えとありますが、
フィルタのどこにどのようなコードを追加すればよいのか分かりません。
デタラメな文章ですが、アドバイスありますでしょうか。。
0243240
2007/03/06(火) 00:47:31ありがとうございます!
まずウィンドウレスモードですが、試そうとしたところ、ビデオをウィンドウに転送するところで
強制再起動が掛かかるなど恐ろしいことになってしまったので、ちょっと置いておきます。
ウィンドウモードで作りこんでしまったこともあり、できればこのままで解決したいと思っております。
他の試みとして、IVMRAspectRatioControlをVMR7から呼び出してSetAspectRatioModeで
アスペクト比固定をしないよう設定したのですが、相変わらずアス比固定でフルスクリーン
になりました・・・。
GetAspectRatioModeで確認しましたが、ちゃんとVMR_ARMODE_NONEになっていました。
そこで、grapheditで調べましたところ、
ttp://vista.jeez.jp/img/vi7310912755.jpg
二つあるフルスクリーンボタンのうち、「Set Full Screen」のほうはアス比固定拡大、「Full Screen Window」
のほうは全体に引き伸ばして表示される、という結果になりました。
先に試したプログラムのほうでは、前者のほうになっているのではないかと考えられます。
後者の「Full Screen Window」ボタンを押すことと等価な処理としては何が考えられるでしょうか?
0244240
2007/03/06(火) 01:37:56ここのウィンドウレスモードの説明を見ていると、こちらのほうが良さそうですし、なんとか
ウィンドウレスモードで動くようにしてみます。
0245デフォルトの名無しさん
2007/03/06(火) 15:01:49古来より DirectShow でフルスクリーン再生をする際には、
レンダラをフルスクリーンモードにするのではなく
単に全画面のウィンドウで再生する方が好しということになっています。
後者はそれでしょう。
0247デフォルトの名無しさん
2007/03/07(水) 21:22:13IEnumMoniker::Next()を繰り返すことでキャプチャデバイスを切り替えるというプログラムを組んでいます。
デバイスが検出されなくなったら、IEnumMoniker::Reset()をして先頭から数えなおすように
しています。
一回の切り替えを細かく説明すると、
ストリームの停止→キャプチャフィルタの削除→上記メソッドで検出した新たなデバイスをグラフに追加
→ICaptureGraphBuilder2::RenderStream()でグラフをVMR9に直に接続→再生
という流れです。
これに問題がありまして、この切り替えを8回繰り返す(4順する)と必ず画面が最後のフレームを
表示したまま固まってしまいます。
考えられる原因や対処法がありましたら、ご教授お願いします。
0248デフォルトの名無しさん
2007/03/08(木) 02:22:270249213
2007/03/08(木) 03:23:24問題が度解決できました。この辺を触る人はあまりいなさそうですがご報告だけでも。
結論からいうと、IKsTopologyInfoを使ってKSNODETYPE_VIDEO_PROCESSINGノードを
検索し、そのノードからIVideoProcAmpインタフェイスをCreateNodeInnstanceで生成することで、
拡張されたプロパティへアクセス出来ました。(IAMVideoProcAmpやIKsPropertySetではなく)
IVideoProcAmpはノードベースのインタフェイスとしてvidcap.hで定義されてますが、
Vista用のWindowsSDKで配布されているバージョンでないと定義自体存在しません。
USB Video ClassがXPSP2以降のサポートだったのでPlatform SDK(2003R2)を使っていたのですが、
これがまず失敗でした。
また、NTDDI_VERSIONとsdkddkver.hを使い、XPSP2以降であることを明示する必要がありました。
あと細かい話ですが、MSDNやWindowsSDKのドキュメントには、IVideoProcAmpノードの
生成時にIIDとしてIID_IVideoProcAmpを指定しろ、と書かれてますが、こいつのオブジェクトが
どこにも存在せずリンクエラーになります。_uuidof(IVideoProcAmp)で指定しないと駄目な模様です。
0250247
2007/03/08(木) 17:52:00原因は二つ目のキャプチャデバイスをRenderStream()するときのみ、間に色空間変換フィルタが
挿入され、キャプチャフィルタを削除したときに色空間変換フィルタ、VMR9間のピンが持つ
アロケータにバッファがどんどん蓄積されていくためだったようです。
デバイスを切り替える度、VMR9との接続を切るようにすると、うまく動作するようになりました。
0251デフォルトの名無しさん
2007/03/09(金) 00:51:33ビルドがどうしてもできません。
お持ちの方がおられましたらお譲りください。
お願いします。
アップローダ
ttp://www.rupan.net/uploader/
環境
WindowsXP SP2
Platform SDK for Windows Server 2003 SP1
Visual Studio 2005 Express Edition
0252デフォルトの名無しさん
2007/03/09(金) 02:40:170253251
2007/03/09(金) 03:08:44いえ、最近になって.slnや.dswのファイルが付属しなくなりまして、makefileがついているんです。
それで
ttp://www.shader.jp/xoops/html/modules/xfsection/article.php?articleid=17
このページと同じように進めてもcl.exeが見つからないようなことを示すエラーが出て、
それじゃあとcl.exeのあるフォルダを環境変数のPathに設定してやると今度はmspdb80.dllが
見つからないと言われて失敗します。
0254デフォルトの名無しさん
2007/03/09(金) 04:01:110255デフォルトの名無しさん
2007/03/09(金) 04:16:23お前の最近は2年前か?
0256251
2007/03/09(金) 04:29:10え!?そうなんですか!?
ttp://www.microsoft.com/downloads/details.aspx?FamilyId=A55B6B43-E24F-4EA3-A93E-40C0EC4F68E5&displaylang=en
ここのPSDK-x86.exeをダウンロードしてインストールしたのですが、違うのでしょうか?
>>255さんの入手経路を教えてください。
0257デフォルトの名無しさん
2007/03/09(金) 05:18:470258251
2007/03/09(金) 07:07:13ttp://ugd555.blog1.fc2.com/page-13.html
同じ症状を解決した方のページを見つけました。
最終的に別のフォルダから5つファイルを持ってこなければいけませんでした。
この問題に18時間費やしました・・・
0259251
2007/03/09(金) 09:44:34ライブラリファイルが無い、と言われどうしようもありません。
そういえば、VC2005EEでDirectShowフィルタを開発したという話を聞いたことがありません。
ちゃんとしたVCを買え、ということでFAでしょうか?
もしそうなら、観念して買いに行きます・・・
0260デフォルトの名無しさん
2007/03/09(金) 09:45:260261デフォルトの名無しさん
2007/03/09(金) 16:37:130262デフォルトの名無しさん
2007/03/09(金) 16:42:53初心者スレにでも行け
DirectShowスレで語るべき内容ではないだろ
0263デフォルトの名無しさん
2007/03/10(土) 01:13:370264デフォルトの名無しさん
2007/03/10(土) 02:25:220265デフォルトの名無しさん
2007/03/10(土) 05:35:57という構成の中の変換フィルタで、キャプチャフィルタからサンプルが1枚くる度に
サンプルに対し処理Aを実行→出力→表示
サンプルに対し処理Bを実行→出力→表示
というように2回の処理、出力を行いたい(フレームレートを倍化したい)のですが、
どうすればよいでしょうか?
なお、キャプチャ出力のフレームレートは上限に設定しています。
タイムスタンプをいじるだけではうまくいきませんでした。
IMemInputPin::Receiveを使うにしても、それを呼び出す頻度をどのようにすれば
合わせられるかが分からずできません。
0266デフォルトの名無しさん
2007/03/10(土) 07:16:470267デフォルトの名無しさん
2007/03/10(土) 11:46:39仮にキャプチャフィルタが30f/secで投げてくるなら0.033...秒間隔のスタンプが設定されているだろうから
自分でつくる変換フィルタは2枚目に0.033.../2秒のタイムスタンプを足して設定してやる。
んで自分が出力ピンからDeliverするときに、自分で送りたい2枚分、下段の入力ピンReceiveを呼ぶ。
2回送信完了してから、上段にDeliverの結果を返す。
0268デフォルトの名無しさん
2007/03/10(土) 17:49:27の658です。
たぶんこっちで質問したほうがいい気がしたので。
何度やっても同じところ(CopyMemory)で落ちます。
原因として思い当たる件があったらご教示願います。
0269デフォルトの名無しさん
2007/03/10(土) 18:11:4124bit以上のソースなら、BITMAPINFOHEADERだな。
0271268
2007/03/10(土) 19:24:59どこが悪いんでしょう?
0272デフォルトの名無しさん
2007/03/10(土) 19:32:55これか、
CopyMemory( &BitmapInfo.bmiHeader, &(pVideoHeader->bmiHeader),
sizeof(BITMAPINFOHEADER));
探すの面倒だから直リンして欲しいな。
http://pc11.2ch.net/test/read.cgi/tech/1168354839/658
コピー先と、コピーするサイズとか確認してみれば。
&BitmapInfo.bmiHeader が有効なメモリを指してる?
&(pVideoHeader->bmiHeader) が有効なメモリを指してる?
sizeof(BITMAPINFOHEADER) これはあっていると思うけどさ。
0273268
2007/03/10(土) 19:37:59&(pVideoHeader->bmiHeader):30
むう?
0274268
2007/03/10(土) 19:41:33&BitmapInfo.bmiHeader:12F044
&(pVideoHeader->bmiHeader):30
&BitmapInfo.bmiHeaderが怪しいですね。
0275268
2007/03/10(土) 19:42:420276デフォルトの名無しさん
2007/03/10(土) 19:49:110277デフォルトの名無しさん
2007/03/10(土) 19:50:180278デフォルトの名無しさん
2007/03/10(土) 19:51:15もう8回くらいリビルドしてますorz
手動でbmiHeaderを初期化したりしてもダメでした。
0279デフォルトの名無しさん
2007/03/10(土) 20:06:490280268
2007/03/10(土) 20:09:100281265
2007/03/10(土) 23:31:42その方法を試すために、まず出力ピンのメディアタイプを取得しようとしたのですが、
原因不明のエラーが出ます。
何がまずいのでしょうか?
HRESULT (作成した変換フィルタクラス名)::Transform( IMediaSample *pIn , IMediaSample *pOut ){
・・・
//出力ピンのメディアタイプを探す
IEnumPins *pEnumPins;
IPin *pPin;
PIN_DIRECTION PinDirThis;
AM_MEDIA_TYPE *pmt;
this->EnumPins( &pEnumPins );
pEnumPins->Reset();
while( pEnumPins->Next( 1 , &pPin , NULL ) == S_OK ){
pPin->QueryDirection( &PinDirThis );
if ( PinDirThis == PINDIR_OUTPUT ){
pPin->ConnectionMediaType( pmt ); ←定義されてないのに使ってるというようなエラー
}
}
DeleteMediaType( pmt ); ←上と同じエラー
・・・
}
0282265
2007/03/10(土) 23:36:19タイムスタンプ修正は行えるのですが、下段の入力ピンのIMemInputPin::Receiveを
どのようにすれば呼び出せるのかが分かりません。
>>281で示したようなコードでIPinクラスは取得できるのですが、
ttp://msdn.microsoft.com/library/ja/jpdx8_c/ds/ref/class/CBaseInputPin.asp?frame=true#CBaseInputPin
ここを見ると、IMemInputPinはIPinの子クラスなので、それに実装されているReceiveメンバに
アクセスできません。
ご教授願います。
0283デフォルトの名無しさん
2007/03/11(日) 00:38:34CTransformFilter、CTransformInputPin、CTransformOutputPinね
入力サンプルがどう入ってきてどこで変換してどうやって出て行くのか
更にしたのベースクラスの知識も必要になるだろうけどさ
既に下段に接続してる相手のメディアタイプが欲しいなら
出力ピンのCurrentMediaTypeでいいだろ
0284デフォルトの名無しさん
2007/03/11(日) 01:14:56m_pOutput->Deliver するだけでOK
0285265
2007/03/11(日) 03:49:55ありがとうございます。
m_pOutput->CurrentMediaTypeでメディアタイプを取得し、pbFormat(VIDEOINFOHEADER)内の
AvgTimePerFrameを変更してやることでフレームレートの変更を試みてみました。
しかし、今まで通りの10000000/29.97[100ns]であれば下流のフィルタ(色空間変換フィルタ)に
繋がるのですが、倍の10000000/59.94[100ns]では接続できませんでした。
残念ながら対応していないようです。
0286265
2007/03/11(日) 03:50:22ありがとうございます。
一枚のサンプルに対し二度出力できるようになりました。
しかし、fpsがきれいに倍化する期間と倍にならない期間が移り変わってうなりのようになっています。
二度の出力中、一枚目のスタートと二枚目のエンドのタイムスタンプはいじっていないので、
そこでの同期は保障されていると思ったのですが・・・
どのようにすれば改善できるでしょうか?
一枚のサンプルに対して行う処理を以下に示しておきます。
//一枚目の処理
・・・
// 入力サンプルのタイムスタンプを取得する
pIn->GetTime( &TimeStart , &TimeEnd );
//エンドタイムを1/59.94[s]早める
TimeEnd -= 166833; //[100ns]
pOut->SetTime( &TimeStart , &TimeEnd );
//下流フィルタにDeliverする
m_pOutput->Deliver( pOut );
//二枚目の処理
・・・
// 入力サンプルのタイムスタンプを取得する
pIn->GetTime( &TimeStart , &TimeEnd );
//スタートタイムを1/59.94[s]遅くする
TimeStart += 166833;//[100ns]
pOut->SetTime( &TimeStart , &TimeEnd );
//下流フィルタにDeliverする
m_pOutput->Deliver( pOut );
0287デフォルトの名無しさん
2007/03/11(日) 05:56:40部分的コードなのでわからないが、サンプル使いまわしたりはしていないよね?
0288265
2007/03/11(日) 09:37:13試しに
AvgTimePerFrame /= 2;
としてみましたが、やはり受け付けませんでした。
AvgTimePerFrame /= 1;
だったら大丈夫です。
>サンプル使いまわしたりはしていないよね?
他の方が作られたサンプルを使いまわししてます。
ですが、Transformメソッドをいじるだけくらいのシンプルな変換フィルタでして、その処理部分に関しては
すべて書き換えています。
0289デフォルトの名無しさん
2007/03/11(日) 11:18:23> Transformメソッドをいじるだけくらい
CTransformFilter::Receive内でもDeliverしてるからな。その辺り大丈夫だよね?
文面から察するに
OutputPin::CurrentMediaTypeでメディアタイプ取得できるってことはピンが繋がっている状態なのだが
一旦Pin接続解除した後にフレームレート倍のメディアタイプを色変換に提示(OutputPin::GetMediaTypeで設定)して
再接続を試みてるんだよね?
0290265
2007/03/11(日) 11:56:35>EndTimeが0で来る場合もあるのでチェックして下さい。
チェックしてみましたが、EndTimeが0で来る様子は見られませんでした。
>CTransformFilter::Receive内でもDeliverしてるからな。その辺り大丈夫だよね?
どうなんでしょう・・・影響があるかは判断しかねます・・・
メディアタイプ変更の件ですが、グラフエディタ上で接続が断たれた状態からピンを繋ごうとしたとき、
キャプチャフィルタのメディアタイプから変更しなかった場合は成功し、変更すると失敗する、というかんじです。
フレームレートの不安定ですが、もしかしたら処理負荷が大きいためかもしれません。
表示ウィンドウのサイズを大きくする(ネイティブサイズは同じ)とフレームレートが落ちていきます。
CPUの使用率は60〜70%ですが、VMR9側の問題でこのようなことになっているのかもしれません。
この負荷の原因として、変換フィルタとVMR9との間に挟まっている色空間変換フィルタが挙げられます。
キャプチャフィルタから直接VMR9に繋ぐときは介在せず、CPU負荷も小さいです。
ところが、同じメディアタイプを設定しているにも関わらず、変換フィルタを挟むと、その後に色空間変換フィルタ入ってきます。
キャプチャから直接VMR9の場合はシステムメモリは介さず、直接ビデオRAMに移す、というようなことでもしているから
こんなことになるのでしょうか?
もし変換フィルタから直接VMR9に繋げられるような方法がありましたら教えてください。
0291268
2007/03/11(日) 16:50:34(そっちのソースはCopyMemoryで落ちないので)
で、そっちのBitmapInfoのbmiHeaderを調べてみたところ、他の値は想定の範囲内なんですが
BitmapInfo.bmiHeader.biCompression = 1685288548
と�dでもない値が入っていて、どうやらこいつが原因だと判明。
これって何なんでしょ?
ぐぐったらdvsdとか出てきたんですがよくわかりません。
0292268
2007/03/11(日) 16:54:12BitmapInfo.bmiHeader.biCompression=BI_RGB;
なんてことをやると一応動くようにはなりました。
ただ取得できる値がおかしいので正確に動いてる感じではありませんが。
0293268
2007/03/11(日) 17:04:27void Cam::getImage()
{
HRESULT hr;
// ビットマップ ヘッダーから DIB を作成し、バッファへのポインタを獲得する。
hBitmap = CreateDIBSection(0, &BitmapInfo, DIB_RGB_COLORS, (void **)&buffer, NULL, 0);
firstDIB = FALSE;
// イメージをバッファにコピーする。
DIBBuffer = (long *)GlobalAlloc(GPTR,bufsize);
hr = pGrab->GetCurrentBuffer(DIBBuffer,NULL);
hr = pGrab->GetCurrentBuffer(DIBBuffer,(long *)buffer);
}
AVIを無理やりBITMAPにしているから無理が生じているような予感がちらほら。
0294デフォルトの名無しさん
2007/03/11(日) 18:34:300295デフォルトの名無しさん
2007/03/11(日) 18:42:48レンダラに直接接続したければ、すべてのフォーマットを出力で対応する必要がある。
まあでも32bitでだいたいの環境はいける。
接続できなければレンダラが対応していないのだろう。正しい接続の仕方ならばね・・・。
0297デフォルトの名無しさん
2007/03/11(日) 20:32:01それをキャプチャデバイスとレンダラの間に入れてみてくれ。
やっぱり色空間変換フィルタが必要とされるか?されないか?
0298デフォルトの名無しさん
2007/03/11(日) 20:35:020299265
2007/03/11(日) 21:09:48自前のWindowsSDKにないのでDirectXのExtrasをダウンロードし、その中からNullInplaceフィルタを見つけたのですが、
ビルドすると、PC内に存在しないatlbase.hが無いと言われてしまいます。
無念です・・・
0300デフォルトの名無しさん
2007/03/11(日) 21:44:59> どうなんでしょう・・・影響があるかは判断しかねます・・・
どう実装してるかわからんけど、もしかしてTransformメソッドの中で2回Deliverしてる?
CTransformFilter::Receive良く読んで理解してるよね?
0301デフォルトの名無しさん
2007/03/12(月) 08:02:05上流フィルタからの映像が来る来ないに関わらず非同期でフレームレートを作るフィルタが出来なかったんだよな。
今悩んでいる子がここまでやるのなら全力でサポートするよ
0302デフォルトの名無しさん
2007/03/12(月) 08:04:430303265
2007/03/12(月) 08:07:00そうです、Transformメソッドの中で2回Deliverしてます。
サンプルの流れがいまいち理解できないです。
そこで今行っている処理の流れを分かる範囲でまとめてみました。
[キャプチャフィルタ]-[変換フィルタ(自作)]-[色空間変換フィルタ]-[VMR9]
[色空間変換フィルタ]の入力ピンからの[変換フィルタ]への呼び出し
CTransformFilter::Receive (CTransformFilter::InitializeOutputSampleを呼び出す)
↓
CTransformFilter::InitializeOutputSample (新しいサンプルを[キャプチャフィルタ]の出力ピンから取得する)
↓
CTransformFilter::Transform
(サンプルの処理)
↓
CBaseOutputPin::Deliver (IMemInputPin::Receiveを呼び出す) ←これを>>286のように2回呼び出しています
↓
IMemInputPin::Receive ([変換フィルタ]の出力サンプルを取得する)
↓
[色空間変換フィルタ]での処理
↓
[VMR9]が付与されたタイムスタンプに従って画面に表示
疑問点
・>>289さんの言う、CTransformFilter::Receive内でもDeliverしている、という記述がMSDNで見つけられませんでした。
上記で言えばどの時点で発生するのでしょうか?
・最初のCTransformFilter::Receiveが呼び出されるタイミングが分かりません。
サンプルが変換フィルタで処理されるサイクルはどのようになっているのでしょうか?
0304265
2007/03/12(月) 10:06:54・タイムスタンプがないプレビューピンからの映像に対して変換を行ったところ、同じうなり現象(>>284)が起きた。
・一枚のサンプルに対して二度の処理を行うが、片方の絵を真っ黒にしてみると、フレームが倍化していないときは
二枚目の絵のみが表示される状態であることが分かった。
・二度目のDeliverを外したところ、フレーム倍化の時間が若干延び、倍化していない期間においても
一枚目の絵と二枚目の絵が交互に表示された。
このとき、キャプチャーピンからの映像では倍化していない期間で絵が0.5秒ほどストップすることが頻繁に起こった。
プレビューピンからの映像ではこのストップ現象は起きない。
0307265
2007/03/12(月) 17:31:09(同時にこの手法のダメさを裏付けるものでもありましたが・・・)
条件は
・キャプチャフィルタのプレビューピンに繋げる(よってタイムスタンプの設定は意味なし)
・二度目のDeliverを無くす(あるともたつきが起こる)
・画面表示をビデオのネイティブサイズである640×480に対し、約2倍以上にするとフレームレートのうなり現象が
無くなり約60fpsで一定となる。
このとき、CPUの使用率はサイズが大きくなるにつれて上がる。
これらの現象から導き出される結論として、
一度目のDeliverと二度目の(本来行われる)Deliverは連続ですぐに行われ、二度目のDeliverにより送信された
二枚目は一枚目で設定したタイムスタンプがあろうが無かろうが即座に描画される。
CPUの負荷が上がり、すぐに二度目のDeliverが処理できない場合、その間一枚目が表示されることとなり、この時間が
ちょうど1/60秒となるときキレイにフレームが倍化されることとなる。
描画サイズが小さいときはCPUに余裕がある期間が存在し、そのときは二枚目のみが表示される。(フレームが倍化されない)
ということが言えると思います。
よって、一度のTransformメソッドで二度のDeliverを用いる作戦はアウトということになりました・・・。
0308デフォルトの名無しさん
2007/03/12(月) 18:47:41出力メディアタイプと違うサンプルを出力しても、期待した通りに動かないよね。
あと処理が間に合わない時も、どこかのフィルタが捨てると思う。
一度CPU負荷がほとんど発生しないプロトタイプを作って実験して、処理遅れなのかそれとも別の問題なのか調べて見ては?接続の問題も解決を。
リアルタイムで処理したいんだよね?
それとDirectShowで「サンプル」といえば、IMediaSample2などのデータの事をしめします。
>>287 は、一度ダウンストリームに送信したサンプルをまた再利用するなよってこと。
0309デフォルトの名無しさん
2007/03/12(月) 21:53:42これがマイナスだとレンダラに間に合って届いている。
プラスだと間に合ってないので到着したとたんにレンダリングされたりして
動きがギクシャクしたり捨てられてカクついたりする
0310デフォルトの名無しさん
2007/03/12(月) 22:14:45>303 サンプルの流れについて
まず上流(キャプチャデバイス)の出力ピンが、変換フィルタの入力ピンCTransformInputPin::Recieveにサンプルを渡す。
入力ピンRecieveはCTranscormFilter::Receiveを呼ぶ。んでTransformメソッドでサンプルを変換した後、
出力ピンから下流(色変換フィルタ)のRecieveを呼び出す(サンプルを渡す) という流れ
>289で「Deliverしてる」って表現したのはマズかったかな。要は下流にサンプルを渡すってことなんだ。
下流の入力ピンのReceiveを呼び出す(サンプルを渡す)。コレがDeliverの正体。
CBaseOutputPin::Deliverメソッドのソースを見てみるといいよ(Baseclassesのamfilter.cppな)
んでTransformフィルタなんだけど、出力ピンのDeliverメソッドは呼んでいないんだ
どうやって送信してるかというと、CTransformFilter::Receiveの中に次のコードがある
hr = m_pOutput->m_pInputPin->Receive(pOutSample);
これ。ここで送信してる。直訳(?)すると、自分の出力ピンに繋がってる入力ピンのReceiveに
Transoformメソッドで変更を加えたサンプルを渡す ってこと。
長いので続く
0311デフォルトの名無しさん
2007/03/12(月) 22:48:26> CTransformFilter::InitializeOutputSample (新しいサンプルを[キャプチャフィルタ]の出力ピンから取得する)
InitializeOutputSampleは出力するサンプルの準備をするメソッドなんだ。
ここでは送信するサンプルのバッファをサンプルと結びつける(バッファ自体は出力ピンが確保してる)
HRESULT hr = m_pOutput->m_pAllocator->GetBuffer(
その後で、上流から受け取ったサンプルのプロパティ(各種フラグと言ったほうがわかりやすいか)や時間情報を
出力するサンプルに設定していく。これがInitializeOutputSampleの役割。
このことから、上流から受けたサンプルと、自分で送るサンプルは全くの別物であるということがわかる。
送信が済んだら、このサンプルをリリースすることでバッファの開放などが行われる
(CTransformFilter::Receiveの最後の方 pOutSample->Release(); )
ちなみに上流から受けたサンプルをダイレクトにそのまま下流に出力するのはCTransInPlaceFilterだ
つづく
0312デフォルトの名無しさん
2007/03/12(月) 23:10:36しかも3回目のサンプルの時間情報は上流から受けた時間そのもの
0313デフォルトの名無しさん
2007/03/12(月) 23:13:13そういう設計なんでこざいます だからここから送信したら ブーブー
TransformInputPin::Receiveをオーバーライドしないとアカンねん
0314デフォルトの名無しさん
2007/03/12(月) 23:23:29サンプルのタイムスタンプ見てレンダラが表示のタイミングを待ったり、時には捨てたりするアルよ
サンプルの不連続性(Discontinuity)とか同期ポイント(SyncPoint)を示すフラグの扱いとか
注意してくれよ キレイなフィルタを作りましょう。んじゃ頑張れ
0315265
2007/03/12(月) 23:33:31了解です。
>それとDirectShowで「サンプル」といえば、IMediaSample2などのデータの事をしめします。
そういうことでしたか・・・
失礼しました。
>>309
ありがとうございます。
調べてみます。
>>310-314
とても丁寧にありがとうございます。
がんばります。
0316デフォルトの名無しさん
2007/03/14(水) 22:52:01dvsdなんかではCreateDIBSectionに失敗しそうな気がするけど、それはないの?
あと、フィルタいじれるなら入力ピンのCheckMediaTypeでMEDIASUBTYPEの
RGB24かRGB32以外を弾くようにすれば、その辺不問にできるような気がするけど・・・。
0317デフォルトの名無しさん
2007/03/15(木) 01:14:32DVDをAVIにして保存したいんですが、YUYをRGBに変換するフィルタとAVIを書くフィルタは自前で作るのですか?
色々やってみてダメだったらヒントください。
ちょっと頑張ってくる。
0319デフォルトの名無しさん
2007/03/15(木) 14:11:19(1) 普通のDIBを用意して、そこにDrawDibDrawで描く
(2) 入力ピンのフォーマットをRGB24/RGB32に限定して、フィルタグラフ側で変換してもらう
(3) 自分でDVをでコードする
1,2は実質的にはaviのというかvfwのdvコーデックが使われる。
「やらなきゃいけない」かどうかは自分で決めればいい。
やりたくないならやらなくていいんじゃない?
0321268
2007/03/15(木) 18:38:43(2)を試してみます。
ttp://webcamxtra.sourceforge.net/
これを活用すればいけそうな気もしてるんですけどね・・・。
今までウェブカメラは自力で処理できていたのでどうにかしたいもんです。orz
0322268
2007/03/15(木) 18:52:30あとはDrawDibDrawの引数だけだと思うので、ちょっくら追ってみます。
0323デフォルトの名無しさん
2007/03/15(木) 23:07:58DVD Navigaterのフィルタを取ってRenderStreamすればAVIにできると思ったのにダメでした。
DVDをAVIにして保存する方法って何かあるんでしょうか。
サンプルグラバつなげられれば保存できる気もするんだけどPINをつなげられない。
0324デフォルトの名無しさん
2007/03/16(金) 00:54:44ビデオ タイプについては、サンプル グラバは VIDEOINFOHEADER 形式を必要とします。VIDEOINFOHEADER2 や DVINFO などの
他の形式タイプを必要とするフィルタに接続することはできません。
このため、MPEG-2 や DV ビデオ、またはフィールド ベースの (インターレース)
ビデオとの互換性はありません。
http://www.microsoft.com/japan/msdn/directx/techart/grabbersample.aspx#limitationsofthedirectshowsamplegrabber
うぉー、絶望的なことかいてあった。orz....
サンプルグラバに繋がらないわけだ。
Overlay Mixer −> サンプルグラバ −>AVIMUX という流れができるか明日ためしてみる。
0325268
2007/03/16(金) 16:53:10というわけで他の方法試してみます。
0326デフォルトの名無しさん
2007/03/16(金) 16:55:370330268
2007/03/16(金) 17:24:46何か記述が足りない気がしてきた。
サンプル探してるんですけど全然見つからないんですよね。orz
0331デフォルトの名無しさん
2007/03/16(金) 21:58:23サンプルグラバ使ってるんですよね?
SetMediaTypeでMEDIASUBTYPE_RGB24指定して
dvsdで流れてこないようにしたらどうですか?
あなたのレスをすべて追っかけてるわけじゃないんで、外してるかもしれませんが。
■ このスレッドは過去ログ倉庫に格納されています