diff options
author | wm4 <wm4@nowhere> | 2016-10-04 19:31:17 +0200 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2016-10-04 19:31:17 +0200 |
commit | 39f515cb6a35b1c47a7b12bf600a673bf35921ac (patch) | |
tree | dda54d449e2ab51d22a8aa965df1fea93815a9d1 /audio/out | |
parent | 13dcf82a96ba2b7db0966d69e38819d5e0feb65d (diff) | |
download | mpv-39f515cb6a35b1c47a7b12bf600a673bf35921ac.tar.bz2 mpv-39f515cb6a35b1c47a7b12bf600a673bf35921ac.tar.xz |
audio/out: prevent underruns with spdif under certain conditions
The player tries to avoid splitting frames with spdif (sample alignment
stuff). This can in certain corner cases with certain drivers lead to
the situation that ao_get_space() returns a number higher than 0 and
lower than the audio frame size. The playloop will round this down to 0
bytes and do nothing, leading to a missed wakeup. This can lead to
underruns or playback completely getting stuck.
It can be reproduced by playing AC3 passthrough with no video and:
--ao=null --ao-null-buffer=0.256 --ao-null-outburst=6100
This commit attempts to fix it by allowing the playloop to write some
additional data (to get a complete frame), that will be buffered within
the AO ringbuffer even if the audio device doesn't want it.
Diffstat (limited to 'audio/out')
-rw-r--r-- | audio/out/push.c | 2 |
1 files changed, 2 insertions, 0 deletions
diff --git a/audio/out/push.c b/audio/out/push.c index 623ee6827a..68606386f2 100644 --- a/audio/out/push.c +++ b/audio/out/push.c @@ -182,6 +182,7 @@ static int unlocked_get_space(struct ao *ao) struct ao_push_state *p = ao->api_priv; int space = mp_audio_buffer_get_write_available(p->buffer); if (ao->driver->get_space) { + int align = af_format_sample_alignment(ao->format); // The following code attempts to keep the total buffered audio to // ao->buffer in order to improve latency. int device_space = ao->driver->get_space(ao); @@ -191,6 +192,7 @@ static int unlocked_get_space(struct ao *ao) // byte based and doesn't do proper chunked processing. int min_buffer = ao->buffer + 64; int missing = min_buffer - device_buffered - soft_buffered; + missing = (missing + align - 1) / align * align; // But always keep the device's buffer filled as much as we can. int device_missing = device_space - soft_buffered; missing = MPMAX(missing, device_missing); |