Signed-off-by: Vittorio Giovara <[email protected]>
---
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
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel