diff options
author | wm4 <wm4@nowhere> | 2013-05-12 21:47:55 +0200 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2013-05-12 21:47:55 +0200 |
commit | e6e5a7b221ef2fcdd5a1982d6fdcb627100447d2 (patch) | |
tree | 08b54ef9bb771434fc7fbe9185793503d3ba314c /audio/decode | |
parent | 6a83ef1552de4a1a71da49e45647ce1a4ce64e53 (diff) | |
parent | 48f94311516dc1426644b3e68b2a48c22727e1e7 (diff) | |
download | mpv-e6e5a7b221ef2fcdd5a1982d6fdcb627100447d2.tar.bz2 mpv-e6e5a7b221ef2fcdd5a1982d6fdcb627100447d2.tar.xz |
Merge branch 'audio_changes'
Conflicts:
audio/out/ao_lavc.c
Diffstat (limited to 'audio/decode')
-rw-r--r-- | audio/decode/ad.h | 6 | ||||
-rw-r--r-- | audio/decode/ad_lavc.c | 85 | ||||
-rw-r--r-- | audio/decode/ad_mpg123.c | 2 | ||||
-rw-r--r-- | audio/decode/ad_spdif.c | 17 | ||||
-rw-r--r-- | audio/decode/dec_audio.c | 72 | ||||
-rw-r--r-- | audio/decode/dec_audio.h | 4 |
6 files changed, 98 insertions, 88 deletions
diff --git a/audio/decode/ad.h b/audio/decode/ad.h index 0bbc11ed9b..ff51ecbe35 100644 --- a/audio/decode/ad.h +++ b/audio/decode/ad.h @@ -48,10 +48,4 @@ extern const ad_functions_t * const mpcodecs_ad_drivers[]; // fallback if ADCTRL_SKIP not implemented: ds_fill_buffer(sh_audio->ds); #define ADCTRL_SKIP_FRAME 2 // skip block/frame, called while seeking -// fallback if ADCTRL_QUERY_FORMAT not implemented: sh_audio->sample_format -#define ADCTRL_QUERY_FORMAT 3 // test for availabilty of a format - -// fallback: use hw mixer in libao -#define ADCTRL_SET_VOLUME 4 // not used at the moment - #endif /* MPLAYER_AD_H */ diff --git a/audio/decode/ad_lavc.c b/audio/decode/ad_lavc.c index 248df307d7..8abc0a6035 100644 --- a/audio/decode/ad_lavc.c +++ b/audio/decode/ad_lavc.c @@ -32,9 +32,11 @@ #include "core/codecs.h" #include "core/mp_msg.h" #include "core/options.h" +#include "core/av_opts.h" #include "ad_internal.h" #include "audio/reorder_ch.h" +#include "audio/fmt-conversion.h" #include "compat/mpbswap.h" #include "compat/libav.h" @@ -49,6 +51,16 @@ struct priv { int output_left; int unitsize; int previous_data_left; // input demuxer packet data + bool force_channel_map; +}; + +#define OPT_BASE_STRUCT struct MPOpts + +const m_option_t ad_lavc_decode_opts_conf[] = { + OPT_FLOATRANGE("ac3drc", ad_lavc_param.ac3drc, 0, 0, 2), + OPT_FLAG("downmix", ad_lavc_param.downmix, 0), + OPT_STRING("o", ad_lavc_param.avopt, 0), + {0} }; struct pcm_map @@ -144,17 +156,9 @@ static int preinit(sh_audio_t *sh) static int setup_format(sh_audio_t *sh_audio, const AVCodecContext *lavc_context) { - int sample_format = sh_audio->sample_format; - switch (av_get_packed_sample_fmt(lavc_context->sample_fmt)) { - case AV_SAMPLE_FMT_U8: sample_format = AF_FORMAT_U8; break; - case AV_SAMPLE_FMT_S16: sample_format = AF_FORMAT_S16_NE; break; - case AV_SAMPLE_FMT_S32: sample_format = AF_FORMAT_S32_NE; break; - case AV_SAMPLE_FMT_FLT: sample_format = AF_FORMAT_FLOAT_NE; break; - default: - mp_msg(MSGT_DECAUDIO, MSGL_FATAL, "Unsupported sample format\n"); - sample_format = AF_FORMAT_UNKNOWN; - } - + struct priv *priv = sh_audio->context; + int sample_format = + af_from_avformat(av_get_packed_sample_fmt(lavc_context->sample_fmt)); bool broken_srate = false; int samplerate = lavc_context->sample_rate; int container_samplerate = sh_audio->container_out_samplerate; @@ -166,10 +170,20 @@ static int setup_format(sh_audio_t *sh_audio, else if (container_samplerate) samplerate = container_samplerate; - if (lavc_context->channels != sh_audio->channels || + struct mp_chmap lavc_chmap; + mp_chmap_from_lavc(&lavc_chmap, lavc_context->channel_layout); + // No channel layout or layout disagrees with channel count + if (lavc_chmap.num != lavc_context->channels) + mp_chmap_from_channels(&lavc_chmap, lavc_context->channels); + if (priv->force_channel_map) { + if (lavc_chmap.num == sh_audio->channels.num) + lavc_chmap = sh_audio->channels; + } + + if (!mp_chmap_equals(&lavc_chmap, &sh_audio->channels) || samplerate != sh_audio->samplerate || sample_format != sh_audio->sample_format) { - sh_audio->channels = lavc_context->channels; + sh_audio->channels = lavc_chmap; sh_audio->samplerate = samplerate; sh_audio->sample_format = sample_format; sh_audio->samplesize = af_fmt2bits(sh_audio->sample_format) / 8; @@ -198,41 +212,59 @@ static void set_from_wf(AVCodecContext *avctx, WAVEFORMATEX *wf) static int init(sh_audio_t *sh_audio, const char *decoder) { - struct MPOpts *opts = sh_audio->opts; + struct MPOpts *mpopts = sh_audio->opts; + struct ad_lavc_param *opts = &mpopts->ad_lavc_param; AVCodecContext *lavc_context; AVCodec *lavc_codec; + struct priv *ctx = talloc_zero(NULL, struct priv); + sh_audio->context = ctx; + if (sh_audio->wf && strcmp(decoder, "pcm") == 0) { decoder = find_pcm_decoder(tag_map, sh_audio->format, sh_audio->wf->wBitsPerSample); } else if (sh_audio->wf && strcmp(decoder, "mp-pcm") == 0) { decoder = find_pcm_decoder(af_map, sh_audio->format, 0); + ctx->force_channel_map = true; } lavc_codec = avcodec_find_decoder_by_name(decoder); if (!lavc_codec) { mp_tmsg(MSGT_DECAUDIO, MSGL_ERR, "Cannot find codec '%s' in libavcodec...\n", decoder); + uninit(sh_audio); return 0; } - struct priv *ctx = talloc_zero(NULL, struct priv); - sh_audio->context = ctx; lavc_context = avcodec_alloc_context3(lavc_codec); ctx->avctx = lavc_context; ctx->avframe = avcodec_alloc_frame(); lavc_context->codec_type = AVMEDIA_TYPE_AUDIO; lavc_context->codec_id = lavc_codec->id; - lavc_context->request_channels = opts->audio_output_channels; + if (opts->downmix) { + lavc_context->request_channels = mpopts->audio_output_channels.num; + lavc_context->request_channel_layout = + mp_chmap_to_lavc(&mpopts->audio_output_channels); + } // Always try to set - option only exists for AC3 at the moment - av_opt_set_double(lavc_context, "drc_scale", opts->drc_level, + av_opt_set_double(lavc_context, "drc_scale", opts->ac3drc, AV_OPT_SEARCH_CHILDREN); + if (opts->avopt) { + if (parse_avopts(lavc_context, opts->avopt) < 0) { + mp_msg(MSGT_DECVIDEO, MSGL_ERR, + "ad_lavc: setting AVOptions '%s' failed.\n", opts->avopt); + uninit(sh_audio); + return 0; + } + } + lavc_context->codec_tag = sh_audio->format; lavc_context->sample_rate = sh_audio->samplerate; lavc_context->bit_rate = sh_audio->i_bps * 8; + lavc_context->channel_layout = mp_chmap_to_lavc(&sh_audio->channels); if (sh_audio->wf) set_from_wf(lavc_context, sh_audio->wf); @@ -279,13 +311,9 @@ static int init(sh_audio_t *sh_audio, const char *decoder) if (sh_audio->wf && sh_audio->wf->nAvgBytesPerSec) sh_audio->i_bps = sh_audio->wf->nAvgBytesPerSec; - switch (av_get_packed_sample_fmt(lavc_context->sample_fmt)) { - case AV_SAMPLE_FMT_U8: - case AV_SAMPLE_FMT_S16: - case AV_SAMPLE_FMT_S32: - case AV_SAMPLE_FMT_FLT: - break; - default: + int af_sample_fmt = + af_from_avformat(av_get_packed_sample_fmt(lavc_context->sample_fmt)); + if (af_sample_fmt == AF_FORMAT_UNKNOWN) { uninit(sh_audio); return 0; } @@ -442,13 +470,6 @@ static int decode_audio(sh_audio_t *sh_audio, unsigned char *buf, int minlen, memcpy(buf, priv->output, size); priv->output += size; priv->output_left -= size; - if (avctx->channels >= 5) { - int samplesize = av_get_bytes_per_sample(avctx->sample_fmt); - reorder_channel_nch(buf, AF_CHANNEL_LAYOUT_LAVC_DEFAULT, - AF_CHANNEL_LAYOUT_MPLAYER_DEFAULT, - avctx->channels, - size / samplesize, samplesize); - } if (len < 0) len = size; else diff --git a/audio/decode/ad_mpg123.c b/audio/decode/ad_mpg123.c index c17edc9197..8699013acf 100644 --- a/audio/decode/ad_mpg123.c +++ b/audio/decode/ad_mpg123.c @@ -358,7 +358,7 @@ static int init(sh_audio_t *sh, const char *decoder) con->mean_count = 0; #endif con->vbr = (finfo.vbr != MPG123_CBR); - sh->channels = channels; + mp_chmap_from_channels(&sh->channels, channels); sh->samplerate = rate; /* Without external force, mpg123 will always choose signed encoding, * and non-16-bit only on builds that don't support it. diff --git a/audio/decode/ad_spdif.c b/audio/decode/ad_spdif.c index 2101721430..1314110062 100644 --- a/audio/decode/ad_spdif.c +++ b/audio/decode/ad_spdif.c @@ -148,19 +148,20 @@ static int init(sh_audio_t *sh, const char *decoder) } sh->ds->buffer_pos -= in_size; + int num_channels = 0; switch (lavf_ctx->streams[0]->codec->codec_id) { case AV_CODEC_ID_AAC: spdif_ctx->iec61937_packet_size = 16384; sh->sample_format = AF_FORMAT_IEC61937_LE; sh->samplerate = srate; - sh->channels = 2; + num_channels = 2; sh->i_bps = bps; break; case AV_CODEC_ID_AC3: spdif_ctx->iec61937_packet_size = 6144; sh->sample_format = AF_FORMAT_AC3_LE; sh->samplerate = srate; - sh->channels = 2; + num_channels = 2; sh->i_bps = bps; break; case AV_CODEC_ID_DTS: @@ -175,13 +176,13 @@ static int init(sh_audio_t *sh, const char *decoder) spdif_ctx->iec61937_packet_size = 32768; sh->sample_format = AF_FORMAT_IEC61937_LE; sh->samplerate = 192000; // DTS core require 48000 - sh->channels = 2*4; + num_channels = 2*4; sh->i_bps = bps; } else { spdif_ctx->iec61937_packet_size = 32768; sh->sample_format = AF_FORMAT_AC3_LE; sh->samplerate = srate; - sh->channels = 2; + num_channels = 2; sh->i_bps = bps; } break; @@ -189,26 +190,28 @@ static int init(sh_audio_t *sh, const char *decoder) spdif_ctx->iec61937_packet_size = 24576; sh->sample_format = AF_FORMAT_IEC61937_LE; sh->samplerate = 192000; - sh->channels = 2; + num_channels = 2; sh->i_bps = bps; break; case AV_CODEC_ID_MP3: spdif_ctx->iec61937_packet_size = 4608; sh->sample_format = AF_FORMAT_MPEG2; sh->samplerate = srate; - sh->channels = 2; + num_channels = 2; sh->i_bps = bps; break; case AV_CODEC_ID_TRUEHD: spdif_ctx->iec61937_packet_size = 61440; sh->sample_format = AF_FORMAT_IEC61937_LE; sh->samplerate = 192000; - sh->channels = 8; + num_channels = 8; sh->i_bps = bps; break; default: break; } + if (num_channels) + mp_chmap_from_channels(&sh->channels, num_channels); return 1; diff --git a/audio/decode/dec_audio.c b/audio/decode/dec_audio.c index cac33a9a31..dc461b81e3 100644 --- a/audio/decode/dec_audio.c +++ b/audio/decode/dec_audio.c @@ -41,22 +41,14 @@ int fakemono = 0; -struct af_cfg af_cfg = {1, NULL}; // Configuration for audio filters +struct af_cfg af_cfg = {0}; // Configuration for audio filters static int init_audio_codec(sh_audio_t *sh_audio, const char *decoder) { assert(!sh_audio->initialized); resync_audio_stream(sh_audio); - sh_audio->samplesize = 2; - sh_audio->sample_format = AF_FORMAT_S16_NE; - if ((af_cfg.force & AF_INIT_FORMAT_MASK) == AF_INIT_FLOAT) { - int fmt = AF_FORMAT_FLOAT_NE; - if (sh_audio->ad_driver->control(sh_audio, ADCTRL_QUERY_FORMAT, - &fmt) == CONTROL_TRUE) { - sh_audio->sample_format = fmt; - sh_audio->samplesize = 4; - } - } + sh_audio->samplesize = 4; + sh_audio->sample_format = AF_FORMAT_FLOAT_NE; 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, "Audio decoder preinit failed.\n"); @@ -94,7 +86,7 @@ static int init_audio_codec(sh_audio_t *sh_audio, const char *decoder) sh_audio->initialized = 1; - if (!sh_audio->channels || !sh_audio->samplerate) { + if (mp_chmap_is_empty(&sh_audio->channels) || !sh_audio->samplerate) { mp_tmsg(MSGT_DECAUDIO, MSGL_ERR, "Audio decoder did not specify " "audio format!\n"); uninit_audio(sh_audio); // free buffers @@ -102,7 +94,7 @@ static int init_audio_codec(sh_audio_t *sh_audio, const char *decoder) } if (!sh_audio->o_bps) - sh_audio->o_bps = sh_audio->channels * sh_audio->samplerate + sh_audio->o_bps = sh_audio->channels.num * sh_audio->samplerate * sh_audio->samplesize; return 1; } @@ -168,14 +160,14 @@ int init_best_audio_codec(sh_audio_t *sh_audio, char *audio_decoders) 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, + sh_audio->samplerate, sh_audio->channels.num, 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); + sh_audio->i_bps * 8, sh_audio->samplerate, sh_audio->channels.num); } else { mp_msg(MSGT_DECAUDIO, MSGL_ERR, "Failed to initialize an audio decoder for codec '%s'.\n", @@ -191,7 +183,7 @@ void uninit_audio(sh_audio_t *sh_audio) if (sh_audio->afilter) { mp_msg(MSGT_DECAUDIO, MSGL_V, "Uninit audio filters...\n"); af_uninit(sh_audio->afilter); - free(sh_audio->afilter); + af_destroy(sh_audio->afilter); sh_audio->afilter = NULL; } if (sh_audio->initialized) { @@ -207,43 +199,41 @@ void uninit_audio(sh_audio_t *sh_audio) int init_audio_filters(sh_audio_t *sh_audio, int in_samplerate, - int *out_samplerate, int *out_channels, int *out_format) + int *out_samplerate, struct mp_chmap *out_channels, + int *out_format) { struct af_stream *afs = sh_audio->afilter; - if (!afs) { - afs = calloc(1, sizeof(struct af_stream)); - afs->opts = sh_audio->opts; - } + if (!afs) + afs = af_new(sh_audio->opts); // input format: same as codec's output format: - afs->input.rate = in_samplerate; - afs->input.nch = sh_audio->channels; - afs->input.format = sh_audio->sample_format; - af_fix_parameters(&(afs->input)); + afs->input.rate = in_samplerate; + mp_audio_set_channels(&afs->input, &sh_audio->channels); + mp_audio_set_format(&afs->input, sh_audio->sample_format); // output format: same as ao driver's input format (if missing, fallback to input) - afs->output.rate = *out_samplerate; - afs->output.nch = *out_channels; - afs->output.format = *out_format; - af_fix_parameters(&(afs->output)); + afs->output.rate = *out_samplerate; + mp_audio_set_channels(&afs->output, out_channels); + mp_audio_set_format(&afs->output, *out_format); // filter config: memcpy(&afs->cfg, &af_cfg, sizeof(struct af_cfg)); + char *s_from = mp_audio_config_to_str(&afs->input); + char *s_to = mp_audio_config_to_str(&afs->output); mp_tmsg(MSGT_DECAUDIO, MSGL_V, - "Building audio filter chain for %dHz/%dch/%s -> %dHz/%dch/%s...\n", - afs->input.rate, afs->input.nch, - af_fmt2str_short(afs->input.format), afs->output.rate, - afs->output.nch, af_fmt2str_short(afs->output.format)); + "Building audio filter chain for %s -> %s...\n", s_from, s_to); + talloc_free(s_from); + talloc_free(s_to); // let's autoprobe it! if (0 != af_init(afs)) { sh_audio->afilter = NULL; - free(afs); + af_destroy(afs); return 0; // failed :( } *out_samplerate = afs->output.rate; - *out_channels = afs->output.nch; + *out_channels = afs->output.channels; *out_format = afs->output.format; // ok! @@ -270,7 +260,7 @@ static int filter_n_bytes(sh_audio_t *sh, struct bstr *outbuf, int len) // Decode more bytes if needed int old_samplerate = sh->samplerate; - int old_channels = sh->channels; + struct mp_chmap old_channels = sh->channels; int old_sample_format = sh->sample_format; while (sh->a_buffer_len < len) { unsigned char *buf = sh->a_buffer + sh->a_buffer_len; @@ -278,7 +268,7 @@ static int filter_n_bytes(sh_audio_t *sh, struct bstr *outbuf, int len) int maxlen = sh->a_buffer_size - sh->a_buffer_len; int ret = sh->ad_driver->decode_audio(sh, buf, minlen, maxlen); int format_change = sh->samplerate != old_samplerate - || sh->channels != old_channels + || !mp_chmap_equals(&sh->channels, &old_channels) || sh->sample_format != old_sample_format; if (ret <= 0 || format_change) { error = format_change ? -2 : -1; @@ -294,10 +284,10 @@ static int filter_n_bytes(sh_audio_t *sh, struct bstr *outbuf, int len) .audio = sh->a_buffer, .len = len, .rate = sh->samplerate, - .nch = sh->channels, - .format = sh->sample_format }; - af_fix_parameters(&filter_input); + mp_audio_set_format(&filter_input, sh->sample_format); + mp_audio_set_channels(&filter_input, &sh->channels); + struct mp_audio *filter_output = af_play(sh->afilter, &filter_input); if (!filter_output) return -1; @@ -325,7 +315,7 @@ int decode_audio(sh_audio_t *sh_audio, struct bstr *outbuf, int minlen) // Indicates that a filter seems to be buffering large amounts of data int huge_filter_buffer = 0; // Decoded audio must be cut at boundaries of this many bytes - int unitsize = sh_audio->channels * sh_audio->samplesize * 16; + int unitsize = sh_audio->channels.num * sh_audio->samplesize * 16; /* Filter output size will be about filter_multiplier times input size. * If some filter buffers audio in big blocks this might only hold diff --git a/audio/decode/dec_audio.h b/audio/decode/dec_audio.h index 9fa6aad8dd..b46f4282fb 100644 --- a/audio/decode/dec_audio.h +++ b/audio/decode/dec_audio.h @@ -19,6 +19,7 @@ #ifndef MPLAYER_DEC_AUDIO_H #define MPLAYER_DEC_AUDIO_H +#include "audio/chmap.h" #include "demux/stheader.h" struct bstr; @@ -33,6 +34,7 @@ void skip_audio_frame(sh_audio_t *sh_audio); void uninit_audio(sh_audio_t *sh_audio); int init_audio_filters(sh_audio_t *sh_audio, int in_samplerate, - int *out_samplerate, int *out_channels, int *out_format); + int *out_samplerate, struct mp_chmap *out_channels, + int *out_format); #endif /* MPLAYER_DEC_AUDIO_H */ |