On Sat, Sep 10, 2016 at 3:37 AM, Claudio Freire <klaussfre...@gmail.com> wrote:
> On Thu, Aug 25, 2016 at 8:57 AM, Rostislav Pehlivanov
> <atomnu...@gmail.com> wrote:
>>> 64ed96a710787ba5d0666746a8562e7d.dee
>>>
>>> Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
>>> Signed-off-by: Michael Niedermayer <mich...@niedermayer.cc>
>>> ---
>>>  libavcodec/aaccoder.c | 8 +++++++-
>>>  1 file changed, 7 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/libavcodec/aaccoder.c b/libavcodec/aaccoder.c
>>> index 284b401..995724b 100644
>>> --- a/libavcodec/aaccoder.c
>>> +++ b/libavcodec/aaccoder.c
>>> @@ -196,7 +196,7 @@ typedef struct TrellisPath {
>>>  static void set_special_band_scalefactors(AACEncContext *s,
>>> SingleChannelElement *sce)
>>>  {
>>>      int w, g;
>>> -    int prevscaler_n = -255, prevscaler_i = 0;
>>> +    int prevscaler_n = -255, prevscaler_i = 0, prevscaler_d = -255;
>>>      int bands = 0;
>>>
>>>      for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) {
>>> @@ -211,6 +211,10 @@ static void set_special_band_scalefactors(AACEncContext
>>> *s, SingleChannelElement
>>>                  if (prevscaler_n == -255)
>>>                      prevscaler_n = sce->sf_idx[w*16+g];
>>>                  bands++;
>>> +            } else {
>>> +                if (prevscaler_d == -255)
>>> +                    prevscaler_d = sce->sf_idx[w*16+g];
>>> +                bands++;
>>>              }
>>>          }
>>>      }
>>> @@ -227,6 +231,8 @@ static void set_special_band_scalefactors(AACEncContext
>>> *s, SingleChannelElement
>>>                  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] = prevscaler_n =
>>> av_clip(sce->sf_idx[w*16+g], prevscaler_n - SCALE_MAX_DIFF, prevscaler_n +
>>> SCALE_MAX_DIFF);
>>> +            } else {
>>> +                sce->sf_idx[w*16+g] = prevscaler_d =
>>> av_clip(sce->sf_idx[w*16+g], prevscaler_d - SCALE_MAX_DIFF, prevscaler_d +
>>> SCALE_MAX_DIFF);
>>>              }
>>>          }
>>>      }
>>> --
>>> 2.9.3
>>>
>>> _______________________________________________
>>> ffmpeg-devel mailing list
>>> ffmpeg-devel@ffmpeg.org
>>> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>>>
>>
>>
>> That fuzzed sample seems to be causing the algorithm which does SF
>> difference normalization between normal and PNS bands to fail. This commit
>> masks the problem downstream. IMO that's not the correct way to solve this,
>> as there's no guarantee that another sample won't trigger the same assert
>> even when limiting all scalefactors. Fixing a single fuzzed sample with a
>> hack which doesn't stop other fuzzed samples from triggering the same bug
>> isn't justified.
>> I have the time right now and I'll try to fix this properly, but it might
>> take me a day or two. I think the problem is that when the twoloop coder
>> does the the normalization it doesn't take into account the fact that IS
>> and PNS have their scalefactors modified by set_special_band_scalefactors()
>> later on before encoding.
>
> It seems the root of the issue is that the two stages of PNS don't
> agree on when they can apply PNS or not.
>
> I have a WIP that eliminates the issue by just making the two agree,
> but I've got unrelated changes so I'll try to distill the patch to the
> minimum necessary to fix this during the weekend.

Sorry for the delay, it turned out to be more complex than that.

There were a few potential violations that I had already identified in
a WIP patch but they did not apply to the fuzzed sample. That sample
triggered an interaction with TNS and trellis band type coding that
resulted in zeroed bands reappearing and thus invalidating all delta
scalefactor validations.

The attached patch series fixes most of the delta scalefactor
violation risks I could find, including that one.

It hasn't been thoroughly tested for quality regressions/improvements.
It's possible that it does change quality since it changes key
decision points that conduce to the violations but also to lots of
audible artifacts. So I believe it should improve quality, but one
never knows without proper ABX testing, which I'll be conducting, at
least in a limited way, in the following days.

