From 40a072480c5d52d7daa21dd6162dfba40954f053 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 17 Apr 2014 22:50:49 +0200 Subject: 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. --- audio/out/push.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'audio/out/push.c') 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; } -- cgit v1.2.3