我正在尝试使用 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
循环替换为对timeSetEvent
from的调用winmm.dll
,并设置了延迟,以便在第一个文件应该结束时立即触发。我使用回调来 Run() 第二个文件。
这两种方法中的任何一种都大大减少了第一个文件结束和第二个文件开始之间的延迟,表明 EC_COMPLETE 消息不会在文件完成后立即到达(我也尝试过挂钩 EC_SEGMENT_COMPLETE 消息,即应该用于在文件中循环,但显然没有人支持这一点 - 至少在我的机器上从未发生过)。
完成上述所有操作已将转换延迟从一秒减少到几乎无法察觉的故障;大约三分之一的时间文件完全没有中断地转换,这表明没有根本原因我不能让它一直工作。
不幸的是,轻微的延迟仍然是不可接受的。我假设(我很容易出错)剩余的延迟是由于调用 IMediaControl.Run() 和视频实际开始播放之间的轻微可变延迟。
有人知道我能做些什么来消除这个小滞后吗? 被告知无论出于何种原因这基本上是不可能的也将有所帮助,这不会让我感到惊讶。我从来没有在 Windows 中遇到过没有这个问题的视频播放器,所以它可能不可行。
更多信息:我正在播放的 AVI 文件完全未压缩(视频和音频未压缩),所以我认为延迟不是因为 DirectShow 必须在播放开始前解压缩视频,尽管它可能仍会提前缓冲当然(这可能是问题的根源)。我会认为开始播放,暂停然后倒回到开头会解决这个问题。
此外,我处理转换的方式实际上是将第二个控件放在第一个控件之下;当第一个完成播放时,我开始第二个,然后在其上调用 BringToFront,创建两个原件之间的单个视频过渡的外观。我不认为故障是由于这个原因,因为它在某些时候工作得很好,即使这是有问题的,它也不能解释匹配的音频故障。
更重要的是:我只是尝试“提前”30-50 毫秒开始第二个视频,这似乎消除了更多的差距,所以我猜 Run() 中的延迟大约有那么长。不过,它似乎是可变的,所以这仍然不是我需要的地方。
还有更多:也许我可以通过从内存而不是从文件中加载 AVI 来消除这种延迟。不幸的是,我不知道该怎么做。IMediaControl 只有一个RenderFile()
方法,而不是类似RenderStream
orRenderMemory
方法的东西。