diff options
author | Uoti Urpala <uau@mplayer2.org> | 2012-03-26 03:47:44 +0300 |
---|---|---|
committer | Uoti Urpala <uau@mplayer2.org> | 2012-03-26 03:55:31 +0300 |
commit | 81de9a52d04c3bbadaeca1852040ba4395b0e6a3 (patch) | |
tree | 932667ad930095c05cb444079ff53f16833749ad /libao2/ao_pulse.c | |
parent | a0de4bc5000823c058aab6b02a7fdfb48275cb32 (diff) |
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...
Diffstat (limited to 'libao2/ao_pulse.c')
-rw-r--r-- | libao2/ao_pulse.c | 20 |
1 files changed, 19 insertions, 1 deletions
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. */ |