Hello, Le vendredi 19 ao?t 2011 21:02:59 David Henningsson, vous avez ?crit : > 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. Nice. > 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. VLC currently assumes that a PulseAudio under-run event implies a silence/glitch. It uses it as an opportunity to resync the audio stream... this is not good if there was no actual under-run :-/ > 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) Yeah. That would certainly be better than the current zero padding of the stream, especially when resuming from pause (i.e. PulseAudio uncorking). But but, VLC does not have a mainloop. A timer is going to need a dedicated thread. Or maybe libpulse can accept user timers in its threaded mainloop? > 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). vlc_timer_*() functions. But I'd rather use the Pulse mainloop if possible. > 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. In my experience, larger tlength caused more underruns. But maybe that's because VLC is more likely to be continuously late? > Also remember to set the PA_STREAM_ADJUST_LATENCY flag. It's not clear to me what this actually will do. > Hopefully this gives a little insight in the current problems with VLC > and PulseAudio! -- R?mi Denis-Courmont http://www.remlab.net/ http://fi.linkedin.com/in/remidenis