delphi - 使用 DirectShow 录制动画时如何确保正确的帧速率?

标签 delphi directshow

我正在尝试使用 DirectShow 将动画(计算机图形,而不是视频)录制到 WMV 文件。设置为:

  • 使用保存动画帧的内存位图的推送源。每次调用 FillBuffer() 时,位图的数据都会复制到样本中,并且样本会带有开始时间(帧编号 * 帧长度)和持续时间(帧长度)的时间戳。过滤器中的帧速率设置为每秒 10 帧。

  • ASF Writer 过滤器。我有一个自定义配置文件,将视频设置为每秒 10 帧。它是纯视频过滤器,因此没有音频。

引脚连接,当图形运行时,会创建一个 wmv 文件。但是...

问题是 DirectShow 似乎正在以大于 10 FPS 的速率从推送源推送数据。因此,生成的 wmv 虽然可播放并包含正确的动画(以及报告正确的 FPS),但由于在录制期间向视频添加了太多帧,因此播放动画的速度太慢。也就是说,10 FPS 的 10 秒视频应该只有 100 帧,但视频中塞入了大约 500 帧,导致视频长度为 50 秒。

我最初尝试的解决方案只是通过添加 1/10 秒的 sleep() 来减慢 FillBuffer() 调用。这确实或多或少起到了作用。但这看起来很黑客,我怀疑这在更高的 FPS 下是否能正常工作。

所以我想知道是否有更好的方法来做到这一点。事实上,我假设有更好的方法,但我只是错过了。或者我只需要改进 Push Source 中 FillBuffer() 的延迟方式并使用更好的计时机制?

如有任何建议,我们将不胜感激!

最佳答案

我用线程来做到这一点。主线程将位图添加到列表中,记录器线程从该列表中获取位图。

主线程

  • 在时间 T 为图形制作动画并渲染位图
  • 将位图添加到渲染列表。如果列表已满(例如超过 8 帧),请等待。这样您就不会使用太多内存。
  • Advance T,其增量时间对应于所需的帧速率

渲染线程

  • 当请求帧时,从渲染列表中选择并删除位图。如果列表为空,请等待。

您需要一个线程安全结构(例如 TThreadList)来保存位图。正确执行有点棘手,但您当前的方法肯定会导致计时问题。

关于delphi - 使用 DirectShow 录制动画时如何确保正确的帧速率?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5988333/

相关文章:

c++ - DirectShow 手动图形内存泄漏

c# - 如何在 C# 中从网络摄像头获取源源不断的位图图像

oracle - 以全局用户身份登录 oracle db

delphi - 如何禁用 Chromium Embedded 中的查看源选项?

delphi - E2016 需要数组类型。使用 PSingle 变量

image - 使用 firebird 从 delphi 中的 blob 字段加载和保存图像

ffmpeg - 转换为 DV AVI Type-1 视频

c# - 为什么当我尝试使用 directshow 将视频捕捉到 mp4 文件时,文件是空的?

c++ - 直接显示捕获过滤器 "wrapper"

delphi - Peter 下面的代码是否存在内存泄漏?