X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Faaccoder.c;h=7d85e43b47fed9b697c724017c15e78057b9ae6d;hb=7d1e985528886139ea00387ad34c75cfab018d48;hp=15d467b8706d942327b5321e0fcbf7a311279ef4;hpb=b77061b5caceb07b4487a08e48f78a5b24c15959;p=ffmpeg diff --git a/libavcodec/aaccoder.c b/libavcodec/aaccoder.c index 15d467b8706..7d85e43b47f 100644 --- a/libavcodec/aaccoder.c +++ b/libavcodec/aaccoder.c @@ -195,23 +195,23 @@ typedef struct TrellisPath { static void set_special_band_scalefactors(AACEncContext *s, SingleChannelElement *sce) { - int w, g, start = 0; - int minscaler_n = sce->sf_idx[0], minscaler_i = sce->sf_idx[0]; + int w, g; + int prevscaler_n = -255, prevscaler_i = 0; int bands = 0; for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) { - start = 0; for (g = 0; g < sce->ics.num_swb; g++) { + if (sce->zeroes[w*16+g]) + continue; if (sce->band_type[w*16+g] == INTENSITY_BT || sce->band_type[w*16+g] == INTENSITY_BT2) { sce->sf_idx[w*16+g] = av_clip(roundf(log2f(sce->is_ener[w*16+g])*2), -155, 100); - minscaler_i = FFMIN(minscaler_i, sce->sf_idx[w*16+g]); bands++; } else if (sce->band_type[w*16+g] == NOISE_BT) { sce->sf_idx[w*16+g] = av_clip(3+ceilf(log2f(sce->pns_ener[w*16+g])*2), -100, 155); - minscaler_n = FFMIN(minscaler_n, sce->sf_idx[w*16+g]); + if (prevscaler_n == -255) + prevscaler_n = sce->sf_idx[w*16+g]; bands++; } - start += sce->ics.swb_sizes[g]; } } @@ -221,10 +221,12 @@ static void set_special_band_scalefactors(AACEncContext *s, SingleChannelElement /* Clip the scalefactor indices */ 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]) + continue; if (sce->band_type[w*16+g] == INTENSITY_BT || sce->band_type[w*16+g] == INTENSITY_BT2) { - sce->sf_idx[w*16+g] = av_clip(sce->sf_idx[w*16+g], minscaler_i, minscaler_i + SCALE_MAX_DIFF); + sce->sf_idx[w*16+g] = prevscaler_i = av_clip(sce->sf_idx[w*16+g], prevscaler_i - SCALE_MAX_DIFF, prevscaler_i + SCALE_MAX_DIFF); } else if (sce->band_type[w*16+g] == NOISE_BT) { - sce->sf_idx[w*16+g] = av_clip(sce->sf_idx[w*16+g], minscaler_n, minscaler_n + SCALE_MAX_DIFF); + sce->sf_idx[w*16+g] = prevscaler_n = av_clip(sce->sf_idx[w*16+g], prevscaler_n - SCALE_MAX_DIFF, prevscaler_n + SCALE_MAX_DIFF); } } } @@ -643,8 +645,11 @@ static void search_for_pns(AACEncContext *s, AVCodecContext *avctx, SingleChanne const int start = wstart+sce->ics.swb_offset[g]; const float freq = (start-wstart)*freq_mult; const float freq_boost = FFMAX(0.88f*freq/NOISE_LOW_LIMIT, 1.0f); - if (freq < NOISE_LOW_LIMIT || (start-wstart) >= cutoff) + if (freq < NOISE_LOW_LIMIT || (start-wstart) >= cutoff) { + 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++) { band = &s->psy.ch[s->cur_channel].psy_bands[(w+w2)*16+g]; sfb_energy += band->energy; @@ -726,9 +731,10 @@ static void search_for_pns(AACEncContext *s, AVCodecContext *avctx, SingleChanne sce->band_type[w*16+g] = NOISE_BT; sce->zeroes[w*16+g] = 0; prev = noise_sfi; + } else { + if (!sce->zeroes[w*16+g]) + prev_sf = sce->sf_idx[w*16+g]; } - if (!sce->zeroes[w*16+g]) - prev_sf = sce->sf_idx[w*16+g]; } } } @@ -827,8 +833,9 @@ static void search_for_ms(AACEncContext *s, ChannelElement *cpe) 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 (!sce0->zeroes[w*16+g] && !sce1->zeroes[w*16+g]) { + if (!cpe->is_mask[w*16+g]) + cpe->ms_mask[w*16+g] = 0; + if (!sce0->zeroes[w*16+g] && !sce1->zeroes[w*16+g] && !cpe->is_mask[w*16+g]) { float Mmax = 0.0f, Smax = 0.0f; /* Must compute mid/side SF and book for the whole window group */ @@ -857,7 +864,7 @@ static void search_for_ms(AACEncContext *s, ChannelElement *cpe) 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 + if (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 */ @@ -890,40 +897,42 @@ static void search_for_ms(AACEncContext *s, ChannelElement *cpe) 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], + sce0->sf_idx[w*16+g], + sce0->band_type[w*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], + sce1->sf_idx[w*16+g], + sce1->band_type[w*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], + mididx, + midcb, 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], + sididx, + sidcb, mslambda / (minthr * bmax), INFINITY, &b4, NULL, 0); B0 += b1+b2; B1 += b3+b4; - dist1 -= B0; - dist2 -= B1; + dist1 -= b1+b2; + dist2 -= b3+b4; } 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) { + if (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; + } else if ((sce0->band_type[w*16+g] != NOISE_BT) ^ (sce1->band_type[w*16+g] != NOISE_BT)) { + /* ms_mask unneeded, and it confuses some decoders */ + cpe->ms_mask[w*16+g] = 0; } break; } else if (B1 > B0) {