diff options
Diffstat (limited to 'audio/decode')
-rw-r--r-- | audio/decode/dec_audio.c | 61 |
1 files changed, 37 insertions, 24 deletions
diff --git a/audio/decode/dec_audio.c b/audio/decode/dec_audio.c index da541de674..3c196709c8 100644 --- a/audio/decode/dec_audio.c +++ b/audio/decode/dec_audio.c @@ -172,6 +172,21 @@ int initial_audio_decode(struct dec_audio *da) return mp_audio_config_valid(da->waiting) ? AD_OK : AD_ERR; } +static bool copy_output(struct af_stream *afs, struct mp_audio_buffer *outbuf, + int minsamples, bool eof) +{ + while (mp_audio_buffer_samples(outbuf) < minsamples) { + if (af_output_frame(afs, eof) < 0) + return true; // error, stop doing stuff + struct mp_audio *mpa = af_read_output_frame(afs); + if (!mpa) + return false; // out of data + mp_audio_buffer_append(outbuf, mpa); + talloc_free(mpa); + } + return true; +} + /* Try to get at least minsamples decoded+filtered samples in outbuf * (total length including possible existing data). * Return 0 on success, or negative AD_* error code. @@ -186,41 +201,39 @@ int audio_decode(struct dec_audio *da, struct mp_audio_buffer *outbuf, MP_STATS(da, "start audio"); - int res = 0; - while (res >= 0 && minsamples >= 0) { - int buffered = mp_audio_buffer_samples(outbuf); - if (minsamples < buffered) - break; - + int res; + while (1) { res = 0; + if (copy_output(afs, outbuf, minsamples, false)) + break; + struct mp_audio *mpa = da->waiting; - if (!mpa) + da->waiting = NULL; + if (!mpa) { res = da->ad_driver->decode_packet(da, &mpa); - - if (res != AD_EOF) { - if (res < 0) + if (res < 0) { + // drain filters first (especially for true EOF case) + copy_output(afs, outbuf, minsamples, true); break; - if (!mpa ) - continue; - } + } + + assert(mpa); - if (mpa) { da->pts_offset += mpa->samples; da->decode_format = *mpa; mp_audio_set_null_data(&da->decode_format); - // On format change, make sure to drain the filter chain. - if (!mp_audio_config_equals(&afs->input, mpa)) { - res = AD_NEW_FMT; - da->waiting = talloc_steal(da, mpa); - mpa = NULL; - } } - if (mpa) - da->waiting = NULL; + // On format change, make sure to drain the filter chain. + if (!mp_audio_config_equals(&afs->input, mpa)) { + da->waiting = talloc_steal(da, mpa); + copy_output(afs, outbuf, minsamples, true); + res = AD_NEW_FMT; + break; + } - if (af_filter(afs, mpa, outbuf) < 0) + if (af_filter_frame(afs, mpa) < 0) return AD_ERR; } @@ -233,7 +246,7 @@ void audio_reset_decoding(struct dec_audio *d_audio) { if (d_audio->ad_driver) d_audio->ad_driver->control(d_audio, ADCTRL_RESET, NULL); - af_control_all(d_audio->afilter, AF_CONTROL_RESET, NULL); + af_seek_reset(d_audio->afilter); d_audio->pts = MP_NOPTS_VALUE; d_audio->pts_offset = 0; if (d_audio->waiting) { |