summaryrefslogtreecommitdiffstats
path: root/audio
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2014-04-17 22:50:49 +0200
committerwm4 <wm4@nowhere>2014-04-17 22:50:49 +0200
commit40a072480c5d52d7daa21dd6162dfba40954f053 (patch)
treec5e5d8593093869fffae319adaff8025827ea94c /audio
parentfe298bc2a571405f38343eb9c6280f694db49ffa (diff)
downloadmpv-40a072480c5d52d7daa21dd6162dfba40954f053.tar.bz2
mpv-40a072480c5d52d7daa21dd6162dfba40954f053.tar.xz
audio: add hack against broken pulseaudio EOF condition
This was reported with PulseAudio 2.1. Apparently it still has problems with reporting the correct delay. Since ao_pulse.c still has our custom get_delay implementation, there's a possibility that this is our fault, but this seems unlikely, because it's full of workarounds for issues like this. It's also possible that this problem doesn't exist on PulseAudio 5.0 anymore (I didn't explicitly retest it). The check is general and works for all push based AOs. For pull based AOs, this can't happen as pull.c implements all the logic correctly.
Diffstat (limited to 'audio')
-rw-r--r--audio/out/push.c17
1 files changed, 16 insertions, 1 deletions
diff --git a/audio/out/push.c b/audio/out/push.c
index 9fb3995d11..6a11dbf2ee 100644
--- a/audio/out/push.c
+++ b/audio/out/push.c
@@ -31,6 +31,7 @@
#include "input/input.h"
#include "osdep/threads.h"
+#include "osdep/timer.h"
#include "compat/atomics.h"
#include "audio/audio.h"
@@ -53,6 +54,7 @@ struct ao_push_state {
// Whether the current buffer contains the complete audio.
bool final_chunk;
+ double expected_end_time;
// -- protected by wakeup_lock
bool need_wakeup;
@@ -88,6 +90,13 @@ static float get_delay(struct ao *ao)
driver_delay = ao->driver->get_delay(ao);
double delay = driver_delay + mp_audio_buffer_seconds(p->buffer);
pthread_mutex_unlock(&p->lock);
+ if (delay >= AO_EOF_DELAY && p->expected_end_time) {
+ if (mp_time_sec() > p->expected_end_time) {
+ MP_ERR(ao, "Audio device EOF reporting is broken!\n");
+ MP_ERR(ao, "Please report this problem.\n");
+ delay = 0;
+ }
+ }
return delay;
}
@@ -121,6 +130,7 @@ static void resume(struct ao *ao)
if (ao->driver->resume)
ao->driver->resume(ao);
p->playing = true; // tentatively
+ p->expected_end_time = 0;
wakeup_playthread(ao);
pthread_mutex_unlock(&p->lock);
}
@@ -178,6 +188,7 @@ static int play(struct ao *ao, void **data, int samples, int flags)
p->final_chunk = !!(flags & AOPLAY_FINAL_CHUNK);
p->playing = true;
+ p->expected_end_time = 0;
wakeup_playthread(ao);
pthread_mutex_unlock(&p->lock);
@@ -206,8 +217,12 @@ static int ao_play_data(struct ao *ao)
}
if (r > 0)
mp_audio_buffer_skip(p->buffer, r);
- if (p->final_chunk && mp_audio_buffer_samples(p->buffer) == 0)
+ if (p->final_chunk && mp_audio_buffer_samples(p->buffer) == 0) {
p->playing = false;
+ p->expected_end_time = mp_time_sec() + AO_EOF_DELAY + 0.25; // + margin
+ if (ao->driver->get_delay)
+ p->expected_end_time += ao->driver->get_delay(ao);
+ }
return r;
}