[pulseaudio-discuss] a question about audio synchronization between local sink and tunnel sink

Tanu Kaskinen tanuk at iki.fi
Wed Oct 24 01:26:30 PDT 2012

On Thu, 2012-10-18 at 21:45 +0300, Tanu Kaskinen wrote:
> On Wed, 2012-10-17 at 18:12 +0000, Sun, Xiaodong wrote:
> > Hi, Tanu,
> > 
> > Yes, with my embedded sink device. I can get synchronized playback
> > eventually. But the time between playing start and synchronization is
> > too long. The minimum is 1.5 minutes (sorry 1.5s is a typo error). So
> > it is not good enough for synchronized playback.
> > 
> > Now there are two directions to improve this. The first (more feasible
> > but not perfect) is tweaking the adjust_rates() function and make
> > synchronization faster when latency is bigger. The second (don't know
> > how much effort but should be a perfect solution) is adding a new
> > algorithm based on timestamp besides current rate adjust algorithm. 
> > 
> > I will try the first one since it is a feasible method for me to try.
> > For the second one, how much effort do you think there is? And do you
> > have any plan to do this kind of improvement?
> Answering the second question first: I don't have any plan of
> implementing synchronized stream start in the foreseeable future. I'm
> not opposed to having such feature, though, if someone else implements
> it.
> Then, how much effort I think there is... You should start by making it
> possible to create a stream in a corked (paused) state and schedule its
> start at an exact point in time.

Actually, I think this is not necessary. I believe module-combine-sink
can do near-perfect synchronization by its own, without touching code
elsewhere. When module-combine-sink creates a new output stream, it can
check the latency of the new stream once the stream is attached to the
output sink. If there are other outputs (so the new output stream needs
to be synchronized with them), module-combine-sink can seek in the input
buffer to an appropriate place when it writes the first chunk of audio
to the new stream. That way the new stream will immediately start
playing at the same place that other streams are playing.

I don't know how big changes this would require in module-combine-sink,
possibly quite big, but at least you don't have to add new functionality
to the pulseaudio core.

Here's how to ask the stream latency: in sink_input_pop_cb() in
module-combine-sink.c, do this when the sink asks for the first chunk of

    pa_usec_t sink_input_latency, sink_latency, total_latency;

    sink_input_latency = pa_sink_input_get_latency_within_thread(i, &sink_latency);
    total_latency = sink_input_latency + sink_latency;
    /* then seek in the input buffer as appropriate */

There's a problem, though: pa_sink_input_get_latency_within_thread()
doesn't exist. But you can add it. The code should look like this:

    pa_usec_t pa_sink_input_get_latency_within_thread(pa_sink_input *i, pa_usec_t *sink_latency) {

        if (sink_latency)
            *sink_latency = pa_sink_get_latency_within_thread(i->sink);

        return pa_bytes_to_usec(pa_memblockq_get_length(i->thread_info.render_memblockq), &i->sink->sample_spec);


More information about the pulseaudio-discuss mailing list