0

我正在研究 DirectShow filtergraph 的基本实现,以从我的应用程序中的网络摄像头获取图像。我已经阅读了文档并创建了一个简单的实现。我创建了这个图:设备 --> samplegrabber -> nullrenderer。

我正在检查所有可能的结果值,并且我没有从 SDK 中得到任何错误。

问题:

不知何故,我的回调被正确调用了,但是每当我在回调函数中添加任何代码(这对 SampleCB 和 BufferCB 都有效)时,我的应用程序就会静默崩溃。

我在 BufferCB 中添加了一个断点,我看到“this”是 0x0000000 / NULL。因为我在创建图表时检查了所有结果值,所以我的猜测是我的图表设置是正确的,并且这个问题可能与 COM 相关。但这只是一个疯狂的猜测。

因为 Windows 7.0 SDK 不提供包含 ISampleGrabber 接口的接口的 qedit.h,所以我自己创建了这个文件并添加了相关接口(我在谷歌搜索时在帖子的某处找到了内容)。

我从文档中复制了 saveGraph 函数,以便可以在 GraphEdit 中测试图形。添加渲染节点时,我看到 GraphEdit 会自动编辑颜色转换节点。当我使用渲染器运行图表时,我可以看到来自网络摄像头的图像(在 graphedit 中)。

我已经在这个要点中粘贴了所有相关代码(带有调用堆栈跟踪+变量)

有人知道我如何调试这个或这个错误可能是什么?它可能与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 相关接口。一种方法是使用旧的 SDK,所有标头仍在上面。另一种方法是#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 似乎以某种方式调用您的回调接口,而它是 eventaully NULL。但如果是这种情况,即使没有向回调实现添加任何代码,您也会看到崩溃。

您可能知道,COM 中的所有接口函数都是virtual. 调用这样的函数涉及首先取消引用接口指针并读取相应vtable条目的内容。因此,在接口指针上调用virtual函数NULL会立即导致访问冲突。OTOH 在对象上调用非虚拟函数NULL是可以的(至少从实现的角度来看,将 C++ 标准放在一边)。

我建议您仔细查看调用堆栈。我相信 COM 方法被正确调用。但是,在您的特定示例中,您可能不会直接实现 COM 回调方法,而是可能由一些包装器代码调用它(很可能是 DirectShow 库)。你应该在那里寻找问题。

于 2013-01-10T19:21:28.817 回答