diff options
Diffstat (limited to 'libavcodec/aaccoder.c')
-rw-r--r-- | libavcodec/aaccoder.c | 78 |
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--; } |