summaryrefslogtreecommitdiffstats
path: root/libao2/ao_pulse.c
diff options
context:
space:
mode:
authorUoti Urpala <uau@mplayer2.org>2012-03-26 03:47:44 +0300
committerUoti Urpala <uau@mplayer2.org>2012-03-26 03:55:31 +0300
commit81de9a52d04c3bbadaeca1852040ba4395b0e6a3 (patch)
tree932667ad930095c05cb444079ff53f16833749ad /libao2/ao_pulse.c
parenta0de4bc5000823c058aab6b02a7fdfb48275cb32 (diff)
downloadmpv-81de9a52d04c3bbadaeca1852040ba4395b0e6a3.tar.bz2
mpv-81de9a52d04c3bbadaeca1852040ba4395b0e6a3.tar.xz
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.c20
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. */