QueryInterface在C#上使用E_NOINTERFACE失败

Spa*_*ark 8 c# camera directshow visual-studio-2008

Hi Stack Overflow成员,

我是C#编程的新手.我正在开发基本的相机流媒体并仍然捕捉应用程序.一旦用户静止不动,我将使用VMR9的位图混合概念在叠加层上显示它.

我做了什么?

  • 我从这里开始使用C#direct show library
  • 首先,我获得所有必需的过滤器接口 找到附加的捕获设备.称为具有源过滤器的渲染流和用于PREVIEW引脚的vmr9.STILL PIN的源过滤器,样本抓取器和空渲染器.
  • 我有三个菜单按钮 - >静止,显示叠加和隐藏叠加.
  • 我正在使用该库中提供的位图混合器示例.
  • 每次用户按下Take Still菜单时,图像将保存在桌面上,并将重新调整为小分辨率并显示在视频叠加上.
  • 显示覆盖并隐藏覆盖调用ShowHideBitmap()执行从vmr9过滤器查询VMR9BitmapMixer接口的操作,填充VMR9AlphaBitmap结构,然后调用IVMRMixerBitmap9.SetAlphaBitmap函数.

我面临什么问题?

  • 静止后,如果我通过菜单选项调用ShowHideBitmap(),则所拍摄的静止图像将在叠加时完美更新.
  • 这是保存静止图像时立即执行叠加自动更新的另一个选项.我创建基于事件的线程,并使其等待使用EventWaitHandle创建的更新事件.在从samplegrabber BufferCB函数返回之前,我设置了此更新事件.这反过来等待线程.在内部线程我调用ShowHideBitmap函数.在这种情况下,我收到如下错误消息.

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.如何处理这种跨线程操作?

Han*_*ant 4

这种例外情况很严重,在 COM 中并不罕见。它的真正含义是“我不知道如何为您提供可以从工作线程使用的接口引用”。这是一种常见的错误,这些 COM 组件根本不是线程安全的。他们通过自动处理从工作线程到所有者线程的调用来强制执行这一点。或者根本不允许您从另一个线程使用它们,因为编组毫无意义,使其速度太慢。VMR 属于后一类。

这与 .NET 非常不同,它还有很多完全线程不安全的类。也是基本的东西,没有一个集合类是例如。但无论如何,它都允许您在线程中使用这些类,由您决定是否使其线程安全。当然,这经常会出错,使用正确的锁定是一项技巧。

COM 在设计上始终是线程感知的。秉承这样的理念:线程很难正确执行,因此应该由聪明的人来处理。95% 的情况下都可以正常工作。其余时间都会让你感到严重的偏头痛。当 COM 处理线程时,由于难以诊断较差的性能而引起的偏头痛。当它不存在时,就会报告蹩脚的错误。

好吧,没有办法,您确实必须在创建 VMR 实例的同一线程中使用该接口。没有办法解决这个问题。