diff options
author | wm4 <wm4@nowhere> | 2017-06-25 15:57:15 +0200 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2017-06-25 15:57:43 +0200 |
commit | 037c37519b305bb5d5ea0379122d62ba356cc103 (patch) | |
tree | 5f93237279937290a3cd882e60a2bc040907a490 /audio/out/push.c | |
parent | 72ef74dab5244753c9bc6f33687aa60a2886c53b (diff) | |
download | mpv-037c37519b305bb5d5ea0379122d62ba356cc103.tar.bz2 mpv-037c37519b305bb5d5ea0379122d62ba356cc103.tar.xz |
audio/out: require AO drivers to report period size and correct buffer
Before this change, AOs could have internal alignment, and play() would
not consume the trailing data if the size passed to it is not aligned.
Change this to require AOs to report their alignment (via period_size),
and make sure to always send aligned data.
The buffer reported by get_space() now always has to be correct and
reliable. If play() does not consume all data provided (which is bounded
by get_space()), an error is printed.
This is preparation for potential further AO changes.
I casually checked alsa/lavc/null/pcm, the other AOs might or might not
work.
Diffstat (limited to 'audio/out/push.c')
-rw-r--r-- | audio/out/push.c | 15 |
1 files changed, 13 insertions, 2 deletions
diff --git a/audio/out/push.c b/audio/out/push.c index a722d19ea2..c271fc0cdc 100644 --- a/audio/out/push.c +++ b/audio/out/push.c @@ -285,6 +285,8 @@ static void ao_play_data(struct ao *ao) int space = ao->driver->get_space(ao); bool play_silence = p->paused || (ao->stream_silence && !p->still_playing); space = MPMAX(space, 0); + if (space % ao->period_size) + MP_ERR(ao, "Audio device reports unaligned available buffer size.\n"); struct mp_audio data; if (play_silence) { ao_get_silence(ao, &data, space); @@ -295,16 +297,25 @@ static void ao_play_data(struct ao *ao) if (data.samples > space) data.samples = space; int flags = 0; - if (p->final_chunk && data.samples == max) + if (p->final_chunk && data.samples == max) { flags |= AOPLAY_FINAL_CHUNK; + } else { + data.samples = data.samples / ao->period_size * ao->period_size; + } MP_STATS(ao, "start ao fill"); int r = 0; if (data.samples) r = ao->driver->play(ao, data.planes, data.samples, flags); MP_STATS(ao, "end ao fill"); if (r > data.samples) { - MP_WARN(ao, "Audio device returned non-sense value.\n"); + MP_ERR(ao, "Audio device returned non-sense value.\n"); r = data.samples; + } else if (r < 0) { + MP_ERR(ao, "Error writing audio to device.\n"); + } else if (r != data.samples) { + MP_ERR(ao, "Audio device returned broken buffer state (sent %d samples, " + "got %d samples, %d period%s)!\n", data.samples, r, + ao->period_size, flags & AOPLAY_FINAL_CHUNK ? " final" : ""); } r = MPMAX(r, 0); // Probably can't copy the rest of the buffer due to period alignment. |