[FFmpeg-cvslog] r23317 - trunk/libavcodec/aaccoder.c

alexc subversion
Tue May 25 20:28:18 CEST 2010


Author: alexc
Date: Tue May 25 20:28:18 2010
New Revision: 23317

Log:
aacenc: Only trellis over a column of 61 scalefactors (reduced from 256).

This still provides plenty of dynamic range, makes every move legal, and greatly reduces the search space.

Modified:
   trunk/libavcodec/aaccoder.c

Modified: trunk/libavcodec/aaccoder.c
==============================================================================
--- trunk/libavcodec/aaccoder.c	Tue May 25 20:24:16 2010	(r23316)
+++ trunk/libavcodec/aaccoder.c	Tue May 25 20:28:18 2010	(r23317)
@@ -30,6 +30,7 @@
  * add sane pulse detection
  ***********************************/
 
+#include <float.h>
 #include "avcodec.h"
 #include "put_bits.h"
 #include "aac.h"
@@ -462,12 +463,10 @@ static void codebook_trellis_rate(AACEnc
 typedef struct TrellisPath {
     float cost;
     int prev;
-    int min_val;
-    int max_val;
 } TrellisPath;
 
 #define TRELLIS_STAGES 121
-#define TRELLIS_STATES 256
+#define TRELLIS_STATES (SCALE_MAX_DIFF+1)
 
 static void search_for_quantizers_anmr(AVCodecContext *avctx, AACEncContext *s,
                                        SingleChannelElement *sce,
@@ -480,19 +479,56 @@ static void search_for_quantizers_anmr(A
     int bandaddr[TRELLIS_STAGES];
     int minq;
     float mincost;
+    float q0f = FLT_MAX, q1f = 0.0f, qnrgf = 0.0f;
+    int q0, q1, qcnt = 0;
+
+    for (i = 0; i < 1024; i++) {
+        float t = fabsf(sce->coeffs[i]);
+        if (t > 0.0f) {
+            q0f = FFMIN(q0f, t);
+            q1f = FFMAX(q1f, t);
+            qnrgf += t*t;
+            qcnt++;
+        }
+    }
+
+    if (!qcnt) {
+        memset(sce->sf_idx, 0, sizeof(sce->sf_idx));
+        memset(sce->zeroes, 1, sizeof(sce->zeroes));
+        return;
+    }
+
+    //minimum scalefactor index is when minimum nonzero coefficient after quantizing is not clipped
+    q0 = av_clip_uint8(log2(q0f)*4 - 69 + SCALE_ONE_POS - SCALE_DIV_512);
+    //maximum scalefactor index is when maximum coefficient after quantizing is still not zero
+    q1 = av_clip_uint8(log2(q1f)*4 +  6 + SCALE_ONE_POS - SCALE_DIV_512);
+    //av_log(NULL, AV_LOG_ERROR, "q0 %d, q1 %d\n", q0, q1);
+    if (q1 - q0 > 60) {
+        int q0low  = q0;
+        int q1high = q1;
+        //minimum scalefactor index is when maximum nonzero coefficient after quantizing is not clipped
+        int qnrg = av_clip_uint8(log2(sqrt(qnrgf/qcnt))*4 - 31 + SCALE_ONE_POS - SCALE_DIV_512);
+        q1 = qnrg + 30;
+        q0 = qnrg - 30;
+    //av_log(NULL, AV_LOG_ERROR, "q0 %d, q1 %d\n", q0, q1);
+        if (q0 < q0low) {
+            q1 += q0low - q0;
+            q0  = q0low;
+        } else if (q1 > q1high) {
+            q0 -= q1 - q1high;
+            q1  = q1high;
+        }
+    }
+    //av_log(NULL, AV_LOG_ERROR, "q0 %d, q1 %d\n", q0, q1);
 
     for (i = 0; i < TRELLIS_STATES; i++) {
         paths[0][i].cost    = 0.0f;
         paths[0][i].prev    = -1;
-        paths[0][i].min_val = i;
-        paths[0][i].max_val = i;
     }
     for (j = 1; j < TRELLIS_STAGES; j++) {
         for (i = 0; i < TRELLIS_STATES; i++) {
             paths[j][i].cost    = INFINITY;
             paths[j][i].prev    = -2;
-            paths[j][i].min_val = INT_MAX;
-            paths[j][i].max_val = 0;
         }
     }
     idx = 1;
@@ -529,6 +565,8 @@ static void search_for_quantizers_anmr(A
                 minscale = av_clip_uint8(log2(qmin)*4 - 69 + SCALE_ONE_POS - SCALE_DIV_512);
                 //maximum scalefactor index is when maximum coefficient after quantizing is still not zero
                 maxscale = av_clip_uint8(log2(qmax)*4 +  6 + SCALE_ONE_POS - SCALE_DIV_512);
+                minscale = av_clip(minscale - q0, 0, TRELLIS_STATES - 1);
+                maxscale = av_clip(maxscale - q0, 0, TRELLIS_STATES);
                 for (q = minscale; q < maxscale; q++) {
                     float dists[12], dist;
                     memset(dists, 0, sizeof(dists));
@@ -537,52 +575,40 @@ static void search_for_quantizers_anmr(A
                         int cb;
                         for (cb = 0; cb <= ESC_BT; cb++)
                             dists[cb] += quantize_band_cost(s, coefs + w2*128, s->scoefs + start + w2*128, sce->ics.swb_sizes[g],
-                                                            q, cb, lambda / band->threshold, INFINITY, NULL);
+                                                            q + q0, cb, lambda / band->threshold, INFINITY, NULL);
                     }
                     dist = dists[0];
                     for (i = 1; i <= ESC_BT; i++)
                         dist = FFMIN(dist, dists[i]);
                     minrd = FFMIN(minrd, dist);
 
-                    for (i = FFMAX(q - SCALE_MAX_DIFF, 0); i < FFMIN(q + SCALE_MAX_DIFF, TRELLIS_STATES); i++) {
+                    for (i = 0; i < q1 - q0; i++) {
                         float cost;
-                        int minv, maxv;
                         if (isinf(paths[idx - 1][i].cost))
                             continue;
                         cost = paths[idx - 1][i].cost + dist
                                + ff_aac_scalefactor_bits[q - i + SCALE_DIFF_ZERO];
-                        minv = FFMIN(paths[idx - 1][i].min_val, q);
-                        maxv = FFMAX(paths[idx - 1][i].max_val, q);
-                        if (cost < paths[idx][q].cost && maxv-minv < SCALE_MAX_DIFF) {
+                        if (cost < paths[idx][q].cost) {
                             paths[idx][q].cost    = cost;
                             paths[idx][q].prev    = i;
-                            paths[idx][q].min_val = minv;
-                            paths[idx][q].max_val = maxv;
                         }
                     }
                 }
             } else {
-                for (q = 0; q < TRELLIS_STATES; q++) {
+                for (q = 0; q < q1 - q0; q++) {
                     if (!isinf(paths[idx - 1][q].cost)) {
                         paths[idx][q].cost = paths[idx - 1][q].cost + 1;
                         paths[idx][q].prev = q;
-                        paths[idx][q].min_val = FFMIN(paths[idx - 1][q].min_val, q);
-                        paths[idx][q].max_val = FFMAX(paths[idx - 1][q].max_val, q);
                         continue;
                     }
-                    for (i = FFMAX(q - SCALE_MAX_DIFF, 0); i < FFMIN(q + SCALE_MAX_DIFF, TRELLIS_STATES); i++) {
+                    for (i = 0; i < q1 - q0; i++) {
                         float cost;
-                        int minv, maxv;
                         if (isinf(paths[idx - 1][i].cost))
                             continue;
                         cost = paths[idx - 1][i].cost + ff_aac_scalefactor_bits[q - i + SCALE_DIFF_ZERO];
-                        minv = FFMIN(paths[idx - 1][i].min_val, q);
-                        maxv = FFMAX(paths[idx - 1][i].max_val, q);
-                        if (cost < paths[idx][q].cost && maxv-minv < SCALE_MAX_DIFF) {
+                        if (cost < paths[idx][q].cost) {
                             paths[idx][q].cost    = cost;
                             paths[idx][q].prev    = i;
-                            paths[idx][q].min_val = minv;
-                            paths[idx][q].max_val = maxv;
                         }
                     }
                 }
@@ -602,7 +628,7 @@ static void search_for_quantizers_anmr(A
         }
     }
     while (idx) {
-        sce->sf_idx[bandaddr[idx]] = minq;
+        sce->sf_idx[bandaddr[idx]] = minq + q0;
         minq = paths[idx][minq].prev;
         idx--;
     }



More information about the ffmpeg-cvslog mailing list