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_DXA_DECODER) += dxa.o | ||||
| OBJS-$(CONFIG_EAC3_DECODER) += eac3dec.o eac3_data.o | OBJS-$(CONFIG_EAC3_DECODER) += eac3dec.o eac3_data.o | ||||
| OBJS-$(CONFIG_EAC3_ENCODER) += eac3enc.o ac3enc.o ac3enc_float.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_EACMV_DECODER) += eacmv.o | ||||
| OBJS-$(CONFIG_EAMAD_DECODER) += eamad.o eaidct.o mpeg12.o \ | OBJS-$(CONFIG_EAMAD_DECODER) += eamad.o eaidct.o mpeg12.o \ | ||||
| mpeg12data.o mpegvideo.o \ | mpeg12data.o mpegvideo.o \ | ||||
| @@ -194,6 +194,7 @@ void ff_ac3_compute_coupling_strategy(AC3EncodeContext *s) | |||||
| { | { | ||||
| int blk, ch; | int blk, ch; | ||||
| int got_cpl_snr; | int got_cpl_snr; | ||||
| int num_cpl_blocks; | |||||
| /* set coupling use flags for each block/channel */ | /* set coupling use flags for each block/channel */ | ||||
| /* TODO: turn coupling on/off and adjust start band based on bit usage */ | /* 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 | /* enable coupling for each block if at least 2 channels have coupling | ||||
| enabled for that block */ | enabled for that block */ | ||||
| got_cpl_snr = 0; | got_cpl_snr = 0; | ||||
| num_cpl_blocks = 0; | |||||
| for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) { | for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) { | ||||
| AC3Block *block = &s->blocks[blk]; | AC3Block *block = &s->blocks[blk]; | ||||
| block->num_cpl_channels = 0; | block->num_cpl_channels = 0; | ||||
| for (ch = 1; ch <= s->fbw_channels; ch++) | for (ch = 1; ch <= s->fbw_channels; ch++) | ||||
| block->num_cpl_channels += block->channel_in_cpl[ch]; | block->num_cpl_channels += block->channel_in_cpl[ch]; | ||||
| block->cpl_in_use = block->num_cpl_channels > 1; | block->cpl_in_use = block->num_cpl_channels > 1; | ||||
| num_cpl_blocks += block->cpl_in_use; | |||||
| if (!block->cpl_in_use) { | if (!block->cpl_in_use) { | ||||
| block->num_cpl_channels = 0; | block->num_cpl_channels = 0; | ||||
| for (ch = 1; ch <= s->fbw_channels; ch++) | 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; | block->new_snr_offsets = 0; | ||||
| } | } | ||||
| } | } | ||||
| if (!num_cpl_blocks) | |||||
| s->cpl_on = 0; | |||||
| /* set bandwidth for each channel */ | /* set bandwidth for each channel */ | ||||
| for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) { | for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) { | ||||
| @@ -301,6 +306,9 @@ static av_cold void exponent_init(AC3EncodeContext *s) | |||||
| } | } | ||||
| /* LFE */ | /* LFE */ | ||||
| exponent_group_tab[0][0][7] = 2; | 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_strategy[0] = EXP_NEW; | ||||
| exp += AC3_MAX_COEFS; | exp += AC3_MAX_COEFS; | ||||
| for (blk = 1; blk < AC3_MAX_BLOCKS; blk++, 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; | exp_strategy[blk] = EXP_NEW; | ||||
| continue; | continue; | ||||
| } | } | ||||
| @@ -377,6 +392,10 @@ static void compute_exp_strategy(AC3EncodeContext *s) | |||||
| for (blk = 1; blk < AC3_MAX_BLOCKS; blk++) | for (blk = 1; blk < AC3_MAX_BLOCKS; blk++) | ||||
| s->exp_strategy[ch][blk] = EXP_REUSE; | 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 += 2; | ||||
| frame_bits += 10; | frame_bits += 10; | ||||
| /* exponent strategy */ | /* 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 */ | /* converter exponent strategy */ | ||||
| frame_bits += s->fbw_channels * 5; | frame_bits += s->fbw_channels * 5; | ||||
| /* snr offsets */ | /* snr offsets */ | ||||
| @@ -735,8 +758,14 @@ static void count_frame_bits(AC3EncodeContext *s) | |||||
| } | } | ||||
| } | } | ||||
| /* coupling exponent strategy */ | /* 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 { | } else { | ||||
| if (opt->audio_production_info) | if (opt->audio_production_info) | ||||
| frame_bits += 7; | frame_bits += 7; | ||||
| @@ -217,6 +217,8 @@ typedef struct AC3EncodeContext { | |||||
| uint8_t *cpl_coord_mant_buffer; | uint8_t *cpl_coord_mant_buffer; | ||||
| uint8_t exp_strategy[AC3_MAX_CHANNELS][AC3_MAX_BLOCKS]; ///< exponent strategies | 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 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) | 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 | int ref_bap_set; ///< indicates if ref_bap pointers have been set | ||||
| @@ -27,6 +27,7 @@ | |||||
| #define CONFIG_AC3ENC_FLOAT 1 | #define CONFIG_AC3ENC_FLOAT 1 | ||||
| #include "ac3enc.h" | #include "ac3enc.h" | ||||
| #include "eac3enc.h" | #include "eac3enc.h" | ||||
| #include "eac3_data.h" | |||||
| #define AC3ENC_TYPE AC3ENC_TYPE_EAC3 | #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 }; | 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) | void ff_eac3_set_cpl_states(AC3EncodeContext *s) | ||||
| { | { | ||||
| int ch, blk; | 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 */ | put_bits(&s->pb, 1, 0); /* no additional bit stream info */ | ||||
| /* frame header */ | /* 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, 1, 0); /* aht enabled = no */ | ||||
| put_bits(&s->pb, 2, 0); /* snr offset strategy = 1 */ | put_bits(&s->pb, 2, 0); /* snr offset strategy = 1 */ | ||||
| put_bits(&s->pb, 1, 0); /* transient pre-noise processing enabled = no */ | 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 */ | /* 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 (blk = 0; blk < AC3_MAX_BLOCKS; blk++) | ||||
| for (ch = !s->blocks[blk].cpl_in_use; ch <= s->fbw_channels; ch++) | for (ch = !s->blocks[blk].cpl_in_use; ch <= s->fbw_channels; ch++) | ||||
| put_bits(&s->pb, 2, s->exp_strategy[ch][blk]); | put_bits(&s->pb, 2, s->exp_strategy[ch][blk]); | ||||
| } | |||||
| if (s->lfe_on) { | if (s->lfe_on) { | ||||
| for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) | for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) | ||||
| put_bits(&s->pb, 1, s->exp_strategy[s->lfe_channel][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...) */ | /* 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 */ | /* snr offsets */ | ||||
| put_bits(&s->pb, 6, s->coarse_snr_offset); | put_bits(&s->pb, 6, s->coarse_snr_offset); | ||||
| put_bits(&s->pb, 4, s->fine_snr_offset[1]); | put_bits(&s->pb, 4, s->fine_snr_offset[1]); | ||||
| @@ -29,6 +29,16 @@ | |||||
| #include "ac3enc.h" | #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. | * Set coupling states. | ||||
| * This determines whether certain flags must be written to the bitstream or | * This determines whether certain flags must be written to the bitstream or | ||||