diff options
Diffstat (limited to 'audio/decode/dec_audio.c')
-rw-r--r-- | audio/decode/dec_audio.c | 228 |
1 files changed, 77 insertions, 151 deletions
diff --git a/audio/decode/dec_audio.c b/audio/decode/dec_audio.c index 0d58bf6012..cac33a9a31 100644 --- a/audio/decode/dec_audio.c +++ b/audio/decode/dec_audio.c @@ -21,14 +21,16 @@ #include <unistd.h> #include <assert.h> +#include "demux/codec_tags.h" + #include "config.h" +#include "core/codecs.h" #include "core/mp_msg.h" #include "core/bstr.h" #include "stream/stream.h" #include "demux/demux.h" -#include "core/codec-cfg.h" #include "demux/stheader.h" #include "dec_audio.h" @@ -41,27 +43,7 @@ int fakemono = 0; struct af_cfg af_cfg = {1, NULL}; // Configuration for audio filters -void afm_help(void) -{ - int i; - mp_tmsg(MSGT_DECAUDIO, MSGL_INFO, - "Available (compiled-in) audio codec families/drivers:\n"); - mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AUDIO_DRIVERS\n"); - mp_msg(MSGT_DECAUDIO, MSGL_INFO, " afm: info: (comment)\n"); - for (i = 0; mpcodecs_ad_drivers[i] != NULL; i++) - if (mpcodecs_ad_drivers[i]->info->comment - && mpcodecs_ad_drivers[i]->info->comment[0]) - mp_msg(MSGT_DECAUDIO, MSGL_INFO, "%9s %s (%s)\n", - mpcodecs_ad_drivers[i]->info->short_name, - mpcodecs_ad_drivers[i]->info->name, - mpcodecs_ad_drivers[i]->info->comment); - else - mp_msg(MSGT_DECAUDIO, MSGL_INFO, "%9s %s\n", - mpcodecs_ad_drivers[i]->info->short_name, - mpcodecs_ad_drivers[i]->info->name); -} - -static int init_audio_codec(sh_audio_t *sh_audio) +static int init_audio_codec(sh_audio_t *sh_audio, const char *decoder) { assert(!sh_audio->initialized); resync_audio_stream(sh_audio); @@ -77,7 +59,7 @@ static int init_audio_codec(sh_audio_t *sh_audio) } sh_audio->audio_out_minsize = 8192; // default, preinit() may change it if (!sh_audio->ad_driver->preinit(sh_audio)) { - mp_tmsg(MSGT_DECAUDIO, MSGL_ERR, "ADecoder preinit failed :(\n"); + mp_tmsg(MSGT_DECAUDIO, MSGL_ERR, "Audio decoder preinit failed.\n"); return 0; } @@ -104,8 +86,8 @@ static int init_audio_codec(sh_audio_t *sh_audio) abort(); sh_audio->a_buffer_len = 0; - if (!sh_audio->ad_driver->init(sh_audio)) { - mp_tmsg(MSGT_DECAUDIO, MSGL_V, "ADecoder init failed :(\n"); + if (!sh_audio->ad_driver->init(sh_audio, decoder)) { + mp_tmsg(MSGT_DECAUDIO, MSGL_V, "Audio decoder init failed.\n"); uninit_audio(sh_audio); // free buffers return 0; } @@ -125,140 +107,83 @@ static int init_audio_codec(sh_audio_t *sh_audio) return 1; } -static int init_audio(sh_audio_t *sh_audio, char *codecname, char *afm, - int status, stringset_t *selected) +struct mp_decoder_list *mp_audio_decoder_list(void) { - int force = 0; - if (codecname && codecname[0] == '+') { - codecname = &codecname[1]; - force = 1; - } - sh_audio->codec = NULL; - while (1) { - const ad_functions_t *mpadec; - sh_audio->ad_driver = 0; - if (!(sh_audio->codec = find_audio_codec(sh_audio->format, NULL, - sh_audio->codec, force))) - break; - // ok we found one codec - if (stringset_test(selected, sh_audio->codec->name)) - continue; // already tried & failed - if (codecname && strcmp(sh_audio->codec->name, codecname)) - continue; // -ac - if (afm && strcmp(sh_audio->codec->drv, afm)) - continue; // afm doesn't match - if (!force && sh_audio->codec->status < status) - continue; // too unstable - stringset_add(selected, sh_audio->codec->name); // tagging it - // ok, it matches all rules, let's find the driver! - int i; - for (i = 0; mpcodecs_ad_drivers[i] != NULL; i++) - if (!strcmp(mpcodecs_ad_drivers[i]->info->short_name, - sh_audio->codec->drv)) - break; - mpadec = mpcodecs_ad_drivers[i]; - if (!mpadec) { // driver not available (==compiled in) - mp_tmsg(MSGT_DECAUDIO, MSGL_ERR, "Requested audio codec family " - "[%s] (afm=%s) not available.\nEnable it at compilation.\n", - sh_audio->codec->name, sh_audio->codec->drv); - continue; - } - // it's available, let's try to init! - // init() - mp_tmsg(MSGT_DECAUDIO, MSGL_V, "Opening audio decoder: [%s] %s\n", - mpadec->info->short_name, mpadec->info->name); - sh_audio->ad_driver = mpadec; - if (!init_audio_codec(sh_audio)) { - mp_tmsg(MSGT_DECAUDIO, MSGL_WARN, "Audio decoder init failed for " - "codecs.conf entry \"%s\".\n", sh_audio->codec->name); - continue; // try next... - } - // Yeah! We got it! - return 1; + struct mp_decoder_list *list = talloc_zero(NULL, struct mp_decoder_list); + for (int i = 0; mpcodecs_ad_drivers[i] != NULL; i++) + mpcodecs_ad_drivers[i]->add_decoders(list); + return list; +} + +static struct mp_decoder_list *mp_select_audio_decoders(const char *codec, + char *selection) +{ + struct mp_decoder_list *list = mp_audio_decoder_list(); + struct mp_decoder_list *new = mp_select_decoders(list, codec, selection); + talloc_free(list); + return new; +} + +static const struct ad_functions *find_driver(const char *name) +{ + for (int i = 0; mpcodecs_ad_drivers[i] != NULL; i++) { + if (strcmp(mpcodecs_ad_drivers[i]->name, name) == 0) + return mpcodecs_ad_drivers[i]; } - return 0; + return NULL; } -int init_best_audio_codec(sh_audio_t *sh_audio, char **audio_codec_list, - char **audio_fm_list) +int init_best_audio_codec(sh_audio_t *sh_audio, char *audio_decoders) { - stringset_t selected; - char *ac_l_default[2] = { - "", (char *) NULL - }; - // hack: - if (!audio_codec_list) - audio_codec_list = ac_l_default; - // Go through the codec.conf and find the best codec... - sh_audio->initialized = 0; - stringset_init(&selected); - while (!sh_audio->initialized && *audio_codec_list) { - char *audio_codec = *(audio_codec_list++); - if (audio_codec[0]) { - if (audio_codec[0] == '-') { - // disable this codec: - stringset_add(&selected, audio_codec + 1); - } else { - // forced codec by name: - mp_tmsg(MSGT_DECAUDIO, MSGL_INFO, "Forced audio codec: %s\n", - audio_codec); - init_audio(sh_audio, audio_codec, NULL, -1, &selected); - } - } else { - int status; - // try in stability order: UNTESTED, WORKING, BUGGY. - // never try CRASHING. - if (audio_fm_list) { - char **fmlist = audio_fm_list; - // try first the preferred codec families: - while (!sh_audio->initialized && *fmlist) { - char *audio_fm = *(fmlist++); - mp_tmsg(MSGT_DECAUDIO, MSGL_INFO, - "Trying to force audio codec driver family %s...\n", - audio_fm); - for (status = CODECS_STATUS__MAX; - status >= CODECS_STATUS__MIN; --status) - if (init_audio(sh_audio, NULL, audio_fm, status, - &selected)) - break; - } - } - if (!sh_audio->initialized) - for (status = CODECS_STATUS__MAX; status >= CODECS_STATUS__MIN; - --status) - if (init_audio(sh_audio, NULL, NULL, status, &selected)) - break; + assert(!sh_audio->initialized); + + struct mp_decoder_entry *decoder = NULL; + struct mp_decoder_list *list = + mp_select_audio_decoders(sh_audio->gsh->codec, audio_decoders); + + mp_print_decoders(MSGT_DECAUDIO, MSGL_V, "Codec list:", list); + + for (int n = 0; n < list->num_entries; n++) { + struct mp_decoder_entry *sel = &list->entries[n]; + const struct ad_functions *driver = find_driver(sel->family); + if (!driver) + 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)) { + decoder = sel; + break; } + sh_audio->ad_driver = NULL; + mp_tmsg(MSGT_DECAUDIO, MSGL_WARN, "Audio decoder init failed for " + "%s:%s\n", sel->family, sel->decoder); } - stringset_free(&selected); - if (!sh_audio->initialized) { - mp_tmsg(MSGT_DECAUDIO, MSGL_ERR, - "Cannot find codec for audio format 0x%X.\n", - sh_audio->format); - return 0; // failed + if (sh_audio->initialized) { + sh_audio->gsh->decoder_desc = + talloc_asprintf(NULL, "%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); + mp_msg(MSGT_DECAUDIO, MSGL_V, + "AUDIO: %d Hz, %d ch, %s, %3.1f kbit/%3.2f%% (ratio: %d->%d)\n", + sh_audio->samplerate, sh_audio->channels, + af_fmt2str_short(sh_audio->sample_format), + sh_audio->i_bps * 8 * 0.001, + ((float) sh_audio->i_bps / sh_audio->o_bps) * 100.0, + sh_audio->i_bps, sh_audio->o_bps); + 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); + } 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>"); } - mp_tmsg(MSGT_DECAUDIO, MSGL_INFO, "Selected audio codec: %s [%s]\n", - sh_audio->codecname ? sh_audio->codecname : sh_audio->codec->info, - sh_audio->ad_driver->info->print_name ? - sh_audio->ad_driver->info->print_name : - sh_audio->ad_driver->info->short_name); - mp_tmsg(MSGT_DECAUDIO, MSGL_V, - "Audio codecs.conf entry: %s (%s) afm: %s\n", - sh_audio->codec->name, sh_audio->codec->info, sh_audio->codec->drv); - mp_msg(MSGT_DECAUDIO, MSGL_V, - "AUDIO: %d Hz, %d ch, %s, %3.1f kbit/%3.2f%% (ratio: %d->%d)\n", - sh_audio->samplerate, sh_audio->channels, - af_fmt2str_short(sh_audio->sample_format), - sh_audio->i_bps * 8 * 0.001, - ((float) sh_audio->i_bps / sh_audio->o_bps) * 100.0, - sh_audio->i_bps, sh_audio->o_bps); - 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); - - return 1; // success + talloc_free(list); + return sh_audio->initialized; } void uninit_audio(sh_audio_t *sh_audio) @@ -270,11 +195,12 @@ void uninit_audio(sh_audio_t *sh_audio) sh_audio->afilter = NULL; } if (sh_audio->initialized) { - mp_tmsg(MSGT_DECAUDIO, MSGL_V, "Uninit audio: %s\n", - sh_audio->codec->drv); + mp_tmsg(MSGT_DECAUDIO, MSGL_V, "Uninit audio.\n"); sh_audio->ad_driver->uninit(sh_audio); sh_audio->initialized = 0; } + talloc_free(sh_audio->gsh->decoder_desc); + sh_audio->gsh->decoder_desc = NULL; av_freep(&sh_audio->a_buffer); av_freep(&sh_audio->a_in_buffer); } |