【问题标题】:IMediaControl.Run() is successful still camera preview is blackIMediaControl.Run() 成功静态相机预览为黑色
【发布时间】:2017-08-30 14:48:56
【问题描述】:

通过使用 Directshow.NET 和 c#,我开发了一个显示相机预览的应用程序。自 1 年以来一切正常,但突然客户抱怨黑色相机预览。

在深入了解问题后,我了解到防病毒程序正在阻止我的应用程序使用相机。将我的应用程序添加到该防病毒程序的排除列表中后,应用程序可以像以前一样工作。

在程序中,我已经为HRESULT 正确抛出异常,如下所示:

try
{
    //FilterGraph creation
    //CaptureGraphBuilder2 creation
    //AddSourceFilterForMoniker()
    //SampleGrabber configuration
    //VMR9 configuration

    hr = mediaControl.Run();
    DsError.ThrowExceptionForHR(hr);
}
catch(Exception ex)
{
    //logging part
}

日志中仍然没有任何内容,即使我在该特定机器上调试该应用程序但程序成功执行。 所以问题是,为避免此类问题,我如何确保实际启动了相机预览?有没有办法检查流是否被阻止。

【问题讨论】:

    标签: directshow directshow.net


    【解决方案1】:

    黑色相机预览不一定是运行图表失败的症状。例如,无论这是否是您的问题,过滤器图 esp。显示 IP 摄像机源可能会进入运行状态,并且视频渲染器会期望接收帧并将其分别处理到它的显示就绪状态。但是,如果防病毒软件或防火墙阻止流量,则视频帧永远不会到达渲染器。过滤器图正在运行,没有失败或错误。

    您通常希望从过滤器图表中的过滤器请求一些统计信息,以证明正在发生有效负载处理。这可能包括:

    • 来自源过滤器的查询,它实际生成数据
    • 一个中间组件,例如能够提供已处理数据统计信息的解码器
    • 管道中的 Sample Grabber 过滤器,带有回调计数样本,无需修改
    • 来自视频渲染器的统计请求(例如IQualProp::get_FramesDrawn“...检索自流式传输开始后实际绘制的帧数”)
    • 尝试从视频渲染器读回当前显示的视频帧的快照

    一旦您看到随着时间的推移正在处理数据,您就知道没有发生意外锁定。

    【讨论】:

    • 好的,但是通过这个我只能识别帧是否进入渲染器,对吗?如果是,那么在深入研究问题时,我在机器上安装了 VLC 并尝试获取相机预览(媒体->打开捕获设备->捕获模式“DirectShow”),VLC 成功显示预览。但是 VLC 并没有被添加到防病毒的排除列表中,尽管它使用 DirectShow 显示预览是否与应用程序告诉防病毒允许使用相机有关,还是像 VLC 使用其他方式一样?
    • 杀毒软件极不可能禁止 DirectShow API。它禁止某些网络流量或被隔离的特定 DLL。这使得您的应用程序和 VLC 的情况大不相同。
    • 我知道这个答案已经很久了..我已经检查了IMediaEventEx.GetEvent() 我从IEventCode 收到ErrorAbort。这足以检测到此类问题吗?
    • ErrorAbort 来自其中一个过滤器,它遇到错误并通知图形,图形又停止,这确实可能导致变黑。你要确定是什么导致了ErrorAbort
    • 管道中的一个 Sample Grabber 过滤器,带有回调计数样本而不进行修改。我检查了BufferCB(),当它的阻塞缓冲区CB 没有被调用时。目前我将通过检查IEventCode.ErrorAbort
    【解决方案2】:

    您可以订阅事件MediaElementBase.NewAllocatorFrame,您可以知道相机源过滤器是否工作。

    【讨论】:

      【解决方案3】:

      我建议您将 DirectShow 过滤器图添加到运行对象表中,从而允许 GraphEdit 对远程过滤器图进行“监视”。 这有助于检查图形连接、过滤状态、引脚属性并更正或优化它以解决问题。

      在构建和/或启动捕获图后,只需调用此方法即可通过 Graphedit 应用程序设置图和过滤状态。

      ///
      /// \fn AddGraphToRot(IUnknown *pUnkGraph, DWORD *pdwRegister)
      /// 
      HRESULT CCapture::AddGraphToRot(IUnknown *pUnkGraph, DWORD *pdwRegister)
      {
          IMoniker * pMoniker;
          IRunningObjectTable *pROT;
          WCHAR wsz[128];
          HRESULT hr;
          ULONG ret = 0;
      
          if (FAILED(GetRunningObjectTable(0, &pROT)))
              return E_FAIL;
      
          wsprintfW(wsz, L"FilterGraph %08x pid %08x", (DWORD_PTR)pUnkGraph,
              GetCurrentProcessId());
      
          hr = CreateItemMoniker(L"!", wsz, &pMoniker);
          if (SUCCEEDED(hr)) {
              hr = pROT->Register(0, pUnkGraph, pMoniker, pdwRegister);
              ret = pMoniker->Release();
          }   
          pROT->Release();
          return hr;
      }
      

      GraphEdit 在 Microsoft Windows 软件开发工具包 (SDK) (http://go.microsoft.com/fwlink/p/?linkid=62332) 中可用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-05-20
        • 2018-06-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多