C# 将.NET位图对象传递给COM(DirectShow筛选器)
我正在尝试创建一个源过滤器,根据一系列图片生成实时视频流。 为此,我制作了一个IUnknown接口:C# 将.NET位图对象传递给COM(DirectShow筛选器),c#,.net,com,directshow,iunknown,C#,.net,Com,Directshow,Iunknown,我正在尝试创建一个源过滤器,根据一系列图片生成实时视频流。 为此,我制作了一个IUnknown接口: [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("F18FC642-5BA2-460D-8D12-23B7ECFA8A3D")] public interface IVirtualCameraFilter_Crop { void SetCurrentImage(Bitmap img); .
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("F18FC642-5BA2-460D-8D12-23B7ECFA8A3D")]
public interface IVirtualCameraFilter_Crop
{
void SetCurrentImage(Bitmap img);
...
};
在我的程序中,我得到了:
pUnk = Marshal.GetIUnknownForObject(sourceFilter);
Marshal.AddRef(pUnk);
filterInterface = Marshal.GetObjectForIUnknown(pUnk) as IVirtualCameraFilter_Crop;
当我通过简单类型时,一切正常。但是当我试图传递一个C#位图对象时,我得到一个错误,无法将Com对象转换为。或应用程序因错误APPCRUSH而关闭
filterInterface.SetCurrentImage(frame);
我知道这不是正确的方式,但我不知道传递参数的其他可能方式。我尝试将IntPtr传递给BitmapData,然后我得到了相同的应用程序。
那么如何将位图传递给DirectShow过滤器呢
结果:
有关代码的完整图片,请引用
创建一个接口:
[ComImport, InterfaceType (ComInterfaceType.InterfaceIsIUnknown), Guid ("F18FC642-5BA2-460D-8D12-23B7ECFA8A3D")]
public interface IVirtualCameraFilter_Crop
{
unsafe void SetPointerToByteArr (byte * array, int length);
};
实施:
unsafe public void SetPointerToByteArr (byte * array, int length)
{
this.array = new byte [length];
Marshal.Copy (new IntPtr (array), this.array, 0, length);
}
在应用中:
byte [] text = ... get data;
unsafe
{
fixed (byte * ptr = & text [0])
{
filterInterface.SetPointerToByteArr (ptr, text.Length);
}
}
System.Drawing.Bitmap是.net类型,而不是COM类型,并且在COM中没有等效项,因此不能将其用作COM接口的参数
或者使用COM接口,这在C#中不容易使用,因为.net MemoryStream没有实现它,或者使用COM接口,或者
还请注意,DirectShow筛选器通常会在非UI线程的线程中调用,因此您应该注意在筛选器中放置适当的锁定机制。您不能将位图对象直接从.NET传递到本机代码中。您可以传递BitmapData IntPtr,但应将该数据复制到筛选器bcs内的缓冲区中。一旦解锁该指针,该指针将无效。传递字节数组应该可以正常工作,您可以这样做:
// interface method declaration
interface IVirtualCameraFilter_Crop
{
[PreserveSig]
int SetImageData([In,MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] _array,[In] int size);
}
// Code implementation
IVirtualCameraFilter_Crop _filter // your filter interface
BitmapData _data = // your BitmapLock
int _size = // your image size while you locking it Width * Height * BPP / 8
byte[] _array = new byte[_size];
Marshal.Copy(_data.Scan0,_array,0,_size);
_filter.SetImageData(_array,_size);
// Passing IntPtr way will be similar just the changes will be in method declaration in interface
[PreserveSig]
int SetImageData([In] IntPtr _array,[In] int size);
// This way you can just pass the _data.Scan0 value
// The C++ interface declaration and handler will be same for both ways
// C++ interface declaration
DECLARE_INTERFACE(IVirtualCameraFilter_Crop,IUnknown)
{
[PreserveSig]
STDMETHOD(SetImageData)(LPBYTE _array,long size)PURE;
}
//C++ implementation
STDMETHODIMP CFilter::SetImageData(LPBYTE _array,long size)
{
CheckPointer(_array,E_POINTER);
CopyMemory(_internalArray,_array,size);
return NOERROR;
}
过滤器崩溃时的另一件事:
1-您不能从给定缓冲区复制数据
2-将数据应用到现有缓冲区而不锁定执行线程
3——在C++方法内部拷贝时不正确计算数据大小
4-结果缓冲区未分配。
实际上,我认为你应该试着用C语言来制作你的过滤器#
下面是BaseClasses.NET及其示例:
以下是虚拟摄像机的实现:
问候,,
格言。对上一条评论进行评论。在那里尝试示例+尝试并查看高级示例,COM问题和多线程问题在那里得到解决,因此工作正常;而且对于过滤器实现来说非常容易。您在COM和DirectShow方面似乎没有太多经验。因此,将.NET位图作为数组或流传递,并在C#中完整地创建筛选器有什么区别?关于应用程序压缩,如果筛选器未捕获任何例外情况,请建议使用MessageBoxs。“你似乎在COM和DirectShow方面没有太多经验”这是真的。这些评论不适合你,关于经验,因为还有其他人的评论。当然,您应该在过滤器中使用try catch stations。MessageBox不建议使用,您可以将数据输出到调试器中,并使用ASSERT检查条件。