History

AAC encoder: improve SF range utilization

This patch does 4 things, all of which interact and thus it woudln't be possible to commit them separately without causing either quality regressions or assertion failures. Fate comparison targets don't all reflect improvements in quality, yet listening tests show substantially improved quality and stability. 1. Increase SF range utilization. The spec requires SF delta values to be constrained within the range -60..60. The previous code was applying that range to the whole SF array and not only the deltas of consecutive values, because doing so requires smarter code: zeroing or otherwise skipping a band may invalidate lots of SF choices. This patch implements that logic to allow the coders to utilize the full dynamic range of scalefactors, increasing quality quite considerably, and fixing delta-SF-related assertion failures, since now the limitation is enforced rather than asserted. 2. PNS tweaks The previous modification makes big improvements in twoloop's efficiency, and every time that happens PNS logic needs to be tweaked accordingly to avoid it from stepping all over twoloop's decisions. This patch includes modifications of the sort. 3. Account for lowpass cutoff during PSY analysis The closer PSY's allocation is to final allocation the better the quality is, and given these modifications, twoloop is now very efficient at avoiding holes. Thus, to compute accurate thresholds, PSY needs to account for the lowpass applied implicitly during twoloop (by zeroing high bands). This patch makes twoloop set the cutoff in psymodel's context the first time it runs, and makes PSY account for it during threshold computation, making PE and threshold computations closer to the final allocation and thus achieving better subjective quality. 4. Tweaks to RC lambda tracking loop in relation to PNS Without this tweak some corner cases cause quality regressions. Basically, lambda needs to react faster to overall bitrate efficiency changes since now PNS can be quite successful in enforcing maximum bitrates, when PSY allocates too many bits to the lower bands, suppressing the signals RC logic uses to lower lambda in those cases and causing aggressive PNS. This tweak makes PNS much less aggressive, though it can still use some further tweaks. Also update MIPS specializations and adjust fuzz Also in lavc/mips/aacpsy_mips.h: remove trailing whitespace

Claudio Freire committed 10 years ago

Commit ca203e91 parent ec83efd11 files · +393 −177Browse files

Showing the changes to libavcodec/aaccoder.c (1 of 11 files). Show all

Unified · Split

