From 81de9a52d04c3bbadaeca1852040ba4395b0e6a3 Mon Sep 17 00:00:00 2001 From: Uoti Urpala Date: Mon, 26 Mar 2012 03:47:44 +0300 Subject: ao_pulse: add hacks to work around seek problems pa_stream_flush() seems to work pretty badly in general. The visible symptoms included at least old audio continuing for a significant time after the call, and bogus latency reporting causing temporary video freezes after a seek. Add some hacks to work around these problems. The result seems to work most of the time on my machine at least... --- libao2/ao_pulse.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'libao2/ao_pulse.c') diff --git a/libao2/ao_pulse.c b/libao2/ao_pulse.c index ddaf35716c..ba95ccf2d2 100644 --- a/libao2/ao_pulse.c +++ b/libao2/ao_pulse.c @@ -49,6 +49,7 @@ struct priv { bool broken_pause; int retval; + bool did_reset; }; #define GENERIC_ERR_MSG(ctx, str) \ @@ -316,25 +317,40 @@ static void cork(struct ao *ao, bool pause) static int play(struct ao *ao, void *data, int len, int flags) { struct priv *priv = ao->priv; + /* For some reason Pulseaudio behaves worse if this is done after + * the write - rapidly repeated seeks result in bogus increasing + * reported latency. */ + if (priv->did_reset) + cork(ao, false); pa_threaded_mainloop_lock(priv->mainloop); if (pa_stream_write(priv->stream, data, len, NULL, 0, PA_SEEK_RELATIVE) < 0) { GENERIC_ERR_MSG(priv->context, "pa_stream_write() failed"); len = -1; } - pa_threaded_mainloop_unlock(priv->mainloop); + if (priv->did_reset) { + priv->did_reset = false; + if (!waitop(priv, pa_stream_update_timing_info(priv->stream, + success_cb, ao)) + || !priv->retval) + GENERIC_ERR_MSG(priv->context, "pa_stream_UPP() failed"); + } else + pa_threaded_mainloop_unlock(priv->mainloop); return len; } // Reset the audio stream, i.e. flush the playback buffer on the server side static void reset(struct ao *ao) { + // pa_stream_flush() works badly if not corked + cork(ao, true); struct priv *priv = ao->priv; pa_threaded_mainloop_lock(priv->mainloop); priv->retval = 0; if (!waitop(priv, pa_stream_flush(priv->stream, success_cb, ao)) || !priv->retval) GENERIC_ERR_MSG(priv->context, "pa_stream_flush() failed"); + priv->did_reset = true; } // Pause the audio stream by corking it on the server @@ -347,6 +363,8 @@ static void pause(struct ao *ao) static void resume(struct ao *ao) { struct priv *priv = ao->priv; + if (priv->did_reset) + return; /* Without this, certain versions will cause an infinite hang because * pa_stream_writable_size returns 0 always. * Note that this workaround causes A-V desync after pause. */ -- cgit v1.2.3