お世話になっています。
USBカメラキャプチャを作成しています。
DirectXの日本語ヘルプにある基準クロックに関連する項にあるサンプル
のクロック作成箇所を初期化部分に追加したのですが、
ビルド時に
error C3861: 'CreateMyPrivateClock': 識別子が見つかりませんでした
というメッセージが出力されます。
他にCreateMyPrivateClock関数を使用しないやり方では
IReferenceClock *pClock = NULL;
hr=m_pGraph->QueryInterface(IID_IReferenceClock, (void**)&pClock);
⇒ hr(戻り値)は、E_NOINTERFACEが帰ってきます。
IBaseFilter *pSrc;モニカでバインドしたオブジェクト
CComPtr<ICaptureGraphBuilder2> pCGB2;
// ↑上記と異なる書き方をしてすみません。
hr=pCGB2->FindInterface(&PIN_CATEGORY_CAPTURE ,&MEDIATYPE_Video,
pSrc, IID_IReferenceClock,(void**)&pClock);
⇒ hr(戻り値)は、E_FAILが帰ってきます。
ピクセルクロックの変更方法をご存知の方がおられましたら、
ご教授願えませんでしょうか?
環境:
WindowsXP(SP2)
Visual Studio 2005 Professional Edition SP1
DirectX SDK(March 2008)
Platform SDK for Windows Server 2003 R2
USBカメラ: エドモンド オプティクス ジャパン EO-0413
ソフト: SDIベース(共有DLLでMFCを使う)
以上よろしくお願いします。
> ピクセルクロックの変更方法をご存知の方がおられましたら、
自分はした事無いので判らない。
マクシムさんの考えている方向(ビデオキャプチャフィルタのクロック変更で実現?)で
合っているのかどうかすら判断不可。
なので、マクシムさんが挙げている事案についての個別回答。
> error C3861: 'CreateMyPrivateClock': 識別子が見つかりませんでした
そのサンプルにこう注意書きがある。
> この例では、CreateMyPrivateClock がクロックを作成し、IReferenceClock ポインタを
> 返すアプリケーション定義関数であることを仮定している。
つまり、CreateMyPrivateClock なんて関数は実際に無いので、↑仕様を満たす関数を
自力で実装してね。って事。
> hr=m_pGraph->QueryInterface(IID_IReferenceClock, (void**)&pClock);
> ⇒ hr(戻り値)は、E_NOINTERFACEが帰ってきます。
要求する相手を間違っている。
--------
// IGraphBuilder m_pGraph;
CComQIPtr<IMediaFilter, &IID_IMediaFilter> filter(m_pGraph);
CComPtr<IReferenceClock> clock;
filter->GetSyncSource(&clock);
> hr=pCGB2->FindInterface(&PIN_CATEGORY_CAPTURE ,&MEDIATYPE_Video, pSrc, IID_IReferenceClock,(void**)&pClock);
> ⇒ hr(戻り値)は、E_FAILが帰ってきます。
IMediaFilter は QueryInterface() による IReferenceClock の公開はしていないので
FindInterface では×…って辺りかも?若しくは検索条件が外れていたとか。
--------
// IBaseFilter pSrc;
pSrc->GetSyncSource(&clock);
gakさん
ご回答ありがとうございました。
見るのが遅れてしまいまい、検証が先程終わりました。
IReferenceClockポインタの取得は、どちらの書き方でも上手くいきました。
どの様になったかは、解決メッセージで後日報告します。
取り急ぎ、お礼まで。
お世話になっています。
少し動作確認できる時間できたので、動かせてみたのですが、
前回IReferenceClockポインタの取得はできましたが、
まだ任意のクロックが変えれません。
// IBaseFilter pSrc;
pSrc->GetSyncSource(&clock);←こちらの方がシンプルでしたので
を行う前にフィルタ等の初期化後、
1度IMediaControlの
Run();
Stop();
を実行してストリーム タイム取得する必要があります。
前回、最高fps動作できたのは、graphedtを使用し、Captureソースを設置
した後、出力のピンプロパティからピクセルクロックを最高周波数に変えていた
からでした。
たしかにクロックを読み出しただけで、クロック変更できないですよね。
それで、IAMClockAdjustのSetClockDeltaを用いて任意の
クロック設定(カレント値からの差分)にしようと思ったのですが、
前回同様どこから取得して良いのかわかりません。
IReferenceClockの時の様にQueryInterface()ではダメでしたから
引数がIAMClockAdjustとなっている関数を探しましたが、見つからず。
インスタンスを作成後、IGraphBuilderに設置してみようとしましたが、
ダメでした。。。
CComPtr<IAMClockAdjust> pSetCLK;
if( S_OK != pSetCLK.CoCreateInstance(CLSID_SystemClock, NULL,
CLSCTX_INPROC) ){TRACE("IAMClockAdjust Failed\n"); return FALSE;}
CComQIPtr< IBaseFilter, &IID_IBaseFilter > pClockFilter(pSetCLK);
if ( S_OK != m_pGraph->AddFilter(pClockFilter, L"Clock Device") ){TRACE("IAMClockAdjust Failed2\n"); return FALSE;}
CSystemClockクラスのインスタンス(CreateInstance)を作成して、
m_pGraphフィルタにどの様にして関連付けたら良いのか
わからなくなってしまい、m_pGraphに関連付けされたSetClockDeltaを
行いたいのですが、どの様にすれば良いか、ご教授願えませんでしょうか?
よろしくお願いします
> IAMClockAdjustのSetClockDeltaを用いて...どこから取得して良いのかわかりません。
MSDNに
> The System Reference Clock exposes this interface.
とあるので IReferenceClock に QI で取れるかと思ったがこっちの環境ではダメだった。
「IReferenceClock は IAMClockAdjust を公開する」と上文から読んだのでちょと意外。
仮定だけど、標準の IReferenceClock では公開(用意)していないのかもしれない。
とりあえず、以降の拡張性を考慮して型のみ用意しているって感じで。
※公式資料を確認した上での回答では全く無い…ただの想像です
>> m_pGraphに関連付けされたSetClockDeltaを行いたいのですが
いっそ IAMClockAdjust を利用しない方向を考えてみてはどう?
http://msdn.microsoft.com/ja-jp/library/cc369470.aspx
にあるサンプルコードを CreateMyPrivateClock()(最初の投稿で話出たヤツ)に
放り込めば、現在マクシムさんが直面している事は実装できそうな気がする。
http://msdn.microsoft.com/en-us/library/ms786617(VS.85).aspx
日本MSDNでは「every second」を「2 秒ごと」とか誤訳していたりするので
英語で問題ないならこっち見た方がよいかもしんない。
gakさん
いつもありがとうございます。
アドバイスを元に試してみましたが、ピクセルクロック
を自前ソフトで変更できませんでした。
このカメラに関しては
graphedt.exeを用いてピクセルクロックを任意に設定
して使用する事にし、ちまちま試みてみようと思います。。
//一連の初期化は省略
CComQIPtr< IMediaControl, &IID_IMediaControl > pMediaControl = m_pGraph;
pMediaControl->Run(); //少し
pMediaControl->Stop();//省略
CComPtr<IReferenceClock> pClock;
CComPtr<IAMClockAdjust> pSetCLK;
IMediaFilter *pMediaFilter = 0;
m_pGraph->QueryInterface(IID_IMediaFilter, (void**)&pMediaFilter);
pMediaFilter->GetSyncSource(&pClock);
DWORD dwAdviseToken;
HANDLE hEvent;
REFERENCE_TIME rtPeriodTime = 10000*500; // Ex:500m秒間隔
REFERENCE_TIME rtNow;
REFERENCE_TIME rtAft;
///////////置き換えStart
hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
pClock->GetTime(&rtNow); time = (double)rtNow;
TRACE("基準時間: %lf(100ns)\n", time);
pClock->AdviseTime( rtNow, rtPeriodTime, (HEVENT)hEvent, &dwAdviseToken );
::WaitForSingleObject(hEvent, INFINITE);
pClock->GetTime(&rtAft); time = (double)rtAft-rtNow;
TRACE("基準時間: %lf(100ns)\n", time);
///////////置き換えEnd
pMediaFilter->SetSyncSource(pClock);
pMediaFilter->Release();
⇒結果
⇒AdviseTimeを用いて(AdvisePeriodicは難しかったので)ためして
⇒みたのですが、
⇒rtAft-rtNowの差分時間が取得できるぐらいです。
⇒rtAft-rtNow == rtPeriodTime = 10000*500; // 500m秒間隔
///////////置き換えStart−End
の箇所を下記の様に変えて
hr=pClock->QueryInterface(IID_IAMClockAdjust, (void**)&pSetCLK);
if(hr!=S_OK) TRACE("Failed\n");
pClock->GetTime(&rtNow); time = (double)rtNow;
TRACE("基準時間: %lf(100ns)\n", time);
rtNow = 5000000;
hr=pSetCLK->SetClockDelta(rtNow);
if(hr!=S_OK) TRACE("Failed2\n");
pClock->GetTime(&rtAft); time = (double)rtAft;
TRACE("基準時間: %lf(100ns)\n", time);
⇒結果
⇒rtAftには、取得したrtNowに5000000プラスされた値に
⇒なっているだけで、ピクセルクロックは変えれてないです。
基準時間からクロックに変換するのが謎です。
graphedt.exeだと、本カメラは5MHz−40MHzと設定できます。
一体どうやっているのでしょう?
> 一体どうやっているのでしょう?
IAMStreamConfig
IAMStreamConfig::SetFormat
VIDEOINFOHEADER
VIDEOINFOHEADER::AvgTimePerFrame
VIDEOINFOHEADER::dwBitRate
辺りなんだろうか。
でもこれだと画像だけでなく音声も影響を受けてしまうのかな?
# IAMStreamConfig を画像/音声個別に取れるなら画像のみのフレームレートを
# 指定できそうではあるが…キャプチャ時に DirectShow フィルタがどんな感じで
# 繋がるかを思い出せない俺には判断できない…
AvgTimePerFrame と dwBitRate の関係についてはこのページにちょっと載ってる
http://msdn.microsoft.com/ja-jp/library/cc371290.aspx
ツイート | ![]() |