Newer
Older
* 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 Libav.
Diego Biurrun
committed
*
* Libav 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
Diego Biurrun
committed
* version 2.1 of the License, or (at your option) any later version.
* Libav 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 Libav; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* The simplest AC-3 encoder.
//#define ASSERT_LEVEL 2
#include "libavutil/avassert.h"
#include "libavutil/crc.h"
#include "libavutil/opt.h"
#include "put_bits.h"
#include "dsputil.h"
#include "audioconvert.h"
#include "ac3enc.h"
#include "eac3enc.h"
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_4POINT5DB,
LEVEL_MINUS_3DB, LEVEL_MINUS_4POINT5DB, LEVEL_MINUS_6DB, LEVEL_ZERO
};
/**
* 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 int64_t ff_ac3_channel_layouts[19] = {
AV_CH_LAYOUT_MONO,
AV_CH_LAYOUT_STEREO,
AV_CH_LAYOUT_2_1,
AV_CH_LAYOUT_SURROUND,
AV_CH_LAYOUT_2_2,
AV_CH_LAYOUT_QUAD,
AV_CH_LAYOUT_4POINT0,
AV_CH_LAYOUT_5POINT0,
AV_CH_LAYOUT_5POINT0_BACK,
(AV_CH_LAYOUT_MONO | AV_CH_LOW_FREQUENCY),
(AV_CH_LAYOUT_STEREO | AV_CH_LOW_FREQUENCY),
(AV_CH_LAYOUT_2_1 | AV_CH_LOW_FREQUENCY),
(AV_CH_LAYOUT_SURROUND | AV_CH_LOW_FREQUENCY),
(AV_CH_LAYOUT_2_2 | AV_CH_LOW_FREQUENCY),
(AV_CH_LAYOUT_QUAD | AV_CH_LOW_FREQUENCY),
(AV_CH_LAYOUT_4POINT0 | AV_CH_LOW_FREQUENCY),
AV_CH_LAYOUT_5POINT1,
AV_CH_LAYOUT_5POINT1_BACK,
0
};
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/**
* 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 } }
};
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
/**
* 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 } },
};
/**
* 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.
void ff_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 +
2 * (s->bits_written * s->sample_rate < s->samples_written * s->bit_rate);
s->bits_written += s->frame_size * 8;
Justin Ruggles
committed
s->samples_written += AC3_BLOCK_SIZE * s->num_blocks;
void ff_ac3_compute_coupling_strategy(AC3EncodeContext *s)
{
int blk, ch;
int got_cpl_snr;
int num_cpl_blocks;
/* set coupling use flags for each block/channel */
/* TODO: turn coupling on/off and adjust start band based on bit usage */
Justin Ruggles
committed
for (blk = 0; blk < s->num_blocks; blk++) {
AC3Block *block = &s->blocks[blk];
for (ch = 1; ch <= s->fbw_channels; ch++)
block->channel_in_cpl[ch] = s->cpl_on;
}
/* enable coupling for each block if at least 2 channels have coupling
enabled for that block */
got_cpl_snr = 0;
num_cpl_blocks = 0;
Justin Ruggles
committed
for (blk = 0; blk < s->num_blocks; blk++) {
AC3Block *block = &s->blocks[blk];
block->num_cpl_channels = 0;
for (ch = 1; ch <= s->fbw_channels; ch++)
block->num_cpl_channels += block->channel_in_cpl[ch];
block->cpl_in_use = block->num_cpl_channels > 1;
num_cpl_blocks += block->cpl_in_use;
if (!block->cpl_in_use) {
block->num_cpl_channels = 0;
for (ch = 1; ch <= s->fbw_channels; ch++)
block->channel_in_cpl[ch] = 0;
}
block->new_cpl_strategy = !blk;
if (blk) {
for (ch = 1; ch <= s->fbw_channels; ch++) {
if (block->channel_in_cpl[ch] != s->blocks[blk-1].channel_in_cpl[ch]) {
block->new_cpl_strategy = 1;
break;
}
}
}
block->new_cpl_leak = block->new_cpl_strategy;
if (!blk || (block->cpl_in_use && !got_cpl_snr)) {
block->new_snr_offsets = 1;
if (block->cpl_in_use)
got_cpl_snr = 1;
} else {
block->new_snr_offsets = 0;
}
}
if (!num_cpl_blocks)
s->cpl_on = 0;
/* set bandwidth for each channel */
Justin Ruggles
committed
for (blk = 0; blk < s->num_blocks; blk++) {
AC3Block *block = &s->blocks[blk];
for (ch = 1; ch <= s->fbw_channels; ch++) {
if (block->channel_in_cpl[ch])
block->end_freq[ch] = s->start_freq[CPL_CH];
else
block->end_freq[ch] = s->bandwidth_code * 3 + 73;
}
}
}
/**
* Apply stereo rematrixing to coefficients based on rematrixing flags.
*/
void ff_ac3_apply_rematrixing(AC3EncodeContext *s)
{
int nb_coefs;
int blk, bnd, i;
int start, end;
uint8_t *flags;
if (!s->rematrixing_enabled)
Justin Ruggles
committed
for (blk = 0; blk < s->num_blocks; blk++) {
AC3Block *block = &s->blocks[blk];
if (block->new_rematrixing_strategy)
flags = block->rematrixing_flags;
nb_coefs = FFMIN(block->end_freq[1], block->end_freq[2]);
for (bnd = 0; bnd < block->num_rematrixing_bands; bnd++) {
if (flags[bnd]) {
start = ff_ac3_rematrix_band_tab[bnd];
end = FFMIN(nb_coefs, ff_ac3_rematrix_band_tab[bnd+1]);
for (i = start; i < end; i++) {
int32_t lt = block->fixed_coef[1][i];
int32_t rt = block->fixed_coef[2][i];
block->fixed_coef[1][i] = (lt + rt) >> 1;
block->fixed_coef[2][i] = (lt - rt) >> 1;
}
}
}
}
}
/**
* Initialize exponent tables.
*/
static av_cold void exponent_init(AC3EncodeContext *s)
{
int expstr, i, grpsize;
for (expstr = EXP_D15-1; expstr <= EXP_D45-1; expstr++) {
grpsize = 3 << expstr;
for (i = 12; i < 256; i++) {
exponent_group_tab[0][expstr][i] = (i + grpsize - 4) / grpsize;
exponent_group_tab[1][expstr][i] = (i ) / grpsize;
}
}
if (CONFIG_EAC3_ENCODER && s->eac3)
ff_eac3_exponent_init();
}
/**
* Extract exponents from the MDCT coefficients.
*/
static void extract_exponents(AC3EncodeContext *s)
int ch = !s->cpl_on;
Justin Ruggles
committed
int chan_size = AC3_MAX_COEFS * s->num_blocks * (s->channels - ch + 1);
AC3Block *block = &s->blocks[0];
s->ac3dsp.extract_exponents(block->exp[ch], block->fixed_coef[ch], chan_size);
Justin Ruggles
committed
/**
* Exponent Difference Threshold.
* New exponents are sent if their SAD exceed this number.
*/
#define EXP_DIFF_THRESHOLD 500
Justin Ruggles
committed
/**
* Table used to select exponent strategy based on exponent reuse block interval.
*/
static const uint8_t exp_strategy_reuse_tab[4][6] = {
{ EXP_D15, EXP_D15, EXP_D15, EXP_D15, EXP_D15, EXP_D15 },
{ EXP_D15, EXP_D15, EXP_D15, EXP_D15, EXP_D15, EXP_D15 },
{ EXP_D25, EXP_D25, EXP_D15, EXP_D15, EXP_D15, EXP_D15 },
{ EXP_D45, EXP_D25, EXP_D25, EXP_D15, EXP_D15, EXP_D15 }
};
/**
* Calculate exponent strategies for all channels.
* Array arrangement is reversed to simplify the per-channel calculation.
static void compute_exp_strategy(AC3EncodeContext *s)
int ch, blk, blk1;
for (ch = !s->cpl_on; ch <= s->fbw_channels; ch++) {
uint8_t *exp_strategy = s->exp_strategy[ch];
uint8_t *exp = s->blocks[0].exp[ch];
int exp_diff;
/* estimate if the exponent variation & decide if they should be
reused in the next frame */
exp_strategy[0] = EXP_NEW;
exp += AC3_MAX_COEFS;
Justin Ruggles
committed
for (blk = 1; blk < s->num_blocks; blk++, exp += AC3_MAX_COEFS) {
if (ch == CPL_CH) {
if (!s->blocks[blk-1].cpl_in_use) {
exp_strategy[blk] = EXP_NEW;
continue;
} else if (!s->blocks[blk].cpl_in_use) {
exp_strategy[blk] = EXP_REUSE;
continue;
}
} else if (s->blocks[blk].channel_in_cpl[ch] != s->blocks[blk-1].channel_in_cpl[ch]) {
exp_strategy[blk] = EXP_NEW;
continue;
}
exp_diff = s->dsp.sad[0](NULL, exp, exp - AC3_MAX_COEFS, 16, 16);
exp_strategy[blk] = EXP_REUSE;
if (ch == CPL_CH && exp_diff > (EXP_DIFF_THRESHOLD * (s->blocks[blk].end_freq[ch] - s->start_freq[ch]) / AC3_MAX_COEFS))
exp_strategy[blk] = EXP_NEW;
else if (ch > CPL_CH && exp_diff > EXP_DIFF_THRESHOLD)
exp_strategy[blk] = EXP_NEW;
}
/* now select the encoding strategy type : if exponents are often
recoded, we use a coarse encoding */
blk = 0;
Justin Ruggles
committed
while (blk < s->num_blocks) {
blk1 = blk + 1;
Justin Ruggles
committed
while (blk1 < s->num_blocks && exp_strategy[blk1] == EXP_REUSE)
blk1++;
Justin Ruggles
committed
exp_strategy[blk] = exp_strategy_reuse_tab[s->num_blks_code][blk1-blk-1];
blk = blk1;
}
}
if (s->lfe_on) {
ch = s->lfe_channel;
s->exp_strategy[ch][0] = EXP_D15;
Justin Ruggles
committed
for (blk = 1; blk < s->num_blocks; blk++)
s->exp_strategy[ch][blk] = EXP_REUSE;
/* for E-AC-3, determine frame exponent strategy */
if (CONFIG_EAC3_ENCODER && s->eac3)
ff_eac3_get_frame_exp_strategy(s);
Justin Ruggles
committed
/**
* Update the exponents so that they are the ones the decoder will decode.
*/
static void encode_exponents_blk_ch(uint8_t *exp, int nb_exps, int exp_strategy,
int cpl)
int nb_groups, i, k;
nb_groups = exponent_group_tab[cpl][exp_strategy-1][nb_exps] * 3;
/* for each group, compute the minimum exponent */
Justin Ruggles
committed
switch(exp_strategy) {
case EXP_D25:
for (i = 1, k = 1-cpl; i <= nb_groups; i++) {
Justin Ruggles
committed
uint8_t exp_min = exp[k];
if (exp[k+1] < exp_min)
exp_min = exp[k+1];
Justin Ruggles
committed
k += 2;
Justin Ruggles
committed
break;
case EXP_D45:
for (i = 1, k = 1-cpl; i <= nb_groups; i++) {
Justin Ruggles
committed
uint8_t exp_min = exp[k];
if (exp[k+1] < exp_min)
exp_min = exp[k+1];
if (exp[k+2] < exp_min)
exp_min = exp[k+2];
if (exp[k+3] < exp_min)
exp_min = exp[k+3];
Justin Ruggles
committed
k += 4;
}
break;
}
exp[0] = 15;
/* decrease the delta between each groups to within 2 so that they can be
differentially encoded */
for (i = 1; i <= nb_groups; i++)
exp[i] = FFMIN(exp[i], exp[i-1] + 2);
Justin Ruggles
committed
i--;
while (--i >= 0)
exp[i] = FFMIN(exp[i], exp[i+1] + 2);
Jeff Muizelaar
committed
if (cpl)
exp[-1] = exp[0] & ~1;
/* now we have the exponent values the decoder will see */
Justin Ruggles
committed
switch (exp_strategy) {
case EXP_D25:
for (i = nb_groups, k = (nb_groups * 2)-cpl; i > 0; i--) {
uint8_t exp1 = exp[i-cpl];
Justin Ruggles
committed
exp[k--] = exp1;
exp[k--] = exp1;
}
break;
case EXP_D45:
for (i = nb_groups, k = (nb_groups * 4)-cpl; i > 0; i--) {
exp[k] = exp[k-1] = exp[k-2] = exp[k-3] = exp[i-cpl];
Justin Ruggles
committed
k -= 4;
}
break;
/**
* Encode exponents from original extracted form to what the decoder will see.
* This copies and groups exponents based on exponent strategy and reduces
* deltas between adjacent exponent groups so that they can be differentially
* encoded.
*/
static void encode_exponents(AC3EncodeContext *s)
uint8_t *exp, *exp_strategy;
int nb_coefs, num_reuse_blocks;
for (ch = !s->cpl_on; ch <= s->channels; ch++) {
exp = s->blocks[0].exp[ch] + s->start_freq[ch];
exp_strategy = s->exp_strategy[ch];
Justin Ruggles
committed
while (blk < s->num_blocks) {
AC3Block *block = &s->blocks[blk];
if (cpl && !block->cpl_in_use) {
exp += AC3_MAX_COEFS;
blk++;
continue;
}
nb_coefs = block->end_freq[ch] - s->start_freq[ch];
/* count the number of EXP_REUSE blocks after the current block
Justin Ruggles
committed
and set exponent reference block numbers */
s->exp_ref_block[ch][blk] = blk;
Justin Ruggles
committed
while (blk1 < s->num_blocks && exp_strategy[blk1] == EXP_REUSE) {
Justin Ruggles
committed
s->exp_ref_block[ch][blk1] = blk;
}
num_reuse_blocks = blk1 - blk - 1;
/* for the EXP_REUSE case we select the min of the exponents */
s->ac3dsp.ac3_exponent_min(exp-s->start_freq[ch], num_reuse_blocks,
AC3_MAX_COEFS);
encode_exponents_blk_ch(exp, nb_coefs, exp_strategy[blk], cpl);
exp += AC3_MAX_COEFS * (num_reuse_blocks + 1);
blk = blk1;
}
}
Justin Ruggles
committed
/* reference block numbers have been changed, so reset ref_bap_set */
s->ref_bap_set = 0;
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
/**
* Count exponent bits based on bandwidth, coupling, and exponent strategies.
*/
static int count_exponent_bits(AC3EncodeContext *s)
{
int blk, ch;
int nb_groups, bit_count;
bit_count = 0;
for (blk = 0; blk < s->num_blocks; blk++) {
AC3Block *block = &s->blocks[blk];
for (ch = !block->cpl_in_use; ch <= s->channels; ch++) {
int exp_strategy = s->exp_strategy[ch][blk];
int cpl = (ch == CPL_CH);
int nb_coefs = block->end_freq[ch] - s->start_freq[ch];
if (exp_strategy == EXP_REUSE)
continue;
nb_groups = exponent_group_tab[cpl][exp_strategy-1][nb_coefs];
bit_count += 4 + (nb_groups * 7);
}
}
return bit_count;
}
/**
* Group exponents.
* 3 delta-encoded exponents are in each 7-bit group. The number of groups
* varies depending on exponent strategy and bandwidth.
*/
void ff_ac3_group_exponents(AC3EncodeContext *s)
int group_size, nb_groups;
uint8_t *p;
int delta0, delta1, delta2;
int exp0, exp1;
Justin Ruggles
committed
for (blk = 0; blk < s->num_blocks; blk++) {
AC3Block *block = &s->blocks[blk];
for (ch = !block->cpl_in_use; ch <= s->channels; ch++) {
Justin Ruggles
committed
int exp_strategy = s->exp_strategy[ch][blk];
if (exp_strategy == EXP_REUSE)
Justin Ruggles
committed
group_size = exp_strategy + (exp_strategy == EXP_D45);
nb_groups = exponent_group_tab[cpl][exp_strategy-1][block->end_freq[ch]-s->start_freq[ch]];
p = block->exp[ch] + s->start_freq[ch] - cpl;
/* DC exponent */
exp1 = *p++;
block->grouped_exp[ch][0] = exp1;
/* remaining exponents are delta encoded */
for (i = 1; i <= nb_groups; i++) {
/* merge three delta in one code */
exp0 = exp1;
exp1 = p[0];
p += group_size;
delta0 = exp1 - exp0 + 2;
exp0 = exp1;
exp1 = p[0];
p += group_size;
delta1 = exp1 - exp0 + 2;
exp0 = exp1;
exp1 = p[0];
p += group_size;
delta2 = exp1 - exp0 + 2;
block->grouped_exp[ch][i] = ((delta0 * 5 + delta1) * 5) + delta2;
}
}
}
}
/**
* Calculate final exponents from the supplied MDCT coefficients and exponent shift.
* Extract exponents from MDCT coefficients, calculate exponent strategies,
* and encode final exponents.
*/
void ff_ac3_process_exponents(AC3EncodeContext *s)
extract_exponents(s);
compute_exp_strategy(s);
encode_exponents(s);
/**
* Count frame bits that are based solely on fixed parameters.
* This only has to be run once when the encoder is initialized.
*/
static void count_frame_bits_fixed(AC3EncodeContext *s)
{
static const int frame_bits_inc[8] = { 0, 0, 2, 2, 2, 4, 2, 4 };
int blk;
int frame_bits;
/* assumptions:
* no dynamic range codes
* bit allocation parameters do not change between blocks
* no delta bit allocation
* no skipped data
* no auxilliary data
*/
/* header */
frame_bits = 16; /* sync info */
if (s->eac3) {
/* bitstream info header */
frame_bits += 35;
Justin Ruggles
committed
frame_bits += 1 + 1;
if (s->num_blocks != 0x6)
frame_bits++;
frame_bits++;
Justin Ruggles
committed
if (s->num_blocks == 6)
frame_bits += 2;
frame_bits += 10;
/* exponent strategy */
if (s->use_frame_exp_strategy)
frame_bits += 5 * s->fbw_channels;
else
Justin Ruggles
committed
frame_bits += s->num_blocks * 2 * s->fbw_channels;
Justin Ruggles
committed
frame_bits += s->num_blocks;
/* converter exponent strategy */
Justin Ruggles
committed
if (s->num_blks_code != 0x3)
frame_bits++;
else
frame_bits += s->fbw_channels * 5;
/* snr offsets */
frame_bits += 10;
/* block start info */
Justin Ruggles
committed
if (s->num_blocks != 1)
frame_bits++;
} else {
frame_bits += 49;
frame_bits += frame_bits_inc[s->channel_mode];
}
/* audio blocks */
Justin Ruggles
committed
for (blk = 0; blk < s->num_blocks; blk++) {
/* block switch flags */
frame_bits += s->fbw_channels;
/* dither flags */
frame_bits += s->fbw_channels;
/* dynamic range */
frame_bits++;
/* spectral extension */
if (s->eac3)
frame_bits++;
if (!s->eac3) {
/* exponent strategy */
frame_bits += 2 * s->fbw_channels;
if (s->lfe_on)
frame_bits++;
/* bit allocation params */
frame_bits++;
if (!blk)
frame_bits += 2 + 2 + 2 + 2 + 3;
/* converter snr offset */
if (s->eac3)
frame_bits++;
if (!s->eac3) {
/* delta bit allocation */
frame_bits++;
/* skipped data */
frame_bits++;
}
/* auxiliary data */
frame_bits++;
/* CRC */
frame_bits += 1 + 16;
s->frame_bits_fixed = frame_bits;
}
/**
* Initialize bit allocation.
* Set default parameter codes and calculate parameter values.
*/
static void bit_alloc_init(AC3EncodeContext *s)
{
int ch;
/* init default parameters */
s->slow_decay_code = 2;
s->fast_decay_code = 1;
s->slow_gain_code = 1;
s->db_per_bit_code = s->eac3 ? 2 : 3;
for (ch = 0; ch <= s->channels; ch++)
s->fast_gain_code[ch] = 4;
/* initial snr offset */
s->coarse_snr_offset = 40;
/* compute real values */
/* currently none of these values change during encoding, so we can just
set them once at initialization */
s->bit_alloc.slow_decay = ff_ac3_slow_decay_tab[s->slow_decay_code] >> s->bit_alloc.sr_shift;
s->bit_alloc.fast_decay = ff_ac3_fast_decay_tab[s->fast_decay_code] >> s->bit_alloc.sr_shift;
s->bit_alloc.slow_gain = ff_ac3_slow_gain_tab[s->slow_gain_code];
s->bit_alloc.db_per_bit = ff_ac3_db_per_bit_tab[s->db_per_bit_code];
s->bit_alloc.floor = ff_ac3_floor_tab[s->floor_code];
s->bit_alloc.cpl_fast_leak = 0;
s->bit_alloc.cpl_slow_leak = 0;
count_frame_bits_fixed(s);
}
/**
* Count the bits used to encode the frame, minus exponents and mantissas.
* Bits based on fixed parameters have already been counted, so now we just
* have to add the bits based on parameters that change during encoding.
static void count_frame_bits(AC3EncodeContext *s)
AC3EncOptions *opt = &s->options;
int blk, ch;
int frame_bits = 0;
/* header */
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++;
Justin Ruggles
committed
for (blk = 1; blk < s->num_blocks; blk++) {
AC3Block *block = &s->blocks[blk];
frame_bits++;
if (block->new_cpl_strategy)
frame_bits++;
}
}
/* coupling exponent strategy */
if (s->cpl_on) {
if (s->use_frame_exp_strategy) {
frame_bits += 5 * s->cpl_on;
} else {
Justin Ruggles
committed
for (blk = 0; blk < s->num_blocks; blk++)
frame_bits += 2 * s->blocks[blk].cpl_in_use;
}
}
if (opt->audio_production_info)
frame_bits += 7;
if (s->bitstream_id == 6) {
if (opt->extended_bsi_1)
frame_bits += 14;
if (opt->extended_bsi_2)
frame_bits += 14;
}
/* audio blocks */
Justin Ruggles
committed
for (blk = 0; blk < s->num_blocks; blk++) {
AC3Block *block = &s->blocks[blk];
/* coupling strategy */
frame_bits++;
frame_bits++;
if (s->eac3)
frame_bits++;
if (!s->eac3 || s->channel_mode != AC3_CHMODE_STEREO)
frame_bits += s->fbw_channels;
if (s->channel_mode == AC3_CHMODE_STEREO)
frame_bits++;
frame_bits += 4 + 4;
if (s->eac3)
frame_bits++;
else
frame_bits += s->num_cpl_subbands - 1;
}
}
/* coupling coordinates */
if (block->cpl_in_use) {
for (ch = 1; ch <= s->fbw_channels; ch++) {
if (block->channel_in_cpl[ch]) {
if (!s->eac3 || block->new_cpl_coords[ch] != 2)
frame_bits++;
if (block->new_cpl_coords[ch]) {
frame_bits += 2;
frame_bits += (4 + 4) * s->num_cpl_bands;
}
}
}
}
/* stereo rematrixing */
if (s->channel_mode == AC3_CHMODE_STEREO) {
frame_bits++;
if (s->blocks[blk].new_rematrixing_strategy)
frame_bits += block->num_rematrixing_bands;
/* bandwidth codes & gain range */
for (ch = 1; ch <= s->fbw_channels; ch++) {
if (s->exp_strategy[ch][blk] != EXP_REUSE) {
if (!block->channel_in_cpl[ch])
frame_bits += 6;
frame_bits += 2;
}
}
/* coupling exponent strategy */
if (!s->eac3 && block->cpl_in_use)
frame_bits += 2;
/* snr offsets and fast gain codes */
frame_bits++;
if (block->new_snr_offsets)
frame_bits += 6 + (s->channels + block->cpl_in_use) * (4 + 3);
/* coupling leak info */
if (block->cpl_in_use) {
if (!s->eac3 || block->new_cpl_leak != 2)
frame_bits++;
if (block->new_cpl_leak)
frame_bits += 3 + 3;
s->frame_bits = s->frame_bits_fixed + frame_bits;
Justin Ruggles
committed
/**
* Calculate masking curve based on the final exponents.
* Also calculate the power spectral densities to use in future calculations.
*/
static void bit_alloc_masking(AC3EncodeContext *s)
{
int blk, ch;
Justin Ruggles
committed
for (blk = 0; blk < s->num_blocks; blk++) {
AC3Block *block = &s->blocks[blk];
for (ch = !block->cpl_in_use; ch <= s->channels; ch++) {
/* We only need psd and mask for calculating bap.
Since we currently do not calculate bap when exponent
strategy is EXP_REUSE we do not need to calculate psd or mask. */
if (s->exp_strategy[ch][blk] != EXP_REUSE) {
ff_ac3_bit_alloc_calc_psd(block->exp[ch], s->start_freq[ch],
block->end_freq[ch], block->psd[ch],
block->band_psd[ch]);
ff_ac3_bit_alloc_calc_mask(&s->bit_alloc, block->band_psd[ch],
s->start_freq[ch], block->end_freq[ch],
ff_ac3_fast_gain_tab[s->fast_gain_code[ch]],
ch == s->lfe_channel,
DBA_NONE, 0, NULL, NULL, NULL,
block->mask[ch]);
}
}
}
}
/**
* Ensure that bap for each block and channel point to the current bap_buffer.
* They may have been switched during the bit allocation search.
*/
static void reset_block_bap(AC3EncodeContext *s)
{
int blk, ch;
Justin Ruggles
committed
uint8_t *ref_bap;
if (s->ref_bap[0][0] == s->bap_buffer && s->ref_bap_set)
Justin Ruggles
committed
ref_bap = s->bap_buffer;
for (ch = 0; ch <= s->channels; ch++) {
Justin Ruggles
committed
for (blk = 0; blk < s->num_blocks; blk++)
Justin Ruggles
committed
s->ref_bap[ch][blk] = ref_bap + AC3_MAX_COEFS * s->exp_ref_block[ch][blk];
Justin Ruggles
committed
ref_bap += AC3_MAX_COEFS * s->num_blocks;
Justin Ruggles
committed
s->ref_bap_set = 1;
Justin Ruggles
committed
/**
* Initialize mantissa counts.
* These are set so that they are padded to the next whole group size when bits
* are counted in compute_mantissa_size.
*/
static void count_mantissa_bits_init(uint16_t mant_cnt[AC3_MAX_BLOCKS][16])
Justin Ruggles
committed
int blk;
for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) {
memset(mant_cnt[blk], 0, sizeof(mant_cnt[blk]));
mant_cnt[blk][1] = mant_cnt[blk][2] = 2;
mant_cnt[blk][4] = 1;
}
}
/**
* Update mantissa bit counts for all blocks in 1 channel in a given bandwidth
* range.
*/
static void count_mantissa_bits_update_ch(AC3EncodeContext *s, int ch,
uint16_t mant_cnt[AC3_MAX_BLOCKS][16],
int start, int end)
{
int blk;
Justin Ruggles
committed
for (blk = 0; blk < s->num_blocks; blk++) {
Justin Ruggles
committed
AC3Block *block = &s->blocks[blk];
Justin Ruggles
committed
if (ch == CPL_CH && !block->cpl_in_use)
continue;