[FFmpeg-cvslog] eac3enc: use frame exponent strategy when applicable.

Justin Ruggles git at videolan.org
Wed Jul 20 18:35:35 CEST 2011


ffmpeg | branch: master | Justin Ruggles <justin.ruggles at gmail.com> | Wed Jul 13 12:20:29 2011 -0400| [08a747afb98c11da48b89339c2f1c5fdc56ced7e] | committer: 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.

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=08a747afb98c11da48b89339c2f1c5fdc56ced7e
---

 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(-)

diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 2c52c8d..26800b3 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 fb4d334..e7a5b16 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 6caf4d8..a4a8fd4 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 0433db4..153428f 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 eacb8cf..a92a24c 100644
--- a/libavcodec/eac3enc.h
+++ b/libavcodec/eac3enc.h
@@ -30,6 +30,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
  * whether they will be implicitly already known by the decoder.



More information about the ffmpeg-cvslog mailing list