summaryrefslogtreecommitdiff
path: root/libavcodec/aaccoder_twoloop.h
diff options
context:
space:
mode:
Diffstat (limited to 'libavcodec/aaccoder_twoloop.h')
-rw-r--r--libavcodec/aaccoder_twoloop.h136
1 files changed, 93 insertions, 43 deletions
diff --git a/libavcodec/aaccoder_twoloop.h b/libavcodec/aaccoder_twoloop.h
index d4290b4023..397a4db5e5 100644
--- a/libavcodec/aaccoder_twoloop.h
+++ b/libavcodec/aaccoder_twoloop.h
@@ -76,6 +76,7 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx,
int refbits = destbits;
int toomanybits, toofewbits;
char nzs[128];
+ uint8_t nextband[128];
int maxsf[128];
float dists[128] = { 0 }, qenergies[128] = { 0 }, uplims[128], euplims[128], energies[128];
float maxvals[128], spread_thr_r[128];
@@ -102,7 +103,7 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx,
*/
float sfoffs = av_clipf(log2f(120.0f / lambda) * 4.0f, -5, 10);
- int fflag, minscaler, maxscaler, nminscaler, minrdsf;
+ int fflag, minscaler, maxscaler, nminscaler;
int its = 0;
int maxits = 30;
int allz = 0;
@@ -158,9 +159,13 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx,
/** search further */
maxits *= 2;
} else {
- /** When using ABR, be strict */
- toomanybits = destbits + destbits/16;
- toofewbits = destbits - destbits/4;
+ /* When using ABR, be strict, but a reasonable leeway is
+ * critical to allow RC to smoothly track desired bitrate
+ * without sudden quality drops that cause audible artifacts.
+ * Symmetry is also desirable, to avoid systematic bias.
+ */
+ toomanybits = destbits + destbits/8;
+ toofewbits = destbits - destbits/8;
sfoffs = 0;
rdlambda = sqrtf(rdlambda);
@@ -191,6 +196,7 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx,
bandwidth = avctx->cutoff;
} else {
bandwidth = FFMAX(3000, AAC_CUTOFF_FROM_BITRATE(frame_bit_rate, 1, avctx->sample_rate));
+ s->psy.cutoff = bandwidth;
}
cutoff = bandwidth * 2 * wlen / avctx->sample_rate;
@@ -241,7 +247,7 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx,
nzs[w*16+g] = nz;
sce->zeroes[w*16+g] = !nz;
allz |= nz;
- if (nz) {
+ if (nz && sce->can_pns[w*16+g]) {
spread_thr_r[w*16+g] = energy * nz / (uplim * spread);
if (min_spread_thr_r < 0) {
min_spread_thr_r = max_spread_thr_r = spread_thr_r[w*16+g];
@@ -433,6 +439,7 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx,
} while (qstep);
overdist = 1;
+ fflag = tbits < toofewbits;
for (i = 0; i < 2 && (overdist || recomprd); ++i) {
if (recomprd) {
/** Must recompute distortion */
@@ -484,13 +491,13 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx,
}
}
}
- if (!i && s->options.pns && its > maxits/2) {
+ if (!i && s->options.pns && its > maxits/2 && tbits > toofewbits) {
float maxoverdist = 0.0f;
+ float ovrfactor = 1.f+(maxits-its)*16.f/maxits;
overdist = recomprd = 0;
for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) {
- float ovrfactor = 2.f+(maxits-its)*16.f/maxits;
for (g = start = 0; g < sce->ics.num_swb; start += sce->ics.swb_sizes[g++]) {
- if (!sce->zeroes[w*16+g] && dists[w*16+g] > uplims[w*16+g]*ovrfactor) {
+ if (!sce->zeroes[w*16+g] && sce->sf_idx[w*16+g] > SCALE_ONE_POS && dists[w*16+g] > uplims[w*16+g]*ovrfactor) {
float ovrdist = dists[w*16+g] / FFMAX(uplims[w*16+g],euplims[w*16+g]);
maxoverdist = FFMAX(maxoverdist, ovrdist);
overdist++;
@@ -506,7 +513,7 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx,
float zspread;
int zeroable = 0;
int zeroed = 0;
- int maxzeroed;
+ int maxzeroed, zloop;
for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) {
for (g = start = 0; g < sce->ics.num_swb; start += sce->ics.swb_sizes[g++]) {
if (start >= pns_start_pos && !sce->zeroes[w*16+g] && sce->can_pns[w*16+g]) {
@@ -517,21 +524,41 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx,
}
}
zspread = (maxspread-minspread) * 0.0125f + minspread;
- zspread = FFMIN(maxoverdist, zspread);
- maxzeroed = zeroable * its / (2 * maxits);
- for (g = sce->ics.num_swb-1; g > 0 && zeroed < maxzeroed; g--) {
- if (sce->ics.swb_offset[g] < pns_start_pos)
- continue;
- for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) {
- if (!sce->zeroes[w*16+g] && sce->can_pns[w*16+g] && spread_thr_r[w*16+g] <= zspread) {
- sce->zeroes[w*16+g] = 1;
- sce->band_type[w*16+g] = 0;
- zeroed++;
+ /* Don't PNS everything even if allowed. It suppresses bit starvation signals from RC,
+ * and forced the hand of the later search_for_pns step.
+ * Instead, PNS a fraction of the spread_thr_r range depending on how starved for bits we are,
+ * and leave further PNSing to search_for_pns if worthwhile.
+ */
+ zspread = FFMIN3(min_spread_thr_r * 8.f, zspread,
+ ((toomanybits - tbits) * min_spread_thr_r + (tbits - toofewbits) * max_spread_thr_r) / (toomanybits - toofewbits + 1));
+ maxzeroed = FFMIN(zeroable, FFMAX(1, (zeroable * its + maxits - 1) / (2 * maxits)));
+ for (zloop = 0; zloop < 2; zloop++) {
+ /* Two passes: first distorted stuff - two birds in one shot and all that,
+ * then anything viable. Viable means not zero, but either CB=zero-able
+ * (too high SF), not SF <= 1 (that means we'd be operating at very high
+ * quality, we don't want PNS when doing VHQ), PNS allowed, and within
+ * the lowest ranking percentile.
+ */
+ float loopovrfactor = (zloop) ? 1.0f : ovrfactor;
+ int loopminsf = (zloop) ? (SCALE_ONE_POS - SCALE_DIV_512) : SCALE_ONE_POS;
+ int mcb;
+ for (g = sce->ics.num_swb-1; g > 0 && zeroed < maxzeroed; g--) {
+ if (sce->ics.swb_offset[g] < pns_start_pos)
+ continue;
+ for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) {
+ if (!sce->zeroes[w*16+g] && sce->can_pns[w*16+g] && spread_thr_r[w*16+g] <= zspread
+ && sce->sf_idx[w*16+g] > loopminsf
+ && (dists[w*16+g] > loopovrfactor*uplims[w*16+g] || !(mcb = find_min_book(maxvals[w*16+g], sce->sf_idx[w*16+g]))
+ || (mcb <= 1 && dists[w*16+g] > FFMIN(uplims[w*16+g], euplims[w*16+g]))) ) {
+ sce->zeroes[w*16+g] = 1;
+ sce->band_type[w*16+g] = 0;
+ zeroed++;
+ }
}
}
}
if (zeroed)
- recomprd = 1;
+ recomprd = fflag = 1;
} else {
overdist = 0;
}
@@ -549,9 +576,8 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx,
}
}
- fflag = 0;
minscaler = nminscaler = av_clip(minscaler, SCALE_ONE_POS - SCALE_DIV_512, SCALE_MAX_POS - SCALE_DIV_512);
- minrdsf = FFMAX3(60, minscaler - 1, maxscaler - SCALE_MAX_DIFF - 1);
+ prev = -1;
for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) {
/** Start with big steps, end up fine-tunning */
int depth = (its > maxits/2) ? ((its > maxits*2/3) ? 1 : 3) : 10;
@@ -561,19 +587,22 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx,
start = w * 128;
for (g = 0; g < sce->ics.num_swb; g++) {
int prevsc = sce->sf_idx[w*16+g];
- int minrdsfboost = (sce->ics.num_windows > 1) ? av_clip(g-4, -2, 0) : av_clip(g-16, -4, 0);
+ if (prev < 0 && !sce->zeroes[w*16+g])
+ prev = sce->sf_idx[0];
if (!sce->zeroes[w*16+g]) {
const float *coefs = sce->coeffs + start;
const float *scaled = s->scoefs + start;
int cmb = find_min_book(maxvals[w*16+g], sce->sf_idx[w*16+g]);
- if ((!cmb || dists[w*16+g] > uplims[w*16+g]) && sce->sf_idx[w*16+g] > minrdsf) {
+ int mindeltasf = FFMAX(0, prev - SCALE_MAX_DIFF);
+ int maxdeltasf = FFMIN(SCALE_MAX_POS - SCALE_DIV_512, prev + SCALE_MAX_DIFF);
+ if ((!cmb || dists[w*16+g] > uplims[w*16+g]) && sce->sf_idx[w*16+g] > mindeltasf) {
/* Try to make sure there is some energy in every nonzero band
* NOTE: This algorithm must be forcibly imbalanced, pushing harder
* on holes or more distorted bands at first, otherwise there's
* no net gain (since the next iteration will offset all bands
* on the opposite direction to compensate for extra bits)
*/
- for (i = 0; i < edepth; ++i) {
+ for (i = 0; i < edepth && sce->sf_idx[w*16+g] > mindeltasf; ++i) {
int cb, bits;
float dist, qenergy;
int mb = find_min_book(maxvals[w*16+g], sce->sf_idx[w*16+g]-1);
@@ -585,6 +614,12 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx,
} else if (i >= depth && dists[w*16+g] < euplims[w*16+g]) {
break;
}
+ /* !g is the DC band, it's important, since quantization error here
+ * applies to less than a cycle, it creates horrible intermodulation
+ * distortion if it doesn't stick to what psy requests
+ */
+ if (!g && sce->ics.num_windows > 1 && dists[w*16+g] >= euplims[w*16+g])
+ maxsf[w*16+g] = FFMIN(sce->sf_idx[w*16+g], maxsf[w*16+g]);
for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) {
int b;
float sqenergy;
@@ -603,19 +638,19 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx,
sce->sf_idx[w*16+g]--;
dists[w*16+g] = dist - bits;
qenergies[w*16+g] = qenergy;
- if (mb && (sce->sf_idx[w*16+g] < (minrdsf+minrdsfboost) || (
+ if (mb && (sce->sf_idx[w*16+g] < mindeltasf || (
(dists[w*16+g] < FFMIN(uplmax*uplims[w*16+g], euplims[w*16+g]))
&& (fabsf(qenergies[w*16+g]-energies[w*16+g]) < euplims[w*16+g])
) )) {
break;
}
}
- } else if (tbits > toofewbits && sce->sf_idx[w*16+g] < maxscaler
+ } else if (tbits > toofewbits && sce->sf_idx[w*16+g] < FFMIN(maxdeltasf, maxsf[w*16+g])
&& (dists[w*16+g] < FFMIN(euplims[w*16+g], uplims[w*16+g]))
&& (fabsf(qenergies[w*16+g]-energies[w*16+g]) < euplims[w*16+g])
) {
/** Um... over target. Save bits for more important stuff. */
- for (i = 0; i < depth; ++i) {
+ for (i = 0; i < depth && sce->sf_idx[w*16+g] < maxdeltasf; ++i) {
int cb, bits;
float dist, qenergy;
cb = find_min_book(maxvals[w*16+g], sce->sf_idx[w*16+g]+1);
@@ -651,38 +686,53 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx,
}
}
}
+ prev = sce->sf_idx[w*16+g] = av_clip(sce->sf_idx[w*16+g], mindeltasf, maxdeltasf);
+ if (sce->sf_idx[w*16+g] != prevsc)
+ fflag = 1;
+ nminscaler = FFMIN(nminscaler, sce->sf_idx[w*16+g]);
+ sce->band_type[w*16+g] = find_min_book(maxvals[w*16+g], sce->sf_idx[w*16+g]);
}
- sce->sf_idx[w*16+g] = av_clip(sce->sf_idx[w*16+g], minrdsf, minscaler + SCALE_MAX_DIFF);
- sce->sf_idx[w*16+g] = FFMIN(sce->sf_idx[w*16+g], SCALE_MAX_POS - SCALE_DIV_512);
- if (sce->sf_idx[w*16+g] != prevsc)
- fflag = 1;
- nminscaler = FFMIN(nminscaler, sce->sf_idx[w*16+g]);
- sce->band_type[w*16+g] = find_min_book(maxvals[w*16+g], sce->sf_idx[w*16+g]);
start += sce->ics.swb_sizes[g];
}
}
- if (nminscaler < minscaler || sce->ics.num_windows > 1) {
- /** SF difference limit violation risk. Must re-clamp. */
- minscaler = nminscaler;
- for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) {
- for (g = 0; g < sce->ics.num_swb; g++) {
- sce->sf_idx[w*16+g] = av_clip(sce->sf_idx[w*16+g], minscaler, minscaler + SCALE_MAX_DIFF);
+
+ /** SF difference limit violation risk. Must re-clamp. */
+ prev = -1;
+ for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) {
+ for (g = 0; g < sce->ics.num_swb; g++) {
+ if (!sce->zeroes[w*16+g]) {
+ int prevsf = sce->sf_idx[w*16+g];
+ if (prev < 0)
+ prev = prevsf;
+ sce->sf_idx[w*16+g] = av_clip(sce->sf_idx[w*16+g], prev - SCALE_MAX_DIFF, prev + SCALE_MAX_DIFF);
sce->band_type[w*16+g] = find_min_book(maxvals[w*16+g], sce->sf_idx[w*16+g]);
+ prev = sce->sf_idx[w*16+g];
+ if (!fflag && prevsf != sce->sf_idx[w*16+g])
+ fflag = 1;
}
}
}
+
its++;
} while (fflag && its < maxits);
+ /** Scout out next nonzero bands */
+ ff_init_nextband_map(sce, nextband);
+
prev = -1;
for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) {
/** Make sure proper codebooks are set */
- for (g = start = 0; g < sce->ics.num_swb; start += sce->ics.swb_sizes[g++]) {
+ for (g = 0; g < sce->ics.num_swb; g++) {
if (!sce->zeroes[w*16+g]) {
sce->band_type[w*16+g] = find_min_book(maxvals[w*16+g], sce->sf_idx[w*16+g]);
if (sce->band_type[w*16+g] <= 0) {
- sce->zeroes[w*16+g] = 1;
- sce->band_type[w*16+g] = 0;
+ if (!ff_sfdelta_can_remove_band(sce, nextband, prev, w*16+g)) {
+ /** Cannot zero out, make sure it's not attempted */
+ sce->band_type[w*16+g] = 1;
+ } else {
+ sce->zeroes[w*16+g] = 1;
+ sce->band_type[w*16+g] = 0;
+ }
}
} else {
sce->band_type[w*16+g] = 0;