[FFmpeg-cvslog] eac3enc: support writing of basic mixing and info metadata
Justin Ruggles
git at videolan.org
Thu Jul 28 09:33:50 CEST 2011
ffmpeg | branch: master | Justin Ruggles <justin.ruggles at gmail.com> | Sun May 29 19:16:46 2011 -0400| [1bca72e1bd2fa5db2585a58e452c384ca73bf0eb] | committer: Justin Ruggles
eac3enc: support writing of basic mixing and info metadata
> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=1bca72e1bd2fa5db2585a58e452c384ca73bf0eb
---
libavcodec/ac3enc.c | 239 ++++++++++++++++++++++++------------
libavcodec/ac3enc.h | 2 +
libavcodec/ac3enc_opts_template.c | 14 +--
libavcodec/ac3enc_template.c | 2 +-
libavcodec/eac3enc.c | 46 +++++++-
5 files changed, 210 insertions(+), 93 deletions(-)
diff --git a/libavcodec/ac3enc.c b/libavcodec/ac3enc.c
index 017b1d4..a3b77ec 100644
--- a/libavcodec/ac3enc.c
+++ b/libavcodec/ac3enc.c
@@ -759,6 +759,30 @@ static void count_frame_bits(AC3EncodeContext *s)
/* header */
if (s->eac3) {
+ if (opt->eac3_mixing_metadata) {
+ if (s->channel_mode > AC3_CHMODE_STEREO)
+ frame_bits += 2;
+ if (s->has_center)
+ frame_bits += 6;
+ if (s->has_surround)
+ frame_bits += 6;
+ frame_bits += s->lfe_on;
+ frame_bits += 1 + 1 + 2;
+ if (s->channel_mode < AC3_CHMODE_STEREO)
+ frame_bits++;
+ frame_bits++;
+ }
+ if (opt->eac3_info_metadata) {
+ frame_bits += 3 + 1 + 1;
+ if (s->channel_mode == AC3_CHMODE_STEREO)
+ frame_bits += 2 + 2;
+ if (s->channel_mode >= AC3_CHMODE_2F2R)
+ frame_bits += 2;
+ frame_bits++;
+ if (opt->audio_production_info)
+ frame_bits += 5 + 2 + 1;
+ frame_bits++;
+ }
/* coupling */
if (s->channel_mode > AC3_CHMODE_MONO) {
frame_bits++;
@@ -1736,93 +1760,162 @@ int ff_ac3_validate_metadata(AC3EncodeContext *s)
AVCodecContext *avctx = s->avctx;
AC3EncOptions *opt = &s->options;
- /* validate mixing levels */
- if (s->has_center) {
- validate_mix_level(avctx, "center_mix_level", &opt->center_mix_level,
- cmixlev_options, CMIXLEV_NUM_OPTIONS, 1, 0,
- &s->center_mix_level);
+ opt->audio_production_info = 0;
+ opt->extended_bsi_1 = 0;
+ opt->extended_bsi_2 = 0;
+ opt->eac3_mixing_metadata = 0;
+ opt->eac3_info_metadata = 0;
+
+ /* determine mixing metadata / xbsi1 use */
+ if (s->channel_mode > AC3_CHMODE_STEREO && opt->preferred_stereo_downmix >= 0) {
+ opt->extended_bsi_1 = 1;
+ opt->eac3_mixing_metadata = 1;
+ }
+ if (s->has_center &&
+ (opt->ltrt_center_mix_level >= 0 || opt->loro_center_mix_level >= 0)) {
+ opt->extended_bsi_1 = 1;
+ opt->eac3_mixing_metadata = 1;
}
- if (s->has_surround) {
- validate_mix_level(avctx, "surround_mix_level", &opt->surround_mix_level,
- surmixlev_options, SURMIXLEV_NUM_OPTIONS, 1, 0,
- &s->surround_mix_level);
+ if (s->has_surround &&
+ (opt->ltrt_surround_mix_level >= 0 || opt->loro_surround_mix_level >= 0)) {
+ opt->extended_bsi_1 = 1;
+ opt->eac3_mixing_metadata = 1;
}
- /* set audio production info flag */
- if (opt->mixing_level >= 0 || opt->room_type >= 0) {
- if (opt->mixing_level < 0) {
- av_log(avctx, AV_LOG_ERROR, "mixing_level must be set if "
- "room_type is set\n");
- return AVERROR(EINVAL);
- }
- if (opt->mixing_level < 80) {
- av_log(avctx, AV_LOG_ERROR, "invalid mixing level. must be between "
- "80dB and 111dB\n");
- return AVERROR(EINVAL);
+ if (s->eac3) {
+ /* determine info metadata use */
+ if (avctx->audio_service_type != AV_AUDIO_SERVICE_TYPE_MAIN)
+ opt->eac3_info_metadata = 1;
+ if (opt->copyright >= 0 || opt->original >= 0)
+ opt->eac3_info_metadata = 1;
+ if (s->channel_mode == AC3_CHMODE_STEREO &&
+ (opt->dolby_headphone_mode >= 0 || opt->dolby_surround_mode >= 0))
+ opt->eac3_info_metadata = 1;
+ if (s->channel_mode >= AC3_CHMODE_2F2R && opt->dolby_surround_ex_mode >= 0)
+ opt->eac3_info_metadata = 1;
+ if (opt->mixing_level >= 0 || opt->room_type >= 0 || opt->ad_converter_type >= 0) {
+ opt->audio_production_info = 1;
+ opt->eac3_info_metadata = 1;
}
- /* default room type */
- if (opt->room_type < 0)
- opt->room_type = 0;
- opt->audio_production_info = 1;
} else {
- opt->audio_production_info = 0;
+ /* determine audio production info use */
+ if (opt->mixing_level >= 0 || opt->room_type >= 0)
+ opt->audio_production_info = 1;
+
+ /* determine xbsi2 use */
+ if (s->channel_mode >= AC3_CHMODE_2F2R && opt->dolby_surround_ex_mode >= 0)
+ opt->extended_bsi_2 = 1;
+ if (s->channel_mode == AC3_CHMODE_STEREO && opt->dolby_headphone_mode >= 0)
+ opt->extended_bsi_2 = 1;
+ if (opt->ad_converter_type >= 0)
+ opt->extended_bsi_2 = 1;
}
- /* set extended bsi 1 flag */
- if ((s->has_center || s->has_surround) &&
- (opt->preferred_stereo_downmix >= 0 ||
- opt->ltrt_center_mix_level >= 0 ||
- opt->ltrt_surround_mix_level >= 0 ||
- opt->loro_center_mix_level >= 0 ||
- opt->loro_surround_mix_level >= 0)) {
+ /* validate AC-3 mixing levels */
+ if (!s->eac3) {
+ if (s->has_center) {
+ validate_mix_level(avctx, "center_mix_level", &opt->center_mix_level,
+ cmixlev_options, CMIXLEV_NUM_OPTIONS, 1, 0,
+ &s->center_mix_level);
+ }
+ if (s->has_surround) {
+ validate_mix_level(avctx, "surround_mix_level", &opt->surround_mix_level,
+ surmixlev_options, SURMIXLEV_NUM_OPTIONS, 1, 0,
+ &s->surround_mix_level);
+ }
+ }
+
+ /* validate extended bsi 1 / mixing metadata */
+ if (opt->extended_bsi_1 || opt->eac3_mixing_metadata) {
/* default preferred stereo downmix */
if (opt->preferred_stereo_downmix < 0)
opt->preferred_stereo_downmix = 0;
- /* validate Lt/Rt center mix level */
- validate_mix_level(avctx, "ltrt_center_mix_level",
- &opt->ltrt_center_mix_level, extmixlev_options,
- EXTMIXLEV_NUM_OPTIONS, 5, 0,
- &s->ltrt_center_mix_level);
- /* validate Lt/Rt surround mix level */
- validate_mix_level(avctx, "ltrt_surround_mix_level",
- &opt->ltrt_surround_mix_level, extmixlev_options,
- EXTMIXLEV_NUM_OPTIONS, 6, 3,
- &s->ltrt_surround_mix_level);
- /* validate Lo/Ro center mix level */
- validate_mix_level(avctx, "loro_center_mix_level",
- &opt->loro_center_mix_level, extmixlev_options,
- EXTMIXLEV_NUM_OPTIONS, 5, 0,
- &s->loro_center_mix_level);
- /* validate Lo/Ro surround mix level */
- validate_mix_level(avctx, "loro_surround_mix_level",
- &opt->loro_surround_mix_level, extmixlev_options,
- EXTMIXLEV_NUM_OPTIONS, 6, 3,
- &s->loro_surround_mix_level);
- opt->extended_bsi_1 = 1;
- } else {
- opt->extended_bsi_1 = 0;
+ if (!s->eac3 || s->has_center) {
+ /* validate Lt/Rt center mix level */
+ validate_mix_level(avctx, "ltrt_center_mix_level",
+ &opt->ltrt_center_mix_level, extmixlev_options,
+ EXTMIXLEV_NUM_OPTIONS, 5, 0,
+ &s->ltrt_center_mix_level);
+ /* validate Lo/Ro center mix level */
+ validate_mix_level(avctx, "loro_center_mix_level",
+ &opt->loro_center_mix_level, extmixlev_options,
+ EXTMIXLEV_NUM_OPTIONS, 5, 0,
+ &s->loro_center_mix_level);
+ }
+ if (!s->eac3 || s->has_surround) {
+ /* validate Lt/Rt surround mix level */
+ validate_mix_level(avctx, "ltrt_surround_mix_level",
+ &opt->ltrt_surround_mix_level, extmixlev_options,
+ EXTMIXLEV_NUM_OPTIONS, 6, 3,
+ &s->ltrt_surround_mix_level);
+ /* validate Lo/Ro surround mix level */
+ validate_mix_level(avctx, "loro_surround_mix_level",
+ &opt->loro_surround_mix_level, extmixlev_options,
+ EXTMIXLEV_NUM_OPTIONS, 6, 3,
+ &s->loro_surround_mix_level);
+ }
}
- /* set extended bsi 2 flag */
- if (opt->dolby_surround_ex_mode >= 0 ||
- opt->dolby_headphone_mode >= 0 ||
- opt->ad_converter_type >= 0) {
- /* default dolby surround ex mode */
- if (opt->dolby_surround_ex_mode < 0)
- opt->dolby_surround_ex_mode = 0;
+ /* validate audio service type / channels combination */
+ if ((avctx->audio_service_type == AV_AUDIO_SERVICE_TYPE_KARAOKE &&
+ avctx->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)) {
+ av_log(avctx, AV_LOG_ERROR, "invalid audio service type for the "
+ "specified number of channels\n");
+ return AVERROR(EINVAL);
+ }
+
+ /* validate extended bsi 2 / info metadata */
+ if (opt->extended_bsi_2 || opt->eac3_info_metadata) {
/* default dolby headphone mode */
if (opt->dolby_headphone_mode < 0)
opt->dolby_headphone_mode = 0;
+ /* default dolby surround ex mode */
+ if (opt->dolby_surround_ex_mode < 0)
+ opt->dolby_surround_ex_mode = 0;
/* default A/D converter type */
if (opt->ad_converter_type < 0)
opt->ad_converter_type = 0;
- opt->extended_bsi_2 = 1;
- } else {
- opt->extended_bsi_2 = 0;
+ }
+
+ /* copyright & original defaults */
+ if (!s->eac3 || opt->eac3_info_metadata) {
+ /* default copyright */
+ if (opt->copyright < 0)
+ opt->copyright = 0;
+ /* default original */
+ if (opt->original < 0)
+ opt->original = 1;
+ }
+
+ /* dolby surround mode default */
+ if (!s->eac3 || opt->eac3_info_metadata) {
+ if (opt->dolby_surround_mode < 0)
+ opt->dolby_surround_mode = 0;
+ }
+
+ /* validate audio production info */
+ if (opt->audio_production_info) {
+ if (opt->mixing_level < 0) {
+ av_log(avctx, AV_LOG_ERROR, "mixing_level must be set if "
+ "room_type is set\n");
+ return AVERROR(EINVAL);
+ }
+ if (opt->mixing_level < 80) {
+ av_log(avctx, AV_LOG_ERROR, "invalid mixing level. must be between "
+ "80dB and 111dB\n");
+ return AVERROR(EINVAL);
+ }
+ /* default room type */
+ if (opt->room_type < 0)
+ opt->room_type = 0;
}
/* set bitstream id for alternate bitstream syntax */
- if (opt->extended_bsi_1 || opt->extended_bsi_2) {
+ if (!s->eac3 && (opt->extended_bsi_1 || opt->extended_bsi_2)) {
if (s->bitstream_id > 8 && s->bitstream_id < 11) {
static int warn_once = 1;
if (warn_once) {
@@ -2041,23 +2134,9 @@ static av_cold int validate_options(AC3EncodeContext *s)
if (s->cutoff > (s->sample_rate >> 1))
s->cutoff = s->sample_rate >> 1;
- /* validate audio service type / channels combination */
- if ((avctx->audio_service_type == AV_AUDIO_SERVICE_TYPE_KARAOKE &&
- avctx->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)) {
- av_log(avctx, AV_LOG_ERROR, "invalid audio service type for the "
- "specified number of channels\n");
- return AVERROR(EINVAL);
- }
-
- if (!s->eac3) {
ret = ff_ac3_validate_metadata(s);
if (ret)
return ret;
- }
s->rematrixing_enabled = s->options.stereo_rematrixing &&
(s->channel_mode == AC3_CHMODE_STEREO);
diff --git a/libavcodec/ac3enc.h b/libavcodec/ac3enc.h
index 407e751..6d57143 100644
--- a/libavcodec/ac3enc.h
+++ b/libavcodec/ac3enc.h
@@ -91,6 +91,8 @@ typedef struct AC3EncOptions {
int dolby_surround_ex_mode;
int dolby_headphone_mode;
int ad_converter_type;
+ int eac3_mixing_metadata;
+ int eac3_info_metadata;
/* other encoding options */
int allow_per_frame_metadata;
diff --git a/libavcodec/ac3enc_opts_template.c b/libavcodec/ac3enc_opts_template.c
index 39138a1..7c0eead 100644
--- a/libavcodec/ac3enc_opts_template.c
+++ b/libavcodec/ac3enc_opts_template.c
@@ -29,12 +29,13 @@ static const AVOption ac3_options[] = {
#else /* AC3ENC_TYPE_EAC3 */
static const AVOption eac3_options[] = {
#endif
-#if AC3ENC_TYPE != AC3ENC_TYPE_EAC3
/* Metadata Options */
{"per_frame_metadata", "Allow Changing Metadata Per-Frame", OFFSET(allow_per_frame_metadata), FF_OPT_TYPE_INT, {.dbl = 0 }, 0, 1, AC3ENC_PARAM},
-/* downmix levels */
+#if AC3ENC_TYPE != AC3ENC_TYPE_EAC3
+/* AC-3 downmix levels */
{"center_mixlev", "Center Mix Level", OFFSET(center_mix_level), FF_OPT_TYPE_FLOAT, {.dbl = LEVEL_MINUS_4POINT5DB }, 0.0, 1.0, AC3ENC_PARAM},
{"surround_mixlev", "Surround Mix Level", OFFSET(surround_mix_level), FF_OPT_TYPE_FLOAT, {.dbl = LEVEL_MINUS_6DB }, 0.0, 1.0, AC3ENC_PARAM},
+#endif
/* audio production information */
{"mixing_level", "Mixing Level", OFFSET(mixing_level), FF_OPT_TYPE_INT, {.dbl = -1 }, -1, 111, AC3ENC_PARAM},
{"room_type", "Room Type", OFFSET(room_type), FF_OPT_TYPE_INT, {.dbl = -1 }, -1, 2, AC3ENC_PARAM, "room_type"},
@@ -42,15 +43,13 @@ static const AVOption eac3_options[] = {
{"large", "Large Room", 0, FF_OPT_TYPE_CONST, {.dbl = 1 }, INT_MIN, INT_MAX, AC3ENC_PARAM, "room_type"},
{"small", "Small Room", 0, FF_OPT_TYPE_CONST, {.dbl = 2 }, INT_MIN, INT_MAX, AC3ENC_PARAM, "room_type"},
/* other metadata options */
-{"copyright", "Copyright Bit", OFFSET(copyright), FF_OPT_TYPE_INT, {.dbl = 0 }, 0, 1, AC3ENC_PARAM},
-#endif
+{"copyright", "Copyright Bit", OFFSET(copyright), FF_OPT_TYPE_INT, {.dbl = -1 }, -1, 1, AC3ENC_PARAM},
{"dialnorm", "Dialogue Level (dB)", OFFSET(dialogue_level), FF_OPT_TYPE_INT, {.dbl = -31 }, -31, -1, AC3ENC_PARAM},
-#if AC3ENC_TYPE != AC3ENC_TYPE_EAC3
-{"dsur_mode", "Dolby Surround Mode", OFFSET(dolby_surround_mode), FF_OPT_TYPE_INT, {.dbl = 0 }, 0, 2, AC3ENC_PARAM, "dsur_mode"},
+{"dsur_mode", "Dolby Surround Mode", OFFSET(dolby_surround_mode), FF_OPT_TYPE_INT, {.dbl = -1 }, -1, 2, AC3ENC_PARAM, "dsur_mode"},
{"notindicated", "Not Indicated (default)", 0, FF_OPT_TYPE_CONST, {.dbl = 0 }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dsur_mode"},
{"on", "Dolby Surround Encoded", 0, FF_OPT_TYPE_CONST, {.dbl = 1 }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dsur_mode"},
{"off", "Not Dolby Surround Encoded", 0, FF_OPT_TYPE_CONST, {.dbl = 2 }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dsur_mode"},
-{"original", "Original Bit Stream", OFFSET(original), FF_OPT_TYPE_INT, {.dbl = 1 }, 0, 1, AC3ENC_PARAM},
+{"original", "Original Bit Stream", OFFSET(original), FF_OPT_TYPE_INT, {.dbl = -1 }, -1, 1, AC3ENC_PARAM},
/* extended bitstream information */
{"dmix_mode", "Preferred Stereo Downmix Mode", OFFSET(preferred_stereo_downmix), FF_OPT_TYPE_INT, {.dbl = -1 }, -1, 2, AC3ENC_PARAM, "dmix_mode"},
{"notindicated", "Not Indicated (default)", 0, FF_OPT_TYPE_CONST, {.dbl = 0 }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dmix_mode"},
@@ -71,7 +70,6 @@ static const AVOption eac3_options[] = {
{"ad_conv_type", "A/D Converter Type", OFFSET(ad_converter_type), FF_OPT_TYPE_INT, {.dbl = -1 }, -1, 1, AC3ENC_PARAM, "ad_conv_type"},
{"standard", "Standard (default)", 0, FF_OPT_TYPE_CONST, {.dbl = 0 }, INT_MIN, INT_MAX, AC3ENC_PARAM, "ad_conv_type"},
{"hdcd", "HDCD", 0, FF_OPT_TYPE_CONST, {.dbl = 1 }, INT_MIN, INT_MAX, AC3ENC_PARAM, "ad_conv_type"},
-#endif
/* Other Encoding Options */
{"stereo_rematrixing", "Stereo Rematrixing", OFFSET(stereo_rematrixing), FF_OPT_TYPE_INT, {.dbl = 1 }, 0, 1, AC3ENC_PARAM},
#if AC3ENC_TYPE != AC3ENC_TYPE_AC3_FIXED
diff --git a/libavcodec/ac3enc_template.c b/libavcodec/ac3enc_template.c
index c4e2a12..103e7b1 100644
--- a/libavcodec/ac3enc_template.c
+++ b/libavcodec/ac3enc_template.c
@@ -423,7 +423,7 @@ int AC3_NAME(encode_frame)(AVCodecContext *avctx, unsigned char *frame,
const SampleType *samples = data;
int ret;
- if (!s->eac3 && s->options.allow_per_frame_metadata) {
+ if (s->options.allow_per_frame_metadata) {
ret = ff_ac3_validate_metadata(s);
if (ret)
return ret;
diff --git a/libavcodec/eac3enc.c b/libavcodec/eac3enc.c
index 038aa2a..75113b2 100644
--- a/libavcodec/eac3enc.c
+++ b/libavcodec/eac3enc.c
@@ -142,10 +142,48 @@ void ff_eac3_output_frame_header(AC3EncodeContext *s)
put_bits(&s->pb, 5, s->bitstream_id); /* bitstream id (EAC3=16) */
put_bits(&s->pb, 5, -opt->dialogue_level); /* dialogue normalization level */
put_bits(&s->pb, 1, 0); /* no compression gain */
- put_bits(&s->pb, 1, 0); /* no mixing metadata */
- /* TODO: mixing metadata */
- put_bits(&s->pb, 1, 0); /* no info metadata */
- /* TODO: info metadata */
+ /* mixing metadata*/
+ put_bits(&s->pb, 1, opt->eac3_mixing_metadata);
+ if (opt->eac3_mixing_metadata) {
+ if (s->channel_mode > AC3_CHMODE_STEREO)
+ put_bits(&s->pb, 2, opt->preferred_stereo_downmix);
+ if (s->has_center) {
+ put_bits(&s->pb, 3, s->ltrt_center_mix_level);
+ put_bits(&s->pb, 3, s->loro_center_mix_level);
+ }
+ if (s->has_surround) {
+ put_bits(&s->pb, 3, s->ltrt_surround_mix_level);
+ put_bits(&s->pb, 3, s->loro_surround_mix_level);
+ }
+ if (s->lfe_on)
+ put_bits(&s->pb, 1, 0);
+ put_bits(&s->pb, 1, 0); /* no program scale */
+ put_bits(&s->pb, 1, 0); /* no ext program scale */
+ put_bits(&s->pb, 2, 0); /* no mixing parameters */
+ if (s->channel_mode < AC3_CHMODE_STEREO)
+ put_bits(&s->pb, 1, 0); /* no pan info */
+ put_bits(&s->pb, 1, 0); /* no frame mix config info */
+ }
+ /* info metadata*/
+ put_bits(&s->pb, 1, opt->eac3_info_metadata);
+ if (opt->eac3_info_metadata) {
+ put_bits(&s->pb, 3, s->bitstream_mode);
+ put_bits(&s->pb, 1, opt->copyright);
+ put_bits(&s->pb, 1, opt->original);
+ if (s->channel_mode == AC3_CHMODE_STEREO) {
+ put_bits(&s->pb, 2, opt->dolby_surround_mode);
+ put_bits(&s->pb, 2, opt->dolby_headphone_mode);
+ }
+ if (s->channel_mode >= AC3_CHMODE_2F2R)
+ put_bits(&s->pb, 2, opt->dolby_surround_ex_mode);
+ put_bits(&s->pb, 1, opt->audio_production_info);
+ if (opt->audio_production_info) {
+ put_bits(&s->pb, 5, opt->mixing_level - 80);
+ put_bits(&s->pb, 2, opt->room_type);
+ put_bits(&s->pb, 1, opt->ad_converter_type);
+ }
+ put_bits(&s->pb, 1, 0);
+ }
if (s->num_blocks != 6)
put_bits(&s->pb, 1, !(s->avctx->frame_number % 6)); /* converter sync flag */
put_bits(&s->pb, 1, 0); /* no additional bit stream info */
More information about the ffmpeg-cvslog
mailing list