Split exponent processing into separate functions.

Originally committed as revision 25991 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
Justin Ruggles 2010-12-14 14:53:02 +00:00
parent 0a0a8500fb
commit dfdf73eb1a

View File

@ -411,6 +411,41 @@ static void apply_mdct(AC3EncodeContext *s,
}
/**
* Extract exponents from the MDCT coefficients.
* This takes into account the normalization that was done to the input samples
* by adjusting the exponents by the exponent shift values.
*/
static void extract_exponents(AC3EncodeContext *s,
int32_t mdct_coef[AC3_MAX_BLOCKS][AC3_MAX_CHANNELS][AC3_MAX_COEFS],
int8_t exp_shift[AC3_MAX_BLOCKS][AC3_MAX_CHANNELS],
uint8_t exp[AC3_MAX_BLOCKS][AC3_MAX_CHANNELS][AC3_MAX_COEFS])
{
int blk, ch, i;
/* extract exponents */
for (ch = 0; ch < s->channels; ch++) {
for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) {
/* compute "exponents". We take into account the normalization there */
for (i = 0; i < AC3_MAX_COEFS; i++) {
int e;
int v = abs(mdct_coef[blk][ch][i]);
if (v == 0)
e = 24;
else {
e = 23 - av_log2(v) + exp_shift[blk][ch];
if (e >= 24) {
e = 24;
mdct_coef[blk][ch][i] = 0;
}
}
exp[blk][ch][i] = e;
}
}
}
}
/**
* Calculate the sum of absolute differences (SAD) between 2 sets of exponents.
*/
@ -472,6 +507,21 @@ static void compute_exp_strategy_ch(uint8_t exp_strategy[AC3_MAX_BLOCKS][AC3_MAX
}
/**
* Calculate exponent strategies for all channels.
*/
static void compute_exp_strategy(AC3EncodeContext *s,
uint8_t exp_strategy[AC3_MAX_BLOCKS][AC3_MAX_CHANNELS],
uint8_t exp[AC3_MAX_BLOCKS][AC3_MAX_CHANNELS][AC3_MAX_COEFS])
{
int ch;
for (ch = 0; ch < s->channels; ch++) {
compute_exp_strategy_ch(exp_strategy, exp, ch, ch == s->lfe_channel);
}
}
/**
* Set each encoded exponent in a block to the minimum of itself and the
* exponent in the same frequency bin of a following block.
@ -539,6 +589,68 @@ static int encode_exponents_blk_ch(uint8_t encoded_exp[AC3_MAX_COEFS],
}
/**
* 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.
* @return bits needed to encode the exponents
*/
static int encode_exponents(AC3EncodeContext *s,
uint8_t exp[AC3_MAX_BLOCKS][AC3_MAX_CHANNELS][AC3_MAX_COEFS],
uint8_t exp_strategy[AC3_MAX_BLOCKS][AC3_MAX_CHANNELS],
uint8_t encoded_exp[AC3_MAX_BLOCKS][AC3_MAX_CHANNELS][AC3_MAX_COEFS])
{
int blk, blk1, blk2, ch;
int frame_bits;
frame_bits = 0;
for (ch = 0; ch < s->channels; ch++) {
/* for the EXP_REUSE case we select the min of the exponents */
blk = 0;
while (blk < AC3_MAX_BLOCKS) {
blk1 = blk + 1;
while (blk1 < AC3_MAX_BLOCKS && exp_strategy[blk1][ch] == EXP_REUSE) {
exponent_min(exp[blk][ch], exp[blk1][ch], s->nb_coefs[ch]);
blk1++;
}
frame_bits += encode_exponents_blk_ch(encoded_exp[blk][ch],
exp[blk][ch], s->nb_coefs[ch],
exp_strategy[blk][ch]);
/* copy encoded exponents for reuse case */
for (blk2 = blk+1; blk2 < blk1; blk2++) {
memcpy(encoded_exp[blk2][ch], encoded_exp[blk][ch],
s->nb_coefs[ch] * sizeof(uint8_t));
}
blk = blk1;
}
}
return frame_bits;
}
/**
* Calculate final exponents from the supplied MDCT coefficients and exponent shift.
* Extract exponents from MDCT coefficients, calculate exponent strategies,
* and encode final exponents.
* @return bits needed to encode the exponents
*/
static int process_exponents(AC3EncodeContext *s,
int32_t mdct_coef[AC3_MAX_BLOCKS][AC3_MAX_CHANNELS][AC3_MAX_COEFS],
int8_t exp_shift[AC3_MAX_BLOCKS][AC3_MAX_CHANNELS],
uint8_t exp[AC3_MAX_BLOCKS][AC3_MAX_CHANNELS][AC3_MAX_COEFS],
uint8_t exp_strategy[AC3_MAX_BLOCKS][AC3_MAX_CHANNELS],
uint8_t encoded_exp[AC3_MAX_BLOCKS][AC3_MAX_CHANNELS][AC3_MAX_COEFS])
{
extract_exponents(s, mdct_coef, exp_shift, exp);
compute_exp_strategy(s, exp_strategy, exp);
return encode_exponents(s, exp, exp_strategy, encoded_exp);
}
/**
* Calculate the number of bits needed to encode a set of mantissas.
*/
@ -1174,8 +1286,7 @@ static int ac3_encode_frame(AVCodecContext *avctx,
{
AC3EncodeContext *s = avctx->priv_data;
const int16_t *samples = data;
int v;
int blk, blk1, blk2, ch, i;
int blk;
int16_t planar_samples[AC3_MAX_CHANNELS][AC3_BLOCK_SIZE+AC3_FRAME_SIZE];
int32_t mdct_coef[AC3_MAX_BLOCKS][AC3_MAX_CHANNELS][AC3_MAX_COEFS];
uint8_t exp[AC3_MAX_BLOCKS][AC3_MAX_CHANNELS][AC3_MAX_COEFS];
@ -1189,56 +1300,7 @@ static int ac3_encode_frame(AVCodecContext *avctx,
apply_mdct(s, planar_samples, exp_shift, mdct_coef);
/* extract exponents */
for (ch = 0; ch < s->channels; ch++) {
for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) {
/* compute "exponents". We take into account the normalization there */
for (i = 0; i < AC3_MAX_COEFS; i++) {
int e;
v = abs(mdct_coef[blk][ch][i]);
if (v == 0)
e = 24;
else {
e = 23 - av_log2(v) + exp_shift[blk][ch];
if (e >= 24) {
e = 24;
mdct_coef[blk][ch][i] = 0;
}
}
exp[blk][ch][i] = e;
}
}
}
/* compute exponent strategies */
for (ch = 0; ch < s->channels; ch++) {
compute_exp_strategy_ch(exp_strategy, exp, ch, ch == s->lfe_channel);
}
/* encode exponents */
frame_bits = 0;
for (ch = 0; ch < s->channels; ch++) {
/* compute the exponents as the decoder will see them. The
EXP_REUSE case must be handled carefully : we select the
min of the exponents */
blk = 0;
while (blk < AC3_MAX_BLOCKS) {
blk1 = blk + 1;
while (blk1 < AC3_MAX_BLOCKS && exp_strategy[blk1][ch] == EXP_REUSE) {
exponent_min(exp[blk][ch], exp[blk1][ch], s->nb_coefs[ch]);
blk1++;
}
frame_bits += encode_exponents_blk_ch(encoded_exp[blk][ch],
exp[blk][ch], s->nb_coefs[ch],
exp_strategy[blk][ch]);
/* copy encoded exponents for reuse case */
for (blk2 = blk+1; blk2 < blk1; blk2++) {
memcpy(encoded_exp[blk2][ch], encoded_exp[blk][ch],
s->nb_coefs[ch] * sizeof(uint8_t));
}
blk = blk1;
}
}
frame_bits = process_exponents(s, mdct_coef, exp_shift, exp, exp_strategy, encoded_exp);
/* adjust for fractional frame sizes */
while (s->bits_written >= s->bit_rate && s->samples_written >= s->sample_rate) {