有效地从视频中抓取像素

Blu*_*doo 1 c# video directshow

我正在寻找一种有效的方法来从视频文件中获取图像数据.我目前正在测试FilgraphManagerClass.GetCurrentImage()Interop.QuartzTypeLib库.这就是我需要的,但速度很慢.我需要处理每个视频的所有帧.我有什么更好的选择?

要求

  • 必须是帧精确的.< - 非常重要!
  • 允许我访问解码的像素缓冲区(int或者数组byte[]),理想情况下是RGB24或RGB32.
  • 可以实时或更快地抓取缓冲区.我不需要显示视频,我只需要分析像素.
  • 处理mp4文件(h264/aac).如果需要,我可以通过AviSynth重新打包或帧服务,但不能涉及重新编码.

欢迎大家提出意见.

一些代码请求:

FilgraphManagerClass graphClass = new FilgraphManagerClass();
graphClass.RenderFile(@"C:\tmp\tmp.avs");

int sz = (graphClass.Width * graphClass.Height + 10) * 4;    
int[] buffer = new int[sz - 1];
Run Code Online (Sandbox Code Playgroud)

然后我逐步走过每一帧.我在循环中有这样的东西:

graphClass.GetCurrentImage(ref sz, out buffer[0]);
//DoStuff(buffer);
graphClass.CurrentPosition += graphClass.AvgTimePerFrame;
Run Code Online (Sandbox Code Playgroud)

Rom*_* R. 5

IBasicVideo::GetCurrentImage您正在使用的方法基本上用于快照,并且仅适用于传统模式下的传统视频渲染.也就是说,(a)它不是时间准确,它可以让你复制帧,或相反,丢帧; (b)它假定您显示视频.

相反,您需要构建以下类型的过滤器图:文件源 - > ... - >样本抓取器过滤器 - >空渲染器.Sample Grabber是一个标准组件,可以提供一个回调,以便它通过它来调用任何帧数据.

然后通过调用SetReferenceClock(null)过滤器图形从图形中删除时钟,使其尽可能快地运行(而不是实时).然后您Run将图表和所有视频帧提供给您的回调.

要在C#中完成任务,您需要使用DirectShow.NET库.它的Capture\DxSnap示例提供了如何使用Sample Grabber的简短示例.他们通过BufferCB代替它来完成它SampleCB并且它也运行良好.其他样品也使用这种方法.

您会发现非常接近此任务的其他代码片段:

关于MP4文件,您应该考虑以下因素:

  1. Windows中对MPEG-4的支持有限,您可能需要安装第三方组件才能使文件可播放.如果GraphEdit可以读取它们,那么你也可以.
  2. Windows Media Player可能正在使用,而且可能是更新的API,您应该更好地查看GraphEdit
  3. 确保在应用程序上使用Win32/ x86platform以避免遇到应用程序在64位域中运行的情况,而对MP4的支持仅存在于安装的32位组件/库中