我正在研究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
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
由于
答案 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
,因此使用了错误的调用约定,this
为NULL
。
答案 1 :(得分:0)
此问题不太可能仅与COM相关。你建议COM似乎以某种方式调用你的回调接口,而它是eventaully NULL
。但如果是这种情况,即使没有向回调实现添加任何代码,您也会看到崩溃。
您可能知道,COM中的所有接口函数都是virtual
。调用这样的函数涉及首先解除引用接口指针并读取相应vtable
条目的内容。因此,在virtual
接口指针上调用NULL
函数会立即导致访问冲突。 OTOH在NULL
对象上调用非虚函数是可以的(至少从实现的角度来看,将C ++标准放在一边)。
我建议你仔细看看callstack。我相信正确调用COM方法。但是在您的特定示例中,您可能无法直接实现COM回调方法,而是可能会被某些包装器代码调用(它很可能是DirectShow库)。你应该在那里寻找问题。