正在调用DirectShow Sample Grabber但回调中的'this'为NULL

时间:2013-01-10 18:52:49

标签: c++ windows webcam directshow samplegrabber

我正在研究DirectShow过滤器图的基本实现来获取图像 从我的应用程序中的网络摄像头。我已经阅读了文档并创建了一个简单的文档 实现。我创建此图:device - > samplegrabber - > nullrenderer。

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

问题:

不知怎的,我的回调被正确调用,但每当我在里面添加任何代码时 我的应用程序的回调函数(这对SampleCB和BufferCB都有效) 无声地崩溃。

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

因为Windows 7.0 SDK不提供包含接口的qedit.h 对于ISampleGrabber接口,我自己创建了这个文件并添加了相关的文件 界面(我在google搜索时在帖子的某个地方找到了内容)。

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

I've pasted all relevat code in this gist (with a callstack trace + variables)

有人知道如何调试此错误或此错误可能是什么?可以吧 与COM有关吗?

更新:尝试访问 ISampleGrabberCB

中的成员时的callstack
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    

由于

2 个答案:

答案 0 :(得分:2)

由于qedit.h不再在Windows SDK上,因此必须定义Sample Grabber相关接口。一种方法是使用较旧的SDK,其中仍然包含所有标头。另一种方法是#import类型库中的接口。而且你总是可以在代码中重新定义它们。

您可以从there获取正确的定义:

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

答案 1 :(得分:0)

此问题不太可能仅与COM相关。你建议COM似乎以某种方式调用你的回调接口,而它是eventaully NULL。但如果是这种情况,即使没有向回调实现添加任何代码,您也会看到崩溃。

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

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