libavcodec/aaccoder.c+41−19
@@ -54,7 +54,7 @@ · 53 unmodified lines
54 54
55/* Parameter of f(x) = a*(lambda/100), defines the maximum fourier spread55/* Parameter of f(x) = a*(lambda/100), defines the maximum fourier spread
56 * beyond which no PNS is used (since the SFBs contain tone rather than noise) */56 * beyond which no PNS is used (since the SFBs contain tone rather than noise) */
57#define NOISE_SPREAD_THRESHOLD 0.5073f57#define NOISE_SPREAD_THRESHOLD 0.9f
58 58
59/* Parameter of f(x) = a*(100/lambda), defines how much PNS is allowed to59/* Parameter of f(x) = a*(100/lambda), defines how much PNS is allowed to
60 * replace low energy non zero bands */60 * replace low energy non zero bands */
@@ -591,6 +591,7 @@ static void search_for_pns(AACEncContext *s, AVCodecContext *avctx, SingleChanne · 530 unmodified lines
591 int bandwidth, cutoff;591 int bandwidth, cutoff;
592 float *PNS = &s->scoefs[0*128], *PNS34 = &s->scoefs[1*128];592 float *PNS = &s->scoefs[0*128], *PNS34 = &s->scoefs[1*128];
593 float *NOR34 = &s->scoefs[3*128];593 float *NOR34 = &s->scoefs[3*128];
594 uint8_t nextband[128];
594 const float lambda = s->lambda;595 const float lambda = s->lambda;
595 const float freq_mult = avctx->sample_rate*0.5f/wlen;596 const float freq_mult = avctx->sample_rate*0.5f/wlen;
596 const float thr_mult = NOISE_LAMBDA_REPLACE*(100.0f/lambda);597 const float thr_mult = NOISE_LAMBDA_REPLACE*(100.0f/lambda);
@@ -604,6 +605,7 @@ static void search_for_pns(AACEncContext *s, AVCodecContext *avctx, SingleChanne · 7 unmodified lines
604 605
605 /** Keep this in sync with twoloop's cutoff selection */606 /** Keep this in sync with twoloop's cutoff selection */
606 float rate_bandwidth_multiplier = 1.5f;607 float rate_bandwidth_multiplier = 1.5f;
608 int prev = -1000, prev_sf = -1;
607 int frame_bit_rate = (avctx->flags & CODEC_FLAG_QSCALE)609 int frame_bit_rate = (avctx->flags & CODEC_FLAG_QSCALE)
608 ? (refbits * rate_bandwidth_multiplier * avctx->sample_rate / 1024)610 ? (refbits * rate_bandwidth_multiplier * avctx->sample_rate / 1024)
609 : (avctx->bit_rate / avctx->channels);611 : (avctx->bit_rate / avctx->channels);
@@ -619,6 +621,7 @@ static void search_for_pns(AACEncContext *s, AVCodecContext *avctx, SingleChanne · 9 unmodified lines
619 cutoff = bandwidth * 2 * wlen / avctx->sample_rate;621 cutoff = bandwidth * 2 * wlen / avctx->sample_rate;
620 622
621 memcpy(sce->band_alt, sce->band_type, sizeof(sce->band_type));623 memcpy(sce->band_alt, sce->band_type, sizeof(sce->band_type));
624 ff_init_nextband_map(sce, nextband);
622 for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) {625 for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) {
623 int wstart = w*128;626 int wstart = w*128;
624 for (g = 0; g < sce->ics.num_swb; g++) {627 for (g = 0; g < sce->ics.num_swb; g++) {
@@ -655,16 +658,27 @@ static void search_for_pns(AACEncContext *s, AVCodecContext *avctx, SingleChanne · 30 unmodified lines
655 *658 *
656 * At this stage, point 2 is relaxed for zeroed bands near the noise threshold (hole avoidance is more important)659 * At this stage, point 2 is relaxed for zeroed bands near the noise threshold (hole avoidance is more important)
657 */660 */
658 if (((sce->zeroes[w*16+g] || !sce->band_alt[w*16+g]) && sfb_energy < threshold*sqrtf(1.5f/freq_boost)) || spread < spread_threshold ||661 if ((!sce->zeroes[w*16+g] && !ff_sfdelta_can_remove_band(sce, nextband, prev_sf, w*16+g)) ||
662 ((sce->zeroes[w*16+g] || !sce->band_alt[w*16+g]) && sfb_energy < threshold*sqrtf(1.0f/freq_boost)) || spread < spread_threshold ||
659 (!sce->zeroes[w*16+g] && sce->band_alt[w*16+g] && sfb_energy > threshold*thr_mult*freq_boost) ||663 (!sce->zeroes[w*16+g] && sce->band_alt[w*16+g] && sfb_energy > threshold*thr_mult*freq_boost) ||
660 min_energy < pns_transient_energy_r * max_energy ) {664 min_energy < pns_transient_energy_r * max_energy ) {
661 sce->pns_ener[w*16+g] = sfb_energy;665 sce->pns_ener[w*16+g] = sfb_energy;
666 if (!sce->zeroes[w*16+g])
667 prev_sf = sce->sf_idx[w*16+g];
662 continue;668 continue;
663 }669 }
664 670
665 pns_tgt_energy = sfb_energy*FFMIN(1.0f, spread*spread);671 pns_tgt_energy = sfb_energy*FFMIN(1.0f, spread*spread);
666 noise_sfi = av_clip(roundf(log2f(pns_tgt_energy)*2), -100, 155); /* Quantize */672 noise_sfi = av_clip(roundf(log2f(pns_tgt_energy)*2), -100, 155); /* Quantize */
667 noise_amp = -ff_aac_pow2sf_tab[noise_sfi + POW_SF2_ZERO]; /* Dequantize */673 noise_amp = -ff_aac_pow2sf_tab[noise_sfi + POW_SF2_ZERO]; /* Dequantize */
674 if (prev != -1000) {
675 int noise_sfdiff = noise_sfi - prev + SCALE_DIFF_ZERO;
676 if (noise_sfdiff < 0 || noise_sfdiff > 2*SCALE_MAX_DIFF) {
677 if (!sce->zeroes[w*16+g])
678 prev_sf = sce->sf_idx[w*16+g];
679 continue;
680 }
681 }
668 for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) {682 for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) {
669 float band_energy, scale, pns_senergy;683 float band_energy, scale, pns_senergy;
670 const int start_c = (w+w2)*128+sce->ics.swb_offset[g];684 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 · 26 unmodified lines
697 if (sce->zeroes[w*16+g] || !sce->band_alt[w*16+g] || (energy_ratio > 0.85f && energy_ratio < 1.25f && dist2 < dist1)) {711 if (sce->zeroes[w*16+g] || !sce->band_alt[w*16+g] || (energy_ratio > 0.85f && energy_ratio < 1.25f && dist2 < dist1)) {
698 sce->band_type[w*16+g] = NOISE_BT;712 sce->band_type[w*16+g] = NOISE_BT;
699 sce->zeroes[w*16+g] = 0;713 sce->zeroes[w*16+g] = 0;
714 prev = noise_sfi;
700 }715 }
716 if (!sce->zeroes[w*16+g])
717 prev_sf = sce->sf_idx[w*16+g];
701 }718 }
702 }719 }
703}720}
@@ -775,7 +792,8 @@ static void mark_pns(AACEncContext *s, AVCodecContext *avctx, SingleChannelEleme · 71 unmodified lines
775 792
776static void search_for_ms(AACEncContext *s, ChannelElement *cpe)793static void search_for_ms(AACEncContext *s, ChannelElement *cpe)
777{794{
778 int start = 0, i, w, w2, g, sid_sf_boost;795 int start = 0, i, w, w2, g, sid_sf_boost, prev_mid, prev_side;
796 uint8_t nextband0[128], nextband1[128];
779 float M[128], S[128];797 float M[128], S[128];
780 float *L34 = s->scoefs, *R34 = s->scoefs + 128, *M34 = s->scoefs + 128*2, *S34 = s->scoefs + 128*3;798 float *L34 = s->scoefs, *R34 = s->scoefs + 128, *M34 = s->scoefs + 128*2, *S34 = s->scoefs + 128*3;
781 const float lambda = s->lambda;799 const float lambda = s->lambda;
@@ -784,21 +802,19 @@ static void search_for_ms(AACEncContext *s, ChannelElement *cpe) · 2 unmodified lines
784 SingleChannelElement *sce1 = &cpe->ch[1];802 SingleChannelElement *sce1 = &cpe->ch[1];
785 if (!cpe->common_window)803 if (!cpe->common_window)
786 return;804 return;
787 for (w = 0; w < sce0->ics.num_windows; w += sce0->ics.group_len[w]) {
788 int min_sf_idx_mid = SCALE_MAX_POS;
789 int min_sf_idx_side = SCALE_MAX_POS;
790 for (g = 0; g < sce0->ics.num_swb; g++) {
791 if (!sce0->zeroes[w*16+g] && sce0->band_type[w*16+g] < RESERVED_BT)
792 min_sf_idx_mid = FFMIN(min_sf_idx_mid, sce0->sf_idx[w*16+g]);
793 if (!sce1->zeroes[w*16+g] && sce1->band_type[w*16+g] < RESERVED_BT)
794 min_sf_idx_side = FFMIN(min_sf_idx_side, sce1->sf_idx[w*16+g]);
795 }
796 805
806 /** Scout out next nonzero bands */
807 ff_init_nextband_map(sce0, nextband0);
808 ff_init_nextband_map(sce1, nextband1);
809
810 prev_mid = sce0->sf_idx[0];
811 prev_side = sce1->sf_idx[0];
812 for (w = 0; w < sce0->ics.num_windows; w += sce0->ics.group_len[w]) {
797 start = 0;813 start = 0;
798 for (g = 0; g < sce0->ics.num_swb; g++) {814 for (g = 0; g < sce0->ics.num_swb; g++) {
799 float bmax = bval2bmax(g * 17.0f / sce0->ics.num_swb) / 0.0045f;815 float bmax = bval2bmax(g * 17.0f / sce0->ics.num_swb) / 0.0045f;
800 cpe->ms_mask[w*16+g] = 0;816 cpe->ms_mask[w*16+g] = 0;
801 if (!cpe->ch[0].zeroes[w*16+g] && !cpe->ch[1].zeroes[w*16+g]) {817 if (!sce0->zeroes[w*16+g] && !sce1->zeroes[w*16+g]) {
802 float Mmax = 0.0f, Smax = 0.0f;818 float Mmax = 0.0f, Smax = 0.0f;
803 819
804 /* Must compute mid/side SF and book for the whole window group */820 /* 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) · 20 unmodified lines
825 int midcb, sidcb;841 int midcb, sidcb;
826 842
827 minidx = FFMIN(sce0->sf_idx[w*16+g], sce1->sf_idx[w*16+g]);843 minidx = FFMIN(sce0->sf_idx[w*16+g], sce1->sf_idx[w*16+g]);
828 mididx = av_clip(minidx, min_sf_idx_mid, min_sf_idx_mid + SCALE_MAX_DIFF);844 mididx = av_clip(minidx, 0, SCALE_MAX_POS - SCALE_DIV_512);
829 sididx = av_clip(minidx - sid_sf_boost * 3, min_sf_idx_side, min_sf_idx_side + SCALE_MAX_DIFF);845 sididx = av_clip(minidx - sid_sf_boost * 3, 0, SCALE_MAX_POS - SCALE_DIV_512);
830 midcb = find_min_book(Mmax, mididx);846 if (!cpe->is_mask[w*16+g] && sce0->band_type[w*16+g] != NOISE_BT && sce1->band_type[w*16+g] != NOISE_BT
831 sidcb = find_min_book(Smax, sididx);847 && ( !ff_sfdelta_can_replace(sce0, nextband0, prev_mid, mididx, w*16+g)
832 848 || !ff_sfdelta_can_replace(sce1, nextband1, prev_side, sididx, w*16+g))) {
833 if ((mididx > minidx) || (sididx > minidx)) {
834 /* scalefactor range violation, bad stuff, will decrease quality unacceptably */849 /* scalefactor range violation, bad stuff, will decrease quality unacceptably */
835 continue;850 continue;
836 }851 }
837 852
853 midcb = find_min_book(Mmax, mididx);
854 sidcb = find_min_book(Smax, sididx);
855
838 /* No CB can be zero */856 /* No CB can be zero */
839 midcb = FFMAX(1,midcb);857 midcb = FFMAX(1,midcb);
840 sidcb = FFMAX(1,sidcb);858 sidcb = FFMAX(1,sidcb);
@@ -900,6 +918,10 @@ static void search_for_ms(AACEncContext *s, ChannelElement *cpe) · 59 unmodified lines
900 }918 }
901 }919 }
902 }920 }
921 if (!sce0->zeroes[w*16+g] && sce0->band_type[w*16+g] < RESERVED_BT)
922 prev_mid = sce0->sf_idx[w*16+g];
923 if (!sce1->zeroes[w*16+g] && !cpe->is_mask[w*16+g] && sce1->band_type[w*16+g] < RESERVED_BT)
924 prev_side = sce1->sf_idx[w*16+g];
903 start += sce0->ics.swb_sizes[g];925 start += sce0->ics.swb_sizes[g];
904 }926 }
905 }927 }

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t