Signed-off-by: Vittorio Giovara <vittorio.giov...@gmail.com> --- libavcodec/ac3dec.c | 49 +++++++++++++++++++++------- libavcodec/ac3dec.h | 2 ++ libavcodec/ac3enc.c | 83 ++++++++++++++++++++++++++++++++++++----------- libavcodec/ac3enc.h | 4 ++- libavcodec/ac3enc_fixed.c | 5 +++ libavcodec/ac3enc_float.c | 5 +++ libavcodec/eac3enc.c | 5 +++ tests/fate/ac3.mak | 12 +++---- 8 files changed, 128 insertions(+), 37 deletions(-)
diff --git a/libavcodec/ac3dec.c b/libavcodec/ac3dec.c index 4be0f1f411..3d3414f7d7 100644 --- a/libavcodec/ac3dec.c +++ b/libavcodec/ac3dec.c @@ -172,6 +172,8 @@ static av_cold void ac3_tables_init(void) static av_cold int ac3_decode_init(AVCodecContext *avctx) { AC3DecodeContext *s = avctx->priv_data; + static AVChannelLayout mono = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; + static AVChannelLayout stereo = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; int i; s->avctx = avctx; @@ -190,12 +192,23 @@ static av_cold int ac3_decode_init(AVCodecContext *avctx) avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; /* allow downmixing to stereo or mono */ - if (avctx->channels > 1 && - avctx->request_channel_layout == AV_CH_LAYOUT_MONO) - avctx->channels = 1; - else if (avctx->channels > 2 && - avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) - avctx->channels = 2; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->request_channel_layout) { + av_channel_layout_uninit(&s->downmix_layout); + av_channel_layout_from_mask(&s->downmix_layout, avctx->request_channel_layout); + } +FF_ENABLE_DEPRECATION_WARNINGS +#endif + if (avctx->ch_layout.nb_channels > 1 && + !av_channel_layout_compare(&s->downmix_layout, &mono)) { + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; + } else if (avctx->ch_layout.nb_channels > 2 && + !av_channel_layout_compare(&s->downmix_layout, &stereo)) { + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; + } s->downmixed = 1; for (i = 0; i < AC3_MAX_CHANNELS; i++) { @@ -1364,6 +1377,7 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data, const float *output[AC3_MAX_CHANNELS]; enum AVMatrixEncoding matrix_encoding; AVDownmixInfo *downmix_info; + uint64_t mask; /* copy input buffer to decoder context to avoid reading past the end of the buffer, which can be caused by a damaged input stream. */ @@ -1440,16 +1454,19 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data, /* channel config */ if (!err || (s->channels && s->out_channels != s->channels)) { + static AVChannelLayout mono = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; + static AVChannelLayout stereo = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; + s->out_channels = s->channels; s->output_mode = s->channel_mode; if (s->lfe_on) s->output_mode |= AC3_OUTPUT_LFEON; if (s->channels > 1 && - avctx->request_channel_layout == AV_CH_LAYOUT_MONO) { + !av_channel_layout_compare(&s->downmix_layout, &mono)) { s->out_channels = 1; s->output_mode = AC3_CHMODE_MONO; } else if (s->channels > 2 && - avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) { + !av_channel_layout_compare(&s->downmix_layout, &stereo)) { s->out_channels = 2; s->output_mode = AC3_CHMODE_STEREO; } @@ -1466,10 +1483,19 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data, av_log(avctx, AV_LOG_ERROR, "unable to determine channel mode\n"); return AVERROR_INVALIDDATA; } - avctx->channels = s->out_channels; - avctx->channel_layout = avpriv_ac3_channel_layout_tab[s->output_mode & ~AC3_OUTPUT_LFEON]; + + mask = avpriv_ac3_channel_layout_tab[s->output_mode & ~AC3_OUTPUT_LFEON]; if (s->output_mode & AC3_OUTPUT_LFEON) - avctx->channel_layout |= AV_CH_LOW_FREQUENCY; + mask |= AV_CH_LOW_FREQUENCY; + + av_channel_layout_uninit(&avctx->ch_layout); + av_channel_layout_from_mask(&avctx->ch_layout, mask); +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + avctx->channels = avctx->ch_layout.nb_channels; + avctx->channel_layout = avctx->ch_layout.u.mask; +FF_ENABLE_DEPRECATION_WARNINGS +#endif /* set audio service type based on bitstream mode for AC-3 */ avctx->audio_service_type = s->bitstream_mode; @@ -1588,6 +1614,7 @@ static av_cold int ac3_decode_end(AVCodecContext *avctx) #define PAR (AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM) static const AVOption options[] = { { "drc_scale", "percentage of dynamic range compression to apply", OFFSET(drc_scale), AV_OPT_TYPE_FLOAT, {.dbl = 1.0}, 0.0, 6.0, PAR }, + { "downmix", "Request a specific channel layout from the decoder", OFFSET(downmix_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.str = NULL}, .flags = PAR }, { NULL}, }; diff --git a/libavcodec/ac3dec.h b/libavcodec/ac3dec.h index 4a7e281932..a5461c8a07 100644 --- a/libavcodec/ac3dec.h +++ b/libavcodec/ac3dec.h @@ -221,6 +221,8 @@ typedef struct AC3DecodeContext { DECLARE_ALIGNED(32, float, output)[AC3_MAX_CHANNELS][AC3_BLOCK_SIZE]; ///< output after imdct transform and windowing DECLARE_ALIGNED(32, uint8_t, input_buffer)[AC3_FRAME_BUFFER_SIZE + AV_INPUT_BUFFER_PADDING_SIZE]; ///< temp buffer to prevent overread ///@} + + AVChannelLayout downmix_layout; } AC3DecodeContext; /** diff --git a/libavcodec/ac3enc.c b/libavcodec/ac3enc.c index 48bc2e79de..a81f95dc8a 100644 --- a/libavcodec/ac3enc.c +++ b/libavcodec/ac3enc.c @@ -78,6 +78,7 @@ static uint8_t exponent_group_tab[2][3][256]; /** * List of supported channel layouts. */ +#if FF_API_OLD_CHANNEL_LAYOUT const uint64_t ff_ac3_channel_layouts[19] = { AV_CH_LAYOUT_MONO, AV_CH_LAYOUT_STEREO, @@ -99,7 +100,47 @@ const uint64_t ff_ac3_channel_layouts[19] = { AV_CH_LAYOUT_5POINT1_BACK, 0 }; +#endif +const AVChannelLayout ff_ac3_ch_layouts[19] = { + AV_CHANNEL_LAYOUT_MONO, + AV_CHANNEL_LAYOUT_STEREO, + AV_CHANNEL_LAYOUT_2_1, + AV_CHANNEL_LAYOUT_SURROUND, + AV_CHANNEL_LAYOUT_2_2, + AV_CHANNEL_LAYOUT_QUAD, + AV_CHANNEL_LAYOUT_4POINT0, + AV_CHANNEL_LAYOUT_5POINT0, + AV_CHANNEL_LAYOUT_5POINT0_BACK, + { + .nb_channels = 2, + .order = AV_CHANNEL_ORDER_NATIVE, + .u.mask = AV_CH_LAYOUT_MONO | AV_CH_LOW_FREQUENCY, + }, + { + .nb_channels = 3, + .order = AV_CHANNEL_ORDER_NATIVE, + .u.mask = AV_CH_LAYOUT_STEREO | AV_CH_LOW_FREQUENCY, + }, + { + .nb_channels = 4, + .order = AV_CHANNEL_ORDER_NATIVE, + .u.mask = AV_CH_LAYOUT_2_1 | AV_CH_LOW_FREQUENCY, + }, + { + .nb_channels = 4, + .order = AV_CHANNEL_ORDER_NATIVE, + .u.mask = AV_CH_LAYOUT_SURROUND | AV_CH_LOW_FREQUENCY, + }, + { + .nb_channels = 5, + .order = AV_CHANNEL_ORDER_NATIVE, + .u.mask = AV_CH_LAYOUT_4POINT0 | AV_CH_LOW_FREQUENCY, + }, + AV_CHANNEL_LAYOUT_5POINT1, + AV_CHANNEL_LAYOUT_5POINT1_BACK, + { 0 }, +}; /** * LUT to select the bandwidth code based on the bit rate, sample rate, and @@ -1681,7 +1722,7 @@ static void dprint_options(AC3EncodeContext *s) { AVCodecContext *avctx = s->avctx; AC3EncOptions *opt = &s->options; - char strbuf[32]; + char *chlstr; switch (s->bitstream_id) { case 6: av_strlcpy(strbuf, "AC-3 (alt syntax)", 32); break; @@ -1693,8 +1734,10 @@ static void dprint_options(AC3EncodeContext *s) } ff_dlog(avctx, "bitstream_id: %s (%d)\n", strbuf, s->bitstream_id); ff_dlog(avctx, "sample_fmt: %s\n", av_get_sample_fmt_name(avctx->sample_fmt)); - av_get_channel_layout_string(strbuf, 32, s->channels, avctx->channel_layout); - ff_dlog(avctx, "channel_layout: %s\n", strbuf); + chlstr = av_channel_layout_describe(&avctx->ch_layout); + if (chlstr) + ff_dlog(avctx, "channel_layout: %s\n", chlstr); + av_free(chlstr); ff_dlog(avctx, "sample_rate: %d\n", s->sample_rate); ff_dlog(avctx, "bit_rate: %d\n", s->bit_rate); ff_dlog(avctx, "blocks/frame: %d (code=%d)\n", s->num_blocks, s->num_blks_code); @@ -1939,11 +1982,11 @@ int ff_ac3_validate_metadata(AC3EncodeContext *s) /* validate audio service type / channels combination */ if ((avctx->audio_service_type == AV_AUDIO_SERVICE_TYPE_KARAOKE && - avctx->channels == 1) || + avctx->ch_layout.nb_channels == 1) || ((avctx->audio_service_type == AV_AUDIO_SERVICE_TYPE_COMMENTARY || avctx->audio_service_type == AV_AUDIO_SERVICE_TYPE_EMERGENCY || avctx->audio_service_type == AV_AUDIO_SERVICE_TYPE_VOICE_OVER) - && avctx->channels > 1)) { + && avctx->ch_layout.nb_channels > 1)) { av_log(avctx, AV_LOG_ERROR, "invalid audio service type for the " "specified number of channels\n"); return AVERROR(EINVAL); @@ -2063,27 +2106,29 @@ av_cold int ff_ac3_encode_close(AVCodecContext *avctx) /* * Set channel information during initialization. */ -static av_cold int set_channel_info(AC3EncodeContext *s, int channels, - uint64_t *channel_layout) +static av_cold int set_channel_info(AVCodecContext *avctx) { - int ch_layout; + AC3EncodeContext *s = avctx->priv_data; + int channels = avctx->ch_layout.nb_channels; + uint64_t mask = avctx->ch_layout.u.mask; if (channels < 1 || channels > AC3_MAX_CHANNELS) return AVERROR(EINVAL); - if (*channel_layout > 0x7FF) + if (mask > 0x7FF) return AVERROR(EINVAL); - ch_layout = *channel_layout; - if (!ch_layout) - ch_layout = av_get_default_channel_layout(channels); - s->lfe_on = !!(ch_layout & AV_CH_LOW_FREQUENCY); + if (!mask) + av_channel_layout_default(&avctx->ch_layout, channels); + mask = avctx->ch_layout.u.mask; + + s->lfe_on = !!(mask & AV_CH_LOW_FREQUENCY); s->channels = channels; s->fbw_channels = channels - s->lfe_on; s->lfe_channel = s->lfe_on ? s->fbw_channels + 1 : -1; if (s->lfe_on) - ch_layout -= AV_CH_LOW_FREQUENCY; + mask -= AV_CH_LOW_FREQUENCY; - switch (ch_layout) { + switch (mask) { case AV_CH_LAYOUT_MONO: s->channel_mode = AC3_CHMODE_MONO; break; case AV_CH_LAYOUT_STEREO: s->channel_mode = AC3_CHMODE_STEREO; break; case AV_CH_LAYOUT_SURROUND: s->channel_mode = AC3_CHMODE_3F; break; @@ -2100,9 +2145,9 @@ static av_cold int set_channel_info(AC3EncodeContext *s, int channels, s->has_surround = s->channel_mode & 0x04; s->channel_map = ff_ac3_enc_channel_map[s->channel_mode][s->lfe_on]; - *channel_layout = ch_layout; if (s->lfe_on) - *channel_layout |= AV_CH_LOW_FREQUENCY; + mask |= AV_CH_LOW_FREQUENCY; + av_channel_layout_from_mask(&avctx->ch_layout, mask); return 0; } @@ -2114,12 +2159,12 @@ static av_cold int validate_options(AC3EncodeContext *s) int i, ret, max_sr; /* validate channel layout */ - if (!avctx->channel_layout) { + if (!avctx->ch_layout.nb_channels) { av_log(avctx, AV_LOG_WARNING, "No channel layout specified. The " "encoder will guess the layout, but it " "might be incorrect.\n"); } - ret = set_channel_info(s, avctx->channels, &avctx->channel_layout); + ret = set_channel_info(avctx); if (ret) { av_log(avctx, AV_LOG_ERROR, "invalid channel layout\n"); return ret; diff --git a/libavcodec/ac3enc.h b/libavcodec/ac3enc.h index 76b6d7f6e5..c588b73fd7 100644 --- a/libavcodec/ac3enc.h +++ b/libavcodec/ac3enc.h @@ -266,8 +266,10 @@ typedef struct AC3EncodeContext { void (*output_frame_header)(struct AC3EncodeContext *s); } AC3EncodeContext; - +#if FF_API_OLD_CHANNEL_LAYOUT extern const uint64_t ff_ac3_channel_layouts[19]; +#endif +extern const AVChannelLayout ff_ac3_ch_layouts[19]; int ff_ac3_encode_init(AVCodecContext *avctx); int ff_ac3_float_encode_init(AVCodecContext *avctx); diff --git a/libavcodec/ac3enc_fixed.c b/libavcodec/ac3enc_fixed.c index a4ab5dfde2..cbd735c69a 100644 --- a/libavcodec/ac3enc_fixed.c +++ b/libavcodec/ac3enc_fixed.c @@ -149,6 +149,11 @@ AVCodec ff_ac3_fixed_encoder = { .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_NONE }, .priv_class = &ac3enc_class, +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS .channel_layouts = ff_ac3_channel_layouts, +FF_ENABLE_DEPRECATION_WARNINGS +#endif + .ch_layouts = ff_ac3_ch_layouts, .defaults = ac3_defaults, }; diff --git a/libavcodec/ac3enc_float.c b/libavcodec/ac3enc_float.c index 95acea7770..8394d5049c 100644 --- a/libavcodec/ac3enc_float.c +++ b/libavcodec/ac3enc_float.c @@ -142,6 +142,11 @@ AVCodec ff_ac3_encoder = { .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, .priv_class = &ac3enc_class, +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS .channel_layouts = ff_ac3_channel_layouts, +FF_ENABLE_DEPRECATION_WARNINGS +#endif + .ch_layouts = ff_ac3_ch_layouts, .defaults = ac3_defaults, }; diff --git a/libavcodec/eac3enc.c b/libavcodec/eac3enc.c index 17757bebef..737e12a323 100644 --- a/libavcodec/eac3enc.c +++ b/libavcodec/eac3enc.c @@ -264,6 +264,11 @@ AVCodec ff_eac3_encoder = { .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, .priv_class = &eac3enc_class, +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS .channel_layouts = ff_ac3_channel_layouts, +FF_ENABLE_DEPRECATION_WARNINGS +#endif + .ch_layouts = ff_ac3_ch_layouts, .defaults = ac3_defaults, }; diff --git a/tests/fate/ac3.mak b/tests/fate/ac3.mak index fee4567288..1ec4b74bac 100644 --- a/tests/fate/ac3.mak +++ b/tests/fate/ac3.mak @@ -6,14 +6,14 @@ FATE_AC3 += fate-ac3-4.0 fate-ac3-4.0: CMD = pcm -i $(TARGET_SAMPLES)/ac3/millers_crossing_4.0.ac3 fate-ac3-4.0: REF = $(SAMPLES)/ac3/millers_crossing_4.0_v2.pcm -#request_channel_layout 4 -> front channel +#downmix 4.0 -> front channel FATE_AC3 += fate-ac3-4.0-downmix-mono -fate-ac3-4.0-downmix-mono: CMD = pcm -request_channel_layout 4 -i $(TARGET_SAMPLES)/ac3/millers_crossing_4.0.ac3 +fate-ac3-4.0-downmix-mono: CMD = pcm -downmix 0x4 -i $(TARGET_SAMPLES)/ac3/millers_crossing_4.0.ac3 fate-ac3-4.0-downmix-mono: REF = $(SAMPLES)/ac3/millers_crossing_4.0_mono_v2.pcm -#request_channel_layout 3 -> left channel + right channel +#downmix 3.0 -> left channel + right channel FATE_AC3 += fate-ac3-4.0-downmix-stereo -fate-ac3-4.0-downmix-stereo: CMD = pcm -request_channel_layout 3 -i $(TARGET_SAMPLES)/ac3/millers_crossing_4.0.ac3 +fate-ac3-4.0-downmix-stereo: CMD = pcm -downmix 0x3 -i $(TARGET_SAMPLES)/ac3/millers_crossing_4.0.ac3 fate-ac3-4.0-downmix-stereo: REF = $(SAMPLES)/ac3/millers_crossing_4.0_stereo_v2.pcm FATE_AC3 += fate-ac3-5.1 @@ -21,11 +21,11 @@ fate-ac3-5.1: CMD = pcm -i $(TARGET_SAMPLES)/ac3/monsters_inc_5.1_448_small.ac3 fate-ac3-5.1: REF = $(SAMPLES)/ac3/monsters_inc_5.1_448_small_v2.pcm FATE_AC3 += fate-ac3-5.1-downmix-mono -fate-ac3-5.1-downmix-mono: CMD = pcm -request_channel_layout 4 -i $(TARGET_SAMPLES)/ac3/monsters_inc_5.1_448_small.ac3 +fate-ac3-5.1-downmix-mono: CMD = pcm -downmix 0x4 -i $(TARGET_SAMPLES)/ac3/monsters_inc_5.1_448_small.ac3 fate-ac3-5.1-downmix-mono: REF = $(SAMPLES)/ac3/monsters_inc_5.1_448_small_mono_v2.pcm FATE_AC3 += fate-ac3-5.1-downmix-stereo -fate-ac3-5.1-downmix-stereo: CMD = pcm -request_channel_layout 3 -i $(TARGET_SAMPLES)/ac3/monsters_inc_5.1_448_small.ac3 +fate-ac3-5.1-downmix-stereo: CMD = pcm -downmix 0x3 -i $(TARGET_SAMPLES)/ac3/monsters_inc_5.1_448_small.ac3 fate-ac3-5.1-downmix-stereo: REF = $(SAMPLES)/ac3/monsters_inc_5.1_448_small_stereo_v2.pcm FATE_EAC3 += fate-eac3-1 -- 2.13.1 _______________________________________________ libav-devel mailing list libav-devel@libav.org https://lists.libav.org/mailman/listinfo/libav-devel