summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2014-07-26 23:19:14 +0200
committerwm4 <wm4@nowhere>2014-07-26 23:20:09 +0200
commitbc6359313f55ef42e2e4737323844a224f17730b (patch)
treec0e96f01f4e505c88056d765d14c5fb1de0d847b
parent77d9e4b8a9286bc6dcd5f5d4c073351a9033def0 (diff)
downloadmpv-bc6359313f55ef42e2e4737323844a224f17730b.tar.bz2
mpv-bc6359313f55ef42e2e4737323844a224f17730b.tar.xz
ao_pulse: allow disabling timing bug workarounds
Add an option that enables using native PulseAudio auto-updated timing information, instead of the manual calculations added in mplayer2 times. You can use --ao=pulse:no-latency-hacks to enable the new code. The code is almost the same as the code that was removed with commit de435ed5, but I didn't readd some bits I didn't understand. Likewise, the option will disable the code added with that commit. In my tests this seemed to work well, though the A/V sync display looks funny when seeking. The default is still the old behavior. See issue #959.
-rw-r--r--DOCS/man/ao.rst6
-rw-r--r--audio/out/ao_pulse.c41
2 files changed, 44 insertions, 3 deletions
diff --git a/DOCS/man/ao.rst b/DOCS/man/ao.rst
index a86f3374db..186512c7a5 100644
--- a/DOCS/man/ao.rst
+++ b/DOCS/man/ao.rst
@@ -149,6 +149,12 @@ Available audio output drivers are:
value makes the audio stream react faster, e.g. to playback speed
changes. Default: 250.
+ ``latency-hacks=<yes|no>``
+ Enable hacks to workaround PulseAudio timing bugs (default: yes). If
+ enabled, mpv will do elaborate latency calculations on its own. If
+ disabled, it will use PulseAudio automatically updated timing
+ information. Disabling this might help with e.g. networked audio.
+
``portaudio``
PortAudio audio output driver. This works on all platforms, and has
extensive MS Windows support.
diff --git a/audio/out/ao_pulse.c b/audio/out/ao_pulse.c
index d0af2a856c..14b5161940 100644
--- a/audio/out/ao_pulse.c
+++ b/audio/out/ao_pulse.c
@@ -63,6 +63,7 @@ struct priv {
char *cfg_host;
char *cfg_sink;
int cfg_buffer;
+ int cfg_latency_hacks;
};
#define GENERIC_ERR_MSG(str) \
@@ -365,8 +366,13 @@ static int init(struct ao *ao)
.minreq = -1,
.fragsize = -1,
};
+
+ int flags = PA_STREAM_NOT_MONOTONIC;
+ if (!priv->cfg_latency_hacks)
+ flags |= PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE;
+
if (pa_stream_connect_playback(priv->stream, sink, &bufattr,
- PA_STREAM_NOT_MONOTONIC, NULL, NULL) < 0)
+ flags, NULL, NULL) < 0)
goto unlock_and_fail;
/* Wait until the stream is ready */
@@ -463,8 +469,7 @@ static int get_space(struct ao *ao)
return space / ao->sstride;
}
-// Return the current latency in seconds
-static float get_delay(struct ao *ao)
+static float get_delay_hackfixed(struct ao *ao)
{
/* This code basically does what pa_stream_get_latency() _should_
* do, but doesn't due to multiple known bugs in PulseAudio (at
@@ -519,6 +524,34 @@ static float get_delay(struct ao *ao)
return latency / 1e6;
}
+static float get_delay_pulse(struct ao *ao)
+{
+ struct priv *priv = ao->priv;
+ pa_usec_t latency = (pa_usec_t) -1;
+ pa_threaded_mainloop_lock(priv->mainloop);
+ while (pa_stream_get_latency(priv->stream, &latency, NULL) < 0) {
+ if (pa_context_errno(priv->context) != PA_ERR_NODATA) {
+ GENERIC_ERR_MSG("pa_stream_get_latency() failed");
+ break;
+ }
+ /* Wait until latency data is available again */
+ pa_threaded_mainloop_wait(priv->mainloop);
+ }
+ pa_threaded_mainloop_unlock(priv->mainloop);
+ return latency == (pa_usec_t) -1 ? 0 : latency / 1000000.0;
+}
+
+// Return the current latency in seconds
+static float get_delay(struct ao *ao)
+{
+ struct priv *priv = ao->priv;
+ if (priv->cfg_latency_hacks) {
+ return get_delay_hackfixed(ao);
+ } else {
+ return get_delay_pulse(ao);
+ }
+}
+
/* A callback function that is called when the
* pa_context_get_sink_input_info() operation completes. Saves the
* volume field of the specified structure to the global variable volume.
@@ -648,11 +681,13 @@ const struct ao_driver audio_out_pulse = {
.priv_size = sizeof(struct priv),
.priv_defaults = &(const struct priv) {
.cfg_buffer = 250,
+ .cfg_latency_hacks = 1,
},
.options = (const struct m_option[]) {
OPT_STRING("host", cfg_host, 0),
OPT_STRING("sink", cfg_sink, 0),
OPT_CHOICE_OR_INT("buffer", cfg_buffer, 0, 1, 2000, ({"native", -1})),
+ OPT_FLAG("latency-hacks", cfg_latency_hacks, 0),
{0}
},
};