[FFmpeg-soc] [soc]: r3711 - aacenc/aacenc.c

kostya subversion at mplayerhq.hu
Fri Sep 5 14:36:48 CEST 2008


Author: kostya
Date: Fri Sep  5 14:36:48 2008
New Revision: 3711

Log:
Improve quantizers search algorithm:
* introduce minimum and maximum quantizer values, so resulting sequence can
always be coded
* change code flow, so optimal quantizer is searched for window group band
instead of bands for individual windows
* copy out the case for zero bands and optimize it for speed


Modified:
   aacenc/aacenc.c

Modified: aacenc/aacenc.c
==============================================================================
--- aacenc/aacenc.c	(original)
+++ aacenc/aacenc.c	Fri Sep  5 14:36:48 2008
@@ -665,11 +665,13 @@ static void quantize_coeffs(AACEncContex
 typedef struct TrellisPath {
     float cost;
     int prev;
+    int min_val;
+    int max_val;
 } TrellisPath;
 
 static void search_for_quantizers(AACEncContext *s, SingleChannelElement *sce)
 {
-    int q, w, g, start = 0;
+    int q, w, w2, g, start = 0;
     int i;
     int qcoeffs[128];
     int idx;
@@ -682,69 +684,101 @@ static void search_for_quantizers(AACEnc
     for(i = 0; i < 256; i++){
         paths[i].cost = 0.0f;
         paths[i].prev = -1;
+        paths[i].min_val = i;
+        paths[i].max_val = i;
     }
     for(i = 256; i < 256*121; i++){
         paths[i].cost = INFINITY;
         paths[i].prev = -2;
+        paths[i].min_val = INT_MAX;
+        paths[i].max_val = 0;
     }
     idx = 256;
-    for(w = 0; w < sce->ics.num_windows*16; w += 16){
+    for(w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]){
+        start = w*128;
         for(g = 0; g < sce->ics.num_swb; g++){
             const float *coefs = sce->coeffs + start;
-            float qmin, qmax, invthr;
-            int minscale, maxscale;
-            FFPsyBand *band = &s->psy.psy_bands[s->cur_channel*PSY_MAX_BANDS+w+g];
+            float qmin, qmax;
+            int nz = 0;
 
-            bandaddr[idx >> 8] = w+g;
-            if(band->energy <= band->threshold){
-                sce->zeroes[w+g] = 1;
-                for(q = 0; q < 256; q++){
+            bandaddr[idx >> 8] = w*16+g;
+            qmin = INT_MAX;
+            qmax = 0.0f;
+            for(w2 = 0; w2 < sce->ics.group_len[w]; w2++){
+                FFPsyBand *band = &s->psy.psy_bands[s->cur_channel*PSY_MAX_BANDS+(w+w2)*16+g];
+                if(band->energy <= band->threshold || band->threshold == 0.0f){
+                    sce->zeroes[(w+w2)*16+g] = 1;
+                    continue;
+                }
+                sce->zeroes[(w+w2)*16+g] = 0;
+                nz = 1;
+                for(i = 0; i < sce->ics.swb_sizes[g]; i++){
+                    float t = fabsf(coefs[w2*128+i]);
+                    if(t > 0.0f) qmin = fminf(qmin, t);
+                    qmax = fmaxf(qmax, t);
+                }
+            }
+            if(nz){
+                int minscale, maxscale;
+                //minimum scalefactor index is when mininum nonzero coefficient after quantizing is not clipped
+                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);
+                for(q = minscale; q < maxscale; q++){
+                    float dist = 0.0f;
+                    int bits = 0, sum = 0;
+                    for(w2 = 0; w2 < sce->ics.group_len[w]; w2++){
+                        FFPsyBand *band = &s->psy.psy_bands[s->cur_channel*PSY_MAX_BANDS+(w+w2)*16+g];
+                        if(sce->zeroes[(w+w2)*16+g])
+                            continue;
+                        sum  += quantize_band(coefs + w2*128, qcoeffs, sce->ics.swb_sizes[g], q);
+                        dist += get_approximate_quant_error(coefs + w2*128, qcoeffs, sce->ics.swb_sizes[g], q) / band->threshold;
+                        bits += get_approximate_bits(qcoeffs, sce->ics.swb_sizes[g]);
+                    }
                     for(i = FFMAX(q - SCALE_MAX_DIFF, 0); i < FFMIN(q + SCALE_MAX_DIFF, 256); i++){
                         float cost;
+                        int minv, maxv;
                         if(isinf(paths[idx - 256 + i].cost))
                             continue;
-                        cost = paths[idx - 256 + i].cost + ff_aac_scalefactor_bits[q - i + SCALE_DIFF_ZERO];
-                        if(cost < paths[idx + q].cost){
+                        cost = paths[idx - 256 + i].cost + dist * lambda + bits
+                               + ff_aac_scalefactor_bits[q - i + SCALE_DIFF_ZERO];
+                        minv = FFMIN(paths[idx - 256 + i].min_val, q);
+                        maxv = FFMAX(paths[idx - 256 + i].max_val, q);
+                        if(cost < paths[idx + q].cost && maxv-minv < SCALE_MAX_DIFF){
                             paths[idx + q].cost = cost;
                             paths[idx + q].prev = idx - 256 + i;
+                            paths[idx + q].min_val = minv;
+                            paths[idx + q].max_val = maxv;
                         }
                     }
                 }
-                start += sce->ics.swb_sizes[g];
-                idx += 256;
-                continue;
-            }
-            sce->zeroes[w+g] = 0;
-            qmin = qmax = fabsf(coefs[0]);
-            if(qmin == 0.0f) qmin = INT_MAX;
-            for(i = 1; i < sce->ics.swb_sizes[g]; i++){
-                float t = fabsf(coefs[i]);
-                if(t > 0.0f) qmin = fminf(qmin, t);
-                qmax = fmaxf(qmax, t);
-            }
-            //minimum scalefactor index is when mininum nonzero coefficient after quantizing is not clipped
-            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);
-            invthr = (band->threshold == 0.0f) ? INFINITY : 1.0 / band->threshold;
-            for(q = minscale; q < maxscale; q++){
-                float dist;
-                int bits, sum;
-                sum = quantize_band(coefs, qcoeffs, sce->ics.swb_sizes[g], q);
-                dist = get_approximate_quant_error(coefs, qcoeffs, sce->ics.swb_sizes[g], q);
-                bits = get_approximate_bits(qcoeffs, sce->ics.swb_sizes[g]);
-                for(i = FFMAX(q - SCALE_MAX_DIFF, 0); i < FFMIN(q + SCALE_MAX_DIFF, 256); i++){
-                    float cost;
-                    if(isinf(paths[idx - 256 + i].cost))
+            }else{
+                for(q = 0; q < 256; q++){
+                    if(!isinf(paths[idx - 256 + q].cost)){
+                        paths[idx + q].cost = paths[idx - 256 + q].cost + 1;
+                        paths[idx + q].prev = idx - 256 + q;
+                        paths[idx + q].min_val = FFMIN(paths[idx - 256 + q].min_val, q);
+                        paths[idx + q].max_val = FFMAX(paths[idx - 256 + q].max_val, q);
                         continue;
-                    cost = paths[idx - 256 + i].cost + dist * invthr * lambda + bits
-                           + ff_aac_scalefactor_bits[q - i + SCALE_DIFF_ZERO];
-                    if(cost < paths[idx + q].cost){
-                        paths[idx + q].cost = cost;
-                        paths[idx + q].prev = idx - 256 + i;
+                    }
+                    for(i = FFMAX(q - SCALE_MAX_DIFF, 0); i < FFMIN(q + SCALE_MAX_DIFF, 256); i++){
+                        float cost;
+                        int minv, maxv;
+                        if(isinf(paths[idx - 256 + i].cost))
+                            continue;
+                        cost = paths[idx - 256 + i].cost + ff_aac_scalefactor_bits[q - i + SCALE_DIFF_ZERO];
+                        minv = FFMIN(paths[idx - 256 + i].min_val, q);
+                        maxv = FFMAX(paths[idx - 256 + i].max_val, q);
+                        if(cost < paths[idx + q].cost && maxv-minv < SCALE_MAX_DIFF){
+                            paths[idx + q].cost = cost;
+                            paths[idx + q].prev = idx - 256 + i;
+                            paths[idx + q].min_val = minv;
+                            paths[idx + q].max_val = maxv;
+                        }
                     }
                 }
             }
+            sce->zeroes[w*16+g] = !nz;
             start += sce->ics.swb_sizes[g];
             idx += 256;
         }



More information about the FFmpeg-soc mailing list