Problem with imported callback to C#

B

Builder

Hello,

I created a DirectShow filter which detects faces from video. Filter
exposes interface, which enables to set a callback, which is called
when a face is detected. I made an application in C# which creates a
DirectShow graph with mentioned face detector filter and calls its
interface.

Excerpt of the face detector interface declaration is as follows
(method SetCallback is important):

/// Interface for callbacks
DECLARE_INTERFACE(IFaceCB)
{
STDMETHOD(BufferCB)
(
LONGLONG FaceTime,
BYTE * pBuffer,
long BufferLen
) PURE;
};

DEFINE_GUID(IID_IFaceDetectorFilter, 0x5e3fa349, 0x566e, 0x49f7, 0x99,
0xfe, 0xb9, 0x91, 0x9b, 0xb7, 0xc4, 0x14);
DECLARE_INTERFACE_(IFaceDetectorFilter, IUnknown)
{
...

// Listener (Callback)
STDMETHOD(SetCallback)(IFaceCB * pCallback) PURE;
};

Interface IFaceDetectorFilter is implemented in the class
CFaceDetectorFilter:

class CFaceDetectorFilter : public CTransInPlaceFilter,
public IFaceDetectorFilter,
public ISpecifyPropertyPages,
public CPersistStream
{
public:

...

STDMETHODIMP SetCallback(IFaceCB * pCallback);

void DetectFace();

private:

IFaceCB* m_pCallback;
}

And implementation of the SetCallback method looks like this:

STDMETHODIMP CFaceDetectorFilter::SetCallback(IFaceCB * pCallback)
{

m_pCallback = pCallback;

return NOERROR;
}

and implementation of the method DetectFace looks like this:

void CFaceDetectorFilter::DetectFace()
{
LONGLONG timestamp; // time, when face was detected
BYTE* data; // image data of the detected face
long data_lenght; // size of the image data
...

if (m_pCallback != NULL)
m_pCallback->BufferCB(timestamp, data, data_lenght);
}

OK, and now follows code in the C# application, which calls interface
of the Face detector filter. First I had to import filter's
interfaces:

public interface IFaceCB
{
int BufferCB(long FaceTime, IntPtr pBuffer, int BufferLen);
}

[ComImport,
Guid("5E3FA349-566E-49F7-99FE-B9919BB7C414"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IFaceDetectorFilter
{
...

[PreserveSig]
int SetCallback(IFaceCB pCallback);
}

Of course, I implemented IFaceCB interface (and its method BufferCB)
and register it with method SetCallback():

public class FaceDetector : IFaceCB
{
public int BufferCB(long theStartTime, IntPtr theDstBuffer,
int theSize)
{
...

return 0;
}

...

public int Init()
{
int hr;
IBaseFilter ibfFaceDetector = null;
IFaceDetectorFilter faceDetectorFilter = null;

...

// create face detector filter
ibfFaceDetector = (IBaseFilter) new FaceDetectorFilter();
faceDetectorFilter = (IFaceDetectorFilter)ibfFaceDetector;

// register callback
hr = faceDetectorFilter.SetCallback(this);
}

public int Run()
{
// start the DirectShow grapg, start face detection
}

...
}

After running the DirectShow graph (after call Run method), face
detection started. But when first face was detected, callback BufferCB
was called from native code and application freeze. I don't know the
reason. Can anybody help me? Did you already encounter a similar
problem when imported calleback to C# is called from native code?
 
M

Mattias Sjögren

After running the DirectShow graph (after call Run method), face
detection started. But when first face was detected, callback BufferCB
was called from native code and application freeze. I don't know the
reason. Can anybody help me? Did you already encounter a similar
problem when imported calleback to C# is called from native code?


If you want to implement IFaceCB in C# you should make it a proper COM
interface and treat the callbac reference as such (calling
AddRef/Release etc).


Mattias
 
A

AlexS

Usually it happens when callback declaration is using non-standard
marshalling - see CallingConvention flags defining how to deal with stack
and what are defaults. If stack doesn't correspond to calling model, you
might see this king of behavior
HTH
Alex

Builder said:
Hello,

I created a DirectShow filter which detects faces from video. Filter
exposes interface, which enables to set a callback, which is called
when a face is detected. I made an application in C# which creates a
DirectShow graph with mentioned face detector filter and calls its
interface.

Excerpt of the face detector interface declaration is as follows
(method SetCallback is important):

/// Interface for callbacks
DECLARE_INTERFACE(IFaceCB)
{
STDMETHOD(BufferCB)
(
LONGLONG FaceTime,
BYTE * pBuffer,
long BufferLen
) PURE;
};

DEFINE_GUID(IID_IFaceDetectorFilter, 0x5e3fa349, 0x566e, 0x49f7, 0x99,
0xfe, 0xb9, 0x91, 0x9b, 0xb7, 0xc4, 0x14);
DECLARE_INTERFACE_(IFaceDetectorFilter, IUnknown)
{
...

// Listener (Callback)
STDMETHOD(SetCallback)(IFaceCB * pCallback) PURE;
};

Interface IFaceDetectorFilter is implemented in the class
CFaceDetectorFilter:

class CFaceDetectorFilter : public CTransInPlaceFilter,
public IFaceDetectorFilter,
public ISpecifyPropertyPages,
public CPersistStream
{
public:

...

STDMETHODIMP SetCallback(IFaceCB * pCallback);

void DetectFace();

private:

IFaceCB* m_pCallback;
}

And implementation of the SetCallback method looks like this:

STDMETHODIMP CFaceDetectorFilter::SetCallback(IFaceCB * pCallback)
{

m_pCallback = pCallback;

return NOERROR;
}

and implementation of the method DetectFace looks like this:

void CFaceDetectorFilter::DetectFace()
{
LONGLONG timestamp; // time, when face was detected
BYTE* data; // image data of the detected face
long data_lenght; // size of the image data
...

if (m_pCallback != NULL)
m_pCallback->BufferCB(timestamp, data, data_lenght);
}

OK, and now follows code in the C# application, which calls interface
of the Face detector filter. First I had to import filter's
interfaces:

public interface IFaceCB
{
int BufferCB(long FaceTime, IntPtr pBuffer, int BufferLen);
}

[ComImport,
Guid("5E3FA349-566E-49F7-99FE-B9919BB7C414"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IFaceDetectorFilter
{
...

[PreserveSig]
int SetCallback(IFaceCB pCallback);
}

Of course, I implemented IFaceCB interface (and its method BufferCB)
and register it with method SetCallback():

public class FaceDetector : IFaceCB
{
public int BufferCB(long theStartTime, IntPtr theDstBuffer,
int theSize)
{
...

return 0;
}

...

public int Init()
{
int hr;
IBaseFilter ibfFaceDetector = null;
IFaceDetectorFilter faceDetectorFilter = null;

...

// create face detector filter
ibfFaceDetector = (IBaseFilter) new FaceDetectorFilter();
faceDetectorFilter = (IFaceDetectorFilter)ibfFaceDetector;

// register callback
hr = faceDetectorFilter.SetCallback(this);
}

public int Run()
{
// start the DirectShow grapg, start face detection
}

...
}

After running the DirectShow graph (after call Run method), face
detection started. But when first face was detected, callback BufferCB
was called from native code and application freeze. I don't know the
reason. Can anybody help me? Did you already encounter a similar
problem when imported calleback to C# is called from native code?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Top