Commit 1b69f8d8 authored by alexc's avatar alexc

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.


git-svn-id: file:///var/local/repositories/ffmpeg/trunk@23317 9553f0bf-9b14-0410-a0b8-cfaf0461ba5b
parent c2dcaa9b
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
* add sane pulse detection * add sane pulse detection
***********************************/ ***********************************/
#include <float.h>
#include "avcodec.h" #include "avcodec.h"
#include "put_bits.h" #include "put_bits.h"
#include "aac.h" #include "aac.h"
...@@ -462,12 +463,10 @@ static void codebook_trellis_rate(AACEncContext *s, SingleChannelElement *sce, ...@@ -462,12 +463,10 @@ static void codebook_trellis_rate(AACEncContext *s, SingleChannelElement *sce,
typedef struct TrellisPath { typedef struct TrellisPath {
float cost; float cost;
int prev; int prev;
int min_val;
int max_val;
} TrellisPath; } TrellisPath;
#define TRELLIS_STAGES 121 #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, static void search_for_quantizers_anmr(AVCodecContext *avctx, AACEncContext *s,
SingleChannelElement *sce, SingleChannelElement *sce,
...@@ -480,19 +479,56 @@ static void search_for_quantizers_anmr(AVCodecContext *avctx, AACEncContext *s, ...@@ -480,19 +479,56 @@ static void search_for_quantizers_anmr(AVCodecContext *avctx, AACEncContext *s,
int bandaddr[TRELLIS_STAGES]; int bandaddr[TRELLIS_STAGES];
int minq; int minq;
float mincost; 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++) { for (i = 0; i < TRELLIS_STATES; i++) {
paths[0][i].cost = 0.0f; paths[0][i].cost = 0.0f;
paths[0][i].prev = -1; 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 (j = 1; j < TRELLIS_STAGES; j++) {
for (i = 0; i < TRELLIS_STATES; i++) { for (i = 0; i < TRELLIS_STATES; i++) {
paths[j][i].cost = INFINITY; paths[j][i].cost = INFINITY;
paths[j][i].prev = -2; paths[j][i].prev = -2;
paths[j][i].min_val = INT_MAX;
paths[j][i].max_val = 0;
} }
} }
idx = 1; idx = 1;
...@@ -529,6 +565,8 @@ static void search_for_quantizers_anmr(AVCodecContext *avctx, AACEncContext *s, ...@@ -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); 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 //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); 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++) { for (q = minscale; q < maxscale; q++) {
float dists[12], dist; float dists[12], dist;
memset(dists, 0, sizeof(dists)); memset(dists, 0, sizeof(dists));
...@@ -537,52 +575,40 @@ static void search_for_quantizers_anmr(AVCodecContext *avctx, AACEncContext *s, ...@@ -537,52 +575,40 @@ static void search_for_quantizers_anmr(AVCodecContext *avctx, AACEncContext *s,
int cb; int cb;
for (cb = 0; cb <= ESC_BT; 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], 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]; dist = dists[0];
for (i = 1; i <= ESC_BT; i++) for (i = 1; i <= ESC_BT; i++)
dist = FFMIN(dist, dists[i]); dist = FFMIN(dist, dists[i]);
minrd = FFMIN(minrd, dist); 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; float cost;
int minv, maxv;
if (isinf(paths[idx - 1][i].cost)) if (isinf(paths[idx - 1][i].cost))
continue; continue;
cost = paths[idx - 1][i].cost + dist cost = paths[idx - 1][i].cost + dist
+ ff_aac_scalefactor_bits[q - i + SCALE_DIFF_ZERO]; + ff_aac_scalefactor_bits[q - i + SCALE_DIFF_ZERO];
minv = FFMIN(paths[idx - 1][i].min_val, q); if (cost < paths[idx][q].cost) {
maxv = FFMAX(paths[idx - 1][i].max_val, q);
if (cost < paths[idx][q].cost && maxv-minv < SCALE_MAX_DIFF) {
paths[idx][q].cost = cost; paths[idx][q].cost = cost;
paths[idx][q].prev = i; paths[idx][q].prev = i;
paths[idx][q].min_val = minv;
paths[idx][q].max_val = maxv;
} }
} }
} }
} else { } else {
for (q = 0; q < TRELLIS_STATES; q++) { for (q = 0; q < q1 - q0; q++) {
if (!isinf(paths[idx - 1][q].cost)) { if (!isinf(paths[idx - 1][q].cost)) {
paths[idx][q].cost = paths[idx - 1][q].cost + 1; paths[idx][q].cost = paths[idx - 1][q].cost + 1;
paths[idx][q].prev = q; 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; 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; float cost;
int minv, maxv;
if (isinf(paths[idx - 1][i].cost)) if (isinf(paths[idx - 1][i].cost))
continue; continue;
cost = paths[idx - 1][i].cost + ff_aac_scalefactor_bits[q - i + SCALE_DIFF_ZERO]; cost = paths[idx - 1][i].cost + ff_aac_scalefactor_bits[q - i + SCALE_DIFF_ZERO];
minv = FFMIN(paths[idx - 1][i].min_val, q); if (cost < paths[idx][q].cost) {
maxv = FFMAX(paths[idx - 1][i].max_val, q);
if (cost < paths[idx][q].cost && maxv-minv < SCALE_MAX_DIFF) {
paths[idx][q].cost = cost; paths[idx][q].cost = cost;
paths[idx][q].prev = i; 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, ...@@ -602,7 +628,7 @@ static void search_for_quantizers_anmr(AVCodecContext *avctx, AACEncContext *s,
} }
} }
while (idx) { while (idx) {
sce->sf_idx[bandaddr[idx]] = minq; sce->sf_idx[bandaddr[idx]] = minq + q0;
minq = paths[idx][minq].prev; minq = paths[idx][minq].prev;
idx--; idx--;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment