From c78b8b2c0cba56bbccfb3f8f8eb5de90b2d4cfeb Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 11 May 2014 20:51:49 +0200 Subject: [PATCH] audio/out: fix previous commit This didn't quite work. The main issue was that get_space tries to be clever to reduce overall buffering, so it will cause the playloop to decode and queue only as much audio as is needed to refill the AO in reasonable time. Also, even if ignoring the problem, the logic of the previous commit was slightly broken. (This required a few retries, because I couldn't reproduce the issue on my own machine.) --- audio/out/push.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/audio/out/push.c b/audio/out/push.c index 8ec8ba28ca..086536001d 100644 --- a/audio/out/push.c +++ b/audio/out/push.c @@ -49,7 +49,6 @@ struct ao_push_state { struct mp_audio_buffer *buffer; - bool newdata; bool terminate; bool playing; @@ -148,10 +147,9 @@ static void drain(struct ao *ao) } } -static int get_space(struct ao *ao) +static int unlocked_get_space(struct ao *ao) { struct ao_push_state *p = ao->api_priv; - pthread_mutex_lock(&p->lock); int space = mp_audio_buffer_get_write_available(p->buffer); if (ao->driver->get_space) { // The following code attempts to keep the total buffered audio to @@ -167,6 +165,14 @@ static int get_space(struct ao *ao) space = MPMIN(space, missing); space = MPMAX(0, space); } + return space; +} + +static int get_space(struct ao *ao) +{ + struct ao_push_state *p = ao->api_priv; + pthread_mutex_lock(&p->lock); + int space = unlocked_get_space(ao); pthread_mutex_unlock(&p->lock); return space; } @@ -186,8 +192,6 @@ static int play(struct ao *ao, void **data, int samples, int flags) audio.planes[n] = data[n]; audio.samples = write_samples; mp_audio_buffer_append(p->buffer, &audio); - if (write_samples > 0) - p->newdata = true; p->final_chunk = !!(flags & AOPLAY_FINAL_CHUNK); p->playing = true; @@ -219,10 +223,8 @@ static int ao_play_data(struct ao *ao) MP_WARN(ao, "Audio device returned non-sense value.\n"); r = data.samples; } - if (r > 0) { + if (r > 0) mp_audio_buffer_skip(p->buffer, r); - p->newdata = false; - } 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 @@ -261,7 +263,7 @@ static void *playthread(void *arg) } // Half of the buffer played -> wakeup playback thread to get more. double min_wait = ao->device_buffer / (double)ao->samplerate; - if (timeout <= min_wait / 2 + 0.001 && !p->newdata) + if (timeout <= min_wait / 2 + 0.001 && unlocked_get_space(ao) > 0) mp_input_wakeup(ao->input_ctx); // Avoid wasting CPU - this assumes ao_play_data() usually fills the // audio buffer as far as possible, so even if the device buffer