diff options
Diffstat (limited to 'audio/decode/dec_audio.c')
-rw-r--r-- | audio/decode/dec_audio.c | 161 |
1 files changed, 86 insertions, 75 deletions
diff --git a/audio/decode/dec_audio.c b/audio/decode/dec_audio.c index e2200918ef..39ee3d5695 100644 --- a/audio/decode/dec_audio.c +++ b/audio/decode/dec_audio.c @@ -64,46 +64,59 @@ static const struct ad_functions * const ad_drivers[] = { #define DECODE_BUFFER_SAMPLES (8192 + DECODE_MAX_UNIT) // Drop audio buffer and reinit it (after format change) -static void reinit_audio_buffer(sh_audio_t *sh) +static void reinit_audio_buffer(struct dec_audio *da) { - mp_audio_buffer_reinit_fmt(sh->decode_buffer, sh->sample_format, + struct sh_audio *sh = da->header->audio; + mp_audio_buffer_reinit_fmt(da->decode_buffer, sh->sample_format, &sh->channels, sh->samplerate); - mp_audio_buffer_preallocate_min(sh->decode_buffer, DECODE_BUFFER_SAMPLES); + mp_audio_buffer_preallocate_min(da->decode_buffer, DECODE_BUFFER_SAMPLES); } -static int init_audio_codec(sh_audio_t *sh_audio, const char *decoder) +static void uninit_decoder(struct dec_audio *d_audio) { - assert(!sh_audio->initialized); - resync_audio_stream(sh_audio); - if (!sh_audio->ad_driver->preinit(sh_audio)) { + if (d_audio->initialized) { + mp_tmsg(MSGT_DECAUDIO, MSGL_V, "Uninit audio decoder.\n"); + d_audio->ad_driver->uninit(d_audio); + d_audio->initialized = 0; + } + talloc_free(d_audio->priv); + d_audio->priv = NULL; +} + +static int init_audio_codec(struct dec_audio *d_audio, const char *decoder) +{ + assert(!d_audio->initialized); + audio_resync_stream(d_audio); + if (!d_audio->ad_driver->preinit(d_audio)) { mp_tmsg(MSGT_DECAUDIO, MSGL_ERR, "Audio decoder preinit failed.\n"); return 0; } - if (!sh_audio->ad_driver->init(sh_audio, decoder)) { + if (!d_audio->ad_driver->init(d_audio, decoder)) { mp_tmsg(MSGT_DECAUDIO, MSGL_V, "Audio decoder init failed.\n"); - uninit_audio(sh_audio); // free buffers + uninit_decoder(d_audio); return 0; } - sh_audio->initialized = 1; + d_audio->initialized = 1; - if (mp_chmap_is_empty(&sh_audio->channels) || !sh_audio->samplerate || - !sh_audio->sample_format) + struct sh_audio *sh = d_audio->header->audio; + if (mp_chmap_is_empty(&sh->channels) || !sh->samplerate || + !sh->sample_format) { mp_tmsg(MSGT_DECAUDIO, MSGL_ERR, "Audio decoder did not specify " "audio format!\n"); - uninit_audio(sh_audio); // free buffers + uninit_decoder(d_audio); return 0; } - sh_audio->decode_buffer = mp_audio_buffer_create(NULL); - reinit_audio_buffer(sh_audio); + d_audio->decode_buffer = mp_audio_buffer_create(NULL); + reinit_audio_buffer(d_audio); return 1; } -struct mp_decoder_list *mp_audio_decoder_list(void) +struct mp_decoder_list *audio_decoder_list(void) { struct mp_decoder_list *list = talloc_zero(NULL, struct mp_decoder_list); for (int i = 0; ad_drivers[i] != NULL; i++) @@ -111,10 +124,10 @@ struct mp_decoder_list *mp_audio_decoder_list(void) return list; } -static struct mp_decoder_list *mp_select_audio_decoders(const char *codec, - char *selection) +static struct mp_decoder_list *audio_select_decoders(const char *codec, + char *selection) { - struct mp_decoder_list *list = mp_audio_decoder_list(); + struct mp_decoder_list *list = audio_decoder_list(); struct mp_decoder_list *new = mp_select_decoders(list, codec, selection); talloc_free(list); return new; @@ -129,13 +142,13 @@ static const struct ad_functions *find_driver(const char *name) return NULL; } -int init_best_audio_codec(sh_audio_t *sh_audio, char *audio_decoders) +int audio_init_best_codec(struct dec_audio *d_audio, char *audio_decoders) { - assert(!sh_audio->initialized); + assert(!d_audio->initialized); struct mp_decoder_entry *decoder = NULL; struct mp_decoder_list *list = - mp_select_audio_decoders(sh_audio->gsh->codec, audio_decoders); + audio_select_decoders(d_audio->header->codec, audio_decoders); mp_print_decoders(MSGT_DECAUDIO, MSGL_V, "Codec list:", list); @@ -146,68 +159,65 @@ int init_best_audio_codec(sh_audio_t *sh_audio, char *audio_decoders) continue; mp_tmsg(MSGT_DECAUDIO, MSGL_V, "Opening audio decoder %s:%s\n", sel->family, sel->decoder); - sh_audio->ad_driver = driver; - if (init_audio_codec(sh_audio, sel->decoder)) { + d_audio->ad_driver = driver; + if (init_audio_codec(d_audio, sel->decoder)) { decoder = sel; break; } - sh_audio->ad_driver = NULL; + d_audio->ad_driver = NULL; mp_tmsg(MSGT_DECAUDIO, MSGL_WARN, "Audio decoder init failed for " "%s:%s\n", sel->family, sel->decoder); } - if (sh_audio->initialized) { - sh_audio->gsh->decoder_desc = - talloc_asprintf(NULL, "%s [%s:%s]", decoder->desc, decoder->family, + if (d_audio->initialized) { + d_audio->decoder_desc = + talloc_asprintf(d_audio, "%s [%s:%s]", decoder->desc, decoder->family, decoder->decoder); mp_msg(MSGT_DECAUDIO, MSGL_INFO, "Selected audio codec: %s\n", - sh_audio->gsh->decoder_desc); + d_audio->decoder_desc); mp_msg(MSGT_DECAUDIO, MSGL_V, "AUDIO: %d Hz, %d ch, %s\n", - sh_audio->samplerate, sh_audio->channels.num, - af_fmt_to_str(sh_audio->sample_format)); + d_audio->header->audio->samplerate, d_audio->header->audio->channels.num, + af_fmt_to_str(d_audio->header->audio->sample_format)); mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AUDIO_BITRATE=%d\nID_AUDIO_RATE=%d\n" "ID_AUDIO_NCH=%d\n", - sh_audio->i_bps * 8, sh_audio->samplerate, sh_audio->channels.num); + d_audio->i_bps * 8, d_audio->header->audio->samplerate, + d_audio->header->audio->channels.num); } else { mp_msg(MSGT_DECAUDIO, MSGL_ERR, "Failed to initialize an audio decoder for codec '%s'.\n", - sh_audio->gsh->codec ? sh_audio->gsh->codec : "<unknown>"); + d_audio->header->codec ? d_audio->header->codec : "<unknown>"); } talloc_free(list); - return sh_audio->initialized; + return d_audio->initialized; } -void uninit_audio(sh_audio_t *sh_audio) +void audio_uninit(struct dec_audio *d_audio) { - if (sh_audio->afilter) { + if (!d_audio) + return; + if (d_audio->afilter) { mp_msg(MSGT_DECAUDIO, MSGL_V, "Uninit audio filters...\n"); - af_destroy(sh_audio->afilter); - sh_audio->afilter = NULL; - } - if (sh_audio->initialized) { - mp_tmsg(MSGT_DECAUDIO, MSGL_V, "Uninit audio.\n"); - sh_audio->ad_driver->uninit(sh_audio); - sh_audio->initialized = 0; + af_destroy(d_audio->afilter); + d_audio->afilter = NULL; } - talloc_free(sh_audio->gsh->decoder_desc); - sh_audio->gsh->decoder_desc = NULL; - talloc_free(sh_audio->decode_buffer); - sh_audio->decode_buffer = NULL; + uninit_decoder(d_audio); + talloc_free(d_audio->decode_buffer); + talloc_free(d_audio); } -int init_audio_filters(sh_audio_t *sh_audio, int in_samplerate, +int audio_init_filters(struct dec_audio *d_audio, int in_samplerate, int *out_samplerate, struct mp_chmap *out_channels, int *out_format) { - if (!sh_audio->afilter) - sh_audio->afilter = af_new(sh_audio->opts); - struct af_stream *afs = sh_audio->afilter; + if (!d_audio->afilter) + d_audio->afilter = af_new(d_audio->opts); + struct af_stream *afs = d_audio->afilter; // input format: same as codec's output format: - mp_audio_buffer_get_format(sh_audio->decode_buffer, &afs->input); + mp_audio_buffer_get_format(d_audio->decode_buffer, &afs->input); // Sample rate can be different when adjusting playback speed afs->input.rate = in_samplerate; @@ -226,7 +236,7 @@ int init_audio_filters(sh_audio_t *sh_audio, int in_samplerate, // let's autoprobe it! if (af_init(afs) != 0) { af_destroy(afs); - sh_audio->afilter = NULL; + d_audio->afilter = NULL; return 0; // failed :( } @@ -238,34 +248,35 @@ int init_audio_filters(sh_audio_t *sh_audio, int in_samplerate, } // Filter len bytes of input, put result into outbuf. -static int filter_n_bytes(sh_audio_t *sh, struct mp_audio_buffer *outbuf, +static int filter_n_bytes(struct dec_audio *da, struct mp_audio_buffer *outbuf, int len) { int error = 0; struct mp_audio config; - mp_audio_buffer_get_format(sh->decode_buffer, &config); + mp_audio_buffer_get_format(da->decode_buffer, &config); - while (mp_audio_buffer_samples(sh->decode_buffer) < len) { - int maxlen = mp_audio_buffer_get_write_available(sh->decode_buffer); + while (mp_audio_buffer_samples(da->decode_buffer) < len) { + int maxlen = mp_audio_buffer_get_write_available(da->decode_buffer); if (maxlen < DECODE_MAX_UNIT) break; struct mp_audio buffer; - mp_audio_buffer_get_write_buffer(sh->decode_buffer, maxlen, &buffer); + mp_audio_buffer_get_write_buffer(da->decode_buffer, maxlen, &buffer); buffer.samples = 0; - error = sh->ad_driver->decode_audio(sh, &buffer, maxlen); + error = da->ad_driver->decode_audio(da, &buffer, maxlen); if (error < 0) break; // Commit the data just read as valid data - mp_audio_buffer_finish_write(sh->decode_buffer, buffer.samples); + mp_audio_buffer_finish_write(da->decode_buffer, buffer.samples); // Format change + struct sh_audio *sh = da->header->audio; if (sh->samplerate != config.rate || !mp_chmap_equals(&sh->channels, &config.channels) || sh->sample_format != config.format) { // If there are still samples left in the buffer, let them drain // first, and don't signal a format change to the caller yet. - if (mp_audio_buffer_samples(sh->decode_buffer) > 0) + if (mp_audio_buffer_samples(da->decode_buffer) > 0) break; error = -2; break; @@ -274,33 +285,33 @@ static int filter_n_bytes(sh_audio_t *sh, struct mp_audio_buffer *outbuf, // Filter struct mp_audio filter_input; - mp_audio_buffer_peek(sh->decode_buffer, &filter_input); - filter_input.rate = sh->afilter->input.rate; // due to playback speed change + mp_audio_buffer_peek(da->decode_buffer, &filter_input); + filter_input.rate = da->afilter->input.rate; // due to playback speed change len = MPMIN(filter_input.samples, len); filter_input.samples = len; - struct mp_audio *filter_output = af_play(sh->afilter, &filter_input); + struct mp_audio *filter_output = af_play(da->afilter, &filter_input); if (!filter_output) return -1; mp_audio_buffer_append(outbuf, filter_output); // remove processed data from decoder buffer: - mp_audio_buffer_skip(sh->decode_buffer, len); + mp_audio_buffer_skip(da->decode_buffer, len); // Assume the filter chain is drained from old data at this point. // (If not, the remaining old data is discarded.) if (error == -2) - reinit_audio_buffer(sh); + reinit_audio_buffer(da); return error; } /* Try to get at least minsamples decoded+filtered samples in outbuf * (total length including possible existing data). - * Return 0 on success, -1 on error/EOF (not distinguished). + * Return 0 on success, -1 on error/EOF (not distinguidaed). * In the former case outbuf has at least minsamples buffered on return. * In case of EOF/error it might or might not be. */ -int decode_audio(sh_audio_t *sh_audio, struct mp_audio_buffer *outbuf, +int audio_decode(struct dec_audio *d_audio, struct mp_audio_buffer *outbuf, int minsamples) { // Indicates that a filter seems to be buffering large amounts of data @@ -312,7 +323,7 @@ int decode_audio(sh_audio_t *sh_audio, struct mp_audio_buffer *outbuf, /* Filter output size will be about filter_multiplier times input size. * If some filter buffers audio in big blocks this might only hold * as average over time. */ - double filter_multiplier = af_calc_filter_multiplier(sh_audio->afilter); + double filter_multiplier = af_calc_filter_multiplier(d_audio->afilter); int prev_buffered = -1; while (minsamples >= 0) { @@ -341,18 +352,18 @@ int decode_audio(sh_audio_t *sh_audio, struct mp_audio_buffer *outbuf, * of buffering in filters */ huge_filter_buffer = 1; - int res = filter_n_bytes(sh_audio, outbuf, decsamples); + int res = filter_n_bytes(d_audio, outbuf, decsamples); if (res < 0) return res; } return 0; } -void resync_audio_stream(sh_audio_t *sh_audio) +void audio_resync_stream(struct dec_audio *d_audio) { - sh_audio->pts = MP_NOPTS_VALUE; - sh_audio->pts_offset = 0; - if (!sh_audio->initialized) + d_audio->pts = MP_NOPTS_VALUE; + d_audio->pts_offset = 0; + if (!d_audio->initialized) return; - sh_audio->ad_driver->control(sh_audio, ADCTRL_RESYNC_STREAM, NULL); + d_audio->ad_driver->control(d_audio, ADCTRL_RESYNC_STREAM, NULL); } |