Delphi 使用DirectShow录制动画时,如何确保正确的帧速率?
我正在尝试使用DirectShow将动画(计算机图形,而不是视频)录制到WMV文件。设置为:Delphi 使用DirectShow录制动画时,如何确保正确的帧速率?,delphi,directshow,Delphi,Directshow,我正在尝试使用DirectShow将动画(计算机图形,而不是视频)录制到WMV文件。设置为: 使用内存中位图保存动画帧的推送源。每次调用FillBuffer()时,位图的数据都会复制到样本中,并在样本上加上开始时间(帧编号*帧长度)和持续时间(帧长度)的时间戳。在过滤器中,帧速率设置为每秒10帧 ASF编写器过滤器。我有一个自定义配置文件,将视频设置为每秒10帧。它是一个仅用于视频的过滤器,因此没有音频 管脚连接,当图形运行时,将创建一个wmv文件。但是 问题在于DirectShow似乎正在
- 使用内存中位图保存动画帧的推送源。每次调用FillBuffer()时,位图的数据都会复制到样本中,并在样本上加上开始时间(帧编号*帧长度)和持续时间(帧长度)的时间戳。在过滤器中,帧速率设置为每秒10帧
- ASF编写器过滤器。我有一个自定义配置文件,将视频设置为每秒10帧。它是一个仅用于视频的过滤器,因此没有音频
如有任何建议,将不胜感激 为了测试整个过程,我正在为我的录像机应用程序(www.videophill.com)做正确的事情 我正在使用
Sleep()
方法延迟帧,但我非常小心地确保帧的时间戳是正确的。另外,当Sleep()
从一帧切换到另一帧时,请尝试使用“绝对”时间差,因为Sleep(100)
将睡眠约100毫秒,而不是100毫秒
如果它对你不起作用,你可以选择iReferenceLock,但我认为这太过分了
因此:
编辑:
请记住:
iwmwitter
是不区分时间的,只要您为它提供了正确的时间戳样本。我使用线程来实现这一点。主线程将位图添加到列表中,记录器线程从该列表中获取位图
主线
- 在时间T设置图形动画并渲染位图
- 将位图添加到渲染列表。如果列表已满(如超过8帧),请等待。这样就不会占用太多内存
- 使用与所需帧速率对应的deltatime前进T
- 请求帧时,从渲染列表中拾取并删除位图。如果列表为空,请等待
您需要一个线程安全结构(如TThreadList)来保存位图。这有点棘手,但您当前的方法肯定会解决计时问题。我是.NET的人,但希望您能从我的代码片段中理解我的意思。谢谢。最后,我使用QueryPerformanceCounter()来获得比仅使用sleep()更精确的计时(您注意到它并不精确)。它主要记录最后一帧的时钟时间,当再次调用FillBuffer()时,会将其暂停适当的时间。生成的WMV文件具有正确的持续时间。您可以使用DateTime,这并不重要。重要的是你要保持绝对的速度,而不是相对于最后一帧。
DateTime start=DateTime.Now;
int frameCounter=0;
while (wePush)
{
FillDataBuffer(...);
frameCounter++;
DateTime nextFrameTime=start.AddMilliseconds(frameCounter*100);
int delay=(nextFrameTime-DateTime.Now).TotalMilliseconds;
Sleep(delay);
}