audio: refactor: separate audio init and filter/output init

Before this commit, reinit_audio_chain() did 2 things: create all the
management data structures and initialize the decoder, and handling lazy
filter/output init (as well as dealing with format changes). For the
second purpose, it could be called multiple times (even though it wasn't
really idempotent). This was pretty weird, so make them separate
functions. The new function is actually idempotent too.

It also turns out the reinit functions don't have to call themselves
recursively for the spdif PCM fallback.
This commit is contained in:
wm4 2016-01-29 22:44:35 +01:00
parent c5a48c6332
commit c00dc5c5c6
1 changed files with 62 additions and 47 deletions

View File

@ -231,52 +231,12 @@ void uninit_audio_chain(struct MPContext *mpctx)
} }
} }
void reinit_audio_chain(struct MPContext *mpctx) static void reinit_audio_filters_and_output(struct MPContext *mpctx)
{ {
struct MPOpts *opts = mpctx->opts; struct MPOpts *opts = mpctx->opts;
struct track *track = mpctx->current_track[0][STREAM_AUDIO];
struct sh_stream *sh = track ? track->stream : NULL;
if (!sh) {
uninit_audio_out(mpctx);
goto no_audio;
}
mp_notify(mpctx, MPV_EVENT_AUDIO_RECONFIG, NULL);
struct ao_chain *ao_c = mpctx->ao_chain; struct ao_chain *ao_c = mpctx->ao_chain;
assert(ao_c);
if (!ao_c) { struct af_stream *afs = ao_c->af;
assert(!ao_c);
ao_c = talloc_zero(NULL, struct ao_chain);
mpctx->ao_chain = ao_c;
ao_c->log = mpctx->log;
ao_c->af = af_new(mpctx->global);
ao_c->af->replaygain_data = sh->codec->replaygain_data;
ao_c->spdif_passthrough = true;
ao_c->pts = MP_NOPTS_VALUE;
ao_c->ao = mpctx->ao;
struct dec_audio *d_audio = talloc_zero(NULL, struct dec_audio);
d_audio->log = mp_log_new(d_audio, mpctx->log, "!ad");
d_audio->global = mpctx->global;
d_audio->opts = opts;
d_audio->header = sh;
track->d_audio = d_audio;
ao_c->audio_src = d_audio;
d_audio->try_spdif = ao_c->spdif_passthrough;
ao_c->ao_buffer = mp_audio_buffer_create(NULL);
if (!audio_init_best_codec(d_audio))
goto init_error;
reset_audio_state(mpctx);
if (mpctx->ao) {
struct mp_audio fmt;
ao_get_format(mpctx->ao, &fmt);
mp_audio_buffer_reinit(ao_c->ao_buffer, &fmt);
}
}
struct mp_audio in_format = ao_c->input_format; struct mp_audio in_format = ao_c->input_format;
@ -294,7 +254,8 @@ void reinit_audio_chain(struct MPContext *mpctx)
uninit_audio_out(mpctx); uninit_audio_out(mpctx);
} }
struct af_stream *afs = ao_c->af; if (mpctx->ao && mp_audio_config_equals(&in_format, &afs->input))
return;
afs->output = (struct mp_audio){0}; afs->output = (struct mp_audio){0};
if (mpctx->ao) { if (mpctx->ao) {
@ -355,7 +316,7 @@ void reinit_audio_chain(struct MPContext *mpctx)
goto init_error; goto init_error;
reset_audio_state(mpctx); reset_audio_state(mpctx);
ao_c->input_format = (struct mp_audio){0}; ao_c->input_format = (struct mp_audio){0};
reinit_audio_chain(mpctx); mpctx->sleeptime = 0; // reinit with new format next time
return; return;
} }
@ -385,6 +346,60 @@ void reinit_audio_chain(struct MPContext *mpctx)
return; return;
init_error:
uninit_audio_chain(mpctx);
uninit_audio_out(mpctx);
struct track *track = mpctx->current_track[0][STREAM_AUDIO];
if (track)
error_on_track(mpctx, track);
}
void reinit_audio_chain(struct MPContext *mpctx)
{
assert(!mpctx->ao_chain);
struct track *track = mpctx->current_track[0][STREAM_AUDIO];
struct sh_stream *sh = track ? track->stream : NULL;
if (!sh) {
uninit_audio_out(mpctx);
goto no_audio;
}
mp_notify(mpctx, MPV_EVENT_AUDIO_RECONFIG, NULL);
struct ao_chain *ao_c = ao_c = talloc_zero(NULL, struct ao_chain);
mpctx->ao_chain = ao_c;
ao_c->log = mpctx->log;
ao_c->af = af_new(mpctx->global);
ao_c->af->replaygain_data = sh->codec->replaygain_data;
ao_c->spdif_passthrough = true;
ao_c->pts = MP_NOPTS_VALUE;
ao_c->ao = mpctx->ao;
struct dec_audio *d_audio = talloc_zero(NULL, struct dec_audio);
d_audio->log = mp_log_new(d_audio, mpctx->log, "!ad");
d_audio->global = mpctx->global;
d_audio->opts = mpctx->opts;
d_audio->header = sh;
track->d_audio = d_audio;
ao_c->audio_src = d_audio;
d_audio->try_spdif = ao_c->spdif_passthrough;
ao_c->ao_buffer = mp_audio_buffer_create(NULL);
if (!audio_init_best_codec(d_audio))
goto init_error;
reset_audio_state(mpctx);
if (mpctx->ao) {
struct mp_audio fmt;
ao_get_format(mpctx->ao, &fmt);
mp_audio_buffer_reinit(ao_c->ao_buffer, &fmt);
}
mpctx->sleeptime = 0;
return;
init_error: init_error:
uninit_audio_chain(mpctx); uninit_audio_chain(mpctx);
uninit_audio_out(mpctx); uninit_audio_out(mpctx);
@ -668,7 +683,7 @@ void fill_audio_out_buffers(struct MPContext *mpctx, double endpts)
int r = decode_new_frame(mpctx->ao_chain); int r = decode_new_frame(mpctx->ao_chain);
if (r == AD_WAIT) if (r == AD_WAIT)
return; // continue later when new data is available return; // continue later when new data is available
reinit_audio_chain(mpctx); reinit_audio_filters_and_output(mpctx);
mpctx->sleeptime = 0; mpctx->sleeptime = 0;
return; // try again next iteration return; // try again next iteration
} }
@ -733,7 +748,7 @@ void fill_audio_out_buffers(struct MPContext *mpctx, double endpts)
*/ */
if (mpctx->opts->gapless_audio < 1) if (mpctx->opts->gapless_audio < 1)
uninit_audio_out(mpctx); uninit_audio_out(mpctx);
reinit_audio_chain(mpctx); reinit_audio_filters_and_output(mpctx);
mpctx->sleeptime = 0; mpctx->sleeptime = 0;
return; // retry on next iteration return; // retry on next iteration
} }