Gstreamer的同步机制

本文编译自gstreamer源代码中的文档,原文的路径是gstreamer/docs/design/part-synchronisation.txt。

本文描述了Gstreamer的同步机制,Gstreamer中实现同步的组件如下:

  • GstClock,是全局的,用于pipeline中的所有elements。
  • GstBuffer的timestamps。
  • buffers之前的NEW_SEGMENT event。

GstClock

GstClock是精确到纳秒的表示当前时间的一个计数。其值用absolute_time表示。这个计数的源的选择如下:

  • 系统时间,精度是微妙。
  • 音频设备。
  • 基于网络的数据包,比如RTP数据包。
  • 其它。

在Gstreamer中任何element都可以提供GstClock,pipeline从所有可用的GstClock中选定一个并用于pipeline中所有的elements。时间计数单调递增,可以不是从0开始计数。

Running time

选定了clock之后pipeline会维护一个基于选定时钟的running_time。running_time指的是pipeline处于PLAYING状态下的时间总和,计算方法如下:

  • 如果pipeline处于NULL或者READY状态则running_time处于undefined。
  • PAUSE状态下,running_time的值保持不变,如果处于刚开始启动时的PAUSE状态,running_time的值为0。
  • flushing seek之后,running_time被置为0。这需要向所有被flush的elemnt指定一个新的base_time。

上述的计算方法在pipeline的状态从PLAYING状态设定为PAUSE状态时记录running_time,当从PAUSE状态转变为PLAYING状态后基于absolute_time恢复running_time。针对PAUSE后继续计数的clock,比如system clock,以及PAUSE后不再计数的clock,比如audioclock都是适用的。

running_time的计算方法如下:

C.running_time = absolute_time - base_time

Timestamps

GstBuffer的timestamps以及NEW_SEGMENT event定义了 buffer timestamps 到 running_time的变换

B: GstBuffer

  • B.timestamp = buffer timestamp (GST_BUFFER_TIMESTAMP)

NS:  NEWSEGMENT event preceeding the buffers.

  • NS.start: start field in the NEWSEGMENT event
  • NS.stop: stop field in the NEWSEGMENT event
  • NS.rate: rate field of NEWSEGMENT event
  • NS.abs_rate: absolute value of rate field of NEWSEGMENT event
  • NS.time: time field in the NEWSEGMENT event
  • NS.accum: total accumulated time of all previous NEWSEGMENT events. This field is kept in the GstSegment structure.

符合同步要求的buffers其B.timestamp需在NS.start和NS.stop之间,B.timestamp不在这个范围内的buffers需要丢掉或者进行修正。

对于running_time存在如下变换:

if (NS.rate > 0.0)
          B.running_time = (B.timestamp - NS.start) / NS.abs_rate + NS.accum
else
          B.running_time = (NS.stop - B.timestamp) / NS.abs_rate + NS.accum

B.running_time由NEWSEGMENT event以及该segment的buffers得到。

可显示的第一个buffer的running_time的值为0。

对于 NS.rate > 1.0,timestamps的值缩小从而使得播放速度加快。

For negative rates, timestamps are received stop NS.stop to NS.start so that the first buffer received will be transformed into B.running_time of 0 (B.timestamp == NS.stop and NS.accum == 0).

Synchronisation

对于running_time的计算方法如下:

  • 采用clock以及element的base_time:
C.running_time = absolute_time - base_time
  • 采用buffer timestamp和其前面的NEWSEGMENT event,假定为正向播放:
B.running_time = (B.timestamp - NS.start) / NS.abs_rate + NS.accum

这里的前缀C.和B.代表不同的计算方法。

同步播放的目的就是确保running_time为B.running_time的buffer在C.running_time的时刻播放。

这需要满足如下条件:

B.running_time = C.running_time

也就是:

B.running_time = absolute_time - base_time

或者

absolute_time = B.running_time + base_time

具有B.running_time的buffer应当被播放时的absolute_time记为B.sync_time,那么:

B.sync_time = B.running_time + base_time

这意味着等到clock到了B.sync_time的时候才播放buffer,对于多个流中具有相同的running_time的buffer应该同时播放。

dumuxer必须确保向输出pads发出的NEWSEGMENT能为buffers生成一样的running_time,从而使之保持同步。通常向pads发出同样的NEWSEGMENT来确保同步的buffer具有一样的timestamp。

Stream time

stream time,也称作在流中的位置,是一个在0和媒体文件长度(时间)之间的值。具有如下用途:

  • report the POSITION query in the pipeline
  • the position used in seek events/queries
  • the position used to synchronize controller values

通过buffer和其前面的NEWSEGMENT event来计算stream time:

stream_time = (B.timestamp - NS.start) * NS.abs_applied_rate + NS.time

对于播放速度为负的情况,B.timestamp将从NS.stop 到 NS.start,使得stream time反向。在PLAYING 状态,也可以采用pipeline clock 计算当前的stream_time。 Give the two formulas above to match the clock times with buffer timestamps allows us to rewrite the above formula for stream_time (and for positive rates).

C.running_time = absolute_time - base_time

B.running_time = (B.timestamp - NS.start) / NS.abs_rate + NS.accum

=>

(B.timestamp - NS.start) / NS.abs_rate + NS.accum = absolute_time - base_time;

=>

(B.timestamp - NS.start) / NS.abs_rate = absolute_time - base_time - NS.accum;

=>

(B.timestamp - NS.start) = (absolute_time - base_time - NS.accum) * NS.abs_rate

  filling (B.timestamp - NS.start) in the above formule for stream time

=>

stream_time = (absolute_time - base_time - NS.accum) * NS.abs_rate * NS.abs_applied_rate + NS.time

最后的计算公式通常是sink用于report当前的position的准确和有效的方式。Note that the stream time is never used for synchronisation against the clock.
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值