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