Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2008/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 查询接口失败,C上没有E_接口#_C#_Visual Studio 2008_Camera_Directshow - Fatal编程技术网

C# 查询接口失败,C上没有E_接口#

C# 查询接口失败,C上没有E_接口#,c#,visual-studio-2008,camera,directshow,C#,Visual Studio 2008,Camera,Directshow,大家好 我是C#编程的新手。我正在开发一个基本的摄像头流媒体和静态捕捉应用程序。一旦用户静止,我将使用VMR9的位图混合概念在覆盖图上显示它 我做了什么? 我正在使用来自的C#direct show库 首先,我得到所有必需的过滤器接口。查找连接的捕获设备。使用源过滤器和vmr9为预览管脚调用渲染流。源过滤器、样本抓取器和静态PIN的空呈现器 我有三个菜单按钮->静止,显示覆盖和隐藏覆盖 我正在使用该库中提供的位图混合器示例 每次用户按下“拍摄静止”菜单时,图像将保存在桌面上,并将重新调整到小分

大家好

我是C#编程的新手。我正在开发一个基本的摄像头流媒体和静态捕捉应用程序。一旦用户静止,我将使用VMR9的位图混合概念在覆盖图上显示它

我做了什么?

  • 我正在使用来自的C#direct show库
  • 首先,我得到所有必需的过滤器接口。查找连接的捕获设备。使用源过滤器和vmr9为预览管脚调用渲染流。源过滤器、样本抓取器和静态PIN的空呈现器
  • 我有三个菜单按钮->静止,显示覆盖和隐藏覆盖
  • 我正在使用该库中提供的位图混合器示例
  • 每次用户按下“拍摄静止”菜单时,图像将保存在桌面上,并将重新调整到小分辨率,并显示在视频叠加上
  • Show Overlay和hide Overlay调用ShowHideBitmap(),执行从vmr9筛选器查询VMR9BitmapMixer接口的操作,填充VMR9AlphaBitmap结构,然后调用IVMRMixerBitmap9.SetAlphaBitmap函数
我面临什么问题?

  • 拍摄静止后,如果我通过菜单选项调用ShowHideBitmap(),拍摄的静止图像将在覆盖上完全更新
  • 这是另一个选项,在保存静止图像后立即执行覆盖的自动更新。我创建了基于事件的线程,并让它等待使用EventWaitHandle创建的更新事件。在从samplegrabber BufferCB函数返回之前,我设置了这个更新事件。这反过来会继续等待线程。在线程内部,我调用ShowHideBitmap函数。在这个场景中,我收到如下错误消息
无法将“DirectShowLib.VideoMixingRenderer9”类型的COM对象大小写为接口类型“DirectShowLib.IVMRMixerBitmap9”。此操作失败,因为对IID为“{ced175e5-1935-4820-81bd-ff6ad00c9108}”的接口的COM组件的QueryInterface调用由于以下错误而失败:不支持此类接口(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);
    }
我曾尝试使用计时器更新此覆盖,计时器在后台以100ms的间隔运行。使用计时器效果良好,但对于此操作,使用计时器是一个错误的选择。因此我使用线程概念

为什么从线程调用时获取接口失败,从菜单选项调用时效果良好?我是否需要处理任何特殊的事情?我甚至尝试过参数化线程,但没有成功

提前感谢你的帮助


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

异常很严重,在COM中并不少见。它真正的意思是“我不知道如何为您提供可以从工作线程使用的接口引用"。这是一种常见的灾难,这些COM组件根本就不是线程安全的。它们通过处理这些组件,自动将工作线程的调用封送到所有者线程来实现这一点。或者根本不让您从另一个线程使用它们,因为封送将毫无意义,这会使它变得太慢w、 VMR属于后一类

这与.NET非常不同,它也有很多类是完全线程不安全的。同样,基本的东西,没有一个集合类是这样。但它允许您在线程中使用这些类,让您自己来确保线程安全。这经常出错。当然,使用适当的锁定是一项技能

COM一直以来都是通过设计来感知线程的。其理念是线程很难得到正确的处理,所以应该由聪明的人来处理。它在95%的时间内工作得非常好。并且在其余时间会给你带来严重的偏头痛。这种偏头痛是由COM处理线程时难以诊断的性能差引起的还有糟糕的错误报告


嗯,不行,你真的必须从创建VMR实例的同一个线程使用该接口。没有办法解决这个问题。

我在尝试使用Delphi库中的侦听器/事件处理程序对象时遇到了错误E_NOINTERFACE。为了克服封送和不同线程的问题,我保存了分配侦听器和使用它来触发事件

接口:

[ComVisible(true)]
[Guid("2FFC2C20-A27B-4D67-AEA3-350223D3655F")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IDataSystemInterfaceEventListener
{
    void OnIntializeCompleted(int status);
    void OnTerminateCompleted(int status);
    void OnRunCompleted(int status);
}

[ComVisible(true)]
[Guid("B9953413-A8C9-4CE2-9263-B488CA02E7EC")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IDataSystemInterface
{
    void Intialize(string config);
    void StartRun(string conditions);
    void StopRun();
    void Terminate();        

    IDataSystemInterfaceEventListener Listener { get; set; }
}
然后执行(注意Dispatcher.CurrentDispatcher已存储)

然后在代码中:

if (Listener != null)
{
    m_dispatcherListener.Invoke((Action)delegate()
    {
        Listener.OnTerminateCompleted((int)TerminateStatus.Completed);
    });
}

如果在不同的线程中调用侦听器,则会产生错误

+1。问题很好。注释,因为我不完全确定…某种程度上是预期的:大多数COM对象预期从单个线程调用…如果可以从多个线程调用,文档可能会显式调用。(我还模糊地记得,在跨线程访问对象之前,您可能需要在其他线程上初始化COM)…嗨,Alexei,是的,你是对的。从主线程以外的多个线程调用COM对象会产生此错误。我甚至尝试将此vmr9mixerBitmap接口初始化为主线程,并在ShowHideBitmap函数中使用相同的接口(而不是在此函数中创建),但结果是相同的。初始化COM,您的意思是我应该在主线程中获取接口,并在线程之间使用相同的接口?是否有关于跨线程访问此COM对象的详细说明?即使违反COM规则,底层VMR接口也可以在线程之间传递。但在本机代码中,不是托管的。在C#COM interop it没有意识到这些肮脏的技巧,我想这可能是一个问题:当它试图通过封送传递接口时,它只是无法这样做,它失去了inte
if (Listener != null)
{
    m_dispatcherListener.Invoke((Action)delegate()
    {
        Listener.OnTerminateCompleted((int)TerminateStatus.Completed);
    });
}