1、延迟
延迟(即latency)是在时间戳0处捕获的样本到达接收器所花费的时间。此时间是根据流水线的时钟测量的。对于只有包含与时钟同步的接收器元素的流水线,latency始终为0,因为没有其他元素延迟缓冲区。对于实时源的管道,必须引入延迟,这主要是因为实时源的工作方式。考虑一个音频源,它将在时间0开始捕获第一个采样。如果该源以44100Hz的频率一次推送具有44100个采样的缓冲区,由于缓冲区的时间戳为0,而现在是时钟的>= 1(单位:44100采样时间),接收器将丢弃此缓冲区。因为为时已晚,在接收器中没有任何延迟补偿的情况下,所有缓冲区将被丢弃。
在以下情况下情况变得更加复杂:
-
2个实时的SrcElement 连接到 2个具有不同延迟的 实时sinkElement
-
具有同步实时预览的音频/视频捕获。
-
由于效果(延迟,重采样器...)而增加了延迟
-
-
1个活动源连接到2个活动接收器
-
firewire DV
-
RTP,由于抖动缓冲区而增加了延迟。
-
-
混合实时源和非实时源方案。
-
同步音频捕获的和非实时的播放。(配音,..)
-
-
由于实时信号源提供了自己的时钟,因此接收器中的时钟从动。
要在上述情况下执行所需的延迟校正,我们必须开发一种算法来计算管道的全局延迟。该算法必须是可扩展的,以便可以优化运行时的延迟。还必须有可能根据特定的应用程序需(所需的最小延迟)来禁用或调整算法。
2、延迟的必要性
我们显示一些示例来演示典型捕获管道中的延迟问题。
例1
音频捕获/播放管道。
-
asrc:音频源,提供时钟
-
asink音频接收器,提供时钟
![](https://i-blog.csdnimg.cn/blog_migrate/c601254013f6f9cfe5fd2ac6119e9cd5.png)
-
NULL→READY:
-
asink: NULL→READY: probes device, returns SUCCESS
-
asrc: NULL→READY: probes device, returns SUCCESS
-
-
READY→PAUSED:
-
asink: READY:→PAUSED open device, returns ASYNC
-
asrc: READY→PAUSED: open device, returns NO_PREROLL
-
-
PAUSED→PLAYING : asrc clock selected because it is the most upstream clock provider. asink can only provide a clock when it received the first buffer and configured the device with the samplerate in the caps.
-
asink: PAUSED:→PLAYING, sets pending state to PLAYING, returns ASYNC because it is not prerolled. The sink will commit state to PLAYING when it prerolls.
-
asrc: PAUSED→PLAYING: starts pushing buffers.
-
-
since the sink is still performing a state change from READY→PAUSED, it remains ASYNC. The pending state will be set to PLAYING.
-
The clock starts running as soon as all the elements have been set to PLAYING.
-
the source is a live source with a latency. Since it is synchronized with the clock, it will produce a buffer with timestamp 0 and duration D after time D, ie. it will only be able to produce the last sample of the buffer (with timestamp D) at time D. This latency depends on the size of the buffer.
-
the sink will receive the buffer with timestamp 0 at time >= D. At this point the buffer is too late already and might be dropped. This state of constantly dropping data will not change unless a constant latency correction is added to the incoming buffer timestamps.
该问题是由于以下事实造成的:将接收器设置为(挂起)PLAYING 而不能进行回滚,这仅在活动管道中发生。
例2
音频捕获/视频捕获/播放的管道:我们同时捕获音频和视频,并使它们再次同步播放。
-
asrc:音频源,提供时钟
-
asink音频接收器,提供时钟
-
vsrc:视频源
-
vsink视频接收器
![](https://i-blog.csdnimg.cn/blog_migrate/126116bc0010c436a4e13c26bb183d0e.png)
状态更改的发生方式与例1相同。两个接收器都以的挂起状态PLAYING和返回值结束,ASYNC直到它们接收到第一个缓冲区。为了使音频和视频同步播放,两个接收器必须补偿其源的延迟,但也必须使用完全相同的延迟校正。假设asrc的延迟为20ms,vsrc的延迟为33ms,则管道中的总延迟必须至少为33ms。这也意味着管道必须在33 - 20 = 13ms音频流上至少具有一个缓冲区,否则在音频接收器等待之前的样本播放时,音频src将不足。
例3
连接到活动接收器(vsink,sink)的非活动(文件)和活动源(vsrc)的组合示例。
![](https://i-blog.csdnimg.cn/blog_migrate/9c2cb2147b307e8b8c26f2faccc613cd.png)
状态更改的发生方式与例1相同。除了接收器能够预滚动(将其提交到PAUSED)。在这种情况下,接收器将没有延迟,但vsink将没有延迟。总延迟应该是vsink的延迟。
请注意,由于存在实时源(vsrc),可以在接收器能够预滚动之前将管道设置为正在播放。如果不对实时源进行补偿,这可能会导致同步问题,因为应该在元素中进行配置,然后才能转到PLAYING。
例4
非实时资源和实时资源的组合示例。非活动源连接到活动接收器,活动源连接到非活动接收器。
![](https://i-blog.csdnimg.cn/blog_migrate/1061afec07873818c78013d51ca690da.png)
状态更改的发生方式与示例3相同。接收器将能够进行预滚动(将状态提交至PAUSED)。文件将无法预卷。接收器没有延迟,因为它没有连接到实时源。文件不执行同步,因此它不关心延迟。流水线中的总延迟为0。vsrc与接收器中的回放同步捕获。与例3一样,接收器只能PLAYING在成功预卷后设置为。
3、查看管道中的延迟
一个跟踪模块,它通过在源中注入自定义事件并在接收器中处理它们来确定从源到接收器的延迟。该元素支持跟踪整个管道延迟和每个元素延迟。默认情况下,仅跟踪管道延迟。'flags'参数可用于启用元素跟踪。
![](https://i-blog.csdnimg.cn/blog_migrate/7097921be44592565cceca7ee127b53e.png)
4、测试rtspsrc latency延迟效果
![](https://i-blog.csdnimg.cn/blog_migrate/b7ffc443000bf560afd9e6f0f43f2c82.png)