0

我已经成功地利用 directshownet DirectShow 包装器来生成视频文件的缩略图。对于许多测试实例,代码工作得很好

但是对于某些人来说,它会在 RenderStream 函数调用中引发“未知异常”。

我一直无法追踪异常的原因,错误代码是'-2147467259',InnerException:null。我没有太多调查COM接口故障的经验,但错误代码似乎没有形成任何逻辑值。

我的第一个想法是缺乏适当的编解码器等。但是问题仍然存在于几台测试机器上,大多数流行的编解码器包都已安装(ffdshow、k-lite 编解码器包等)。该视频在应用程序之外也可以正常播放。

这些机器运行的是x64版本的windows(windows 7和win server 2008 r2),已经安装了x64版本的ffdshow编解码器包,然后进行了其他设置,例如安装了32位版本的ffdshow,以及在x64中编译测试应用程序与 x86 构建模式一样。在示例剪辑上始终失败。还尝试在 FFDSHOW 设置面板中启用/禁用特定编解码器,特别是查看 h264 的。没有什么。有问题的示例视频使用以下规范进行编码:v-codec:H264 - MPEG-4 AVC (part 10) avc1 Resolution:1280x768 FPS:23..

我认为构建 Graph 的代码很好,因为它适用于很多测试用例,但是这里是:

 private void SetupGraph( string FileName)
 {
     int hr;

     // Get the graphbuilder object
     m_FilterGraph = new FilterGraph() as IFilterGraph2;

     // Get a ICaptureGraphBuilder2 to help build the graph
     ICaptureGraphBuilder2 icgb2 = new CaptureGraphBuilder2() as ICaptureGraphBuilder2;

     try
     {
         // Link the ICaptureGraphBuilder2 to the IFilterGraph2
         hr = icgb2.SetFiltergraph(m_FilterGraph);
         DsError.ThrowExceptionForHR(hr);

         // Add the filters necessary to render the file.  This function will
         // work with a number of different file types.
         IBaseFilter sourceFilter = null;

         hr = m_FilterGraph.AddSourceFilter(FileName, null, out sourceFilter);
         DsError.ThrowExceptionForHR(hr);

         // Get the SampleGrabber interface
         m_sampGrabber = (ISampleGrabber)new SampleGrabber();
         IBaseFilter baseGrabFlt = (IBaseFilter)m_sampGrabber;

         // Configure the Sample Grabber
         ConfigureSampleGrabber(m_sampGrabber);

         // Add it to the filter
         hr = m_FilterGraph.AddFilter(baseGrabFlt, "Ds.NET Grabber");
         DsError.ThrowExceptionForHR(hr);


         // Connect the pieces together, use the default renderer
         hr = icgb2.RenderStream(null, null, sourceFilter, baseGrabFlt, null);
         DsError.ThrowExceptionForHR(hr); // **HERE** is where the 'unknown exception' is thrown.

         // Now that the graph is built, read the dimensions of the bitmaps we'll be getting
         SaveSizeInfo(m_sampGrabber);

         // Configure the Video Window
         IVideoWindow videoWindow = m_FilterGraph as IVideoWindow;
         videoWindow.put_AutoShow(OABool.False);
         // ConfigureVideoWindow(videoWindow, hWin);
         //
         // Grab some other interfaces
         m_mediaEvent = m_FilterGraph as IMediaEvent;
         m_mediaCtrl = m_FilterGraph as IMediaControl;
         m_mediaSeeking = m_FilterGraph as IMediaSeeking;
         m_mediaSample = m_FilterGraph as IMediaSample;
         m_mediaPosition = m_FilterGraph as IMediaPosition;

     }
     catch
     { }
     finally
     {
         if (icgb2 != null)
         {
             Marshal.ReleaseComObject(icgb2);
             icgb2 = null;
         }
     }

 }

仍在尝试缩小问题范围。任何评论都将不胜感激,因为我已经没有想法了。 更新:似乎问题可以更具体:如何修改上图以使 DirecShow utlize h264 编解码器在系统上可用?从表面上看,它不会自行发生。另一个我认为值得更新的内容:我已经深入研究了构建 grapsh 等主题。我还下载了 GrapStudio 软件以使用不同的过滤器设置。但是,一旦我选择了“渲染媒体文件”子菜单并将其指向有问题的视频,它就会显示“无法渲染文件”!仅此而已,视频文件在 Windows 媒体播放器或 VLC 中播放得很好。它使用 FFDSHOW 提供的 h264video 编解码器进行编码。

另一个更新:我已经设法使用 K-Lite 编解码器包 x64 制作了 GraphStudio 渲染电影(文件->渲染媒体文件)。该图已构建(使用 LAV Video Decoder)。我的应用程序仍然无法自动生成图表,尽管它也针对 x64 平台并且从我读过的 GraphStudio 中调用了相同的 API 函数。这很奇怪。所以我决定建立一个半自动图。

    Guid gui = new Guid("EE30215D-164F-4A92-A4EB-9D4C13390F9F");
Object o;
ty = Type.GetTypeFromCLSID(gui);
o = Activator.CreateInstance(ty, false);
IBaseFilter ibfVideoDec = (IBaseFilter)o;
hr=m_FilterGraph.AddFilter(ibfVideoDec, "LAV Video decoder");
DsError.ThrowExceptionForHR(hr);

在添加我需要的其他过滤器时,然后调用 RenderFile。没有什么。所有过滤器均由其相应的 CLSID 初始化,没有错误。它不会渲染。有人吗?如果您问我 DirectShowNet 或 DirectShow 整体在使用现代编解码器等方面的文档非常丰富。

4

1 回答 1

0

错误是0x80004005 E_FAIL“未指定的错误”。图形生成器会从某些内部组件向您转发错误,而不会向您提供详细信息。如果不以更精细的步骤构建图表,就无法找到原因。它可以是任何东西,包括系统中出现故障的第三方组件(这很可能是您安装的编解码器包一个接一个)。分解RenderStream成个体Connects和AddFitlers会解释原因。

于 2012-11-09T01:53:31.420 回答