You've already forked FFmpeg
							
							
				mirror of
				https://github.com/FFmpeg/FFmpeg.git
				synced 2025-10-30 23:18:11 +02:00 
			
		
		
		
	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.
This commit is contained in:
		| @@ -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 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user