我正在尝试使用 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/