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.tags/n0.9
| @@ -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 \ | |||
| @@ -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; | |||
| @@ -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 | |||
| @@ -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]); | |||
| @@ -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 | |||