problem with synchronization between multiple audio clients

Carlos Rafael Giani dv at pseudoterminal.org
Thu Nov 14 02:51:52 PST 2013


On 2013-11-13 15:35, Javier Domingo wrote:
> Hi Tim!,
>
> Thanks a lot for the info! I was just wondering whether if the RTP[1]
> standard would be capable of that. I had already seen aurena, but I
> prefer the RTP solution. I will be doing experiments with it though,
> and report back if I encounter something interesting,
>
> Cheers,
>
> Javier Domingo Cansino
> Research & Development Junior Engineer
> Fon Labs Workgroup, Getxo - Spain
>
> [1] RTP Standard: http://tools.ietf.org/html/rfc3550
> _______________________________________________
> gstreamer-devel mailing list
> gstreamer-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel

RTP is definitely capable of this. We use RTP/RTCP in our software stack 
for this very purpose, and the phase shift between the receivers is 
typically less than 2ms over Wi-Fi. It could be even better, but this 
would require a thorough analysis of the entire audio sink layer. A very 
useful tool for this purpose that has been proposed is a test audio 
sink, together with a test audio clock, to be able to formulate unit 
tests and to try out the synchronization algorithms in the sink, be able 
to plot results etc.

If you want synchronized audio receivers with GStreamer, you need three 
components: the synchronized clock, the RTP/RTCP logic, and the 
synchronized sink.
The first one is easy: just use the GstNetClientClock on the receiver 
and the GstNetTimeProvider on the sender. The second is given to you by 
the rtpbin. The third is tricky though. I will elaborate on this a bit. 
Perhaps some information is redundant, I'm not sure:

The audio sink has to compensate the difference between clock speeds 
(pipeline clock vs. audio clock). The audio hardware often has its own 
Quartz crystal, and no two crystals oscillate with the exact same 
frequency. Plus, if your receiver's pipeline clock is synchronized to 
the sender's, its speed will differ from the audio clock's anyway. If 
this is not compensated, an drift between the clocks will build up, 
since playback on the receiver may be a bit faster, or a bit slower, 
compared to another receiver.

The sink calls the compensation modes "slave-methods", as in "slaving 
the audio clock to the pipeline clock". The default is to skew the 
playout pointer; the audio sink lets the drift accumulate, until a 
certain threshold is reached, at which point the sink moves the current 
playback position inside its ring buffer, effectively "cutting out" or 
"skipping" samples. While this works, it introduces artifacts, which are 
sometimes audible. Also, it is not accurate. Overall, the measured 
"skew" (= the current drift between the clocks) is *very* noisy. The 
audio sink internally tries to compensate for that by using a running 
average, but it often is not enough. So the method will skew the pointer 
more often than it should, based on incorrect data. The likelihood of 
this happening depends directly on the drift-tolerance property value, 
which is the aforementioned threshold. Try to set it to 500 microseconds 
for example, and run a pipeline like: GST_DEBUG=*audiobasesink*:2 
gst-launch audiotestsrc ! alsasink provide-clock=false 
drift-tolerance=500 . You will get lots of warnings about the sink 
skewing the pointer.

If you want very low average drift, and no "cuts", you'll need to 
compensate the drift yourself. I submitted a patch to allow for 
installing a custom callback where you can install your own compensation 
algorithm. We use a PLL on our hardware to increase/decrease the audio 
clock's frequency. This combats the drift in a much more fine-grained 
way. Another option would be to use an asynchronous resampler, which 
allows fluctuations of the input or output sample rate by a few ppm.

One strange problem that is left unanswered is the presence of an 
initial drift. The skew value is not close to zero in the beginning as I 
expected it to be. Instead, it is quite large, so I had to come up with 
an initial phase where I cut down this drift quickly by skewing the 
playout pointer, then switching to fine-grained PLL control. Ideally, 
this initial phase would be unnecessary. This is precisely where the 
test audio sink & clock would be useful.

Also, be aware that the net client clock is susceptible to some effects 
that are rather common on Wi-Fi, like heavily delayed time sync packets 
(which arrive far too late and therefore mess up the synchronization), 
or a significant asymmetry between provider->client and client->provider 
transmission speeds. Patches for that are currently being considered.

cheers


More information about the gstreamer-devel mailing list