gpt4 book ai didi

c# - QueryInterface 在 C# 上因 E_NOINTERFACE 而失败

转载 作者:太空狗 更新时间:2023-10-29 19:41:17 26 4
gpt4 key购买 nike

嗨 Stack Overflow 成员,

我是 C# 编程的新手。我正在开发一个基本的相机流和静态捕获应用程序。一旦用户静止不动,我将使用 VMR9 的位图混合概念在叠加层上显示它。

我做了什么?

  • 我正在使用来自 here 的 C# 直接显示库
  • 首先,我获得了所有必需的过滤器接口(interface)。找到连接的捕获设备。为 PREVIEW pin 调用带有源过滤器和 vmr9 的渲染流。 STILL PIN 的源过滤器、样本采集器和空渲染器。
  • 我有三个菜单按钮 -> 静止不动、显示叠加层和隐藏叠加层。
  • 我正在使用该库中提供的位图混合器示例。
  • 每次用户按 Take Still 菜单时,图像都会保存在桌面上,并会调整为较小的分辨率并显示在视频叠加层上。
  • Show Overlay 和 hide overlay 调用 ShowHideBitmap() 执行从 vmr9 过滤器查询 VMR9BitmapMixer 接口(interface)的操作,填充 VMR9AlphaBitmap 结构,然后调用 IVMRMixerBitmap9.SetAlphaBitmap 函数。

我面临什么问题?

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

无法将类型为“DirectShowLib.VideoMixingRenderer9”的 COM 对象转换为接口(interface)类型“DirectShowLib.IVMRMixerBitmap9”。此操作失败,因为 IID 为“{ced175e5-1935-4820-81bd-ff6ad00c9108}”的接口(interface)的 COM 组件上的 QueryInterface 调用因以下错误而失败:不支持此类接口(interface)(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);
}
}
}

这是等待更新事件的线程。

    Thread overlayupdatethreadhandle = new Thread(new ThreadStart(overlayupdatethread));
overlayupdatethreadhandle.Start();

private void overlayupdatethread()
{
do
{
overlayupdateeventhandle.WaitOne();
ShowHideBitmap(GlobalVar.m_ShowOverlay);
} while (true);
}

我已经尝试使用在后台运行的计时器更新此叠加层,间隔为 100 毫秒。使用计时器效果很好,但对于此操作,使用计时器是一个糟糕的选择。所以我转向了线程概念。

为什么在从线程调用时获取界面失败,而在从菜单选项调用时效果很好?我需要处理什么特别的事情吗?我什至尝试过参数化线程,但没有成功。

预先感谢您的帮助。

编辑:如果从主线程调用 ShowHideBitmap,一切正常。如果从工作线程调用 ShowHideBitmap,则 COM 对象会创建异常。如何处理这种跨线程操作?

最佳答案

异常很棘手,在 COM 中并不少见。它真正的意思是“我不知道如何给你一个你可以从工作线程使用的接口(interface)引用”。这是一种常见的事故,这类 COM 组件根本不是线程安全的。他们通过处理它来强制执行这一点,自动将工作线程的调用编码到所有者线程。或者根本不让您从另一个线程使用它们,因为编码(marshal)处理将毫无意义,使其速度太慢。 VMR 属于后一类。

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

COM 在设计上一直是线程感知的。有了线程很难正确处理的理念,所以应该由聪明的人来处理。这在 95% 的时间里都非常有效。并且在剩下的时间里会给你带来严重的偏头痛。当 COM 负责线程处理时,由于难以诊断性能不佳而引起的偏头痛。当它没有时,糟糕的错误报告。

好吧,没办法,您确实必须从创建 VMR 实例的同一线程使用该接口(interface)。没办法。

关于c# - QueryInterface 在 C# 上因 E_NOINTERFACE 而失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15653311/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com