Search code examples
c#.netcomdirectshowiunknown

Pass .NET Bitmap object to COM (DirectShow filter)


I'm trying to create a source filter that makes a live video stream based on a sequence of pictures. To do this, I make an interface of IUnknown:

[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("F18FC642-5BA2-460D-8D12-23B7ECFA8A3D")]
public interface IVirtualCameraFilter_Crop
{
    void SetCurrentImage(Bitmap img);
    ...
};

And in my programm I get it:

pUnk = Marshal.GetIUnknownForObject(sourceFilter);
Marshal.AddRef(pUnk);
filterInterface = Marshal.GetObjectForIUnknown(pUnk) as IVirtualCameraFilter_Crop;

When I pass simple types everything works fine. But when I try to pass a C# Bitmap object I get an error unable to cast Com object to <my object type>. Or application shutting down with error APPCRUSH.

filterInterface.SetCurrentImage(frame);

I understand that it`s not the correct way but I do not know other possible ways of passing parameters. I tried to pass IntPtr to BitmapData and then I get the same application crush. So How can I pass the bitmap to the DirectShow filter?

Result: For a complete picture of the code cite Create an interface:

[ComImport, InterfaceType (ComInterfaceType.InterfaceIsIUnknown), Guid ("F18FC642-5BA2-460D-8D12-23B7ECFA8A3D")]
public interface IVirtualCameraFilter_Crop
{
    unsafe void SetPointerToByteArr (byte * array, int length);
};

implementation:

unsafe public void SetPointerToByteArr (byte * array, int length)
{
    this.array = new byte [length];
    Marshal.Copy (new IntPtr (array), this.array, 0, length);
}

In application:

byte [] text = ... get data;
unsafe
{
    fixed (byte * ptr = & text [0])
     {
          filterInterface.SetPointerToByteArr (ptr, text.Length); 
     }
}

Solution

  • System.Drawing.Bitmap is a .net type, not COM type, and there is no equivalent for it in COM, so you cannot use it as a parameter of a COM interface.

    Either use the COM interface IStream, which is not easy to use in C# since .net MemoryStream does not implements it, or use the COM interface IPicture, or just an array of bytes.

    Also be aware that your DirectShow filter will usually be called in a thread that is not the UI thread, so you are supposed to take care of putting the proper lock mechanisms inside your filter.