我已经成功地利用 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 整体在使用现代编解码器等方面的文档非常丰富。