Spa*_*ark 8 c# camera directshow visual-studio-2008
Hi Stack Overflow成员,
我是C#编程的新手.我正在开发基本的相机流媒体并仍然捕捉应用程序.一旦用户静止不动,我将使用VMR9的位图混合概念在叠加层上显示它.
我做了什么?
我面临什么问题?
Unable to case COM object of type 'DirectShowLib.VideoMixingRenderer9' to interface type 'DirectShowLib.IVMRMixerBitmap9'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{ced175e5-1935-4820-81bd-ff6ad00c9108}' failed due to the following error: No such interface supported (Exception from HRESULT: 0X80040002 (E_NOINTERFACE)
这是ShowHideBitmap函数的代码块
//Declarations
private static IBaseFilter vmr9 = null;
private static IVMRMixerBitmap9 vmr9mixerBitmap = null;
private IVMRWindowlessControl9 vmr9windowlessCtrl = null;
private static void ShowHideBitmap(Boolean bEnable)
{
int hr = 0;
VMR9AlphaBitmap alphaBmp;
if (!bEnable)
{
if (vmr9mixerBitmap != null)
{
// Get current Alpha Bitmap Parameters
hr = vmr9mixerBitmap.GetAlphaBitmapParameters(out alphaBmp);
DsError.ThrowExceptionForHR(hr);
// Disable them
alphaBmp.dwFlags = VMR9AlphaBitmapFlags.Disable;
// Update the Alpha Bitmap Parameters
hr = vmr9mixerBitmap.UpdateAlphaBitmapParameters(ref alphaBmp);
DsError.ThrowExceptionForHR(hr);
// Create a surface from our alpha bitmap
surface.Dispose();
vmr9mixerBitmap = null;
//Release this alpha bitmap source.
if (alphaBitmap != null)
{
alphaBitmap.Dispose();
}
}
return;
}
else
{
try
{
alphaBitmap = BitmapGenerator.GenerateAlphaBitmap();
// Create a surface from our alpha bitmap
if(surface == null)
surface = new Surface(device, alphaBitmap, Pool.SystemMemory);
// Get the unmanaged pointer
unmanagedSurface = surface.GetObjectByValue(DxMagicNumber);
if (vmr9mixerBitmap == null)
vmr9mixerBitmap = (IVMRMixerBitmap9)vmr9;
// Set Alpha Bitmap Parameters for using a Direct3D surface
alphaBmp = new VMR9AlphaBitmap();
alphaBmp.dwFlags = VMR9AlphaBitmapFlags.EntireDDS;
alphaBmp.pDDS = unmanagedSurface;
alphaBmp.rDest = GetDestRectangle();
alphaBmp.fAlpha = 1.0f;
// Set Alpha Bitmap Parameters
hr = vmr9mixerBitmap.SetAlphaBitmap(ref alphaBmp);
DsError.ThrowExceptionForHR(hr);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是等待更新事件的线程.
Thread overlayupdatethreadhandle = new Thread(new ThreadStart(overlayupdatethread));
overlayupdatethreadhandle.Start();
private void overlayupdatethread()
{
do
{
overlayupdateeventhandle.WaitOne();
ShowHideBitmap(GlobalVar.m_ShowOverlay);
} while (true);
}
Run Code Online (Sandbox Code Playgroud)
我尝试使用在间隔为100毫秒的背景下运行的计时器更新此叠加层.使用计时器工作正常,但对于此操作,使用计时器是不好的选择.所以我采用了线程概念.
为什么从线程调用时接口失败并且在从菜单选项调用时工作正常?我应该照顾任何特别的东西吗?我甚至尝试过参数化线程,但没有运气.
在此先感谢您的帮助.
编辑:如果从主线程调用ShowHideBitmap,每件事都可以正常工作.如果从工作线程调用ShowHideBitmap,COM对象将创建Exception.如何处理这种跨线程操作?
这种例外情况很严重,在 COM 中并不罕见。它的真正含义是“我不知道如何为您提供可以从工作线程使用的接口引用”。这是一种常见的错误,这些 COM 组件根本不是线程安全的。他们通过自动处理从工作线程到所有者线程的调用来强制执行这一点。或者根本不允许您从另一个线程使用它们,因为编组毫无意义,使其速度太慢。VMR 属于后一类。
这与 .NET 非常不同,它还有很多完全线程不安全的类。也是基本的东西,没有一个集合类是例如。但无论如何,它都允许您在线程中使用这些类,由您决定是否使其线程安全。当然,这经常会出错,使用正确的锁定是一项技巧。
COM 在设计上始终是线程感知的。秉承这样的理念:线程很难正确执行,因此应该由聪明的人来处理。95% 的情况下都可以正常工作。其余时间都会让你感到严重的偏头痛。当 COM 处理线程时,由于难以诊断较差的性能而引起的偏头痛。当它不存在时,就会报告蹩脚的错误。
好吧,没有办法,您确实必须在创建 VMR 实例的同一线程中使用该接口。没有办法解决这个问题。