In the meantime, I'm attaching the patch series for review.
From c14007975b40fcd1e4f550a9a37cb695d80c1c20 Mon Sep 17 00:00:00 2001
From: Claudio Freire <klaussfre...@gmail.com>
Date: Wed, 21 Sep 2016 02:46:41 -0300
Subject: [PATCH 1/4] AAC Encoder: fix encoding issues with PNS

The two phases of PNS encoding (mark_pns and search_for_pns) were
not in aggreement when PNS could be used, which could cause holes
and illegally PNS'd bands (ie: that would make scalefactor delta
of normal bands exceed the allowed range).
---
 libavcodec/aaccoder.c         | 17 ++++++++---------
 libavcodec/aaccoder_twoloop.h |  2 ++
 2 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/libavcodec/aaccoder.c b/libavcodec/aaccoder.c
index 284b401..b53b3fc 100644
--- a/libavcodec/aaccoder.c
+++ b/libavcodec/aaccoder.c
@@ -552,9 +552,7 @@ static void search_for_pns(AACEncContext *s, AVCodecContext *avctx, SingleChanne
     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);
-    const float spread_threshold = FFMIN(0.75f, NOISE_SPREAD_THRESHOLD*FFMAX(0.5f, lambda/100.f));
     const float dist_bias = av_clipf(4.f * 120 / lambda, 0.25f, 4.0f);
-    const float pns_transient_energy_r = FFMIN(0.7f, lambda / 140.f);
 
     int refbits = avctx->bit_rate * 1024.0 / avctx->sample_rate
         / ((avctx->flags & CODEC_FLAG_QSCALE) ? 2.0f : avctx->channels)
