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

kostya subversion at mplayerhq.hu
Tue Sep 16 19:13:45 CEST 2008


Author: kostya
Date: Tue Sep 16 19:13:45 2008
New Revision: 3744

Log:
Another major step to RD-optimal encoder:
* RD-aware quantization code
* RD-aware codebook selection
* Miscellaneous fixes to scalefactor determination code
* Theoretical M/S detection code


Modified:
   aacenc/aacenc.c

Modified: aacenc/aacenc.c
==============================================================================
--- aacenc/aacenc.c	(original)
+++ aacenc/aacenc.c	Tue Sep 16 19:13:45 2008
@@ -171,15 +171,6 @@ static const uint8_t aac_chan_configs[6]
 };
 
 /**
- * structure used in optimal codebook search
- */
-typedef struct BandCodingPath {
-    int prev_idx; ///< pointer to the previous path point
-    int codebook; ///< codebook for coding band run
-    int bits;     ///< number of bit needed to code given number of bands
-} BandCodingPath;
-
-/**
  * AAC encoder context
  */
 typedef struct {
@@ -197,6 +188,7 @@ typedef struct {
     struct FFPsyPreprocessContext* psypp;
     int cur_channel;
     int last_frame;
+    float lambda;
 } AACEncContext;
 
 /**
@@ -372,219 +364,257 @@ static av_always_inline int quant(float 
     return av_clip((int)(pow(fabsf(coef) * Q, 0.75) + 0.4054), 0, 8191);
 }
 
-static inline float get_approximate_quant_error(const float *q, const int *c, int size, int scale_idx)
-{
-    int i;
-    float coef, unquant, sum = 0.0f;
-    const float IQ = ff_aac_pow2sf_tab[200 + scale_idx - SCALE_ONE_POS + SCALE_DIV_512];
-    for(i = 0; i < size; i++){
-        coef = fabsf(q[i]);
-        unquant = (c[i] * cbrt(c[i])) * IQ;
-        sum += (coef - unquant) * (coef - unquant);
-    }
-    return sum;
-}
-
 /**
- * Convert coefficients to integers.
- * @fixme make it RD-optimal
- * @return sum of coefficient absolute values
+ * Calculate rate distortion cost for quantizing with given codebook
+ *
+ * @return quantization distortion
  */
-static inline int quantize_band(const float *in, int *out, int size, int scale_idx)
+static float quantize_band_cost(const float *in, int size, int scale_idx, int cb,
+                                 const float lambda, const float uplim)
 {
-    int i, sign, sum = 0;
-    const float Q = ff_aac_pow2sf_tab[200 - scale_idx + SCALE_ONE_POS - SCALE_DIV_512];
-    for(i = 0; i < size; i++){
-        sign = in[i] > 0.0;
-        out[i] = quant(in[i], Q);
-        sum += out[i];
-        if(sign) out[i] = -out[i];
-    }
-    return sum;
-}
+    const float Q = ff_aac_pow2sf_tab[200 + scale_idx - SCALE_ONE_POS + SCALE_DIV_512];
+    int i, j, k;
+    float cost = 0;
+    const int dim = cb < FIRST_PAIR_BT ? 4 : 2;
 
-static inline int get_approximate_bits(const int *in, int size)
-{
-    int i, bits = 0;
-    for(i = 0; i < size; i += 2){
-        int j, idx = 0;
-        for(j = 0; j < 2; j++){
-            int t = FFABS(in[i+j]);
-            if(t)
-                bits++;
-            if(t > 16)
-                bits += av_log2(t)*2 + 4 - 1;
-            idx = idx*17 + FFMIN(t, 16);
-        }
-        bits += ff_aac_spectral_bits[ESC_BT-1][idx];
+    if(!cb){
+        for(i = 0; i < size; i++)
+            cost += in[i]*in[i]*lambda;
+        return cost;
     }
-    return bits;
-}
-
-/**
- * Calculate the number of bits needed to code all coefficient signs in current band.
- */
-static int calculate_band_sign_bits(AACEncContext *s, SingleChannelElement *sce,
-                                    int group_len, int start, int size)
-{
-    int bits = 0;
-    int i, w;
-    for(w = 0; w < group_len; w++){
-        for(i = 0; i < size; i++){
-            if(sce->icoefs[start + i])
-                bits++;
+    for(i = 0; i < size; i += dim){
+        float mincost = INFINITY;
+        int minidx = 0;
+        int minbits = 0;
+        const float *vec = ff_aac_codebook_vectors[cb-1];
+        for(j = 0; j < ff_aac_spectral_sizes[cb-1]; j++, vec += dim){
+            float rd = 0.0f;
+            int curbits = ff_aac_spectral_bits[cb-1][minidx];
+            if(IS_CODEBOOK_UNSIGNED(cb)){
+                for(k = 0; k < dim; k++){
+                    float t = fabsf(in[i+k]);
+                    float di;
+                    //do not code with escape sequence small values
+                    if(vec[k] == 64.0f && t < 39.0f*Q){
+                        rd = INFINITY;
+                        break;
+                    }
+                    if(vec[k] == 64.0f){//FIXME: slow
+                        if(t >= 165140.0f*Q){ // clipped value
+                            di = t - 165140.0f;
+                            curbits += 21;
+                        }else{
+                            int c = quant(t, 1.0/Q);
+                            di = t - c*cbrt(c)*Q;
+                            curbits += av_log2(c)*2 - 4 + 1;
+                        }
+                    }else{
+                        di = t - vec[k]*Q;
+                    }
+                    if(vec[k] != 0.0f)
+                        curbits++;
+                    rd += di*di*lambda;
+                }
+            }else{
+                for(k = 0; k < dim; k++){
+                    float di = in[i+k] - vec[k]*Q;
+                    rd += di*di*lambda;
+                }
+            }
+            rd += curbits;
+            if(rd < mincost){
+                mincost = rd;
+                minidx = j;
+                minbits = curbits;
+            }
         }
-        start += 128;
+        cost += mincost;
+        if(cost >= uplim)
+            return uplim;
     }
-    return bits;
+
+    return cost;
 }
 
 /**
- * Calculate the number of bits needed to code given band with given codebook.
+ * Prepare coefficients for encoding.
  *
- * @param s         encoder context
- * @param sce       channel element
- * @param group_len window group length
- * @param start     scalefactor band position in spectral coefficients
- * @param size      scalefactor band size
- * @param cb        codebook number
+ * @return sum of coefficient absolute values
  */
-static int calculate_band_bits(AACEncContext *s, SingleChannelElement *sce,
-                               int group_len, int start, int size, int cb)
+static void quantize_and_encode_band(PutBitContext *pb, const float *in, int size,
+                                      int scale_idx, int cb, const float lambda)
 {
-    int i, j, w;
-    int bits = 0, dim, idx;
-    int range = aac_cb_info[cb].range;
-
-    if(range == -1) return 0;
-    cb--;
-    dim = cb < FIRST_PAIR_BT ? 4 : 2;
+    const float Q  = ff_aac_pow2sf_tab[200 + scale_idx - SCALE_ONE_POS + SCALE_DIV_512];
+    const float IQ = ff_aac_pow2sf_tab[200 - scale_idx + SCALE_ONE_POS - SCALE_DIV_512];
+    int i, j, k;
+    const int dim = cb < FIRST_PAIR_BT ? 4 : 2;
+    if(!cb)
+        return;
 
-    if(cb == ESC_BT){
-        for(w = 0; w < group_len; w++){
-        int coef_abs[2];
-            for(i = 0; i < size; i += 2){
-               idx = 0;
-               for(j = 0; j < 2; j++){
-                    coef_abs[j] = FFABS(sce->icoefs[start+i+j]);
-                    idx = idx*17 + FFMIN(coef_abs[j], 16);
-                    if(coef_abs[j] > 15){
-                        bits += av_log2(coef_abs[j])*2 - 4 + 1;
+    for(i = 0; i < size; i += dim){
+        float mincost = INFINITY;
+        int minidx = 0;
+        int minbits = 0;
+        const float *vec = ff_aac_codebook_vectors[cb-1];
+        for(j = 0; j < ff_aac_spectral_sizes[cb-1]; j++, vec += dim){
+            float rd = 0.0f;
+            int curbits = ff_aac_spectral_bits[cb-1][minidx];
+            if(IS_CODEBOOK_UNSIGNED(cb)){
+                for(k = 0; k < dim; k++){
+                    float t = fabsf(in[i+k]);
+                    float di;
+                    if(vec[k] != 0.0f)
+                        curbits++;
+                    //do not code with escape sequence small values
+                    if(vec[k] == 64.0f && t < 39.0f*Q){
+                        rd = INFINITY;
+                        break;
                     }
+                    if(vec[k] == 64.0f){//FIXME: slow
+                        if(t*IQ >= 165140.0f){ // clipped value
+                            di = t - 165140.0f;
+                            curbits += 21;
+                        }else{
+                            int c = quant(t, IQ);
+                            di = t - c*cbrt(c)*Q;
+                            curbits += av_log2(c)*2 - 4 + 1;
+                        }
+                    }else{
+                        di = t - vec[k]*Q;
+                    }
+                    rd += di*di*lambda;
                 }
-                bits += ff_aac_spectral_bits[cb][idx];
-            }
-            start += 128;
-        }
-    }else if(IS_CODEBOOK_UNSIGNED(cb)){
-        for(w = 0; w < group_len; w++){
-            for(i = 0; i < size; i += dim){
-                idx = FFABS(sce->icoefs[start+i]);
-                for(j = 1; j < dim; j++){
-                    idx = idx * range + FFABS(sce->icoefs[start+i+j]);
+            }else{
+                for(k = 0; k < dim; k++){
+                    float di = in[i+k] - vec[k]*Q;
+                    rd += di*di*lambda;
                 }
-                bits += ff_aac_spectral_bits[cb][idx];
             }
-            start += 128;
+            rd += curbits;
+            if(rd < mincost){
+                mincost = rd;
+                minidx = j;
+                minbits = curbits;
+            }
         }
-    }else{
-        for(w = 0; w < group_len; w++){
-            for(i = 0; i < size; i += dim){
-                idx = sce->icoefs[start+i];
-                for(j = 1; j < dim; j++)
-                    idx = idx * range + sce->icoefs[start+i+j];
-                //it turned out that all signed codebooks use the same offset for index coding
-                idx += 40;
-                bits += ff_aac_spectral_bits[cb][idx];
+        put_bits(pb, ff_aac_spectral_bits[cb-1][minidx], ff_aac_spectral_codes[cb-1][minidx]);
+        if(IS_CODEBOOK_UNSIGNED(cb))
+            for(j = 0; j < dim; j++)
+                if(ff_aac_codebook_vectors[cb-1][minidx*dim+j] != 0.0f)
+                    put_bits(pb, 1, in[i+j] < 0.0f);
+        if(cb == ESC_BT){
+            for(j = 0; j < 2; j++){
+                if(ff_aac_codebook_vectors[cb-1][minidx*2+j] == 64.0f){
+                    int coef = quant(in[i+j], IQ);
+                    int len = av_log2(coef);
+
+                    put_bits(pb, len - 4 + 1, (1 << (len - 4 + 1)) - 2);
+                    put_bits(pb, len, coef & ((1 << len) - 1));
+                }
             }
-            start += 128;
         }
     }
-    return bits;
 }
 
 /**
+ * structure used in optimal codebook search
+ */
+typedef struct BandCodingPath {
+    int prev_idx; ///< pointer to the previous path point
+    int codebook; ///< codebook for coding band run
+    float cost;   ///< path cost
+    int run;
+} BandCodingPath;
+
+/**
  * Encode band info for single window group bands.
  */
 static void encode_window_bands_info(AACEncContext *s, SingleChannelElement *sce,
                                      int win, int group_len)
 {
-    BandCodingPath path[64];
-    int band_bits[64][12];
+    BandCodingPath path[120][12];
     int w, swb, cb, start, start2, size;
     int i, j;
     const int max_sfb = sce->ics.max_sfb;
     const int run_bits = sce->ics.num_windows == 1 ? 5 : 3;
     const int run_esc = (1 << run_bits) - 1;
-    int bits, sbits, idx, count;
-    int stack[64], stack_len;
+    int idx, ppos, count;
+    int stackrun[120], stackcb[120], stack_len;
 
     start = win*128;
+    for(cb = 0; cb < 12; cb++){
+        path[0][cb].cost = 0.0f;
+        path[0][cb].prev_idx = -1;
+        path[0][cb].run = 0;
+    }
     for(swb = 0; swb < max_sfb; swb++){
-        int maxval = 0;
         start2 = start;
         size = sce->ics.swb_sizes[swb];
         if(sce->zeroes[win*16 + swb]){
-            maxval = 0;
+            for(cb = 0; cb < 12; cb++){
+                path[swb+1][cb].prev_idx = cb;
+                path[swb+1][cb].cost = path[swb][cb].cost;
+                path[swb+1][cb].run = path[swb][cb].run + 1;
+            }
         }else{
-            for(w = 0; w < group_len; w++){
-                for(i = start2; i < start2 + size; i++){
-                    maxval = FFMAX(maxval, FFABS(sce->icoefs[i]));
+            float minrd = INFINITY;
+            int mincb = 0;
+            for(cb = 0; cb < 12; cb++){
+                float rd = 0.0f;
+                for(w = 0; w < group_len; w++){
+                    FFPsyBand *band = &s->psy.psy_bands[s->cur_channel*PSY_MAX_BANDS+(win+w)*16+swb];
+                    rd += quantize_band_cost(sce->coeffs + start + w*128, size,
+                                             sce->sf_idx[(win+w)*16+swb], cb,
+                                             s->lambda / band->threshold, INFINITY);
                 }
-                start2 += 128;
-            }
-        }
-        sbits = calculate_band_sign_bits(s, sce, group_len, start, size);
-        for(cb = 0; cb < 12; cb++){
-            if(aac_cb_info[cb].maxval < maxval){
-                band_bits[swb][cb] = INT_MAX;
-            }else{
-                band_bits[swb][cb] = calculate_band_bits(s, sce, group_len, start, size, cb);
-                if(IS_CODEBOOK_UNSIGNED(cb-1)){
-                    band_bits[swb][cb] += sbits;
+                if(   run_value_bits[sce->ics.num_windows == 8][path[swb][cb].run]
+                   != run_value_bits[sce->ics.num_windows == 8][path[swb][cb].run+1])
+                    rd += run_bits;
+                path[swb+1][cb].prev_idx = cb;
+                path[swb+1][cb].cost = path[swb][cb].cost + rd;
+                path[swb+1][cb].run = path[swb][cb].run + 1;
+                if(rd < minrd){
+                    minrd = rd;
+                    mincb = cb;
                 }
             }
-        }
-        start += sce->ics.swb_sizes[swb];
-    }
-    path[0].bits = 0;
-    for(i = 1; i <= max_sfb; i++)
-        path[i].bits = INT_MAX;
-    for(i = 0; i < max_sfb; i++){
-        for(cb = 0; cb < 12; cb++){
-            int sum = 0;
-            for(j = 1; j <= max_sfb - i; j++){
-                if(band_bits[i+j-1][cb] == INT_MAX)
-                    break;
-                sum += band_bits[i+j-1][cb];
-                bits = sum + path[i].bits + run_value_bits[sce->ics.num_windows == 8][j];
-                if(bits < path[i+j].bits){
-                    path[i+j].bits     = bits;
-                    path[i+j].codebook = cb;
-                    path[i+j].prev_idx = i;
+            for(cb = 0; cb < 12; cb++){
+                float cost = path[swb][cb].cost + minrd + run_bits + 4;
+                if(cost < path[swb+1][cb].cost){
+                    path[swb+1][cb].prev_idx = mincb;
+                    path[swb+1][cb].cost = cost;
+                    path[swb+1][cb].run = 1;
                 }
             }
         }
+        start += sce->ics.swb_sizes[swb];
     }
-    assert(path[max_sfb].bits != INT_MAX);
 
     //convert resulting path from backward-linked list
     stack_len = 0;
-    idx = max_sfb;
-    while(idx > 0){
-        stack[stack_len++] = idx;
-        idx = path[idx].prev_idx;
+    idx = 0;
+    for(cb = 1; cb < 12; cb++){
+        if(path[max_sfb][cb].cost < path[max_sfb][idx].cost)
+            idx = cb;
+    }
+    ppos = max_sfb;
+    while(ppos > 0){
+        cb = idx;
+        stackrun[stack_len] = path[ppos][cb].run;
+        stackcb [stack_len] = cb;
+        idx = path[ppos][cb].prev_idx;
+        ppos -= path[ppos][cb].run;
+        stack_len++;
     }
-
     //perform actual band info encoding
     start = 0;
     for(i = stack_len - 1; i >= 0; i--){
-        put_bits(&s->pb, 4, path[stack[i]].codebook);
-        count = stack[i] - path[stack[i]].prev_idx;
-        memset(sce->zeroes + win*16 + start, !path[stack[i]].codebook, count);
+        put_bits(&s->pb, 4, stackcb[i]);
+        count = stackrun[i];
+        memset(sce->zeroes + win*16 + start, !stackcb[i], count);
         //XXX: memset when band_type is also uint8_t
         for(j = 0; j < count; j++){
-            sce->band_type[win*16 + start] =  path[stack[i]].codebook;
+            sce->band_type[win*16 + start] =  stackcb[i];
             start++;
         }
         while(count >= run_esc){
@@ -598,7 +628,7 @@ static void encode_window_bands_info(AAC
 /**
  * Produce integer coefficients from scalefactors provided by the model.
  */
-static void quantize_coeffs(AACEncContext *apc, ChannelElement *cpe, int chans)
+static void adjust_frame_information(AACEncContext *apc, ChannelElement *cpe, int chans)
 {
     int i, w, w2, g, ch;
     int start, sum, maxsfb, cmaxsfb;
@@ -618,14 +648,6 @@ static void quantize_coeffs(AACEncContex
                         cpe->ch[1].coeffs[start+i] =  cpe->ch[0].coeffs[start+i] - cpe->ch[1].coeffs[start+i];
                     }
                 }
-                if(!cpe->ch[ch].zeroes[w + g])
-                    sum = quantize_band(cpe->ch[ch].coeffs + start,
-                                        cpe->ch[ch].icoefs + start,
-                                        ics->swb_sizes[g],
-                                        cpe->ch[ch].sf_idx[w + g]);
-                else
-                    memset(cpe->ch[ch].icoefs + start, 0, ics->swb_sizes[g] * sizeof(cpe->ch[0].icoefs[0]));
-                cpe->ch[ch].zeroes[w + g] = !sum;
                 start += ics->swb_sizes[g];
             }
             for(cmaxsfb = ics->num_swb; cmaxsfb > 0 && cpe->ch[ch].zeroes[w+cmaxsfb-1]; cmaxsfb--);
@@ -669,200 +691,191 @@ typedef struct TrellisPath {
     int max_val;
 } TrellisPath;
 
-static void search_for_quantizers(AACEncContext *s, ChannelElement *cpe, int channels)
+static void search_for_quantizers_anmr(AACEncContext *s, SingleChannelElement *sce, const float lambda)
 {
-    int q, ch, w, w2, g, start = 0;
+    int q, w, w2, g, start = 0;
     int i;
-    int qcoeffs[128];
     int idx;
     TrellisPath paths[256*121];
     int bandaddr[121];
-    const float lambda = 5e-7f;
     int minq;
     float mincost;
 
-    for(ch = 0; ch < channels; ch++){
-        SingleChannelElement *sce = &cpe->ch[ch];
-        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; 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;
-                int nz = 0;
+    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; 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;
+            int nz = 0;
 
-                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);
-                    }
+            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;
                 }
-                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 + 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;
-                            }
+                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;
+                float minrd = INFINITY;
+                //minimum scalefactor index is when minimum 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 dists[12], dist;
+                    memset(dists, 0, sizeof(dists));
+                    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];
+                        int cb;
+                        for(cb = 0; cb <= ESC_BT; cb++){
+                            dists[cb] += quantize_band_cost(coefs + w2*128, sce->ics.swb_sizes[g],
+                                                            q, cb, s->lambda / band->threshold, INFINITY);
                         }
                     }
-                }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);
+                    dist = dists[0];
+                    for(i = 1; i <= ESC_BT; i++)
+                        dist = fminf(dist, dists[i]);
+                    minrd = fminf(minrd, dist);
+
+                    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 + dist
+                               + 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;
                         }
-                        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;
-                            }
+                    }
+                }
+            }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;
+                    }
+                    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;
-            }
-        }
-        idx -= 256;
-        mincost = paths[idx].cost;
-        minq = idx;
-        for(i = 1; i < 256; i++){
-            if(paths[idx + i].cost < mincost){
-                mincost = paths[idx + i].cost;
-                minq = idx + i;
             }
+            sce->zeroes[w*16+g] = !nz;
+            start += sce->ics.swb_sizes[g];
+            idx += 256;
         }
-        while(minq >= 256){
-            sce->sf_idx[bandaddr[minq>>8]] = minq & 0xFF;
-            minq = paths[minq].prev;
+    }
+    idx -= 256;
+    mincost = paths[idx].cost;
+    minq = idx;
+    for(i = 1; i < 256; i++){
+        if(paths[idx + i].cost < mincost){
+            mincost = paths[idx + i].cost;
+            minq = idx + i;
         }
-        //set the same quantizers inside window groups
-        for(w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w])
-            for(g = 0;  g < sce->ics.num_swb; g++)
-                for(w2 = 1; w2 < sce->ics.group_len[w]; w2++)
-                    sce->sf_idx[(w+w2)*16+g] = sce->sf_idx[w*16+g];
     }
+    while(minq >= 256){
+        sce->sf_idx[bandaddr[minq>>8]] = minq & 0xFF;
+        minq = paths[minq].prev;
+    }
+    //set the same quantizers inside window groups
+    for(w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w])
+        for(g = 0;  g < sce->ics.num_swb; g++)
+            for(w2 = 1; w2 < sce->ics.group_len[w]; w2++)
+                sce->sf_idx[(w+w2)*16+g] = sce->sf_idx[w*16+g];
 }
 
-/**
- * Encode the coefficients of one scalefactor band with selected codebook.
- */
-static void encode_band_coeffs(AACEncContext *s, SingleChannelElement *sce,
-                               int start, int size, int cb)
+static void search_for_ms(AACEncContext *s, ChannelElement *cpe, const float lambda)
 {
-    const uint8_t  *bits  = ff_aac_spectral_bits [cb - 1];
-    const uint16_t *codes = ff_aac_spectral_codes[cb - 1];
-    const int range = aac_cb_info[cb].range;
-    const int dim = (cb < FIRST_PAIR_BT) ? 4 : 2;
-    int i, j, idx;
-
-    //do not encode zero or special codebooks
-    if(range == -1) return;
-
-    if(cb == ESC_BT){
-        int coef_abs[2];
-        for(i = start; i < start + size; i += 2){
-            idx = 0;
-            for(j = 0; j < 2; j++){
-                coef_abs[j] = FFABS(sce->icoefs[i+j]);
-                idx = idx*17 + FFMIN(coef_abs[j], 16);
-            }
-            put_bits(&s->pb, bits[idx], codes[idx]);
-            //output signs
-            for(j = 0; j < 2; j++)
-                if(sce->icoefs[i+j])
-                    put_bits(&s->pb, 1, sce->icoefs[i+j] < 0);
-            //output escape values
-            for(j = 0; j < 2; j++){
-                if(coef_abs[j] > 15){
-                    int len = av_log2(coef_abs[j]);
-
-                    put_bits(&s->pb, len - 4 + 1, (1 << (len - 4 + 1)) - 2);
-                    put_bits(&s->pb, len, coef_abs[j] & ((1 << len) - 1));
+    int start = 0, i, w, w2, g;
+    float M[128], S[128];
+    SingleChannelElement *sce0 = &cpe->ch[0];
+    SingleChannelElement *sce1 = &cpe->ch[1];
+    if(!cpe->common_window)
+        return;
+    for(w = 0; w < sce0->ics.num_windows; w += sce0->ics.group_len[w]){
+        for(g = 0;  g < sce0->ics.num_swb; g++){
+            if(!cpe->ch[0].zeroes[w*16+g] && !cpe->ch[1].zeroes[w*16+g]){
+                float dist1 = 0.0f, dist2 = 0.0f;
+                for(w2 = 0; w2 < sce0->ics.group_len[w]; w2++){
+                    FFPsyBand *band0 = &s->psy.psy_bands[(s->cur_channel+0)*PSY_MAX_BANDS+(w+w2)*16+g];
+                    FFPsyBand *band1 = &s->psy.psy_bands[(s->cur_channel+1)*PSY_MAX_BANDS+(w+w2)*16+g];
+                    float minthr = fminf(band0->threshold, band1->threshold);
+                    float maxthr = fmaxf(band0->threshold, band1->threshold);
+                    for(i = 0; i < sce0->ics.swb_sizes[g]; i++){
+                        M[i] = (sce0->coeffs[start+w2*128+i]
+                              + sce1->coeffs[start+w2*128+i])*0.5;
+                        S[i] =  sce0->coeffs[start+w2*128+i]
+                              - sce1->coeffs[start+w2*128+i];
+                    }
+                    dist1 += quantize_band_cost(sce0->coeffs + start + w2*128,
+                                                sce0->ics.swb_sizes[g],
+                                                sce0->sf_idx[(w+w2)*16+g],
+                                                sce0->band_type[(w+w2)*16+g],
+                                                lambda / band0->threshold, INFINITY);
+                    dist1 += quantize_band_cost(sce1->coeffs + start + w2*128,
+                                                sce1->ics.swb_sizes[g],
+                                                sce1->sf_idx[(w+w2)*16+g],
+                                                sce1->band_type[(w+w2)*16+g],
+                                                lambda / band1->threshold, INFINITY);
+                    dist2 += quantize_band_cost(M,
+                                                sce0->ics.swb_sizes[g],
+                                                sce0->sf_idx[(w+w2)*16+g],
+                                                sce0->band_type[(w+w2)*16+g],
+                                                lambda / maxthr, INFINITY);
+                    dist2 += quantize_band_cost(S,
+                                                sce1->ics.swb_sizes[g],
+                                                sce1->sf_idx[(w+w2)*16+g],
+                                                sce1->band_type[(w+w2)*16+g],
+                                                lambda / minthr, INFINITY);
                 }
+                cpe->ms_mask[w*16+g] = dist2 < dist1;
             }
-        }
-    }else if(IS_CODEBOOK_UNSIGNED(cb)){
-        for(i = start; i < start + size; i += dim){
-            idx = FFABS(sce->icoefs[i]);
-            for(j = 1; j < dim; j++)
-                idx = idx * range + FFABS(sce->icoefs[i+j]);
-            put_bits(&s->pb, bits[idx], codes[idx]);
-            //output signs
-            for(j = 0; j < dim; j++)
-                if(sce->icoefs[i+j])
-                    put_bits(&s->pb, 1, sce->icoefs[i+j] < 0);
-        }
-    }else{
-        for(i = start; i < start + size; i += dim){
-            idx = sce->icoefs[i];
-            for(j = 1; j < dim; j++)
-                idx = idx * range + sce->icoefs[i+j];
-            //it turned out that all signed codebooks use the same offset for index coding
-            idx += 40;
-            put_bits(&s->pb, bits[idx], codes[idx]);
+            start += sce0->ics.swb_sizes[g];
         }
     }
 }
@@ -932,9 +945,11 @@ static void encode_spectral_coeffs(AACEn
                 continue;
             }
             for(w2 = w; w2 < w + sce->ics.group_len[w]; w2++){
-                encode_band_coeffs(s, sce, start + w2*128,
-                                   sce->ics.swb_sizes[i],
-                                   sce->band_type[w*16 + i]);
+                quantize_and_encode_band(&s->pb, sce->coeffs + start + w2*128,
+                                         sce->ics.swb_sizes[i],
+                                         sce->sf_idx[w*16 + i],
+                                         sce->band_type[w*16 + i],
+                                         s->lambda);
             }
             start += sce->ics.swb_sizes[i];
         }
@@ -1022,6 +1037,7 @@ static int aac_encode_frame(AVCodecConte
         samples2 = samples + start_ch;
         la = samples2 + 1024 * avctx->channels + start_ch;
         if(!data) la = NULL;
+        s->lambda = 5e-7f;
         for(j = 0; j < chans; j++){
             IndividualChannelStream *ics = &cpe->ch[j].ics;
             int k;
@@ -1036,7 +1052,9 @@ static int aac_encode_frame(AVCodecConte
             for(k = 0; k < ics->num_windows; k++)
                 ics->group_len[k] = wi[j].grouping[k];
 
+            s->cur_channel = start_ch + j;
             apply_window_and_mdct(avctx, s, &cpe->ch[j], samples2, j);
+            search_for_quantizers_anmr(s, &cpe->ch[j], s->lambda);
         }
         cpe->common_window = 0;
         if(chans > 1
@@ -1051,8 +1069,8 @@ static int aac_encode_frame(AVCodecConte
                 }
             }
         }
-        search_for_quantizers(s, cpe, chans);
-        quantize_coeffs(s, cpe, chans);
+//        search_for_ms(s, cpe, s->lambda);
+        adjust_frame_information(s, cpe, chans);
         put_bits(&s->pb, 3, tag);
         put_bits(&s->pb, 4, chan_el_counter[tag]++);
         if(chans == 2){



More information about the FFmpeg-soc mailing list