1

我正在寻找一种从视频文件中获取图像数据的有效方法。我目前正在图书馆进行测试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];

然后我逐步浏览每一帧。我在循环中有这样的东西:

graphClass.GetCurrentImage(ref sz, out buffer[0]);
//DoStuff(buffer);
graphClass.CurrentPosition += graphClass.AvgTimePerFrame;
4

2 回答 2

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 位组件/库中
于 2012-07-21T18:04:10.610 回答
0

您还可以查看使用Windows Media Foundation创建分配器演示器。这将为您提供解码后的视频帧作为 GPU 纹理,您还可以使用 CUDA 或 OpenCL 执行所需的处理(如果可能),这将极大地提高您的处理速度。

于 2012-07-21T19:04:08.703 回答