@@ -582,7 +580,7 @@ static void search_for_pns(AACEncContext *s, AVCodecContext *avctx, SingleChanne
     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++) {
-            int noise_sfi;
+            int noise_sfi, real_zero = 1;
             float dist1 = 0.0f, dist2 = 0.0f, noise_amp;
             float pns_energy = 0.0f, pns_tgt_energy, energy_ratio, dist_thresh;
             float sfb_energy = 0.0f, threshold = 0.0f, spread = 2.0f;
@@ -600,6 +598,8 @@ static void search_for_pns(AACEncContext *s, AVCodecContext *avctx, SingleChanne
                 sfb_energy += band->energy;
                 spread     = FFMIN(spread, band->spread);
                 threshold  += band->threshold;
+                if (real_zero && band->energy > band->threshold)
+                    real_zero = 0;
                 if (!w2) {
                     min_energy = max_energy = band->energy;
                 } else {
@@ -618,10 +618,10 @@ 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] && !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 ) {
+            if ((!sce->can_pns[w*16+g] && (!sce->zeroes[w*16+g] || sce->band_alt[w*16+g] || real_zero) ) ||
+                (!sce->zeroes[w*16+g] && sce->band_alt[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]) && real_zero) ||
+                (!sce->zeroes[w*16+g] && sce->band_alt[w*16+g] && sfb_energy > threshold*thr_mult*freq_boost)) {
                 sce->pns_ener[w*16+g] = sfb_energy;
                 if (!sce->zeroes[w*16+g])
                     prev_sf = sce->sf_idx[w*16+g];
@@ -722,7 +722,6 @@ static void mark_pns(AACEncContext *s, AVCodecContext *avctx, SingleChannelEleme
             float min_energy = -1.0f, max_energy = 0.0f;
             const int start = sce->ics.swb_offset[g];
             const float freq = start*freq_mult;
-            const float freq_boost = FFMAX(0.88f*freq/NOISE_LOW_LIMIT, 1.0f);
             if (freq < NOISE_LOW_LIMIT || start >= cutoff) {
                 sce->can_pns[w*16+g] = 0;
                 continue;
@@ -746,7 +745,7 @@ static void mark_pns(AACEncContext *s, AVCodecContext *avctx, SingleChannelEleme
              * 3. on short window groups, all windows have similar energy (variations in energy would be destroyed by PNS)
              */
             sce->pns_ener[w*16+g] = sfb_energy;
-            if (sfb_energy < threshold*sqrtf(1.5f/freq_boost) || spread < spread_threshold || min_energy < pns_transient_energy_r * max_energy) {
+            if (spread < spread_threshold || min_energy < pns_transient_energy_r * max_energy) {
                 sce->can_pns[w*16+g] = 0;
             } else {
                 sce->can_pns[w*16+g] = 1;
diff --git a/libavcodec/aaccoder_twoloop.h b/libavcodec/aaccoder_twoloop.h
index 42aea52..2098318 100644
--- a/libavcodec/aaccoder_twoloop.h
+++ b/libavcodec/aaccoder_twoloop.h
@@ -714,6 +714,8 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx,
                         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]);
+                    if (sce->band_type[w*16+g])
+                        sce->band_type[w*16+g] = 1;
                     prev = sce->sf_idx[w*16+g];
                     if (!fflag && prevsf != sce->sf_idx[w*16+g])
                         fflag = 1;
-- 
1.8.4.5

From 4f110df74176e9702802e678bc744c6d4525ab6e Mon Sep 17 00:00:00 2001
From: Claudio Freire <klaussfre...@gmail.com>
Date: Thu, 22 Sep 2016 03:01:57 -0300
Subject: [PATCH 2/4] AAC Encoder: Set I/S band_type and sf_idx properly

I/S coding would not set the proper band_type and sf_idx when short
windows are concerned, leading to artifacts and possible sf_idx
delta range violations
---
 libavcodec/aacenc_is.c | 25 +++++++++++++++++++------
 libavcodec/aacenc_is.h |  2 ++
 2 files changed, 21 insertions(+), 6 deletions(-)

diff --git a/libavcodec/aacenc_is.c b/libavcodec/aacenc_is.c
index 473897b..b845166 100644
--- a/libavcodec/aacenc_is.c
+++ b/libavcodec/aacenc_is.c
@@ -42,7 +42,8 @@ struct AACISError ff_aac_is_encoding_err(AACEncContext *s, ChannelElement *cpe,
     float *R = use_pcoeffs ? sce1->pcoeffs : sce1->coeffs;
     float *L34 = &s->scoefs[256*0], *R34 = &s->scoefs[256*1];
     float *IS  = &s->scoefs[256*2], *I34 = &s->scoefs[256*3];
-    float dist1 = 0.0f, dist2 = 0.0f;
+    float dist1 = 0.0f, dist2 = 0.0f, maxval = 0.0f;
+    int is_band_type, is_sf_idx;
     struct AACISError is_error = {0};
 
     if (ener01 <= 0 || ener0 <= 0) {
@@ -51,19 +52,27 @@ struct AACISError ff_aac_is_encoding_err(AACEncContext *s, ChannelElement *cpe,
     }
 
     for (w2 = 0; w2 < sce0->ics.group_len[w]; w2++) {
+        float nmaxval;
+        for (i = 0; i < sce0->ics.swb_sizes[g]; i++)
+            IS[i] = (L[start+(w+w2)*128+i] + phase*R[start+(w+w2)*128+i])*sqrt(ener0/ener01);
+        abs_pow34_v(I34, IS,                   sce0->ics.swb_sizes[g]);
+        nmaxval = find_max_val(1, sce0->ics.swb_sizes[g], I34);
+        maxval = FFMAX(maxval, nmaxval);
+    }
+    is_sf_idx = FFMAX(1, sce0->sf_idx[w*16+g]);
+    is_band_type = find_min_book(maxval, is_sf_idx);
+
+    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];
-        int is_band_type, is_sf_idx = FFMAX(1, sce0->sf_idx[w*16+g]-4);
         float e01_34 = phase*pos_pow34(ener1/ener0);
-        float maxval, dist_spec_err = 0.0f;
+        float dist_spec_err = 0.0f;
         float minthr = FFMIN(band0->threshold, band1->threshold);
         for (i = 0; i < sce0->ics.swb_sizes[g]; i++)
             IS[i] = (L[start+(w+w2)*128+i] + phase*R[start+(w+w2)*128+i])*sqrt(ener0/ener01);
         abs_pow34_v(L34, &L[start+(w+w2)*128], sce0->ics.swb_sizes[g]);
         abs_pow34_v(R34, &R[start+(w+w2)*128], sce0->ics.swb_sizes[g]);
         abs_pow34_v(I34, IS,                   sce0->ics.swb_sizes[g]);
-        maxval = find_max_val(1, sce0->ics.swb_sizes[g], I34);
-        is_band_type = find_min_book(maxval, is_sf_idx);
         dist1 += quantize_band_cost(s, &L[start + (w+w2)*128], L34,
                                     sce0->ics.swb_sizes[g],
                                     sce0->sf_idx[w*16+g],
@@ -91,6 +100,8 @@ struct AACISError ff_aac_is_encoding_err(AACEncContext *s, ChannelElement *cpe,
     is_error.dist1 = dist1;
     is_error.dist2 = dist2;
     is_error.ener01 = ener01;
+    is_error.band_type = is_band_type;
+    is_error.sf_idx = is_sf_idx;
 
     return is_error;
 }
@@ -112,7 +123,7 @@ void ff_aac_search_for_is(AACEncContext *s, AVCodecContext *avctx, ChannelElemen
     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) &&
+            if (start*freq_mult > INT_STEREO_LOW_LIMIT &&
                 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] &&
                 ff_sfdelta_can_remove_band(sce1, nextband1, prev_sf1, w*16+g)) {
@@ -139,6 +150,8 @@ void ff_aac_search_for_is(AACEncContext *s, AVCodecContext *avctx, ChannelElemen
                     cpe->ch[0].is_ener[w*16+g] = sqrt(ener0 / best->ener01);
                     cpe->ch[1].is_ener[w*16+g] = ener0/ener1;
                     cpe->ch[1].band_type[w*16+g] = (best->phase > 0) ? INTENSITY_BT : INTENSITY_BT2;
+                    cpe->ch[0].band_type[w*16+g] = best->band_type;
+                    cpe->ch[0].sf_idx[w*16+g] = best->sf_idx;
                     if (prev_is && prev_bt != cpe->ch[1].band_type[w*16+g]) {
                         /** Flip M/S mask and pick the other CB, since it encodes more efficiently */
                         cpe->ms_mask[w*16+g] = 1;
diff --git a/libavcodec/aacenc_is.h b/libavcodec/aacenc_is.h
index 269fd1a..9b04a5f 100644
--- a/libavcodec/aacenc_is.h
+++ b/libavcodec/aacenc_is.h
@@ -40,6 +40,8 @@ struct AACISError {
     float dist1; /* From original coeffs */
     float dist2; /* From IS'd coeffs     */
     float ener01;
+    int sf_idx;
+    int band_type;
 };
 
 struct AACISError ff_aac_is_encoding_err(AACEncContext *s, ChannelElement *cpe,
-- 
1.8.4.5

From 66854ab6a92ce7d69cd60f4d49d647acebc14a0b Mon Sep 17 00:00:00 2001
From: Claudio Freire <klaussfre...@gmail.com>
Date: Thu, 22 Sep 2016 03:08:29 -0300
Subject: [PATCH 3/4] AAC Encoder: M/S coding scalefactor delta limit

Avoid setting scalefactors outside the valid delta range during
M/S encoding
---
 libavcodec/aaccoder.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libavcodec/aaccoder.c b/libavcodec/aaccoder.c
index b53b3fc..1445ab4 100644
--- a/libavcodec/aaccoder.c
+++ b/libavcodec/aaccoder.c
@@ -806,8 +806,8 @@ 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, 0, SCALE_MAX_POS - SCALE_DIV_512);
-                    sididx = av_clip(minidx - sid_sf_boost * 3, 0, SCALE_MAX_POS - SCALE_DIV_512);
+                    mididx = av_clip(av_clip(minidx, prev_mid - SCALE_MAX_DIFF, prev_mid + SCALE_MAX_DIFF), 0, SCALE_MAX_POS);
+                    sididx = av_clip(av_clip(minidx - sid_sf_boost * 3, prev_side - SCALE_MAX_DIFF, prev_side + SCALE_MAX_DIFF), 0, SCALE_MAX_POS);
                     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))) {
-- 
1.8.4.5

From 5a3fb7e7fcd156108cc05fb8221722544631c1b7 Mon Sep 17 00:00:00 2001
From: Claudio Freire <klaussfre...@gmail.com>
Date: Thu, 22 Sep 2016 06:37:54 -0300
Subject: [PATCH 4/4] AAC Encoder: prevent TNS from inducing sfdelta asserts

TNS filtering can change the required minimum coding book for bands
it applies to, so recompute band_type when TNS is being applied.

Similarly, zero flags must match for all windows in a window group
for code post-tns to work correctly, so make sure twoloop fills in
the zero flags appropriately.
---
 libavcodec/aaccoder.c         |  4 ++--
 libavcodec/aaccoder_twoloop.h | 14 +++++++++++++-
 libavcodec/aacenc_tns.c       | 21 ++++++++++++++++++++-
 3 files changed, 35 insertions(+), 4 deletions(-)

diff --git a/libavcodec/aaccoder.c b/libavcodec/aaccoder.c
index 1445ab4..a6edfa4 100644
--- a/libavcodec/aaccoder.c
+++ b/libavcodec/aaccoder.c
@@ -659,8 +659,8 @@ static void search_for_pns(AACEncContext *s, AVCodecContext *avctx, SingleChanne
                 dist1 += quantize_band_cost(s, &sce->coeffs[start_c],
                                             NOR34,
                                             sce->ics.swb_sizes[g],
-                                            sce->sf_idx[(w+w2)*16+g],
-                                            sce->band_alt[(w+w2)*16+g],
+                                            sce->sf_idx[w*16+g],
+                                            sce->band_alt[w*16+g],
                                             lambda/band->threshold, INFINITY, NULL, NULL, 0);
                 /* Estimate rd on average as 5 bits for SF, 4 for the CB, plus spread energy * lambda/thr */
                 dist2 += band->energy/(band->spread*band->spread)*lambda*dist_thresh/band->threshold;
diff --git a/libavcodec/aaccoder_twoloop.h b/libavcodec/aaccoder_twoloop.h
index 2098318..1bc1298 100644
--- a/libavcodec/aaccoder_twoloop.h
+++ b/libavcodec/aaccoder_twoloop.h
@@ -714,7 +714,7 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx,
                         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]);
-                    if (sce->band_type[w*16+g])
+                    if (sce->band_type[w*16+g] == 0)
                         sce->band_type[w*16+g] = 1;
                     prev = sce->sf_idx[w*16+g];
                     if (!fflag && prevsf != sce->sf_idx[w*16+g])
@@ -760,6 +760,18 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx,
             }
         }
     }
+
+    /** Broadcast zero flags on all windows in the group to keep things consistent */
+    for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) {
+        if (sce->ics.group_len[w] > 1) {
+            /** Make sure proper codebooks are set */
+            for (g = 0; g < sce->ics.num_swb; g++) {
+                int z = sce->zeroes[w*16+g];
+                for (w2 = 0; w2 < sce->ics.group_len[w]; w2++)
+                    sce->zeroes[(w+w2)*16+g] = z;
+            }
+        }
+    }
 }
 
 #endif /* AVCODEC_AACCODER_TWOLOOP_H */
diff --git a/libavcodec/aacenc_tns.c b/libavcodec/aacenc_tns.c
index 2ffe1f8..2ba1940 100644
--- a/libavcodec/aacenc_tns.c
+++ b/libavcodec/aacenc_tns.c
@@ -103,9 +103,10 @@ void ff_aac_apply_tns(AACEncContext *s, SingleChannelElement *sce)
 {
     TemporalNoiseShaping *tns = &sce->tns;
     IndividualChannelStream *ics = &sce->ics;
-    int w, filt, m, i, top, order, bottom, start, end, size, inc;
+    int w, filt, m, i, top, order, bottom, start, end, size, inc, g;
     const int mmm = FFMIN(ics->tns_max_bands, ics->max_sfb);
     float lpc[TNS_MAX_ORDER];
+    int has_filt = 0;
 
     for (w = 0; w < ics->num_windows; w++) {
         bottom = ics->num_swb;
@@ -137,6 +138,24 @@ void ff_aac_apply_tns(AACEncContext *s, SingleChannelElement *sce)
                     sce->coeffs[start] += lpc[i-1]*sce->pcoeffs[start - i*inc];
                 }
             }
+
+            has_filt = 1;
+        }
+    }
+
+    if (has_filt) {
+        abs_pow34_v(s->scoefs, sce->coeffs, 1024);
+        for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) {
+            start = w*128;
+            for (g = 0; g < sce->ics.num_swb; g++) {
+                if (!sce->zeroes[w*16+g]) {
+                    float maxval = find_max_val(sce->ics.group_len[w], sce->ics.swb_sizes[g], s->scoefs+start);
+                    int cb = find_min_book(maxval, sce->sf_idx[w*16+g]);
+                    if (sce->band_type[w*16+g] < cb)
+                        sce->band_type[w*16+g] = cb;
+                }
+                start += sce->ics.swb_sizes[g];
+            }
         }
     }
 }
-- 
1.8.4.5

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

Reply via email to