From 08a747afb98c11da48b89339c2f1c5fdc56ced7e Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Wed, 13 Jul 2011 12:20:29 -0400 Subject: eac3enc: use frame exponent strategy when applicable. This checks if the set of selected exponent strategies for all blocks in a channel are in the frame exponent strategy table, and if so, writes the table index instead of each strategy. This saves up to 7 bits per channel per frame, so the overall effect on quality is small. --- libavcodec/Makefile | 2 +- libavcodec/ac3enc.c | 41 +++++++++++++++++++++++++++++------ libavcodec/ac3enc.h | 2 ++ libavcodec/eac3enc.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++--- libavcodec/eac3enc.h | 10 +++++++++ 5 files changed, 106 insertions(+), 10 deletions(-) (limited to 'libavcodec') diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 2c52c8d453..26800b3851 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -124,7 +124,7 @@ OBJS-$(CONFIG_DVVIDEO_ENCODER) += dv.o dvdata.o OBJS-$(CONFIG_DXA_DECODER) += dxa.o OBJS-$(CONFIG_EAC3_DECODER) += eac3dec.o eac3_data.o OBJS-$(CONFIG_EAC3_ENCODER) += eac3enc.o ac3enc.o ac3enc_float.o \ - ac3tab.o ac3.o kbdwin.o + ac3tab.o ac3.o kbdwin.o eac3_data.o OBJS-$(CONFIG_EACMV_DECODER) += eacmv.o OBJS-$(CONFIG_EAMAD_DECODER) += eamad.o eaidct.o mpeg12.o \ mpeg12data.o mpegvideo.o \ diff --git a/libavcodec/ac3enc.c b/libavcodec/ac3enc.c index fb4d33441e..e7a5b1611e 100644 --- a/libavcodec/ac3enc.c +++ b/libavcodec/ac3enc.c @@ -194,6 +194,7 @@ 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 */ @@ -206,12 +207,14 @@ void ff_ac3_compute_coupling_strategy(AC3EncodeContext *s) /* enable coupling for each block if at least 2 channels have coupling enabled for that block */ got_cpl_snr = 0; + num_cpl_blocks = 0; for (blk = 0; blk < AC3_MAX_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++) @@ -237,6 +240,8 @@ void ff_ac3_compute_coupling_strategy(AC3EncodeContext *s) block->new_snr_offsets = 0; } } + if (!num_cpl_blocks) + s->cpl_on = 0; /* set bandwidth for each channel */ for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) { @@ -301,6 +306,9 @@ static av_cold void exponent_init(AC3EncodeContext *s) } /* LFE */ exponent_group_tab[0][0][7] = 2; + + if (CONFIG_EAC3_ENCODER && s->eac3) + ff_eac3_exponent_init(); } @@ -342,8 +350,15 @@ static void compute_exp_strategy(AC3EncodeContext *s) exp_strategy[0] = EXP_NEW; exp += AC3_MAX_COEFS; for (blk = 1; blk < AC3_MAX_BLOCKS; blk++, exp += AC3_MAX_COEFS) { - if ((ch == CPL_CH && (!s->blocks[blk].cpl_in_use || !s->blocks[blk-1].cpl_in_use)) || - (ch > CPL_CH && (s->blocks[blk].channel_in_cpl[ch] != s->blocks[blk-1].channel_in_cpl[ch]))) { + 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; } @@ -377,6 +392,10 @@ static void compute_exp_strategy(AC3EncodeContext *s) for (blk = 1; blk < AC3_MAX_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); } @@ -611,8 +630,12 @@ static void count_frame_bits_fixed(AC3EncodeContext *s) frame_bits += 2; frame_bits += 10; /* exponent strategy */ - for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) - frame_bits += 2 * s->fbw_channels + s->lfe_on; + if (s->use_frame_exp_strategy) + frame_bits += 5 * s->fbw_channels; + else + frame_bits += AC3_MAX_BLOCKS * 2 * s->fbw_channels; + if (s->lfe_on) + frame_bits += AC3_MAX_BLOCKS; /* converter exponent strategy */ frame_bits += s->fbw_channels * 5; /* snr offsets */ @@ -735,8 +758,14 @@ static void count_frame_bits(AC3EncodeContext *s) } } /* coupling exponent strategy */ - for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) - frame_bits += 2 * s->blocks[blk].cpl_in_use; + if (s->cpl_on) { + if (s->use_frame_exp_strategy) { + frame_bits += 5 * s->cpl_on; + } else { + for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) + frame_bits += 2 * s->blocks[blk].cpl_in_use; + } + } } else { if (opt->audio_production_info) frame_bits += 7; diff --git a/libavcodec/ac3enc.h b/libavcodec/ac3enc.h index 6caf4d80c4..a4a8fd4325 100644 --- a/libavcodec/ac3enc.h +++ b/libavcodec/ac3enc.h @@ -217,6 +217,8 @@ typedef struct AC3EncodeContext { uint8_t *cpl_coord_mant_buffer; uint8_t exp_strategy[AC3_MAX_CHANNELS][AC3_MAX_BLOCKS]; ///< exponent strategies + uint8_t frame_exp_strategy[AC3_MAX_CHANNELS]; ///< frame exp strategy index + int use_frame_exp_strategy; ///< indicates use of frame exp strategy uint8_t exp_ref_block[AC3_MAX_CHANNELS][AC3_MAX_BLOCKS]; ///< reference blocks for EXP_REUSE uint8_t *ref_bap [AC3_MAX_CHANNELS][AC3_MAX_BLOCKS]; ///< bit allocation pointers (bap) int ref_bap_set; ///< indicates if ref_bap pointers have been set diff --git a/libavcodec/eac3enc.c b/libavcodec/eac3enc.c index 0433db49d7..153428fdfb 100644 --- a/libavcodec/eac3enc.c +++ b/libavcodec/eac3enc.c @@ -27,6 +27,7 @@ #define CONFIG_AC3ENC_FLOAT 1 #include "ac3enc.h" #include "eac3enc.h" +#include "eac3_data.h" #define AC3ENC_TYPE AC3ENC_TYPE_EAC3 @@ -35,6 +36,51 @@ static const AVClass eac3enc_class = { "E-AC-3 Encoder", av_default_item_name, eac3_options, LIBAVUTIL_VERSION_INT }; +/** + * LUT for finding a matching frame exponent strategy index from a set of + * exponent strategies for a single channel across all 6 blocks. + */ +static int8_t eac3_frame_expstr_index_tab[3][4][4][4][4][4]; + + +void ff_eac3_exponent_init(void) +{ + int i; + + memset(eac3_frame_expstr_index_tab, -1, sizeof(eac3_frame_expstr_index_tab)); + for (i = 0; i < 32; i++) { + eac3_frame_expstr_index_tab[ff_eac3_frm_expstr[i][0]-1] + [ff_eac3_frm_expstr[i][1]] + [ff_eac3_frm_expstr[i][2]] + [ff_eac3_frm_expstr[i][3]] + [ff_eac3_frm_expstr[i][4]] + [ff_eac3_frm_expstr[i][5]] = i; + } +} + + +void ff_eac3_get_frame_exp_strategy(AC3EncodeContext *s) +{ + int ch; + + s->use_frame_exp_strategy = 1; + for (ch = !s->cpl_on; ch <= s->fbw_channels; ch++) { + int expstr = eac3_frame_expstr_index_tab[s->exp_strategy[ch][0]-1] + [s->exp_strategy[ch][1]] + [s->exp_strategy[ch][2]] + [s->exp_strategy[ch][3]] + [s->exp_strategy[ch][4]] + [s->exp_strategy[ch][5]]; + if (expstr < 0) { + s->use_frame_exp_strategy = 0; + break; + } + s->frame_exp_strategy[ch] = expstr; + } +} + + + void ff_eac3_set_cpl_states(AC3EncodeContext *s) { int ch, blk; @@ -98,7 +144,7 @@ void ff_eac3_output_frame_header(AC3EncodeContext *s) put_bits(&s->pb, 1, 0); /* no additional bit stream info */ /* frame header */ - put_bits(&s->pb, 1, 1); /* exponent strategy syntax = each block */ + put_bits(&s->pb, 1, !s->use_frame_exp_strategy);/* exponent strategy syntax */ put_bits(&s->pb, 1, 0); /* aht enabled = no */ put_bits(&s->pb, 2, 0); /* snr offset strategy = 1 */ put_bits(&s->pb, 1, 0); /* transient pre-noise processing enabled = no */ @@ -120,16 +166,25 @@ void ff_eac3_output_frame_header(AC3EncodeContext *s) } } /* exponent strategy */ + if (s->use_frame_exp_strategy) { + for (ch = !s->cpl_on; ch <= s->fbw_channels; ch++) + put_bits(&s->pb, 5, s->frame_exp_strategy[ch]); + } else { for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) for (ch = !s->blocks[blk].cpl_in_use; ch <= s->fbw_channels; ch++) put_bits(&s->pb, 2, s->exp_strategy[ch][blk]); + } if (s->lfe_on) { for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) put_bits(&s->pb, 1, s->exp_strategy[s->lfe_channel][blk]); } /* E-AC-3 to AC-3 converter exponent strategy (unfortunately not optional...) */ - for (ch = 1; ch <= s->fbw_channels; ch++) - put_bits(&s->pb, 5, 0); + for (ch = 1; ch <= s->fbw_channels; ch++) { + if (s->use_frame_exp_strategy) + put_bits(&s->pb, 5, s->frame_exp_strategy[ch]); + else + put_bits(&s->pb, 5, 0); + } /* snr offsets */ put_bits(&s->pb, 6, s->coarse_snr_offset); put_bits(&s->pb, 4, s->fine_snr_offset[1]); diff --git a/libavcodec/eac3enc.h b/libavcodec/eac3enc.h index eacb8cf164..a92a24c2fa 100644 --- a/libavcodec/eac3enc.h +++ b/libavcodec/eac3enc.h @@ -29,6 +29,16 @@ #include "ac3enc.h" +/** + * Initialize E-AC-3 exponent tables. + */ +void ff_eac3_exponent_init(void); + +/** + * Determine frame exponent strategy use and indices. + */ +void ff_eac3_get_frame_exp_strategy(AC3EncodeContext *s); + /** * Set coupling states. * This determines whether certain flags must be written to the bitstream or -- cgit v1.2.3