audio: remove handling of partially written data

Remove the ao_buffer_playable_samples field. This contained the number
of samples that fill_audio_out_buffers() wanted to write to the AO (i.e.
this data was supposed to be played at some point), but ao_play()
rejected it due to partial fill.

This could happen with many AOs, notably those which align all written
data to an internal period size (often called "outburst" in the AO
code), and the accepted number of samples is rounded down to period
boundaries. The left-over samples at the end were still kept in
mpctx->ao_buffer, and had to be played later.

The reason ao_buffer_playable_samples had to exist was to make sure that
at EOF, the correct number of left-over samples was played (and not
possibly other data in the buffer that had to be sliced off due to
endpts in fill_audio_out_buffers()). (You'd think you could just slice
the entire buffer, but I suspect this wasn't done because the end time
could actually change due to A/V sync changes. Maybe that was the reason
it's so complicated.)

Some commits ago, ao.c gained internal buffering, and ao_play() will
never return partial writes - as long as you don't try to write more
samples than ao_get_space() reports. This is always the case. The only
exception is filling the audio buffers while paused. In this case, we
decode and play only 1 sample in order to initialize decoding (e.g. on
seeking). Actually playing this 1 sample is in fact a bug, but even of
the AO doesn't have period size alignment, you won't notice it. In
summary, this means we can safely remove the code.
This commit is contained in:
wm4 2014-03-09 01:20:36 +01:00
parent e16c91d07a
commit 7b6e211e63
3 changed files with 1 additions and 21 deletions

View File

@ -352,13 +352,11 @@ static int audio_start_sync(struct MPContext *mpctx, int playsize)
res = audio_decode(d_audio, mpctx->ao_buffer, a);
if (skip_samples <= mp_audio_buffer_samples(mpctx->ao_buffer)) {
mp_audio_buffer_skip(mpctx->ao_buffer, skip_samples);
mpctx->ao_buffer_playable_samples = 0;
if (res < 0)
return res;
return audio_decode(d_audio, mpctx->ao_buffer, playsize);
}
mp_audio_buffer_clear(mpctx->ao_buffer);
mpctx->ao_buffer_playable_samples = 0;
if (res < 0)
return res;
}
@ -458,15 +456,11 @@ int fill_audio_out_buffers(struct MPContext *mpctx, double endpts)
}
}
assert(mpctx->ao_buffer_playable_samples <=
mp_audio_buffer_samples(mpctx->ao_buffer));
struct mp_audio data;
mp_audio_buffer_peek(mpctx->ao_buffer, &data);
data.samples = MPMIN(data.samples, playsize);
int played = write_to_ao(mpctx, &data, playflags, written_audio_pts(mpctx));
assert(played >= 0 && played <= data.samples);
mpctx->ao_buffer_playable_samples = playsize - played;
if (played > 0) {
mp_audio_buffer_skip(mpctx->ao_buffer, played);
@ -485,7 +479,6 @@ void clear_audio_output_buffers(struct MPContext *mpctx)
if (mpctx->ao) {
ao_reset(mpctx->ao);
mp_audio_buffer_clear(mpctx->ao_buffer);
mpctx->ao_buffer_playable_samples = 0;
}
}

View File

@ -225,8 +225,6 @@ typedef struct MPContext {
struct ao *ao;
double ao_pts;
struct mp_audio_buffer *ao_buffer; // queued audio; passed to ao_play() later
int ao_buffer_playable_samples; // part of the part of the buffer the AO
// hasn't accepted yet with play()
struct vo *video_out;

View File

@ -174,19 +174,8 @@ void uninit_player(struct MPContext *mpctx, unsigned int mask)
mpctx->initialized_flags &= ~INITIALIZED_AO;
if (ao) {
// Note: with gapless_audio, stop_play is not correctly set
if (opts->gapless_audio || mpctx->stop_play == AT_END_OF_FILE) {
struct mp_audio data;
mp_audio_buffer_peek(mpctx->ao_buffer, &data);
int samples = mpctx->ao_buffer_playable_samples;
assert(samples <= data.samples);
if (samples > 0) {
int played = ao_play(ao, data.planes, samples,
AOPLAY_FINAL_CHUNK);
if (played < samples)
MP_WARN(mpctx, "Audio output truncated at end.\n");
}
if (opts->gapless_audio || mpctx->stop_play == AT_END_OF_FILE)
ao_drain(ao);
}
ao_uninit(ao);
}
mpctx->ao = NULL;