summaryrefslogtreecommitdiffstats
path: root/audio/decode/dec_audio.c
diff options
context:
space:
mode:
Diffstat (limited to 'audio/decode/dec_audio.c')
-rw-r--r--audio/decode/dec_audio.c61
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) {