【发布时间】:2010-03-18 12:45:40
【问题描述】:
我正在尝试使用 DirectShow 连续播放两个 AVI 文件(一个接一个),这样当播放器从一个文件转换到下一个文件时,音频或视频不会中断。
我的表单上有两个自定义控件。每个都预加载了一个 AVI 文件,在开始播放之前,我设置了所有 DirectShow 接口,设置视频窗口并调整它们的大小,调用 IMediaControl.Run(),然后是 IMediaControl.Pause(),然后是 IMediaSeeking.SetPositions在两个控件上重置为第 0 帧。在表单上,您可以看到两个文件都在其初始帧处暂停。
然后我在第一个控件上调用 IMediaControl.Run(),并等待它完成,然后再在第二个控件上调用 Run()。最初,我连接到第一个视频的 EC_COMPLETE 通知消息,并用它来启动第二个。考虑到这个事件可能会来得很慢(事实证明确实如此,但出于一个奇怪的原因),我尝试了另外两种方法:
- 检查第一个视频的当前位置在每秒钟左右关闭的计时器内(使用 IMediaPosition.get_CurrentPosition)。当当前位置在视频停止时间的一秒内(从 IMediaPosition.get_StopTime 提前知道),我进入紧密的
while循环并等待当前位置等于停止时间,然后调用 Run()在第二个视频中。 - 与第一个相同,除了我将
while循环替换为从winmm.dll调用timeSetEvent,并设置了延迟,以便在第一个文件应该结束时立即触发。我使用回调来 Run() 第二个文件。
这两种方法中的任何一种都大大减少了第一个文件结束和第二个文件开始之间的延迟,表明EC_COMPLETE消息不会在文件完成后立即到达(我也尝试过挂钩EC_SEGMENT_COMPLETE消息,它应该用于在文件中循环,但显然没有人支持这一点 - 至少在我的机器上不会发生)。
以上所有操作都将转换延迟从一秒缩短到几乎无法察觉的故障;大约三分之一的时间文件转换时完全没有中断,这表明没有根本原因我不能让它一直工作。
不幸的是,轻微的延迟仍然是不可接受的。我假设(我很容易出错)剩余的延迟是由于调用 IMediaControl.Run() 和视频实际开始播放之间的轻微可变延迟。
有人知道我可以做些什么来消除这个小滞后吗? 告诉我这从根本上是不可能的,无论出于何种原因,这也不会让我感到惊讶。我从来没有在 Windows 中遇到过没有这个问题的视频播放器,所以它可能不可行。
更多信息:我正在播放的 AVI 文件完全未压缩(视频和音频未压缩),所以我认为延迟不是因为 DirectShow 必须提前解压缩视频播放开始,尽管它可能仍然会提前缓冲(这可能是问题的根源)。我会认为开始播放、暂停然后倒回到开头可以解决这个问题。
另外,我处理转换的方式实际上是将第二个控件置于第一个控件之下;当第一个完成播放时,我开始第二个,然后在其上调用 BringToFront,创建两个原件之间的单个视频过渡的外观。我不认为故障是由于这个原因,因为它在某些时候工作得很好,即使这是有问题的,它也不能解释匹配的音频故障。
甚至更多:我只是尝试“提前”30-50 毫秒开始第二个视频,这似乎消除了更多的差距,所以我猜测 Run() 中的滞后大约有那么长。不过,它似乎是可变的,所以这仍然不是我需要的地方。
还有更多:也许我可以通过从内存而不是从文件中加载 AVI 来消除这种延迟。不幸的是,我不知道该怎么做。 IMediaControl 只有RenderFile() 方法,而不是RenderStream 或RenderMemory 方法。
【问题讨论】: