summaryrefslogtreecommitdiff
path: root/libavcodec/aaccoder.c
diff options
context:
space:
mode:
authorAlex Converse <alex.converse@gmail.com>2010-05-25 18:28:18 +0000
committerAlex Converse <alex.converse@gmail.com>2010-05-25 18:28:18 +0000
commit144c5e3dd248dcd621644499f8f5e6168993ae62 (patch)
tree3a0d0bd25aaa8487b28a8b07f359d0228e168f0d /libavcodec/aaccoder.c
parent05e659ef833b53d22244e60d963c60ce821efe8d (diff)
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. Originally committed as revision 23317 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavcodec/aaccoder.c')
-rw-r--r--libavcodec/aaccoder.c78
1 files changed, 52 insertions, 26 deletions
diff --git a/libavcodec/aaccoder.c b/libavcodec/aaccoder.c
index 8a92f3c736..f67657292d 100644
--- a/libavcodec/aaccoder.c
+++ b/libavcodec/aaccoder.c
@@ -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(AACEncContext *s, SingleChannelElement *sce,
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(AVCodecContext *avctx, AACEncContext *s,
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(AVCodecContext *avctx, AACEncContext *s,
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(AVCodecContext *avctx, AACEncContext *s,
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(AVCodecContext *avctx, AACEncContext *s,
}
}
while (idx) {
- sce->sf_idx[bandaddr[idx]] = minq;
+ sce->sf_idx[bandaddr[idx]] = minq + q0;
minq = paths[idx][minq].prev;
idx--;
}