diff options
author | Justin Ruggles <justin.ruggles@gmail.com> | 2011-01-09 02:21:17 +0300 |
---|---|---|
committer | Justin Ruggles <justin.ruggles@gmail.com> | 2011-01-09 02:21:17 +0300 |
commit | dc7e07ac1f015117a3abaa9c5f3a594cc7fd0b7a (patch) | |
tree | ddbd5861f46a4a12808c7c9fe6f846faa8dc7b01 /libavcodec/ac3enc.c | |
parent | d267b339e4dbf8d70455e3163b2d39aff0efe314 (diff) |
Add stereo rematrixing support to the AC-3 encoders.
This improves the audio quality significantly for stereo source with both the
fixed-point and floating-point AC-3 encoders.
Update acodec-ac3_fixed and seek-ac3_rm test references.
Originally committed as revision 26271 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavcodec/ac3enc.c')
-rw-r--r-- | libavcodec/ac3enc.c | 147 |
1 files changed, 135 insertions, 12 deletions
diff --git a/libavcodec/ac3enc.c b/libavcodec/ac3enc.c index d9a54325c0..f96883464f 100644 --- a/libavcodec/ac3enc.c +++ b/libavcodec/ac3enc.c @@ -45,6 +45,12 @@ /** Maximum number of exponent groups. +1 for separate DC exponent. */ #define AC3_MAX_EXP_GROUPS 85 +/* stereo rematrixing algorithms */ +#define AC3_REMATRIXING_IS_STATIC 0x1 +#define AC3_REMATRIXING_SUMS 0 +#define AC3_REMATRIXING_NONE 1 +#define AC3_REMATRIXING_ALWAYS 3 + /** Scale a float value by 2^bits and convert to an integer. */ #define SCALE_FLOAT(a, bits) lrintf((a) * (float)(1 << (bits))) @@ -71,6 +77,8 @@ typedef struct AC3Block { uint16_t **qmant; ///< quantized mantissas uint8_t exp_strategy[AC3_MAX_CHANNELS]; ///< exponent strategies int8_t exp_shift[AC3_MAX_CHANNELS]; ///< exponent shift values + uint8_t new_rematrixing_strategy; ///< send new rematrixing flags in this block + uint8_t rematrixing_flags[4]; ///< rematrixing flags } AC3Block; /** @@ -107,6 +115,8 @@ typedef struct AC3EncodeContext { int bandwidth_code[AC3_MAX_CHANNELS]; ///< bandwidth code (0 to 60) (chbwcod) int nb_coefs[AC3_MAX_CHANNELS]; + int rematrixing; ///< determines how rematrixing strategy is calculated + /* bitrate allocation control */ int slow_gain_code; ///< slow gain code (sgaincod) int slow_decay_code; ///< slow decay code (sdcycod) @@ -262,6 +272,114 @@ static void apply_mdct(AC3EncodeContext *s) /** + * Initialize stereo rematrixing. + * If the strategy does not change for each frame, set the rematrixing flags. + */ +static void rematrixing_init(AC3EncodeContext *s) +{ + if (s->channel_mode == AC3_CHMODE_STEREO) + s->rematrixing = AC3_REMATRIXING_SUMS; + else + s->rematrixing = AC3_REMATRIXING_NONE; + /* NOTE: AC3_REMATRIXING_ALWAYS might be used in + the future in conjunction with channel coupling. */ + + if (s->rematrixing & AC3_REMATRIXING_IS_STATIC) { + int flag = (s->rematrixing == AC3_REMATRIXING_ALWAYS); + s->blocks[0].new_rematrixing_strategy = 1; + memset(s->blocks[0].rematrixing_flags, flag, + sizeof(s->blocks[0].rematrixing_flags)); + } +} + + +/** + * Determine rematrixing flags for each block and band. + */ +static void compute_rematrixing_strategy(AC3EncodeContext *s) +{ + int nb_coefs; + int blk, bnd, i; + AC3Block *block, *block0; + + if (s->rematrixing & AC3_REMATRIXING_IS_STATIC) + return; + + nb_coefs = FFMIN(s->nb_coefs[0], s->nb_coefs[1]); + + s->blocks[0].new_rematrixing_strategy = 1; + for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) { + block = &s->blocks[blk]; + for (bnd = 0; bnd < 4; bnd++) { + /* calculate calculate sum of squared coeffs for one band in one block */ + int start = ff_ac3_rematrix_band_tab[bnd]; + int end = FFMIN(nb_coefs, ff_ac3_rematrix_band_tab[bnd+1]); + CoefSumType sum[4] = {0,}; + for (i = start; i < end; i++) { + CoefType lt = block->mdct_coef[0][i]; + CoefType rt = block->mdct_coef[1][i]; + CoefType md = lt + rt; + CoefType sd = lt - rt; + sum[0] += lt * lt; + sum[1] += rt * rt; + sum[2] += md * md; + sum[3] += sd * sd; + } + + /* compare sums to determine if rematrixing will be used for this band */ + if (FFMIN(sum[2], sum[3]) < FFMIN(sum[0], sum[1])) + block->rematrixing_flags[bnd] = 1; + else + block->rematrixing_flags[bnd] = 0; + + /* determine if new rematrixing flags will be sent */ + if (blk && + !block->new_rematrixing_strategy && + block->rematrixing_flags[bnd] != block0->rematrixing_flags[bnd]) { + block->new_rematrixing_strategy = 1; + } + } + block0 = block; + } +} + + +/** + * Apply stereo rematrixing to coefficients based on rematrixing flags. + */ +static void apply_rematrixing(AC3EncodeContext *s) +{ + int nb_coefs; + int blk, bnd, i; + int start, end; + uint8_t *flags; + + if (s->rematrixing == AC3_REMATRIXING_NONE) + return; + + nb_coefs = FFMIN(s->nb_coefs[0], s->nb_coefs[1]); + + for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) { + AC3Block *block = &s->blocks[blk]; + if (block->new_rematrixing_strategy) + flags = block->rematrixing_flags; + for (bnd = 0; bnd < 4; 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[0][i]; + int32_t rt = block->fixed_coef[1][i]; + block->fixed_coef[0][i] = (lt + rt) >> 1; + block->fixed_coef[1][i] = (lt - rt) >> 1; + } + } + } + } +} + + +/** * Initialize exponent tables. */ static av_cold void exponent_init(AC3EncodeContext *s) @@ -592,7 +710,6 @@ static void count_frame_bits_fixed(AC3EncodeContext *s) /* assumptions: * no dynamic range codes * no channel coupling - * no rematrixing * bit allocation parameters do not change between blocks * SNR offsets do not change between blocks * no delta bit allocation @@ -609,8 +726,6 @@ static void count_frame_bits_fixed(AC3EncodeContext *s) frame_bits += s->fbw_channels * 2 + 2; /* blksw * c, dithflag * c, dynrnge, cplstre */ if (s->channel_mode == AC3_CHMODE_STEREO) { frame_bits++; /* rematstr */ - if (!blk) - frame_bits += 4; } frame_bits += 2 * s->fbw_channels; /* chexpstr[2] * c */ if (s->lfe_on) @@ -681,6 +796,13 @@ static void count_frame_bits(AC3EncodeContext *s) for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) { uint8_t *exp_strategy = s->blocks[blk].exp_strategy; + + /* stereo rematrixing */ + if (s->channel_mode == AC3_CHMODE_STEREO && + s->blocks[blk].new_rematrixing_strategy) { + frame_bits += 4; + } + for (ch = 0; ch < s->fbw_channels; ch++) { if (exp_strategy[ch] != EXP_REUSE) frame_bits += 6 + 2; /* chbwcod[6], gainrng[2] */ @@ -1194,16 +1316,11 @@ static void output_audio_block(AC3EncodeContext *s, int block_num) /* stereo rematrixing */ if (s->channel_mode == AC3_CHMODE_STEREO) { - if (!block_num) { - /* first block must define rematrixing (rematstr) */ - put_bits(&s->pb, 1, 1); - - /* dummy rematrixing rematflg(1:4)=0 */ + put_bits(&s->pb, 1, block->new_rematrixing_strategy); + if (block->new_rematrixing_strategy) { + /* rematrixing flags */ for (rbnd = 0; rbnd < 4; rbnd++) - put_bits(&s->pb, 1, 0); - } else { - /* no matrixing (but should be used in the future) */ - put_bits(&s->pb, 1, 0); + put_bits(&s->pb, 1, block->rematrixing_flags[rbnd]); } } @@ -1394,8 +1511,12 @@ static int ac3_encode_frame(AVCodecContext *avctx, unsigned char *frame, apply_mdct(s); + compute_rematrixing_strategy(s); + scale_coefficients(s); + apply_rematrixing(s); + process_exponents(s); ret = compute_bit_allocation(s); @@ -1707,6 +1828,8 @@ static av_cold int ac3_encode_init(AVCodecContext *avctx) set_bandwidth(s); + rematrixing_init(s); + exponent_init(s); bit_alloc_init(s); |