/* * The simplest AC-3 encoder * Copyright (c) 2000 Fabrice Bellard * Copyright (c) 2006-2010 Justin Ruggles <justin.ruggles@gmail.com> * Copyright (c) 2006-2010 Prakash Punnoor <prakash@punnoor.de> * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /** * @file * The simplest AC-3 encoder. */ #include <stdint.h> #include "libavutil/attributes.h"#include "libavutil/avassert.h"#include "libavutil/channel_layout.h"#include "libavutil/crc.h"#include "libavutil/emms.h"#include "libavutil/internal.h"#include "libavutil/mem.h"#include "libavutil/mem_internal.h"#include "libavutil/opt.h"#include "libavutil/thread.h"#include "avcodec.h"#include "codec_internal.h"#include "config_components.h"#include "encode.h"#include "me_cmp.h"#include "put_bits.h"#include "audiodsp.h"#include "ac3dsp.h"#include "ac3.h"#include "ac3defs.h"#include "ac3tab.h"#include "ac3enc.h"#include "eac3enc.h" #define SAMPLETYPE_SIZE(ctx) (sizeof(float) == sizeof(int32_t) ? sizeof(float) : \ (ctx)->fixed_point ? sizeof(int32_t) : sizeof(float)) typedef struct AC3Mant { int16_t *qmant1_ptr, *qmant2_ptr, *qmant4_ptr; ///< mantissa pointers for bap=1,2,4 int mant1_cnt, mant2_cnt, mant4_cnt; ///< mantissa counts for bap=1,2,4} AC3Mant; #define CMIXLEV_NUM_OPTIONS 3static const float cmixlev_options[CMIXLEV_NUM_OPTIONS] = { LEVEL_MINUS_3DB, LEVEL_MINUS_4POINT5DB, LEVEL_MINUS_6DB}; #define SURMIXLEV_NUM_OPTIONS 3static const float surmixlev_options[SURMIXLEV_NUM_OPTIONS] = { LEVEL_MINUS_3DB, LEVEL_MINUS_6DB, LEVEL_ZERO}; #define EXTMIXLEV_NUM_OPTIONS 8static const float extmixlev_options[EXTMIXLEV_NUM_OPTIONS] = { LEVEL_PLUS_3DB, LEVEL_PLUS_1POINT5DB, LEVEL_ONE, LEVEL_MINUS_1POINT5DB, LEVEL_MINUS_3DB, LEVEL_MINUS_4POINT5DB, LEVEL_MINUS_6DB, LEVEL_ZERO}; /* The first two options apply only to the AC-3 encoders; * the rest is also valid for EAC-3. When modifying it, * it might be necessary to adapt said offset in eac3enc.c. */#define OFFSET(param) offsetof(AC3EncodeContext, options.param)#define AC3ENC_PARAM (AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM)const AVOption ff_ac3_enc_options[] = {/* AC-3 downmix levels */{"center_mixlev", "Center Mix Level", OFFSET(center_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = LEVEL_MINUS_4POINT5DB }, 0.0, 1.0, AC3ENC_PARAM},{"surround_mixlev", "Surround Mix Level", OFFSET(surround_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = LEVEL_MINUS_6DB }, 0.0, 1.0, AC3ENC_PARAM},/* audio production information */{"mixing_level", "Mixing Level", OFFSET(mixing_level), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, 111, AC3ENC_PARAM},{"room_type", "Room Type", OFFSET(room_type), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, AC3ENC_OPT_SMALL_ROOM, AC3ENC_PARAM, .unit = "room_type"}, {"notindicated", "Not Indicated (default)", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_NOT_INDICATED }, INT_MIN, INT_MAX, AC3ENC_PARAM, .unit = "room_type"}, {"large", "Large Room", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_LARGE_ROOM }, INT_MIN, INT_MAX, AC3ENC_PARAM, .unit = "room_type"}, {"small", "Small Room", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_SMALL_ROOM }, INT_MIN, INT_MAX, AC3ENC_PARAM, .unit = "room_type"},/* Metadata Options */{"per_frame_metadata", "Allow Changing Metadata Per-Frame", OFFSET(allow_per_frame_metadata), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, AC3ENC_PARAM},{"copyright", "Copyright Bit", OFFSET(copyright), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, 1, AC3ENC_PARAM},{"dialnorm", "Dialogue Level (dB)", OFFSET(dialogue_level), AV_OPT_TYPE_INT, {.i64 = -31 }, -31, -1, AC3ENC_PARAM},{"dsur_mode", "Dolby Surround Mode", OFFSET(dolby_surround_mode), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, AC3ENC_OPT_MODE_ON, AC3ENC_PARAM, .unit = "dsur_mode"}, {"notindicated", "Not Indicated (default)", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_NOT_INDICATED }, INT_MIN, INT_MAX, AC3ENC_PARAM, .unit = "dsur_mode"}, {"on", "Dolby Surround Encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_MODE_ON }, INT_MIN, INT_MAX, AC3ENC_PARAM, .unit = "dsur_mode"}, {"off", "Not Dolby Surround Encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_MODE_OFF }, INT_MIN, INT_MAX, AC3ENC_PARAM, .unit = "dsur_mode"},{"original", "Original Bit Stream", OFFSET(original), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, 1, AC3ENC_PARAM},/* extended bitstream information */{"dmix_mode", "Preferred Stereo Downmix Mode", OFFSET(preferred_stereo_downmix), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, AC3ENC_OPT_DOWNMIX_DPLII, AC3ENC_PARAM, .unit = "dmix_mode"}, {"notindicated", "Not Indicated (default)", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_NOT_INDICATED }, INT_MIN, INT_MAX, AC3ENC_PARAM, .unit = "dmix_mode"}, {"ltrt", "Lt/Rt Downmix Preferred", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_DOWNMIX_LTRT }, INT_MIN, INT_MAX, AC3ENC_PARAM, .unit = "dmix_mode"}, {"loro", "Lo/Ro Downmix Preferred", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_DOWNMIX_LORO }, INT_MIN, INT_MAX, AC3ENC_PARAM, .unit = "dmix_mode"}, {"dplii", "Dolby Pro Logic II Downmix Preferred", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_DOWNMIX_DPLII }, INT_MIN, INT_MAX, AC3ENC_PARAM, .unit = "dmix_mode"},{"ltrt_cmixlev", "Lt/Rt Center Mix Level", OFFSET(ltrt_center_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, AC3ENC_PARAM},{"ltrt_surmixlev", "Lt/Rt Surround Mix Level", OFFSET(ltrt_surround_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, AC3ENC_PARAM},{"loro_cmixlev", "Lo/Ro Center Mix Level", OFFSET(loro_center_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, AC3ENC_PARAM},{"loro_surmixlev", "Lo/Ro Surround Mix Level", OFFSET(loro_surround_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, AC3ENC_PARAM},{"dsurex_mode", "Dolby Surround EX Mode", OFFSET(dolby_surround_ex_mode), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, AC3ENC_OPT_DSUREX_DPLIIZ, AC3ENC_PARAM, .unit = "dsurex_mode"}, {"notindicated", "Not Indicated (default)", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_NOT_INDICATED }, INT_MIN, INT_MAX, AC3ENC_PARAM, .unit = "dsurex_mode"}, {"on", "Dolby Surround EX Encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_MODE_ON }, INT_MIN, INT_MAX, AC3ENC_PARAM, .unit = "dsurex_mode"}, {"off", "Not Dolby Surround EX Encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_MODE_OFF }, INT_MIN, INT_MAX, AC3ENC_PARAM, .unit = "dsurex_mode"}, {"dpliiz", "Dolby Pro Logic IIz-encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_DSUREX_DPLIIZ }, INT_MIN, INT_MAX, AC3ENC_PARAM, .unit = "dsurex_mode"},{"dheadphone_mode", "Dolby Headphone Mode", OFFSET(dolby_headphone_mode), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, AC3ENC_OPT_MODE_ON, AC3ENC_PARAM, .unit = "dheadphone_mode"}, {"notindicated", "Not Indicated (default)", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_NOT_INDICATED }, INT_MIN, INT_MAX, AC3ENC_PARAM, .unit = "dheadphone_mode"}, {"on", "Dolby Headphone Encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_MODE_ON }, INT_MIN, INT_MAX, AC3ENC_PARAM, .unit = "dheadphone_mode"}, {"off", "Not Dolby Headphone Encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_MODE_OFF }, INT_MIN, INT_MAX, AC3ENC_PARAM, .unit = "dheadphone_mode"},{"ad_conv_type", "A/D Converter Type", OFFSET(ad_converter_type), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, AC3ENC_OPT_ADCONV_HDCD, AC3ENC_PARAM, .unit = "ad_conv_type"}, {"standard", "Standard (default)", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_ADCONV_STANDARD }, INT_MIN, INT_MAX, AC3ENC_PARAM, .unit = "ad_conv_type"}, {"hdcd", "HDCD", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_ADCONV_HDCD }, INT_MIN, INT_MAX, AC3ENC_PARAM, .unit = "ad_conv_type"},/* Other Encoding Options */{"stereo_rematrixing", "Stereo Rematrixing", OFFSET(stereo_rematrixing), AV_OPT_TYPE_BOOL, {.i64 = 1 }, 0, 1, AC3ENC_PARAM},{"channel_coupling", "Channel Coupling", OFFSET(channel_coupling), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_AUTO }, AC3ENC_OPT_AUTO, AC3ENC_OPT_ON, AC3ENC_PARAM, .unit = "channel_coupling"}, {"auto", "Selected by the Encoder", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_AUTO }, INT_MIN, INT_MAX, AC3ENC_PARAM, .unit = "channel_coupling"},{"cpl_start_band", "Coupling Start Band", OFFSET(cpl_start), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_AUTO }, AC3ENC_OPT_AUTO, 15, AC3ENC_PARAM, .unit = "cpl_start_band"}, {"auto", "Selected by the Encoder", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_AUTO }, INT_MIN, INT_MAX, AC3ENC_PARAM, .unit = "cpl_start_band"},{NULL}}; const AVClass ff_ac3enc_class = { .class_name = "AC-3 Encoder", .item_name = av_default_item_name, .option = ff_ac3_enc_options, .version = LIBAVUTIL_VERSION_INT,}; const FFCodecDefault ff_ac3_enc_defaults[] = { { "b", "0" }, { NULL }}; /** * LUT for number of exponent groups. * exponent_group_tab[coupling][exponent strategy-1][number of coefficients] */static uint8_t exponent_group_tab[2][3][256]; /** * List of supported channel layouts. */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 },}; /** * Table to remap channels from SMPTE order to AC-3 order. * [channel_mode][lfe][ch] */static const uint8_t ac3_enc_channel_map[8][2][6] = { COMMON_CHANNEL_MAP { { 0, 1, 2, 3, }, { 0, 1, 3, 4, 2, } }, { { 0, 2, 1, 3, 4, }, { 0, 2, 1, 4, 5, 3 } },}; /** * LUT to select the bandwidth code based on the bit rate, sample rate, and * number of full-bandwidth channels. * bandwidth_tab[fbw_channels-1][sample rate code][bit rate code] */static const uint8_t ac3_bandwidth_tab[5][3][19] = {// 32 40 48 56 64 80 96 112 128 160 192 224 256 320 384 448 512 576 640 { { 0, 0, 0, 12, 16, 32, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48 }, { 0, 0, 0, 16, 20, 36, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56 }, { 0, 0, 0, 32, 40, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60 } }, { { 0, 0, 0, 0, 0, 0, 0, 20, 24, 32, 48, 48, 48, 48, 48, 48, 48, 48, 48 }, { 0, 0, 0, 0, 0, 0, 4, 24, 28, 36, 56, 56, 56, 56, 56, 56, 56, 56, 56 }, { 0, 0, 0, 0, 0, 0, 20, 44, 52, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60 } }, { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 24, 32, 40, 48, 48, 48, 48, 48, 48 }, { 0, 0, 0, 0, 0, 0, 0, 0, 4, 20, 28, 36, 44, 56, 56, 56, 56, 56, 56 }, { 0, 0, 0, 0, 0, 0, 0, 0, 20, 40, 48, 60, 60, 60, 60, 60, 60, 60, 60 } }, { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 24, 32, 48, 48, 48, 48, 48, 48 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 28, 36, 56, 56, 56, 56, 56, 56 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 48, 60, 60, 60, 60, 60, 60, 60 } }, { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 20, 32, 40, 48, 48, 48, 48 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 24, 36, 44, 56, 56, 56, 56 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 44, 60, 60, 60, 60, 60, 60 } }}; /** * LUT to select the coupling start band based on the bit rate, sample rate, and * number of full-bandwidth channels. -1 = coupling off * ac3_coupling_start_tab[channel_mode-2][sample rate code][bit rate code] * * TODO: more testing for optimal parameters. * multi-channel tests at 44.1kHz and 32kHz. */static const int8_t ac3_coupling_start_tab[6][3][19] = {// 32 40 48 56 64 80 96 112 128 160 192 224 256 320 384 448 512 576 640 // 2/0 { { 0, 0, 0, 0, 0, 0, 0, 1, 1, 7, 8, 11, 12, -1, -1, -1, -1, -1, -1 }, { 0, 0, 0, 0, 0, 0, 1, 3, 5, 7, 10, 12, 13, -1, -1, -1, -1, -1, -1 }, { 0, 0, 0, 0, 1, 2, 2, 9, 13, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, // 3/0 { { 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 6, 9, 11, 12, 13, -1, -1, -1, -1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 6, 9, 11, 12, 13, -1, -1, -1, -1 }, { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, // 2/1 - untested { { 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 6, 9, 11, 12, 13, -1, -1, -1, -1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 6, 9, 11, 12, 13, -1, -1, -1, -1 }, { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, // 3/1 { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2, 10, 11, 11, 12, 12, 14, -1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2, 10, 11, 11, 12, 12, 14, -1 }, { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, // 2/2 - untested { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2, 10, 11, 11, 12, 12, 14, -1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2, 10, 11, 11, 12, 12, 14, -1 }, { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, // 3/2 { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 6, 8, 11, 12, 12, -1, -1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 6, 8, 11, 12, 12, -1, -1 }, { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } },}; #define FLT_OPTION_THRESHOLD 0.01 static int validate_float_option(float v, const float *v_list, int v_list_size){ int i; for (i = 0; i < v_list_size; i++) { if (v < (v_list[i] + FLT_OPTION_THRESHOLD) && v > (v_list[i] - FLT_OPTION_THRESHOLD)) break; } if (i == v_list_size) return AVERROR(EINVAL); return i;} static void validate_mix_level(void *log_ctx, const char *opt_name, float *opt_param, const float *list, int list_size, int default_value, int min_value, int *ctx_param){ int mixlev = validate_float_option(*opt_param, list, list_size); if (mixlev < min_value) { mixlev = default_value; if (*opt_param >= 0.0) { av_log(log_ctx, AV_LOG_WARNING, "requested %s is not valid. using " "default value: %0.3f\n", opt_name, list[mixlev]); } } *opt_param = list[mixlev]; *ctx_param = mixlev;} /** * Validate metadata options as set by AVOption system. * These values can optionally be changed per-frame. * * @param s AC-3 encoder private context */static int ac3_validate_metadata(AC3EncodeContext *s){ AVCodecContext *avctx = s->avctx; AC3EncOptions *opt = &s->options; 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 != AC3ENC_OPT_NONE) { 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 && (opt->ltrt_surround_mix_level >= 0 || opt->loro_surround_mix_level >= 0)) { opt->extended_bsi_1 = 1; opt->eac3_mixing_metadata = 1; } 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 != AC3ENC_OPT_NONE || opt->original != AC3ENC_OPT_NONE) opt->eac3_info_metadata = 1; if (s->channel_mode == AC3_CHMODE_STEREO && (opt->dolby_headphone_mode != AC3ENC_OPT_NONE || opt->dolby_surround_mode != AC3ENC_OPT_NONE)) opt->eac3_info_metadata = 1; if (s->channel_mode >= AC3_CHMODE_2F2R && opt->dolby_surround_ex_mode != AC3ENC_OPT_NONE) opt->eac3_info_metadata = 1; if (opt->mixing_level != AC3ENC_OPT_NONE || opt->room_type != AC3ENC_OPT_NONE || opt->ad_converter_type != AC3ENC_OPT_NONE) { opt->audio_production_info = 1; opt->eac3_info_metadata = 1; } } else { /* determine audio production info use */ if (opt->mixing_level != AC3ENC_OPT_NONE || opt->room_type != AC3ENC_OPT_NONE) opt->audio_production_info = 1; /* determine xbsi2 use */ if (s->channel_mode >= AC3_CHMODE_2F2R && opt->dolby_surround_ex_mode != AC3ENC_OPT_NONE) opt->extended_bsi_2 = 1; if (s->channel_mode == AC3_CHMODE_STEREO && opt->dolby_headphone_mode != AC3ENC_OPT_NONE) opt->extended_bsi_2 = 1; if (opt->ad_converter_type != AC3ENC_OPT_NONE) opt->extended_bsi_2 = 1; } /* 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 == AC3ENC_OPT_NONE) opt->preferred_stereo_downmix = AC3ENC_OPT_NOT_INDICATED; 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); } } /* validate audio service type / channels combination */ if ((avctx->audio_service_type == AV_AUDIO_SERVICE_TYPE_KARAOKE && 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->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); } /* validate extended bsi 2 / info metadata */ if (opt->extended_bsi_2 || opt->eac3_info_metadata) { /* default dolby headphone mode */ if (opt->dolby_headphone_mode == AC3ENC_OPT_NONE) opt->dolby_headphone_mode = AC3ENC_OPT_NOT_INDICATED; /* default dolby surround ex mode */ if (opt->dolby_surround_ex_mode == AC3ENC_OPT_NONE) opt->dolby_surround_ex_mode = AC3ENC_OPT_NOT_INDICATED; /* default A/D converter type */ if (opt->ad_converter_type == AC3ENC_OPT_NONE) opt->ad_converter_type = AC3ENC_OPT_ADCONV_STANDARD; } /* copyright & original defaults */ if (!s->eac3 || opt->eac3_info_metadata) { /* default copyright */ if (opt->copyright == AC3ENC_OPT_NONE) opt->copyright = AC3ENC_OPT_OFF; /* default original */ if (opt->original == AC3ENC_OPT_NONE) opt->original = AC3ENC_OPT_ON; } /* dolby surround mode default */ if (!s->eac3 || opt->eac3_info_metadata) { if (opt->dolby_surround_mode == AC3ENC_OPT_NONE) opt->dolby_surround_mode = AC3ENC_OPT_NOT_INDICATED; } /* validate audio production info */ if (opt->audio_production_info) { if (opt->mixing_level == AC3ENC_OPT_NONE) { 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 == AC3ENC_OPT_NONE) opt->room_type = AC3ENC_OPT_NOT_INDICATED; } /* set bitstream id for alternate bitstream syntax */ if (!s->eac3 && (opt->extended_bsi_1 || opt->extended_bsi_2)) s->bitstream_id = 6; return 0;} /** * Adjust the frame size to make the average bit rate match the target bit rate. * This is only needed for 11025, 22050, and 44100 sample rates or any E-AC-3. * * @param s AC-3 encoder private context */static void ac3_adjust_frame_size(AC3EncodeContext *s){ while (s->bits_written >= s->bit_rate && s->samples_written >= s->sample_rate) { s->bits_written -= s->bit_rate; s->samples_written -= s->sample_rate; } s->frame_size = s->frame_size_min +Lines 1–500 of 2526. Load more
/* * The simplest AC-3 encoder * Copyright (c) 2000 Fabrice Bellard * Copyright (c) 2006-2010 Justin Ruggles <justin.ruggles@gmail.com> * Copyright (c) 2006-2010 Prakash Punnoor <prakash@punnoor.de> * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /** * @file * The simplest AC-3 encoder. */ #include <stdint.h> #include "libavutil/attributes.h" #include "libavutil/avassert.h" #include "libavutil/channel_layout.h" #include "libavutil/crc.h" #include "libavutil/emms.h" #include "libavutil/internal.h" #include "libavutil/mem.h" #include "libavutil/mem_internal.h" #include "libavutil/opt.h" #include "libavutil/thread.h" #include "avcodec.h" #include "codec_internal.h" #include "config_components.h" #include "encode.h" #include "me_cmp.h" #include "put_bits.h" #include "audiodsp.h" #include "ac3dsp.h" #include "ac3.h" #include "ac3defs.h" #include "ac3tab.h" #include "ac3enc.h" #include "eac3enc.h" #define SAMPLETYPE_SIZE(ctx) (sizeof(float) == sizeof(int32_t) ? sizeof(float) : \ (ctx)->fixed_point ? sizeof(int32_t) : sizeof(float)) typedef struct AC3Mant { int16_t *qmant1_ptr, *qmant2_ptr, *qmant4_ptr; ///< mantissa pointers for bap=1,2,4 int mant1_cnt, mant2_cnt, mant4_cnt; ///< mantissa counts for bap=1,2,4 } AC3Mant; #define CMIXLEV_NUM_OPTIONS 3 static const float cmixlev_options[CMIXLEV_NUM_OPTIONS] = { LEVEL_MINUS_3DB, LEVEL_MINUS_4POINT5DB, LEVEL_MINUS_6DB }; #define SURMIXLEV_NUM_OPTIONS 3 static const float surmixlev_options[SURMIXLEV_NUM_OPTIONS] = { LEVEL_MINUS_3DB, LEVEL_MINUS_6DB, LEVEL_ZERO }; #define EXTMIXLEV_NUM_OPTIONS 8 static const float extmixlev_options[EXTMIXLEV_NUM_OPTIONS] = { LEVEL_PLUS_3DB, LEVEL_PLUS_1POINT5DB, LEVEL_ONE, LEVEL_MINUS_1POINT5DB, LEVEL_MINUS_3DB, LEVEL_MINUS_4POINT5DB, LEVEL_MINUS_6DB, LEVEL_ZERO }; /* The first two options apply only to the AC-3 encoders; * the rest is also valid for EAC-3. When modifying it, * it might be necessary to adapt said offset in eac3enc.c. */ #define OFFSET(param) offsetof(AC3EncodeContext, options.param) #define AC3ENC_PARAM (AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM) const AVOption ff_ac3_enc_options[] = { /* AC-3 downmix levels */ {"center_mixlev", "Center Mix Level", OFFSET(center_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = LEVEL_MINUS_4POINT5DB }, 0.0, 1.0, AC3ENC_PARAM}, {"surround_mixlev", "Surround Mix Level", OFFSET(surround_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = LEVEL_MINUS_6DB }, 0.0, 1.0, AC3ENC_PARAM}, /* audio production information */ {"mixing_level", "Mixing Level", OFFSET(mixing_level), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, 111, AC3ENC_PARAM}, {"room_type", "Room Type", OFFSET(room_type), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, AC3ENC_OPT_SMALL_ROOM, AC3ENC_PARAM, .unit = "room_type"}, {"notindicated", "Not Indicated (default)", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_NOT_INDICATED }, INT_MIN, INT_MAX, AC3ENC_PARAM, .unit = "room_type"}, {"large", "Large Room", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_LARGE_ROOM }, INT_MIN, INT_MAX, AC3ENC_PARAM, .unit = "room_type"}, {"small", "Small Room", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_SMALL_ROOM }, INT_MIN, INT_MAX, AC3ENC_PARAM, .unit = "room_type"}, /* Metadata Options */ {"per_frame_metadata", "Allow Changing Metadata Per-Frame", OFFSET(allow_per_frame_metadata), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, AC3ENC_PARAM}, {"copyright", "Copyright Bit", OFFSET(copyright), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, 1, AC3ENC_PARAM}, {"dialnorm", "Dialogue Level (dB)", OFFSET(dialogue_level), AV_OPT_TYPE_INT, {.i64 = -31 }, -31, -1, AC3ENC_PARAM}, {"dsur_mode", "Dolby Surround Mode", OFFSET(dolby_surround_mode), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, AC3ENC_OPT_MODE_ON, AC3ENC_PARAM, .unit = "dsur_mode"}, {"notindicated", "Not Indicated (default)", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_NOT_INDICATED }, INT_MIN, INT_MAX, AC3ENC_PARAM, .unit = "dsur_mode"}, {"on", "Dolby Surround Encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_MODE_ON }, INT_MIN, INT_MAX, AC3ENC_PARAM, .unit = "dsur_mode"}, {"off", "Not Dolby Surround Encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_MODE_OFF }, INT_MIN, INT_MAX, AC3ENC_PARAM, .unit = "dsur_mode"}, {"original", "Original Bit Stream", OFFSET(original), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, 1, AC3ENC_PARAM}, /* extended bitstream information */ {"dmix_mode", "Preferred Stereo Downmix Mode", OFFSET(preferred_stereo_downmix), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, AC3ENC_OPT_DOWNMIX_DPLII, AC3ENC_PARAM, .unit = "dmix_mode"}, {"notindicated", "Not Indicated (default)", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_NOT_INDICATED }, INT_MIN, INT_MAX, AC3ENC_PARAM, .unit = "dmix_mode"}, {"ltrt", "Lt/Rt Downmix Preferred", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_DOWNMIX_LTRT }, INT_MIN, INT_MAX, AC3ENC_PARAM, .unit = "dmix_mode"}, {"loro", "Lo/Ro Downmix Preferred", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_DOWNMIX_LORO }, INT_MIN, INT_MAX, AC3ENC_PARAM, .unit = "dmix_mode"}, {"dplii", "Dolby Pro Logic II Downmix Preferred", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_DOWNMIX_DPLII }, INT_MIN, INT_MAX, AC3ENC_PARAM, .unit = "dmix_mode"}, {"ltrt_cmixlev", "Lt/Rt Center Mix Level", OFFSET(ltrt_center_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, AC3ENC_PARAM}, {"ltrt_surmixlev", "Lt/Rt Surround Mix Level", OFFSET(ltrt_surround_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, AC3ENC_PARAM}, {"loro_cmixlev", "Lo/Ro Center Mix Level", OFFSET(loro_center_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, AC3ENC_PARAM}, {"loro_surmixlev", "Lo/Ro Surround Mix Level", OFFSET(loro_surround_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, AC3ENC_PARAM}, {"dsurex_mode", "Dolby Surround EX Mode", OFFSET(dolby_surround_ex_mode), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, AC3ENC_OPT_DSUREX_DPLIIZ, AC3ENC_PARAM, .unit = "dsurex_mode"}, {"notindicated", "Not Indicated (default)", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_NOT_INDICATED }, INT_MIN, INT_MAX, AC3ENC_PARAM, .unit = "dsurex_mode"}, {"on", "Dolby Surround EX Encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_MODE_ON }, INT_MIN, INT_MAX, AC3ENC_PARAM, .unit = "dsurex_mode"}, {"off", "Not Dolby Surround EX Encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_MODE_OFF }, INT_MIN, INT_MAX, AC3ENC_PARAM, .unit = "dsurex_mode"}, {"dpliiz", "Dolby Pro Logic IIz-encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_DSUREX_DPLIIZ }, INT_MIN, INT_MAX, AC3ENC_PARAM, .unit = "dsurex_mode"}, {"dheadphone_mode", "Dolby Headphone Mode", OFFSET(dolby_headphone_mode), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, AC3ENC_OPT_MODE_ON, AC3ENC_PARAM, .unit = "dheadphone_mode"}, {"notindicated", "Not Indicated (default)", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_NOT_INDICATED }, INT_MIN, INT_MAX, AC3ENC_PARAM, .unit = "dheadphone_mode"}, {"on", "Dolby Headphone Encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_MODE_ON }, INT_MIN, INT_MAX, AC3ENC_PARAM, .unit = "dheadphone_mode"}, {"off", "Not Dolby Headphone Encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_MODE_OFF }, INT_MIN, INT_MAX, AC3ENC_PARAM, .unit = "dheadphone_mode"}, {"ad_conv_type", "A/D Converter Type", OFFSET(ad_converter_type), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, AC3ENC_OPT_ADCONV_HDCD, AC3ENC_PARAM, .unit = "ad_conv_type"}, {"standard", "Standard (default)", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_ADCONV_STANDARD }, INT_MIN, INT_MAX, AC3ENC_PARAM, .unit = "ad_conv_type"}, {"hdcd", "HDCD", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_ADCONV_HDCD }, INT_MIN, INT_MAX, AC3ENC_PARAM, .unit = "ad_conv_type"}, /* Other Encoding Options */ {"stereo_rematrixing", "Stereo Rematrixing", OFFSET(stereo_rematrixing), AV_OPT_TYPE_BOOL, {.i64 = 1 }, 0, 1, AC3ENC_PARAM}, {"channel_coupling", "Channel Coupling", OFFSET(channel_coupling), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_AUTO }, AC3ENC_OPT_AUTO, AC3ENC_OPT_ON, AC3ENC_PARAM, .unit = "channel_coupling"}, {"auto", "Selected by the Encoder", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_AUTO }, INT_MIN, INT_MAX, AC3ENC_PARAM, .unit = "channel_coupling"}, {"cpl_start_band", "Coupling Start Band", OFFSET(cpl_start), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_AUTO }, AC3ENC_OPT_AUTO, 15, AC3ENC_PARAM, .unit = "cpl_start_band"}, {"auto", "Selected by the Encoder", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_AUTO }, INT_MIN, INT_MAX, AC3ENC_PARAM, .unit = "cpl_start_band"}, {NULL} }; const AVClass ff_ac3enc_class = { .class_name = "AC-3 Encoder", .item_name = av_default_item_name, .option = ff_ac3_enc_options, .version = LIBAVUTIL_VERSION_INT, }; const FFCodecDefault ff_ac3_enc_defaults[] = { { "b", "0" }, { NULL } }; /** * LUT for number of exponent groups. * exponent_group_tab[coupling][exponent strategy-1][number of coefficients] */ static uint8_t exponent_group_tab[2][3][256]; /** * List of supported channel layouts. */ 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 }, }; /** * Table to remap channels from SMPTE order to AC-3 order. * [channel_mode][lfe][ch] */ static const uint8_t ac3_enc_channel_map[8][2][6] = { COMMON_CHANNEL_MAP { { 0, 1, 2, 3, }, { 0, 1, 3, 4, 2, } }, { { 0, 2, 1, 3, 4, }, { 0, 2, 1, 4, 5, 3 } }, }; /** * LUT to select the bandwidth code based on the bit rate, sample rate, and * number of full-bandwidth channels. * bandwidth_tab[fbw_channels-1][sample rate code][bit rate code] */ static const uint8_t ac3_bandwidth_tab[5][3][19] = { // 32 40 48 56 64 80 96 112 128 160 192 224 256 320 384 448 512 576 640 { { 0, 0, 0, 12, 16, 32, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48 }, { 0, 0, 0, 16, 20, 36, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56 }, { 0, 0, 0, 32, 40, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60 } }, { { 0, 0, 0, 0, 0, 0, 0, 20, 24, 32, 48, 48, 48, 48, 48, 48, 48, 48, 48 }, { 0, 0, 0, 0, 0, 0, 4, 24, 28, 36, 56, 56, 56, 56, 56, 56, 56, 56, 56 }, { 0, 0, 0, 0, 0, 0, 20, 44, 52, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60 } }, { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 24, 32, 40, 48, 48, 48, 48, 48, 48 }, { 0, 0, 0, 0, 0, 0, 0, 0, 4, 20, 28, 36, 44, 56, 56, 56, 56, 56, 56 }, { 0, 0, 0, 0, 0, 0, 0, 0, 20, 40, 48, 60, 60, 60, 60, 60, 60, 60, 60 } }, { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 24, 32, 48, 48, 48, 48, 48, 48 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 28, 36, 56, 56, 56, 56, 56, 56 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 48, 60, 60, 60, 60, 60, 60, 60 } }, { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 20, 32, 40, 48, 48, 48, 48 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 24, 36, 44, 56, 56, 56, 56 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 44, 60, 60, 60, 60, 60, 60 } } }; /** * LUT to select the coupling start band based on the bit rate, sample rate, and * number of full-bandwidth channels. -1 = coupling off * ac3_coupling_start_tab[channel_mode-2][sample rate code][bit rate code] * * TODO: more testing for optimal parameters. * multi-channel tests at 44.1kHz and 32kHz. */ static const int8_t ac3_coupling_start_tab[6][3][19] = { // 32 40 48 56 64 80 96 112 128 160 192 224 256 320 384 448 512 576 640 // 2/0 { { 0, 0, 0, 0, 0, 0, 0, 1, 1, 7, 8, 11, 12, -1, -1, -1, -1, -1, -1 }, { 0, 0, 0, 0, 0, 0, 1, 3, 5, 7, 10, 12, 13, -1, -1, -1, -1, -1, -1 }, { 0, 0, 0, 0, 1, 2, 2, 9, 13, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, // 3/0 { { 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 6, 9, 11, 12, 13, -1, -1, -1, -1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 6, 9, 11, 12, 13, -1, -1, -1, -1 }, { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, // 2/1 - untested { { 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 6, 9, 11, 12, 13, -1, -1, -1, -1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 6, 9, 11, 12, 13, -1, -1, -1, -1 }, { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, // 3/1 { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2, 10, 11, 11, 12, 12, 14, -1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2, 10, 11, 11, 12, 12, 14, -1 }, { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, // 2/2 - untested { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2, 10, 11, 11, 12, 12, 14, -1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2, 10, 11, 11, 12, 12, 14, -1 }, { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, // 3/2 { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 6, 8, 11, 12, 12, -1, -1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 6, 8, 11, 12, 12, -1, -1 }, { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, }; #define FLT_OPTION_THRESHOLD 0.01 static int validate_float_option(float v, const float *v_list, int v_list_size) { int i; for (i = 0; i < v_list_size; i++) { if (v < (v_list[i] + FLT_OPTION_THRESHOLD) && v > (v_list[i] - FLT_OPTION_THRESHOLD)) break; } if (i == v_list_size) return AVERROR(EINVAL); return i; } static void validate_mix_level(void *log_ctx, const char *opt_name, float *opt_param, const float *list, int list_size, int default_value, int min_value, int *ctx_param) { int mixlev = validate_float_option(*opt_param, list, list_size); if (mixlev < min_value) { mixlev = default_value; if (*opt_param >= 0.0) { av_log(log_ctx, AV_LOG_WARNING, "requested %s is not valid. using " "default value: %0.3f\n", opt_name, list[mixlev]); } } *opt_param = list[mixlev]; *ctx_param = mixlev; } /** * Validate metadata options as set by AVOption system. * These values can optionally be changed per-frame. * * @param s AC-3 encoder private context */ static int ac3_validate_metadata(AC3EncodeContext *s) { AVCodecContext *avctx = s->avctx; AC3EncOptions *opt = &s->options; 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 != AC3ENC_OPT_NONE) { 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 && (opt->ltrt_surround_mix_level >= 0 || opt->loro_surround_mix_level >= 0)) { opt->extended_bsi_1 = 1; opt->eac3_mixing_metadata = 1; } 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 != AC3ENC_OPT_NONE || opt->original != AC3ENC_OPT_NONE) opt->eac3_info_metadata = 1; if (s->channel_mode == AC3_CHMODE_STEREO && (opt->dolby_headphone_mode != AC3ENC_OPT_NONE || opt->dolby_surround_mode != AC3ENC_OPT_NONE)) opt->eac3_info_metadata = 1; if (s->channel_mode >= AC3_CHMODE_2F2R && opt->dolby_surround_ex_mode != AC3ENC_OPT_NONE) opt->eac3_info_metadata = 1; if (opt->mixing_level != AC3ENC_OPT_NONE || opt->room_type != AC3ENC_OPT_NONE || opt->ad_converter_type != AC3ENC_OPT_NONE) { opt->audio_production_info = 1; opt->eac3_info_metadata = 1; } } else { /* determine audio production info use */ if (opt->mixing_level != AC3ENC_OPT_NONE || opt->room_type != AC3ENC_OPT_NONE) opt->audio_production_info = 1; /* determine xbsi2 use */ if (s->channel_mode >= AC3_CHMODE_2F2R && opt->dolby_surround_ex_mode != AC3ENC_OPT_NONE) opt->extended_bsi_2 = 1; if (s->channel_mode == AC3_CHMODE_STEREO && opt->dolby_headphone_mode != AC3ENC_OPT_NONE) opt->extended_bsi_2 = 1; if (opt->ad_converter_type != AC3ENC_OPT_NONE) opt->extended_bsi_2 = 1; } /* 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 == AC3ENC_OPT_NONE) opt->preferred_stereo_downmix = AC3ENC_OPT_NOT_INDICATED; 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); } } /* validate audio service type / channels combination */ if ((avctx->audio_service_type == AV_AUDIO_SERVICE_TYPE_KARAOKE && 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->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); } /* validate extended bsi 2 / info metadata */ if (opt->extended_bsi_2 || opt->eac3_info_metadata) { /* default dolby headphone mode */ if (opt->dolby_headphone_mode == AC3ENC_OPT_NONE) opt->dolby_headphone_mode = AC3ENC_OPT_NOT_INDICATED; /* default dolby surround ex mode */ if (opt->dolby_surround_ex_mode == AC3ENC_OPT_NONE) opt->dolby_surround_ex_mode = AC3ENC_OPT_NOT_INDICATED; /* default A/D converter type */ if (opt->ad_converter_type == AC3ENC_OPT_NONE) opt->ad_converter_type = AC3ENC_OPT_ADCONV_STANDARD; } /* copyright & original defaults */ if (!s->eac3 || opt->eac3_info_metadata) { /* default copyright */ if (opt->copyright == AC3ENC_OPT_NONE) opt->copyright = AC3ENC_OPT_OFF; /* default original */ if (opt->original == AC3ENC_OPT_NONE) opt->original = AC3ENC_OPT_ON; } /* dolby surround mode default */ if (!s->eac3 || opt->eac3_info_metadata) { if (opt->dolby_surround_mode == AC3ENC_OPT_NONE) opt->dolby_surround_mode = AC3ENC_OPT_NOT_INDICATED; } /* validate audio production info */ if (opt->audio_production_info) { if (opt->mixing_level == AC3ENC_OPT_NONE) { 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 == AC3ENC_OPT_NONE) opt->room_type = AC3ENC_OPT_NOT_INDICATED; } /* set bitstream id for alternate bitstream syntax */ if (!s->eac3 && (opt->extended_bsi_1 || opt->extended_bsi_2)) s->bitstream_id = 6; return 0; } /** * Adjust the frame size to make the average bit rate match the target bit rate. * This is only needed for 11025, 22050, and 44100 sample rates or any E-AC-3. * * @param s AC-3 encoder private context */ static void ac3_adjust_frame_size(AC3EncodeContext *s) { while (s->bits_written >= s->bit_rate && s->samples_written >= s->sample_rate) { s->bits_written -= s->bit_rate; s->samples_written -= s->sample_rate; } s->frame_size = s->frame_size_min +