[pulseaudio-discuss] VLC, PulseAudio and large tlengths

David Henningsson david.henningsson at canonical.com
Fri Aug 19 11:02:59 PDT 2011


I've spent most the afternoon trying to figure out why VLC doesn't work 
well with a large tlengths. I seem to have found suboptimal behaviour on 
both the PulseAudio and VLC sides.

What bothers me on the PulseAudio side is this call (in alsa-sink.c, 
mmap_write):

pa_sink_render_into_full(u->sink, &chunk);

For this example, assume tlength is 500 ms and minreq is 50 ms. In 
adjust latency mode (which I understand is recommended for power 
efficiency), this is configured to the client's tlength/2 - minreq = 200 
ms. The problem here is that if the client is filled up to only e g 130 
ms, PulseAudio will take the 130 ms, the client will underrun, and hand 
out 70 ms of silence. A better behaviour would be to write the 130 ms 
that are available, and go to sleep until the 130 ms is almost up and 
see if more data has come in at that time.

However, things are probably not as bad as it looks. If a new package 
comes in from the client in time, I believe PulseAudio would rewind back 
the 70 ms of silence and write the new data, and no glitch will be 
heard. So the worst thing is actually the somewhat "false alarm" sent to 
the client.

However messing with PulseAudio's buffering mechanisms isn't giving me 
warm and fuzzy feelings, at least not right before the 1.0 release :-D

So over to the VLC side. I started off with the current git head of VLC.

For the synchronisation, I believe the correct way is to do something like:
1) when the first packet arrives, notice its timestamp (pts), and set a 
system timer to trigger at that point in time (i e trigger in i->pts - 
mdate() usecs)
2) the callback from the system timer would then uncork/trigger the stream.
At that point, PulseAudio's buffer has been filled up by all the other 
calls to Play that happened in between.

I did a quick hack myself: I didn't know how to do system timers in VLC 
so I set it to check at every call to Play, if it was yet time to start 
the stream. (And commented out the call to stream_resync.) That gave 
good synchronisation as well as I could see (being layman on observing 
synchronisation issues).

For the buffering attributes, I tried setting tlength to 500 ms (note: 
AOUT_MAX_PREPARE_TIME is actually 2000 ms, not 500 ms as I originally 
thought).
Given an initial filled buffer as suggested above, that did not 
underrun. That was with playing back a local video file.
I set minreq to AOUT_MIN_PREPARE_TIME (40 ms), which is mostly taken out 
of the air.

However, given the reasoning above, if you want to be certain to avoid 
the false underrun alarms as outlined in the PulseAudio section, I 
believe a minreq of AOUT_MIN_PREPARE_TIME and tlength of 
AOUT_MIN_PREPARE_TIME * 4 = 160 ms should be a relatively safe setting.

Also remember to set the PA_STREAM_ADJUST_LATENCY flag.

Hopefully this gives a little insight in the current problems with VLC 
and PulseAudio!

-- 
David Henningsson, Canonical Ltd.
http://launchpad.net/~diwic


More information about the pulseaudio-discuss mailing list