[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