C#上的NOINTERFACE

嗨堆栈溢出成员,

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

我做了什么?

  • 我正在使用这里的C#直接显示库
  • 首先我得到所有必需的过滤器接口。 找到附加的捕捉设备。 称为Render流与源过滤器和vmr9 PREVIEW引脚。 STILL PIN的源过滤器,采样器和空呈现器。
  • 我有三个菜单按钮 - >静止,显示覆盖和隐藏覆盖。
  • 我正在使用该库中提供的位图混合器示例。
  • 每次用户按下“拍摄静止”菜单时,图像将保存在桌面上,并将重新调整大小以适应小分辨率并显示在视频叠加层上。
  • 显示覆盖并隐藏覆盖调用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);
        }
    }
    }
    

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

        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对象会创建Exception。 如何处理这个跨线程操作?


    例外情况很糟糕,在COM中并不罕见。 它的真正含义是“我不知道如何给你一个你可以在工作线程中使用的接口引用”。 这是一种常见的事故,这些COM组件根本不是线程安全的。 他们通过照顾它来强制执行该操作,将工作线程的调用自动封送到所有者线程。 或者不要让你从另一个线程中使用它们,因为编组会变得毫无意义,从而导致它太慢。 VMR属于后一类。

    这与.NET非常不同,它也有很多完全线程不安全的类。 基本的东西,例如,没有任何集合类。 但它可以让你在一个线程中使用这些类,让它保持线程安全。 这当然经常出错,使用适当的锁定是一种技巧。

    COM通过设计始终是线程感知的。 有了这样的哲学,线程是很难得到正确的,所以它应该由聪明的人来照顾。 95%的时间非常有效。 剩下的时间给你一个主要的偏头痛。 当COM处理穿线时,由于难以诊断差的性能而引起的那种偏头痛。 当它不这样做时,会报告糟糕的错误。

    那么,无法做到,您确实必须使用创建VMR实例的同一线程中的该接口。 没办法。


    尝试使用Delphi库中的Listener / Event处理程序对象时,出现错误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存储)

    [ComVisible(true)]
    [Guid("0818F830-DA37-4167-BF31-3A2C55A9BF2B")]        
    public class DataSystemModule : IDataSystemInterface
    {
        private Dispatcher m_dispatcherListener = null;
        private IDataSystemInterfaceEventListener m_listener = null;
        public IDataSystemInterfaceEventListener Listener
        {
            get
            {
                return m_listener;
            }
            set
            {
                m_dispatcherListener = Dispatcher.CurrentDispatcher;
                m_listener = value;
            }
        } 
    }
    

    然后在代码中:

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

    如果Listener在不同的线程中被调用,则不会产生错误

    链接地址: http://www.djcxy.com/p/70265.html

    上一篇: NOINTERFACE on C#

    下一篇: how to change highstock date to persian date