0
0
mirror of https://github.com/mpv-player/mpv.git synced 2024-09-20 12:02:23 +02:00

audio/out: avoid wakeup feedback loop

When the audio buffer went low, but could not be refilled yet, it could
happen that the AO playback thread and the decode thread could enter a
wakeup feedback loop, causing up to 100% CPU usage doing nothing. This
happened because the decoder thread would wake up the AO thread when
writing 0 bytes of newly decoded data, and the AO thread in reaction
wakes up the decoder thread after writing 0 bytes to the AO buffer.

Fix this by waking up the decoder thread only if data was actually
played or queued. (This will still cause some redundant wakeups, but
will eventually settle down, reducing CPU usage close to ideal.)
This commit is contained in:
wm4 2014-05-11 19:00:05 +02:00
parent fd56e2dbe6
commit 665c8b59be

View File

@ -49,6 +49,7 @@ struct ao_push_state {
struct mp_audio_buffer *buffer;
bool newdata;
bool terminate;
bool playing;
@ -185,6 +186,8 @@ 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;
@ -216,8 +219,10 @@ 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
@ -256,7 +261,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)
if (timeout <= min_wait / 2 + 0.001 && !p->newdata)
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