0
votes

I'm working on a basic implementation of a DirectShow filtergraph to get images from my webcam in my application. I've read the documentation and created a simple implementation. I create this graph: device --> samplegrabber -> nullrenderer.

I'm checking all the result values I possibly can and I get no errors form the SDK.

The problem:

Somehow my callback is being called correctly, but whenever I add any code inside the callback functions (this counts for both SampleCB and BufferCB) my application crashes silently.

I've added a breakpoint in my BufferCB and I see that 'this' is 0x0000000 / NULL. Because I check all the result values when I create my graph, my guess is that my graph setup is correct and that this problem could be related to COM.. but this is just a wild guess.

Because the Windows 7.0 SDK does not provide a qedit.h, which contains the interface for the ISampleGrabber interface, I created this file myself and added the relevant interface (I found the contents somewhere on a post while googling).

I copied the saveGraph function from the documentation so I could test the graph in GraphEdit. When I add a render node, I see that automatically a color conversion node is edit by GraphEdit. When I run the graph with a renderer I can see the images from the webcam (in graphedit).

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

Does someone have any idea how I can debug this or what this error might be? Could it be COM related?

Update: callstack when trying to access a member in my 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    

Thanks

2
That's way too much code to go through. And way too many (void**)&something to understand what pointers it uses.Bo Persson
How do you define ISampleGrabberCB after all? If you defined it incorrectly, the symptom will be exactly as you are having. Here is how you need to do it: alax.info/trac/public/browser/trunk/Utilities/…Roman R.
Roman R, thanks, this is how I have defined it: gist.github.com/687700c5ac58067db0ba I'm going to try to use the one you pastedroxlu
Your missing __stdcall AKA STDMETHODCALLTYPE - this is the cause.Roman R.
Roman R, you're the best! I added "STDMETHODCALLTYPE" for both SampleCB and BufferCB and now 'this' is not NULL anymore. Going to read up on this.roxlu

2 Answers

2
votes

Since qedit.h is no longer on Windows SDK you have to get definition of Sample Grabber related interfaces. One method is to use older SDK with all headers still on it. Another method is to #import the interfaces from type library. And you can always re-defined them right in code.

You can grab the correct definition from 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;
};

Because you did not have __stdcall on yours, the wrong calling convention was used and your this was NULL.

0
votes

It's very unlikely that this problem is related to COM only. You suggest that COM seems somehow to call your callback interface whereas it's eventaully NULL. But if that was the case you'd see the crash even without adding any code to your callback implementation.

As you probably know, all the interface functions in COM are virtual. Calling such a function involves first dereferencing the interface pointer and reading the contents of the appropriate vtable entry. Hence calling virtual function on a NULL interface pointer immediately causes an access violation. OTOH calling a non-virtual function on NULL object is ok (at least from the implementation point of view, leaving the C++ standard aside).

I suggest you look at the callstack carefully. I believe the COM method is invoked correctly. However in your specific sample you may not implement the COM callback method directly, instead it may be called by some wrapper code (it's very likely for DirectShow library). You should look for the problem there.