Commit 08a747af authored by Justin Ruggles's avatar Justin Ruggles

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.
parent 31b69928
...@@ -124,7 +124,7 @@ OBJS-$(CONFIG_DVVIDEO_ENCODER) += dv.o dvdata.o ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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)) || if (ch == CPL_CH) {
(ch > CPL_CH && (s->blocks[blk].channel_in_cpl[ch] != s->blocks[blk-1].channel_in_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) ...@@ -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) ...@@ -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++) if (s->use_frame_exp_strategy)
frame_bits += 2 * s->fbw_channels + s->lfe_on; 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) ...@@ -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++) if (s->cpl_on) {
frame_bits += 2 * s->blocks[blk].cpl_in_use; 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 { ...@@ -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 @@ ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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++) for (ch = 1; ch <= s->fbw_channels; ch++) {
put_bits(&s->pb, 5, 0); 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 @@ ...@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment