[FFmpeg-cvslog] aacenc_tns: encode coefficients directly and reenable compression

Rostislav Pehlivanov git at videolan.org
Sat Sep 12 14:19:05 CEST 2015


ffmpeg | branch: master | Rostislav Pehlivanov <atomnuker at gmail.com> | Sat Sep 12 13:10:28 2015 +0100| [7b7866387bab1d343d17d49b5470dd93a649a61b] | committer: Rostislav Pehlivanov

aacenc_tns: encode coefficients directly and reenable compression

This commit was made possible with the earlier commits since the
new quantization method basically means we're working always with
unsigned values. The specifications mention to use compression when
the first 2 bits are identical but they didn't mention if this should
happen before or after the conversion to signed values. Actually
they said nothing about conversion to signed values.

With this commit, coefficient compression usually always happens
which saves a lot of space, especially at extremely low bitrates
and doesn't change the quality at all.

Signed-off-by: Rostislav Pehlivanov <atomnuker at gmail.com>

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

 libavcodec/aacenc_tns.c |   33 +++++++++++++++++++++++++--------
 1 file changed, 25 insertions(+), 8 deletions(-)

diff --git a/libavcodec/aacenc_tns.c b/libavcodec/aacenc_tns.c
index da353d6..8e0a00f 100644
--- a/libavcodec/aacenc_tns.c
+++ b/libavcodec/aacenc_tns.c
@@ -31,17 +31,34 @@
 #include "aacenc_utils.h"
 #include "aacenc_quantization.h"
 
+/*
+ * Shifts the values as well if compression is possible.
+ */
+static inline int compress_coeffs(int *coef, int order, int c_bits)
+{
+    int i, res = 0;
+    const int low_idx   = c_bits ?  4 : 2;
+    const int shift_val = c_bits ?  8 : 4;
+    const int high_idx  = c_bits ? 11 : 5;
+    for (i = 0; i < order; i++)
+        if (coef[i] < low_idx && coef[i] > high_idx)
+            res++;
+    if (res == order)
+        for (i = 0; i < order; i++)
+            coef[i] -= (coef[i] > high_idx) ? shift_val : 0;
+    return res == order;
+}
+
 /**
  * Encode TNS data.
  * Coefficient compression saves a single bit per coefficient.
  */
 void ff_aac_encode_tns_info(AACEncContext *s, SingleChannelElement *sce)
 {
-    uint8_t u_coef;
-    const uint8_t coef_res = TNS_Q_BITS == 4;
     int i, w, filt, coef_len, coef_compress = 0;
     const int is8 = sce->ics.window_sequence[0] == EIGHT_SHORT_SEQUENCE;
     TemporalNoiseShaping *tns = &sce->tns;
+    const int c_bits = is8 ? TNS_Q_BITS_SHORT == 4 : TNS_Q_BITS == 4;
 
     if (!sce->tns.present)
         return;
@@ -49,18 +66,18 @@ void ff_aac_encode_tns_info(AACEncContext *s, SingleChannelElement *sce)
     for (i = 0; i < sce->ics.num_windows; i++) {
         put_bits(&s->pb, 2 - is8, sce->tns.n_filt[i]);
         if (tns->n_filt[i]) {
-            put_bits(&s->pb, 1, coef_res);
+            put_bits(&s->pb, 1, c_bits);
             for (filt = 0; filt < tns->n_filt[i]; filt++) {
                 put_bits(&s->pb, 6 - 2 * is8, tns->length[i][filt]);
                 put_bits(&s->pb, 5 - 2 * is8, tns->order[i][filt]);
                 if (tns->order[i][filt]) {
+                    coef_compress = compress_coeffs(tns->coef_idx[i][filt],
+                                                    tns->order[i][filt], c_bits);
                     put_bits(&s->pb, 1, !!tns->direction[i][filt]);
                     put_bits(&s->pb, 1, !!coef_compress);
-                    coef_len = coef_res + 3 - coef_compress;
-                    for (w = 0; w < tns->order[i][filt]; w++) {
-                        u_coef = (tns->coef_idx[i][filt][w])&(~(~0<<coef_len));
-                        put_bits(&s->pb, coef_len, u_coef);
-                    }
+                    coef_len = c_bits + 3 - coef_compress;
+                    for (w = 0; w < tns->order[i][filt]; w++)
+                        put_bits(&s->pb, coef_len, tns->coef_idx[i][filt][w]);
                 }
             }
         }



More information about the ffmpeg-cvslog mailing list