diff options
author | Justin Ruggles <justin.ruggles@gmail.com> | 2011-05-29 19:16:46 -0400 |
---|---|---|
committer | Justin Ruggles <justin.ruggles@gmail.com> | 2011-07-27 11:51:46 -0400 |
commit | 1bca72e1bd2fa5db2585a58e452c384ca73bf0eb (patch) | |
tree | a1111f2c8b47861bcb20798b85207df67e3cb3b9 | |
parent | e72f3d10f64f5c65a67aa21dcc79a85ee55e912e (diff) | |
download | ffmpeg-1bca72e1bd2fa5db2585a58e452c384ca73bf0eb.tar.gz |
eac3enc: support writing of basic mixing and info metadata
-rw-r--r-- | libavcodec/ac3enc.c | 239 | ||||
-rw-r--r-- | libavcodec/ac3enc.h | 2 | ||||
-rw-r--r-- | libavcodec/ac3enc_opts_template.c | 14 | ||||
-rw-r--r-- | libavcodec/ac3enc_template.c | 2 | ||||
-rw-r--r-- | libavcodec/eac3enc.c | 46 |
5 files changed, 210 insertions, 93 deletions
diff --git a/libavcodec/ac3enc.c b/libavcodec/ac3enc.c index 017b1d4b93..a3b77ec6ed 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 407e751b40..6d57143a01 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 39138a1083..7c0eead011 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 c4e2a121bf..103e7b1a96 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 038aa2a234..75113b272f 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 */ |