Transmit absolute time

Sebastian Dröge sebastian at
Wed Oct 14 23:38:03 PDT 2015

On Do, 2015-10-15 at 00:45 +0200, Carlos Rafael Giani wrote:
> Here's how I achieved something similar.
> First, I synchronized the clocks of all devices.

That's not really necessary, you can keep the system clocks as they are
and just use to the correct clocks inside GStreamer for the pipeline :)

>  This was before 
> GStreamer 1.6, so GstPTPClock wasn't available. I'd probably use this
> one now. Instead, I used the GstNetClientClock. On the sender, I
> started a GstNetTimeProvider, and installed a monotonic
> GstSystemClock as the sender's pipeline clock. The net time provider
> provided this clock to the receivers. On the receivers, I used
> GstNetClientClocks as the pipeline clocks.

Ack, and PTP/NTP clocks work basically the same.

> Since in my case, both sender and receiver were under my full
> control, I opted for adding a header extension to the RTP packets. On
> the sender side, I first converted the buffer presentation timestamps
> to running time using gst_segment_to_running_time(), and then added
> the running-time to these converted timestamps. In short: I moved the

I think you mean adding base-time, not running-time here.

> timestamps into clock-time. On the receiver side, I made sure the 
> pipeline doesn't set the base-time of the contained elements by
> calling gst_element_set_start_time(pipeline, GST_CLOCK_TIME_NONE).
> This makes sure all elements have base-time 0. Since running-time =
> clock-time - base-time, this means that running-time = clock-time.

If you put the clock time in the header extension, this base time stuff
is not really needed. You can have different base times on all
pipelines, and then convert the clock time to the running time by
subtracting the individual base times of each pipeline.

> And because the timestamps the sender put in these header extensions,
> all I have to do at the receiver is to pull out the timestamps from
> these headers (I ignore the RTP timestamps), and put them into the
> corresponding GstBuffers, effectively restoring their timestamps just
> like they were at the sender's side. I do not use RTCP or rtpbin,
> because it is unnecessary here.

That way you get accurate timestamps at the cost of a header extension.
Alternatively you could use RTCP to distribute the same information,
but that would be less accurate (based on RTP clock rate) and also only
every now and then instead of for up to every single packet.

RFC7273 has yet another way of doing this, by telling you exactly which
clock was used for timestamping a media and telling you the offset
between RTP timestamp and clock epoch. With that you get the same
accuracy as with RTCP, but have all information available from the very
beginning without any other communication than the media transport.

> As for the time between devices: you don't actually need to know it.
> All you have to do is to add a fixed delay, effectively "moving the
> timestamps into the future". In a basic setup, you add a fixed delay
> D to your timestamp T in the sender. In regular playback, T, together
> with the base-time, will be a timestamp that is in the present. In
> other words, the delta between T and the current time is very close
> to 0. So,
> T + D = Tf . Tf is now "in the future" by an interval D. You use this
> timestamp both for the local playback  and for the transmissions.
> Since the sender's and receiver's clocks are synchronized, the packet
> with the timestamp Tf will arrive at the receiver before the clock
> reaches Tf; once the packet arrives at the receiver, its timestamp
> still is "in the future". When timestamps are in the future, sinks
> wait. And because both pipeline clocks are synchronized, both sinks
> will wait until the same time (Tf) is reached, and they both will
> start playing at the same time.
> This waiting happens only initially of course.
> In practice, you may not need to add D to the timestamps of the
> buffers that you send out (you do still need to do that for the local
> playback at the sender), since the rtpjitterbuffer can be used to
> that end. It adds latency to the pipeline, which does the same - it
> causes the pipeline to add an extra time (the latency time) to
> timestamps. So, if you set the length of the rtpjitterbuffer to D,
> you get the same effect.

Instead of all this (and even more accurate) is to just use
gst_pipeline_set_latency() on all receivers with the same (high
enough!) value. Then you can pass through timestamps as is without
adding a delay and also handle different decoder/sink/filter latencies
on the different receivers. Receiver A might have 10 frames decoder
latency, while receiver B only has 2... giving you a synchronisation
difference of 8 frames between the two unless you use

Sebastian Dröge, Centricular Ltd ·

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 949 bytes
Desc: This is a digitally signed message part
URL: <>

More information about the gstreamer-devel mailing list