0

アプリケーションで Web カメラから画像を取得するために、DirectShow フィルターグラフの基本的な実装に取り​​組んでいます。ドキュメントを読み、簡単な実装を作成しました。このグラフを作成します: device --> samplegrabber -> nullrenderer.

可能なすべての結果値をチェックしていますが、SDK からエラーは発生しません。

問題:

どういうわけか、コールバックは正しく呼び出されていますが、コールバック関数内にコードを追加するたびに (これは SampleCB と BufferCB の両方でカウントされます)、アプリケーションが静かにクラッシュします。

BufferCB にブレークポイントを追加しましたが、'this' が 0x0000000 / NULL であることがわかります。グラフを作成するときにすべての結果値をチェックするので、私の推測では、グラフの設定は正しく、この問題は COM に関連している可能性があります。しかし、これは単なる推測です。

Windows 7.0 SDK には、ISampleGrabber インターフェイスのインターフェイスを含む qedit.h が用意されていないため、このファイルを自分で作成し、関連するインターフェイスを追加しました (内容は、グーグル検索中に投稿のどこかにありました)。

ドキュメントから saveGraph 関数をコピーして、GraphEdit でグラフをテストできるようにしました。レンダー ノードを追加すると、自動的に色変換ノードが GraphEdit によって編集されることがわかります。レンダラーでグラフを実行すると、(graphedit で) Web カメラからの画像を見ることができます。

関連するすべてのコードをこの要点に貼り付けました (コールスタック トレース + 変数を含む)

これをデバッグする方法や、このエラーが何であるかを知っている人はいますか? COM関連でしょうか?

更新:私のメンバーにアクセスしようとしたときのコールスタック ISampleGrabberCB

ntdll.dll!_ZwRaiseException@12()  + 0x12 bytes  
ntdll.dll!_ZwRaiseException@12()  + 0x12 bytes  
msvcr100d.dll!__lock_fhandle(int fh)  Line 467  C
qedit.dll!CSampleGrabber::Receive()  + 0x18c bytes  
qedit.dll!CTransformInputPin::Receive()  + 0x33 bytes   
quartz.dll!CBaseOutputPin::Deliver()  + 0x22 bytes  
quartz.dll!CVideoTransformFilter::Receive()  + 0x1aa bytes  
quartz.dll!CTransformInputPin::Receive()  + 0x33 bytes  
quartz.dll!CBaseInputPin::ReceiveMultiple()  + 0x33 bytes   
qcap.dll!COutputQueue::ThreadProc()  + 0x103 bytes  
qcap.dll!COutputQueue::InitialThreadProc()  + 0x16 bytes    
kernel32.dll!@BaseThreadInitThunk@12()  + 0x12 bytes    
ntdll.dll!___RtlUserThreadStart@8()  + 0x27 bytes   
ntdll.dll!__RtlUserThreadStart@8()  + 0x1b bytes    

ありがとう

4

2 に答える 2

2

qedit.h は Windows SDK に含まれなくなったため、Sample Grabber 関連のインターフェイスの定義を取得する必要があります。1 つの方法は、すべてのヘッダーが残っている古い SDK を使用することです。もう 1 つの方法は#import、タイプ ライブラリからインターフェイスを使用することです。そして、コード内でいつでも再定義できます。

そこから正しい定義を取得できます。

struct __declspec(uuid("0579154a-2b53-4994-b0d0-e773148eff85"))
ISampleGrabberCB : IUnknown
{
  virtual HRESULT __stdcall SampleCB (double SampleTime, struct IMediaSample * pSample ) = 0;
  virtual HRESULT __stdcall BufferCB (double SampleTime, unsigned char * pBuffer, long BufferLen ) = 0;
};

あなたはあなたのものを持っていなかったので__stdcall、間違った呼び出し規約が使用され、あなたthisNULL.

于 2013-01-10T19:59:33.367 に答える
0

この問題がCOMのみに関連している可能性はほとんどありません。あなたは、COMがどういうわけかあなたのコールバックインターフェースを呼び出すように見えるが、それは最終的にはであることを提案しますNULL。ただし、その場合は、コールバック実装にコードを追加しなくてもクラッシュが発生します。

ご存知かもしれませんが、COMのすべてのインターフェース機能はvirtualです。このような関数を呼び出すには、最初にインターフェイスポインターを逆参照し、適切なvtableエントリの内容を読み取る必要があります。したがってvirtual、インターフェイスポインタで関数を呼び出すNULLと、すぐにアクセス違反が発生します。オブジェクトに対して非仮想関数を呼び出すOTOHは問題ありませんNULL(少なくとも実装の観点からは、C ++標準は別として)。

コールスタックを注意深く見ることをお勧めします。COMメソッドが正しく呼び出されていると思います。ただし、特定のサンプルでは、​​COMコールバックメソッドを直接実装しない場合があります。代わりに、ラッパーコードによって呼び出される場合があります(DirectShowライブラリの場合は非常に可能性があります)。そこで問題を探す必要があります。

于 2013-01-10T19:21:28.817 に答える