mirror of
https://github.com/mpv-player/mpv
synced 2024-12-25 08:12:17 +00: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:
parent
fd56e2dbe6
commit
665c8b59be
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user