summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libavcodec/aaccoder.c60
-rw-r--r--libavcodec/aaccoder_twoloop.h136
-rw-r--r--libavcodec/aacenc.c2
-rw-r--r--libavcodec/aacenc_is.c11
-rw-r--r--libavcodec/aacenc_utils.h63
-rw-r--r--libavcodec/aacpsy.c20
-rw-r--r--libavcodec/mips/aaccoder_mips.c172
-rw-r--r--libavcodec/mips/aacpsy_mips.h78
-rw-r--r--libavcodec/psymodel.c1
-rw-r--r--libavcodec/psymodel.h1
-rw-r--r--tests/fate/aac.mak26
11 files changed, 393 insertions, 177 deletions
diff --git a/libavcodec/aaccoder.c b/libavcodec/aaccoder.c
index 2a66045c8e..2a0cb1f6b5 100644
--- a/libavcodec/aaccoder.c
+++ b/libavcodec/aaccoder.c
@@ -54,7 +54,7 @@
/* Parameter of f(x) = a*(lambda/100), defines the maximum fourier spread
* beyond which no PNS is used (since the SFBs contain tone rather than noise) */
-#define NOISE_SPREAD_THRESHOLD 0.5073f
+#define NOISE_SPREAD_THRESHOLD 0.9f
/* Parameter of f(x) = a*(100/lambda), defines how much PNS is allowed to
* replace low energy non zero bands */
@@ -591,6 +591,7 @@ static void search_for_pns(AACEncContext *s, AVCodecContext *avctx, SingleChanne
int bandwidth, cutoff;
float *PNS = &s->scoefs[0*128], *PNS34 = &s->scoefs[1*128];
float *NOR34 = &s->scoefs[3*128];
+ uint8_t nextband[128];
const float lambda = s->lambda;
const float freq_mult = avctx->sample_rate*0.5f/wlen;
const float thr_mult = NOISE_LAMBDA_REPLACE*(100.0f/lambda);
@@ -604,6 +605,7 @@ static void search_for_pns(AACEncContext *s, AVCodecContext *avctx, SingleChanne
/** Keep this in sync with twoloop's cutoff selection */
float rate_bandwidth_multiplier = 1.5f;
+ int prev = -1000, prev_sf = -1;
int frame_bit_rate = (avctx->flags & CODEC_FLAG_QSCALE)
? (refbits * rate_bandwidth_multiplier * avctx->sample_rate / 1024)
: (avctx->bit_rate / avctx->channels);
@@ -619,6 +621,7 @@ static void search_for_pns(AACEncContext *s, AVCodecContext *avctx, SingleChanne
cutoff = bandwidth * 2 * wlen / avctx->sample_rate;
memcpy(sce->band_alt, sce->band_type, sizeof(sce->band_type));
+ ff_init_nextband_map(sce, nextband);
for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) {
int wstart = w*128;
for (g = 0; g < sce->ics.num_swb; g++) {
@@ -655,16 +658,27 @@ static void search_for_pns(AACEncContext *s, AVCodecContext *avctx, SingleChanne
*
* At this stage, point 2 is relaxed for zeroed bands near the noise threshold (hole avoidance is more important)
*/
- if (((sce->zeroes[w*16+g] || !sce->band_alt[w*16+g]) && sfb_energy < threshold*sqrtf(1.5f/freq_boost)) || spread < spread_threshold ||
+ if ((!sce->zeroes[w*16+g] && !ff_sfdelta_can_remove_band(sce, nextband, prev_sf, w*16+g)) ||
+ ((sce->zeroes[w*16+g] || !sce->band_alt[w*16+g]) && sfb_energy < threshold*sqrtf(1.0f/freq_boost)) || spread < spread_threshold ||
(!sce->zeroes[w*16+g] && sce->band_alt[w*16+g] && sfb_energy > threshold*thr_mult*freq_boost) ||
min_energy < pns_transient_energy_r * max_energy ) {
sce->pns_ener[w*16+g] = sfb_energy;
+ if (!sce->zeroes[w*16+g])
+ prev_sf = sce->sf_idx[w*16+g];
continue;
}
pns_tgt_energy = sfb_energy*FFMIN(1.0f, spread*spread);
noise_sfi = av_clip(roundf(log2f(pns_tgt_energy)*2), -100, 155); /* Quantize */
noise_amp = -ff_aac_pow2sf_tab[noise_sfi + POW_SF2_ZERO]; /* Dequantize */
+ if (prev != -1000) {
+ int noise_sfdiff = noise_sfi - prev + SCALE_DIFF_ZERO;
+ if (noise_sfdiff < 0 || noise_sfdiff > 2*SCALE_MAX_DIFF) {
+ if (!sce->zeroes[w*16+g])
+ prev_sf = sce->sf_idx[w*16+g];
+ continue;
+ }
+ }
for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) {
float band_energy, scale, pns_senergy;
const int start_c = (w+w2)*128+sce->ics.swb_offset[g];
@@ -697,7 +711,10 @@ static void search_for_pns(AACEncContext *s, AVCodecContext *avctx, SingleChanne
if (sce->zeroes[w*16+g] || !sce->band_alt[w*16+g] || (energy_ratio > 0.85f && energy_ratio < 1.25f && dist2 < dist1)) {
sce->band_type[w*16+g] = NOISE_BT;
sce->zeroes[w*16+g] = 0;
+ prev = noise_sfi;
}
+ if (!sce->zeroes[w*16+g])
+ prev_sf = sce->sf_idx[w*16+g];
}
}
}
@@ -775,7 +792,8 @@ static void mark_pns(AACEncContext *s, AVCodecContext *avctx, SingleChannelEleme
static void search_for_ms(AACEncContext *s, ChannelElement *cpe)
{
- int start = 0, i, w, w2, g, sid_sf_boost;
+ int start = 0, i, w, w2, g, sid_sf_boost, prev_mid, prev_side;
+ uint8_t nextband0[128], nextband1[128];
float M[128], S[128];
float *L34 = s->scoefs, *R34 = s->scoefs + 128, *M34 = s->scoefs + 128*2, *S34 = s->scoefs + 128*3;
const float lambda = s->lambda;
@@ -784,21 +802,19 @@ static void search_for_ms(AACEncContext *s, ChannelElement *cpe)
SingleChannelElement *sce1 = &cpe->ch[1];
if (!cpe->common_window)
return;
- for (w = 0; w < sce0->ics.num_windows; w += sce0->ics.group_len[w]) {
- int min_sf_idx_mid = SCALE_MAX_POS;
- int min_sf_idx_side = SCALE_MAX_POS;
- for (g = 0; g < sce0->ics.num_swb; g++) {
- if (!sce0->zeroes[w*16+g] && sce0->band_type[w*16+g] < RESERVED_BT)
- min_sf_idx_mid = FFMIN(min_sf_idx_mid, sce0->sf_idx[w*16+g]);
- if (!sce1->zeroes[w*16+g] && sce1->band_type[w*16+g] < RESERVED_BT)
- min_sf_idx_side = FFMIN(min_sf_idx_side, sce1->sf_idx[w*16+g]);
- }
+ /** Scout out next nonzero bands */
+ ff_init_nextband_map(sce0, nextband0);
+ ff_init_nextband_map(sce1, nextband1);
+
+ prev_mid = sce0->sf_idx[0];
+ prev_side = sce1->sf_idx[0];
+ for (w = 0; w < sce0->ics.num_windows; w += sce0->ics.group_len[w]) {
start = 0;
for (g = 0; g < sce0->ics.num_swb; g++) {
float bmax = bval2bmax(g * 17.0f / sce0->ics.num_swb) / 0.0045f;
cpe->ms_mask[w*16+g] = 0;
- if (!cpe->ch[0].zeroes[w*16+g] && !cpe->ch[1].zeroes[w*16+g]) {
+ if (!sce0->zeroes[w*16+g] && !sce1->zeroes[w*16+g]) {
float Mmax = 0.0f, Smax = 0.0f;
/* Must compute mid/side SF and book for the whole window group */
@@ -825,16 +841,18 @@ static void search_for_ms(AACEncContext *s, ChannelElement *cpe)
int midcb, sidcb;
minidx = FFMIN(sce0->sf_idx[w*16+g], sce1->sf_idx[w*16+g]);
- mididx = av_clip(minidx, min_sf_idx_mid, min_sf_idx_mid + SCALE_MAX_DIFF);
- sididx = av_clip(minidx - sid_sf_boost * 3, min_sf_idx_side, min_sf_idx_side + SCALE_MAX_DIFF);
- midcb = find_min_book(Mmax, mididx);
- sidcb = find_min_book(Smax, sididx);
-
- if ((mididx > minidx) || (sididx > minidx)) {
+ mididx = av_clip(minidx, 0, SCALE_MAX_POS - SCALE_DIV_512);
+ sididx = av_clip(minidx - sid_sf_boost * 3, 0, SCALE_MAX_POS - SCALE_DIV_512);
+ if (!cpe->is_mask[w*16+g] && sce0->band_type[w*16+g] != NOISE_BT && sce1->band_type[w*16+g] != NOISE_BT
+ && ( !ff_sfdelta_can_replace(sce0, nextband0, prev_mid, mididx, w*16+g)
+ || !ff_sfdelta_can_replace(sce1, nextband1, prev_side, sididx, w*16+g))) {
/* scalefactor range violation, bad stuff, will decrease quality unacceptably */
continue;
}
+ midcb = find_min_book(Mmax, mididx);
+ sidcb = find_min_book(Smax, sididx);
+
/* No CB can be zero */
midcb = FFMAX(1,midcb);
sidcb = FFMAX(1,sidcb);
@@ -900,6 +918,10 @@ static void search_for_ms(AACEncContext *s, ChannelElement *cpe)
}
}
}
+ if (!sce0->zeroes[w*16+g] && sce0->band_type[w*16+g] < RESERVED_BT)
+ prev_mid = sce0->sf_idx[w*16+g];
+ if (!sce1->zeroes[w*16+g] && !cpe->is_mask[w*16+g] && sce1->band_type[w*16+g] < RESERVED_BT)
+ prev_side = sce1->sf_idx[w*16+g];
start += sce0->ics.swb_sizes[g];
}
}
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;
diff --git a/libavcodec/aacenc.c b/libavcodec/aacenc.c
index 0bd8891ff2..971f8ab0e1 100644
--- a/libavcodec/aacenc.c
+++ b/libavcodec/aacenc.c
@@ -793,7 +793,7 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
s->lambda = FFMIN(s->lambda * ratio, 65536.f);
/* Keep iterating if we must reduce and lambda is in the sky */
- if ((s->lambda < 300.f || ratio > 0.9f) && (s->lambda > 10.f || ratio < 1.1f)) {
+ if (ratio > 0.9f && ratio < 1.1f) {
break;
} else {
if (is_mode || ms_mode || tns_mode || pred_mode) {
diff --git a/libavcodec/aacenc_is.c b/libavcodec/aacenc_is.c
index 97be9b3412..a4b8916197 100644
--- a/libavcodec/aacenc_is.c
+++ b/libavcodec/aacenc_is.c
@@ -99,18 +99,23 @@ void ff_aac_search_for_is(AACEncContext *s, AVCodecContext *avctx, ChannelElemen
{
SingleChannelElement *sce0 = &cpe->ch[0];
SingleChannelElement *sce1 = &cpe->ch[1];
- int start = 0, count = 0, w, w2, g, i;
+ int start = 0, count = 0, w, w2, g, i, prev_sf1 = -1;
const float freq_mult = avctx->sample_rate/(1024.0f/sce0->ics.num_windows)/2.0f;
+ uint8_t nextband1[128];
if (!cpe->common_window)
return;
+ /** Scout out next nonzero bands */
+ ff_init_nextband_map(sce1, nextband1);
+
for (w = 0; w < sce0->ics.num_windows; w += sce0->ics.group_len[w]) {
start = 0;
for (g = 0; g < sce0->ics.num_swb; g++) {
if (start*freq_mult > INT_STEREO_LOW_LIMIT*(s->lambda/170.0f) &&
cpe->ch[0].band_type[w*16+g] != NOISE_BT && !cpe->ch[0].zeroes[w*16+g] &&
- cpe->ch[1].band_type[w*16+g] != NOISE_BT && !cpe->ch[1].zeroes[w*16+g]) {
+ cpe->ch[1].band_type[w*16+g] != NOISE_BT && !cpe->ch[1].zeroes[w*16+g] &&
+ ff_sfdelta_can_remove_band(sce1, nextband1, prev_sf1, w*16+g)) {
float ener0 = 0.0f, ener1 = 0.0f, ener01 = 0.0f, ener01p = 0.0f;
struct AACISError ph_err1, ph_err2, *erf;
if (sce0->band_type[w*16+g] == NOISE_BT ||
@@ -142,6 +147,8 @@ void ff_aac_search_for_is(AACEncContext *s, AVCodecContext *avctx, ChannelElemen
count++;
}
}
+ if (!sce1->zeroes[w*16+g] && sce1->band_type[w*16+g] < RESERVED_BT)
+ prev_sf1 = sce1->sf_idx[w*16+g];
start += sce0->ics.swb_sizes[g];
}
}
diff --git a/libavcodec/aacenc_utils.h b/libavcodec/aacenc_utils.h
index 40e1746639..5b308f2efe 100644
--- a/libavcodec/aacenc_utils.h
+++ b/libavcodec/aacenc_utils.h
@@ -191,6 +191,69 @@ static inline int lcg_random(unsigned previous_val)
return v.s;
}
+
+/*
+ * Compute a nextband map to be used with SF delta constraint utilities.
+ * The nextband array should contain 128 elements, and positions that don't
+ * map to valid, nonzero bands of the form w*16+g (with w being the initial
+ * window of the window group, only) are left indetermined.
+ */
+static inline void ff_init_nextband_map(const SingleChannelElement *sce, uint8_t *nextband)
+{
+ unsigned char prevband = 0;
+ int w, g;
+ /** Just a safe default */
+ for (g = 0; g < 128; g++)
+ nextband[g] = g;
+
+ /** Now really navigate the nonzero band chain */
+ 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] && sce->band_type[w*16+g] < RESERVED_BT)
+ prevband = nextband[prevband] = w*16+g;
+ }
+ }
+ nextband[prevband] = prevband; /* terminate */
+}
+
+/*
+ * Updates nextband to reflect a removed band (equivalent to
+ * calling ff_init_nextband_map after marking a band as zero)
+ */
+static inline void ff_nextband_remove(uint8_t *nextband, int prevband, int band)
+{
+ nextband[prevband] = nextband[band];
+}
+
+/*
+ * Checks whether the specified band could be removed without inducing
+ * scalefactor delta that violates SF delta encoding constraints.
+ * prev_sf has to be the scalefactor of the previous nonzero, nonspecial
+ * band, in encoding order, or negative if there was no such band.
+ */
+static inline int ff_sfdelta_can_remove_band(const SingleChannelElement *sce,
+ const uint8_t *nextband, int prev_sf, int band)
+{
+ return prev_sf >= 0
+ && sce->sf_idx[nextband[band]] >= (prev_sf - SCALE_MAX_DIFF)
+ && sce->sf_idx[nextband[band]] <= (prev_sf + SCALE_MAX_DIFF);
+}
+
+/*
+ * Checks whether the specified band's scalefactor could be replaced
+ * with another one without violating SF delta encoding constraints.
+ * prev_sf has to be the scalefactor of the previous nonzero, nonsepcial
+ * band, in encoding order, or negative if there was no such band.
+ */
+static inline int ff_sfdelta_can_replace(const SingleChannelElement *sce,
+ const uint8_t *nextband, int prev_sf, int new_sf, int band)
+{
+ return new_sf >= (prev_sf - SCALE_MAX_DIFF)
+ && new_sf <= (prev_sf + SCALE_MAX_DIFF)
+ && sce->sf_idx[nextband[band]] >= (new_sf - SCALE_MAX_DIFF)
+ && sce->sf_idx[nextband[band]] <= (new_sf + SCALE_MAX_DIFF);
+}
+
#define ERROR_IF(cond, ...) \
if (cond) { \
av_log(avctx, AV_LOG_ERROR, __VA_ARGS__); \
diff --git a/libavcodec/aacpsy.c b/libavcodec/aacpsy.c
index 40b3b41e56..71eeb3e547 100644
--- a/libavcodec/aacpsy.c
+++ b/libavcodec/aacpsy.c
@@ -305,7 +305,7 @@ static av_cold int psy_3gpp_init(FFPsyContext *ctx) {
float prev, minscale, minath, minsnr, pe_min;
int chan_bitrate = ctx->avctx->bit_rate / ((ctx->avctx->flags & CODEC_FLAG_QSCALE) ? 2.0f : ctx->avctx->channels);
- const int bandwidth = ctx->avctx->cutoff ? ctx->avctx->cutoff : AAC_CUTOFF(ctx->avctx);
+ const int bandwidth = ctx->cutoff ? ctx->cutoff : AAC_CUTOFF(ctx->avctx);
const float num_bark = calc_bark((float)bandwidth);
ctx->model_priv_data = av_mallocz(sizeof(AacPsyContext));
@@ -595,26 +595,30 @@ static float calc_reduced_thr_3gpp(AacPsyBand *band, float min_snr,
#ifndef calc_thr_3gpp
static void calc_thr_3gpp(const FFPsyWindowInfo *wi, const int num_bands, AacPsyChannel *pch,
- const uint8_t *band_sizes, const float *coefs)
+ const uint8_t *band_sizes, const float *coefs, const int cutoff)
{
int i, w, g;
- int start = 0;
+ int start = 0, wstart = 0;
for (w = 0; w < wi->num_windows*16; w += 16) {
+ wstart = 0;
for (g = 0; g < num_bands; g++) {
AacPsyBand *band = &pch->band[w+g];
float form_factor = 0.0f;
float Temp;
band->energy = 0.0f;
- for (i = 0; i < band_sizes[g]; i++) {
- band->energy += coefs[start+i] * coefs[start+i];
- form_factor += sqrtf(fabs(coefs[start+i]));
+ if (wstart < cutoff) {
+ for (i = 0; i < band_sizes[g]; i++) {
+ band->energy += coefs[start+i] * coefs[start+i];
+ form_factor += sqrtf(fabs(coefs[start+i]));
+ }
}
Temp = band->energy > 0 ? sqrtf((float)band_sizes[g] / band->energy) : 0;
band->thr = band->energy * 0.001258925f;
band->nz_lines = form_factor * sqrtf(Temp);
start += band_sizes[g];
+ wstart += band_sizes[g];
}
}
}
@@ -655,9 +659,11 @@ static void psy_3gpp_analyze_channel(FFPsyContext *ctx, int channel,
const uint8_t *band_sizes = ctx->bands[wi->num_windows == 8];
AacPsyCoeffs *coeffs = pctx->psy_coef[wi->num_windows == 8];
const float avoid_hole_thr = wi->num_windows == 8 ? PSY_3GPP_AH_THR_SHORT : PSY_3GPP_AH_THR_LONG;
+ const int bandwidth = ctx->cutoff ? ctx->cutoff : AAC_CUTOFF(ctx->avctx);
+ const int cutoff = bandwidth * 2048 / wi->num_windows / ctx->avctx->sample_rate;
//calculate energies, initial thresholds and related values - 5.4.2 "Threshold Calculation"
- calc_thr_3gpp(wi, num_bands, pch, band_sizes, coefs);
+ calc_thr_3gpp(wi, num_bands, pch, band_sizes, coefs, cutoff);
//modify thresholds and energies - spread, threshold in quiet, pre-echo control
for (w = 0; w < wi->num_windows*16; w += 16) {
diff --git a/libavcodec/mips/aaccoder_mips.c b/libavcodec/mips/aaccoder_mips.c
index e8e1e623f6..04b3dca9de 100644
--- a/libavcodec/mips/aaccoder_mips.c
+++ b/libavcodec/mips/aaccoder_mips.c
@@ -2336,74 +2336,136 @@ static float quantize_band_cost(struct AACEncContext *s, const float *in,
static void search_for_ms_mips(AACEncContext *s, ChannelElement *cpe)
{
- int start = 0, i, w, w2, g;
+ int start = 0, i, w, w2, g, sid_sf_boost, prev_mid, prev_side;
+ uint8_t nextband0[128], nextband1[128];
float M[128], S[128];
float *L34 = s->scoefs, *R34 = s->scoefs + 128, *M34 = s->scoefs + 128*2, *S34 = s->scoefs + 128*3;
const float lambda = s->lambda;
+ const float mslambda = FFMIN(1.0f, lambda / 120.f);
SingleChannelElement *sce0 = &cpe->ch[0];
SingleChannelElement *sce1 = &cpe->ch[1];
if (!cpe->common_window)
return;
+
+ /** Scout out next nonzero bands */
+ ff_init_nextband_map(sce0, nextband0);
+ ff_init_nextband_map(sce1, nextband1);
+
+ prev_mid = sce0->sf_idx[0];
+ prev_side = sce1->sf_idx[0];
for (w = 0; w < sce0->ics.num_windows; w += sce0->ics.group_len[w]) {
start = 0;
for (g = 0; g < sce0->ics.num_swb; g++) {
- if (!cpe->ch[0].zeroes[w*16+g] && !cpe->ch[1].zeroes[w*16+g]) {
- float dist1 = 0.0f, dist2 = 0.0f;
+ float bmax = bval2bmax(g * 17.0f / sce0->ics.num_swb) / 0.0045f;
+ cpe->ms_mask[w*16+g] = 0;
+ if (!sce0->zeroes[w*16+g] && !sce1->zeroes[w*16+g]) {
+ float Mmax = 0.0f, Smax = 0.0f;
+
+ /* Must compute mid/side SF and book for the whole window group */
for (w2 = 0; w2 < sce0->ics.group_len[w]; w2++) {
- FFPsyBand *band0 = &s->psy.ch[s->cur_channel+0].psy_bands[(w+w2)*16+g];
- FFPsyBand *band1 = &s->psy.ch[s->cur_channel+1].psy_bands[(w+w2)*16+g];
- float minthr = FFMIN(band0->threshold, band1->threshold);
- float maxthr = FFMAX(band0->threshold, band1->threshold);
- for (i = 0; i < sce0->ics.swb_sizes[g]; i+=4) {
- M[i ] = (sce0->coeffs[start+w2*128+i ]
- + sce1->coeffs[start+w2*128+i ]) * 0.5;
- M[i+1] = (sce0->coeffs[start+w2*128+i+1]
- + sce1->coeffs[start+w2*128+i+1]) * 0.5;
- M[i+2] = (sce0->coeffs[start+w2*128+i+2]
- + sce1->coeffs[start+w2*128+i+2]) * 0.5;
- M[i+3] = (sce0->coeffs[start+w2*128+i+3]
- + sce1->coeffs[start+w2*128+i+3]) * 0.5;
-
- S[i ] = M[i ]
- - sce1->coeffs[start+w2*128+i ];
- S[i+1] = M[i+1]
- - sce1->coeffs[start+w2*128+i+1];
- S[i+2] = M[i+2]
- - sce1->coeffs[start+w2*128+i+2];
- S[i+3] = M[i+3]
- - sce1->coeffs[start+w2*128+i+3];
- }
- abs_pow34_v(L34, sce0->coeffs+start+(w+w2)*128, sce0->ics.swb_sizes[g]);
- abs_pow34_v(R34, sce1->coeffs+start+(w+w2)*128, sce0->ics.swb_sizes[g]);
- abs_pow34_v(M34, M, sce0->ics.swb_sizes[g]);
- abs_pow34_v(S34, S, sce0->ics.swb_sizes[g]);
- dist1 += quantize_band_cost(s, &sce0->coeffs[start + (w+w2)*128],
- L34,
- sce0->ics.swb_sizes[g],
- sce0->sf_idx[(w+w2)*16+g],
- sce0->band_type[(w+w2)*16+g],
- lambda / band0->threshold, INFINITY, NULL, NULL, 0);
- dist1 += quantize_band_cost(s, &sce1->coeffs[start + (w+w2)*128],
- R34,
- sce1->ics.swb_sizes[g],
- sce1->sf_idx[(w+w2)*16+g],
- sce1->band_type[(w+w2)*16+g],
- lambda / band1->threshold, INFINITY, NULL, NULL, 0);
- dist2 += quantize_band_cost(s, M,
- M34,
- sce0->ics.swb_sizes[g],
- sce0->sf_idx[(w+w2)*16+g],
- sce0->band_type[(w+w2)*16+g],
- lambda / maxthr, INFINITY, NULL, NULL, 0);
- dist2 += quantize_band_cost(s, S,
- S34,
- sce1->ics.swb_sizes[g],
- sce1->sf_idx[(w+w2)*16+g],
- sce1->band_type[(w+w2)*16+g],
- lambda / minthr, INFINITY, NULL, NULL, 0);
+ for (i = 0; i < sce0->ics.swb_sizes[g]; i++) {
+ M[i] = (sce0->coeffs[start+(w+w2)*128+i]
+ + sce1->coeffs[start+(w+w2)*128+i]) * 0.5;
+ S[i] = M[i]
+ - sce1->coeffs[start+(w+w2)*128+i];
+ }
+ abs_pow34_v(M34, M, sce0->ics.swb_sizes[g]);
+ abs_pow34_v(S34, S, sce0->ics.swb_sizes[g]);
+ for (i = 0; i < sce0->ics.swb_sizes[g]; i++ ) {
+ Mmax = FFMAX(Mmax, M34[i]);
+ Smax = FFMAX(Smax, S34[i]);
+ }
+ }
+
+ for (sid_sf_boost = 0; sid_sf_boost < 4; sid_sf_boost++) {
+ float dist1 = 0.0f, dist2 = 0.0f;
+ int B0 = 0, B1 = 0;
+ int minidx;
+ int mididx, sididx;
+ int midcb, sidcb;
+
+ minidx = FFMIN(sce0->sf_idx[w*16+g], sce1->sf_idx[w*16+g]);
+ mididx = av_clip(minidx, 0, SCALE_MAX_POS - SCALE_DIV_512);
+ sididx = av_clip(minidx - sid_sf_boost * 3, 0, SCALE_MAX_POS - SCALE_DIV_512);
+ if (!cpe->is_mask[w*16+g] && sce0->band_type[w*16+g] != NOISE_BT && sce1->band_type[w*16+g] != NOISE_BT
+ && ( !ff_sfdelta_can_replace(sce0, nextband0, prev_mid, mididx, w*16+g)
+ || !ff_sfdelta_can_replace(sce1, nextband1, prev_side, sididx, w*16+g))) {
+ /* scalefactor range violation, bad stuff, will decrease quality unacceptably */
+ continue;
+ }
+
+ midcb = find_min_book(Mmax, mididx);
+ sidcb = find_min_book(Smax, sididx);
+
+ /* No CB can be zero */
+ midcb = FFMAX(1,midcb);
+ sidcb = FFMAX(1,sidcb);
+
+ for (w2 = 0; w2 < sce0->ics.group_len[w]; w2++) {
+ FFPsyBand *band0 = &s->psy.ch[s->cur_channel+0].psy_bands[(w+w2)*16+g];
+ FFPsyBand *band1 = &s->psy.ch[s->cur_channel+1].psy_bands[(w+w2)*16+g];
+ float minthr = FFMIN(band0->threshold, band1->threshold);
+ int b1,b2,b3,b4;
+ for (i = 0; i < sce0->ics.swb_sizes[g]; i++) {
+ M[i] = (sce0->coeffs[start+(w+w2)*128+i]
+ + sce1->coeffs[start+(w+w2)*128+i]) * 0.5;
+ S[i] = M[i]
+ - sce1->coeffs[start+(w+w2)*128+i];
+ }
+
+ abs_pow34_v(L34, sce0->coeffs+start+(w+w2)*128, sce0->ics.swb_sizes[g]);
+ abs_pow34_v(R34, sce1->coeffs+start+(w+w2)*128, sce0->ics.swb_sizes[g]);
+ abs_pow34_v(M34, M, sce0->ics.swb_sizes[g]);
+ abs_pow34_v(S34, S, sce0->ics.swb_sizes[g]);
+ dist1 += quantize_band_cost(s, &sce0->coeffs[start + (w+w2)*128],
+ L34,
+ sce0->ics.swb_sizes[g],
+ sce0->sf_idx[(w+w2)*16+g],
+ sce0->band_type[(w+w2)*16+g],
+ lambda / band0->threshold, INFINITY, &b1, NULL, 0);
+ dist1 += quantize_band_cost(s, &sce1->coeffs[start + (w+w2)*128],
+ R34,
+ sce1->ics.swb_sizes[g],
+ sce1->sf_idx[(w+w2)*16+g],
+ sce1->band_type[(w+w2)*16+g],
+ lambda / band1->threshold, INFINITY, &b2, NULL, 0);
+ dist2 += quantize_band_cost(s, M,
+ M34,
+ sce0->ics.swb_sizes[g],
+ sce0->sf_idx[(w+w2)*16+g],
+ sce0->band_type[(w+w2)*16+g],
+ lambda / minthr, INFINITY, &b3, NULL, 0);
+ dist2 += quantize_band_cost(s, S,
+ S34,
+ sce1->ics.swb_sizes[g],
+ sce1->sf_idx[(w+w2)*16+g],
+ sce1->band_type[(w+w2)*16+g],
+ mslambda / (minthr * bmax), INFINITY, &b4, NULL, 0);
+ B0 += b1+b2;
+ B1 += b3+b4;
+ dist1 -= B0;
+ dist2 -= B1;
+ }
+ cpe->ms_mask[w*16+g] = dist2 <= dist1 && B1 < B0;
+ if (cpe->ms_mask[w*16+g]) {
+ /* Setting the M/S mask is useful with I/S or PNS, but only the flag */
+ if (!cpe->is_mask[w*16+g] && sce0->band_type[w*16+g] != NOISE_BT && sce1->band_type[w*16+g] != NOISE_BT) {
+ sce0->sf_idx[w*16+g] = mididx;
+ sce1->sf_idx[w*16+g] = sididx;
+ sce0->band_type[w*16+g] = midcb;
+ sce1->band_type[w*16+g] = sidcb;
+ }
+ break;
+ } else if (B1 > B0) {
+ /* More boost won't fix this */
+ break;
+ }
}
- cpe->ms_mask[w*16+g] = dist2 < dist1;
}
+ if (!sce0->zeroes[w*16+g] && sce0->band_type[w*16+g] < RESERVED_BT)
+ prev_mid = sce0->sf_idx[w*16+g];
+ if (!sce1->zeroes[w*16+g] && !cpe->is_mask[w*16+g] && sce1->band_type[w*16+g] < RESERVED_BT)
+ prev_side = sce1->sf_idx[w*16+g];
start += sce0->ics.swb_sizes[g];
}
}
diff --git a/libavcodec/mips/aacpsy_mips.h b/libavcodec/mips/aacpsy_mips.h
index 596dcaddd0..42ff442a59 100644
--- a/libavcodec/mips/aacpsy_mips.h
+++ b/libavcodec/mips/aacpsy_mips.h
@@ -61,58 +61,62 @@
#if HAVE_INLINE_ASM && HAVE_MIPSFPU && ( PSY_LAME_FIR_LEN == 21 )
static void calc_thr_3gpp_mips(const FFPsyWindowInfo *wi, const int num_bands,
AacPsyChannel *pch, const uint8_t *band_sizes,
- const float *coefs)
+ const float *coefs, const int cutoff)
{
int i, w, g;
- int start = 0;
+ int start = 0, wstart = 0;
for (w = 0; w < wi->num_windows*16; w += 16) {
+ wstart = 0;
for (g = 0; g < num_bands; g++) {
AacPsyBand *band = &pch->band[w+g];
float form_factor = 0.0f;
float Temp;
band->energy = 0.0f;
- for (i = 0; i < band_sizes[g]; i+=4) {
- float a, b, c, d;
- float ax, bx, cx, dx;
- float *cf = (float *)&coefs[start+i];
-
- __asm__ volatile (
- "lwc1 %[a], 0(%[cf]) \n\t"
- "lwc1 %[b], 4(%[cf]) \n\t"
- "lwc1 %[c], 8(%[cf]) \n\t"
- "lwc1 %[d], 12(%[cf]) \n\t"
- "abs.s %[a], %[a] \n\t"
- "abs.s %[b], %[b] \n\t"
- "abs.s %[c], %[c] \n\t"
- "abs.s %[d], %[d] \n\t"
- "sqrt.s %[ax], %[a] \n\t"
- "sqrt.s %[bx], %[b] \n\t"
- "sqrt.s %[cx], %[c] \n\t"
- "sqrt.s %[dx], %[d] \n\t"
- "madd.s %[e], %[e], %[a], %[a] \n\t"
- "madd.s %[e], %[e], %[b], %[b] \n\t"
- "madd.s %[e], %[e], %[c], %[c] \n\t"
- "madd.s %[e], %[e], %[d], %[d] \n\t"
- "add.s %[f], %[f], %[ax] \n\t"
- "add.s %[f], %[f], %[bx] \n\t"
- "add.s %[f], %[f], %[cx] \n\t"
- "add.s %[f], %[f], %[dx] \n\t"
-
- : [a]"=&f"(a), [b]"=&f"(b),
- [c]"=&f"(c), [d]"=&f"(d),
- [e]"+f"(band->energy), [f]"+f"(form_factor),
- [ax]"=&f"(ax), [bx]"=&f"(bx),
- [cx]"=&f"(cx), [dx]"=&f"(dx)
- : [cf]"r"(cf)
- : "memory"
- );
+ if (wstart < cutoff) {
+ for (i = 0; i < band_sizes[g]; i+=4) {
+ float a, b, c, d;
+ float ax, bx, cx, dx;
+ float *cf = (float *)&coefs[start+i];
+
+ __asm__ volatile (
+ "lwc1 %[a], 0(%[cf]) \n\t"
+ "lwc1 %[b], 4(%[cf]) \n\t"
+ "lwc1 %[c], 8(%[cf]) \n\t"
+ "lwc1 %[d], 12(%[cf]) \n\t"
+ "abs.s %[a], %[a] \n\t"
+ "abs.s %[b], %[b] \n\t"
+ "abs.s %[c], %[c] \n\t"
+ "abs.s %[d], %[d] \n\t"
+ "sqrt.s %[ax], %[a] \n\t"
+ "sqrt.s %[bx], %[b] \n\t"
+ "sqrt.s %[cx], %[c] \n\t"
+ "sqrt.s %[dx], %[d] \n\t"
+ "madd.s %[e], %[e], %[a], %[a] \n\t"
+ "madd.s %[e], %[e], %[b], %[b] \n\t"
+ "madd.s %[e], %[e], %[c], %[c] \n\t"
+ "madd.s %[e], %[e], %[d], %[d] \n\t"
+ "add.s %[f], %[f], %[ax] \n\t"
+ "add.s %[f], %[f], %[bx] \n\t"
+ "add.s %[f], %[f], %[cx] \n\t"
+ "add.s %[f], %[f], %[dx] \n\t"
+
+ : [a]"=&f"(a), [b]"=&f"(b),
+ [c]"=&f"(c), [d]"=&f"(d),
+ [e]"+f"(band->energy), [f]"+f"(form_factor),
+ [ax]"=&f"(ax), [bx]"=&f"(bx),
+ [cx]"=&f"(cx), [dx]"=&f"(dx)
+ : [cf]"r"(cf)
+ : "memory"
+ );
+ }
}
Temp = sqrtf((float)band_sizes[g] / band->energy);
band->thr = band->energy * 0.001258925f;
band->nz_lines = form_factor * sqrtf(Temp);
start += band_sizes[g];
+ wstart += band_sizes[g];
}
}
}
diff --git a/libavcodec/psymodel.c b/libavcodec/psymodel.c
index 76221243cb..6274a49ea9 100644
--- a/libavcodec/psymodel.c
+++ b/libavcodec/psymodel.c
@@ -39,6 +39,7 @@ av_cold int ff_psy_init(FFPsyContext *ctx, AVCodecContext *avctx, int num_lens,
ctx->group = av_mallocz_array(sizeof(ctx->group[0]), num_groups);
ctx->bands = av_malloc_array (sizeof(ctx->bands[0]), num_lens);
ctx->num_bands = av_malloc_array (sizeof(ctx->num_bands[0]), num_lens);
+ ctx->cutoff = avctx->cutoff;
if (!ctx->ch || !ctx->group || !ctx->bands || !ctx->num_bands) {
ff_psy_end(ctx);
diff --git a/libavcodec/psymodel.h b/libavcodec/psymodel.h
index 565117db73..35d184c710 100644
--- a/libavcodec/psymodel.h
+++ b/libavcodec/psymodel.h
@@ -93,6 +93,7 @@ typedef struct FFPsyContext {
FFPsyChannel *ch; ///< single channel information
FFPsyChannelGroup *group; ///< channel group information
int num_groups; ///< number of channel groups
+ int cutoff; ///< lowpass frequency cutoff for analysis
uint8_t **bands; ///< scalefactor band sizes for possible frame sizes
int *num_bands; ///< number of scalefactor bands for possible frame sizes
diff --git a/tests/fate/aac.mak b/tests/fate/aac.mak
index 2d418885be..7a6c734bf7 100644
--- a/tests/fate/aac.mak
+++ b/tests/fate/aac.mak
@@ -146,16 +146,16 @@ fate-aac-aref-encode: CMD = enc_dec_pcm adts wav s16le $(REF) -strict -2 -c:a aa
fate-aac-aref-encode: CMP = stddev
fate-aac-aref-encode: REF = ./tests/data/asynth-44100-2.wav
fate-aac-aref-encode: CMP_SHIFT = -4096
-fate-aac-aref-encode: CMP_TARGET = 1139
+fate-aac-aref-encode: CMP_TARGET = 670
fate-aac-aref-encode: SIZE_TOLERANCE = 2464
-fate-aac-aref-encode: FUZZ = 6
+fate-aac-aref-encode: FUZZ = 89
FATE_AAC_ENCODE += fate-aac-ln-encode
fate-aac-ln-encode: CMD = enc_dec_pcm adts wav s16le $(TARGET_SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav -strict -2 -c:a aac -aac_is 0 -aac_pns 0 -aac_ms 0 -aac_tns 0 -b:a 512k
fate-aac-ln-encode: CMP = stddev
fate-aac-ln-encode: REF = $(SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav
fate-aac-ln-encode: CMP_SHIFT = -4096
-fate-aac-ln-encode: CMP_TARGET = 80
+fate-aac-ln-encode: CMP_TARGET = 50
fate-aac-ln-encode: SIZE_TOLERANCE = 3560
fate-aac-ln-encode: FUZZ = 30
@@ -164,7 +164,7 @@ fate-aac-ln-encode-128k: CMD = enc_dec_pcm adts wav s16le $(TARGET_SAMPLES)/audi
fate-aac-ln-encode-128k: CMP = stddev
fate-aac-ln-encode-128k: REF = $(SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav
fate-aac-ln-encode-128k: CMP_SHIFT = -4096
-fate-aac-ln-encode-128k: CMP_TARGET = 745
+fate-aac-ln-encode-128k: CMP_TARGET = 798
fate-aac-ln-encode-128k: SIZE_TOLERANCE = 3560
fate-aac-ln-encode-128k: FUZZ = 5
@@ -173,16 +173,16 @@ fate-aac-pns-encode: CMD = enc_dec_pcm adts wav s16le $(TARGET_SAMPLES)/audio-re
fate-aac-pns-encode: CMP = stddev
fate-aac-pns-encode: REF = $(SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav
fate-aac-pns-encode: CMP_SHIFT = -4096
-fate-aac-pns-encode: CMP_TARGET = 695
+fate-aac-pns-encode: CMP_TARGET = 663
fate-aac-pns-encode: SIZE_TOLERANCE = 3560
-fate-aac-pns-encode: FUZZ = 25
+fate-aac-pns-encode: FUZZ = 72
FATE_AAC_ENCODE += fate-aac-tns-encode
fate-aac-tns-encode: CMD = enc_dec_pcm adts wav s16le $(TARGET_SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav -strict -2 -c:a aac -aac_tns 1 -aac_is 0 -aac_pns 0 -aac_ms 0 -b:a 128k -cutoff 22050
fate-aac-tns-encode: CMP = stddev
fate-aac-tns-encode: REF = $(SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav
fate-aac-tns-encode: CMP_SHIFT = -4096
-fate-aac-tns-encode: CMP_TARGET = 766
+fate-aac-tns-encode: CMP_TARGET = 857
fate-aac-tns-encode: FUZZ = 6
fate-aac-tns-encode: SIZE_TOLERANCE = 3560
@@ -191,25 +191,25 @@ fate-aac-is-encode: CMD = enc_dec_pcm adts wav s16le $(TARGET_SAMPLES)/audio-ref
fate-aac-is-encode: CMP = stddev
fate-aac-is-encode: REF = $(SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav
fate-aac-is-encode: CMP_SHIFT = -4096
-fate-aac-is-encode: CMP_TARGET = 584
+fate-aac-is-encode: CMP_TARGET = 725
fate-aac-is-encode: SIZE_TOLERANCE = 3560
-fate-aac-is-encode: FUZZ = 1
+fate-aac-is-encode: FUZZ = 5
FATE_AAC_ENCODE += fate-aac-ms-encode
fate-aac-ms-encode: CMD = enc_dec_pcm adts wav s16le $(TARGET_SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav -strict -2 -c:a aac -aac_pns 0 -aac_is 0 -aac_ms 1 -aac_tns 0 -b:a 128k -cutoff 22050
fate-aac-ms-encode: CMP = stddev
fate-aac-ms-encode: REF = $(SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav
fate-aac-ms-encode: CMP_SHIFT = -4096
-fate-aac-ms-encode: CMP_TARGET = 615
+fate-aac-ms-encode: CMP_TARGET = 682
fate-aac-ms-encode: SIZE_TOLERANCE = 3560
-fate-aac-ms-encode: FUZZ = 10
+fate-aac-ms-encode: FUZZ = 15
FATE_AAC_ENCODE += fate-aac-ltp-encode
fate-aac-ltp-encode: CMD = enc_dec_pcm adts wav s16le $(TARGET_SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav -strict -2 -c:a aac -profile:a aac_ltp -aac_pns 0 -aac_is 0 -aac_ms 0 -aac_tns 0 -b:a 36k -fflags +bitexact -flags +bitexact
fate-aac-ltp-encode: CMP = stddev
fate-aac-ltp-encode: REF = $(SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav
fate-aac-ltp-encode: CMP_SHIFT = -4096
-fate-aac-ltp-encode: CMP_TARGET = 1120
+fate-aac-ltp-encode: CMP_TARGET = 1284
fate-aac-ltp-encode: SIZE_TOLERANCE = 3560
fate-aac-ltp-encode: FUZZ = 17
@@ -218,7 +218,7 @@ fate-aac-pred-encode: CMD = enc_dec_pcm adts wav s16le $(TARGET_SAMPLES)/audio-r
fate-aac-pred-encode: CMP = stddev
fate-aac-pred-encode: REF = $(SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav
fate-aac-pred-encode: CMP_SHIFT = -4096
-fate-aac-pred-encode: CMP_TARGET = 790
+fate-aac-pred-encode: CMP_TARGET = 835
fate-aac-pred-encode: FUZZ = 12
fate-aac-pred-encode: SIZE_TOLERANCE = 3560