Commit 72844226eb for ffmpeg

commit 72844226eb8c7fc76bc71ce81f8343d09332f1a1
Author: Lynne <dev@lynne.ee>
Date:   Sun Nov 8 02:19:58 2026 +0800

    avcodec/aacenc: bound the frame re-encode loop

    A frame over the decoder buffer was re-encoded at an ever lower lambda
    until it fit, without a bound: a coder that could not fit it at any
    lambda hung the encoder (#25580), and so did strict rate control asking
    for less than a frame needs, e.g. -b:a 1 -bt 0 on silence.

    - Bound the overflow and the strict-rate retries at 16, as the QSCALE
      ones already were.
    - Restart an overflow from the nominal lambda. Over quiet passages
      twoloop winds lambda up to around 24000, far above where it responds,
      and the steady-state clamp then lowered it by only 10% a retry: the
      #25580 onset frame took 47 retries. Shrink by at least the overshoot
      as well; that frame now fits after one.
    - If a frame still does not fit, keep the coarsest lambda reached and
      lowpass its spectrum in steps until it does, rather than fail the
      encode or emit a frame a conforming decoder may reject.
    - Restore the pristine coefficients at the start of every retry. The
      strict-rate retries never did, so psy re-analyzed, and the stereo
      tools and TNS re-filtered, coefficients they had already transformed.

diff --git a/libavcodec/aacenc.c b/libavcodec/aacenc.c
index 50a1460e61..aadb9e6e17 100644
--- a/libavcodec/aacenc.c
+++ b/libavcodec/aacenc.c
@@ -1291,9 +1291,8 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
     ChannelElement *cpe;
     SingleChannelElement *sce;
     IndividualChannelStream *ics;
-    int i, its, ch, w, chans, tag, start_ch, ret, frame_bits;
+    int i, its, ch, w, chans, tag, start_ch, ret, frame_bits, cutoff;
     int target_bits, rate_bits, too_many_bits, too_few_bits;
-    int ms_mode = 0, is_mode = 0, tns_mode = 0, pred_mode = 0;
     int chan_el_counter[4];
     FFPsyWindowInfo windows[AAC_MAX_CHANNELS];

@@ -1425,7 +1424,28 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
     if ((ret = ff_alloc_packet(avctx, avpkt, 8192 * s->channels)) < 0)
         return ret;
     frame_bits = its = 0;
+    cutoff = 1024;
     do {
+        /* every retry starts from the pristine spectrum: the stereo tools,
+         * TNS and prediction filter the coefficients in place, and psy
+         * re-analyzes them */
+        if (its) {
+            for (i = 0; i < s->chan_map[0]; i++) {
+                chans = s->chan_map[i + 1] == TYPE_CPE ? 2 : 1;
+                for (ch = 0; ch < chans; ch++) {
+                    sce = &s->cpe[i].ch[ch];
+                    memcpy(sce->coeffs, sce->pcoeffs, sizeof(sce->coeffs));
+                    if (cutoff < 1024) {
+                        /* lowpass, per window */
+                        int nw = sce->ics.window_sequence[0] == EIGHT_SHORT_SEQUENCE ? 8 : 1;
+                        int len = 1024 / nw, cut = cutoff / nw;
+                        for (w = 0; w < nw; w++)
+                            memset(&sce->coeffs[w*len + cut], 0,
+                                   (len - cut) * sizeof(sce->coeffs[0]));
+                    }
+                }
+            }
+        }
         init_put_bits(&s->pb, avpkt->data, avpkt->size);

         if ((avctx->frame_num & 0xFF)==1 && !(avctx->flags & AV_CODEC_FLAG_BITEXACT))
@@ -1491,8 +1511,6 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
                         s->coder->mark_pns(s, avctx, sce);
                     s->coder->search_for_tns(s, sce);
                     s->coder->apply_tns_filt(s, sce);
-                    if (sce->tns.present)
-                        tns_mode = 1;
                 }
             }

@@ -1531,8 +1549,6 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
                 if (!tns_first && use_tns) {
                     s->coder->search_for_tns(s, sce);
                     s->coder->apply_tns_filt(s, sce);
-                    if (sce->tns.present)
-                        tns_mode = 1;
                 }
                 if (s->options.pns && s->coder->search_for_pns)
                     s->coder->search_for_pns(s, avctx, sce);
@@ -1544,7 +1560,6 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
                         s->coder->search_for_is(s, avctx, cpe);
                     apply_intensity_stereo(cpe);
                 }
-                if (cpe->is_mode) is_mode = 1;
             }
             if (s->options.mid_side && s->options.coder != AAC_CODER_NMR) { /* Mid/Side stereo */
                 if (s->options.mid_side == -1 && s->coder->search_for_ms)
@@ -1559,7 +1574,6 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
                 if (cpe->common_window) {
                     put_ics_info(s, &cpe->ch[0].ics);
                     encode_ms_info(&s->pb, cpe);
-                    if (cpe->ms_mode) ms_mode = 1;
                 }
             }
             for (ch = 0; ch < chans; ch++) {
@@ -1569,26 +1583,32 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
             start_ch += chans;
         }

+        frame_bits = put_bits_count(&s->pb);
+
+        /* Out of lambda retries and still over the decoder buffer: rather
+         * than fail the encode or emit a frame a conforming decoder may
+         * reject, keep the coarsest lambda reached and shed the highest
+         * frequencies until the frame fits (an empty spectrum always does). */
+        if (frame_bits >= 6144 * s->channels - 3 && its >= 16 && cutoff) {
+            if (cutoff == 1024)
+                av_log(avctx, AV_LOG_WARNING, "Frame of %d bits exceeds the decoder "
+                       "buffer, reducing its bandwidth\n", frame_bits);
+            cutoff = cutoff * 3 / 4;
+            its++;
+            continue;
+        }
+
         if (avctx->flags & AV_CODEC_FLAG_QSCALE) {
             /* When using a constant Q-scale, don't mess with lambda, unless
              * the frame does not fit the decoder buffer: retry coarser (the
              * coders' legality caps shrink with lambda) */
-            frame_bits = put_bits_count(&s->pb);
             if (frame_bits < 6144 * s->channels - 3 || its >= 16)
                 break;
             s->lambda *= FFMIN(0.9f, (6144.0f * s->channels - 3) / frame_bits);
-            for (i = 0; i < s->chan_map[0]; i++) {
-                chans = s->chan_map[i + 1] == TYPE_CPE ? 2 : 1;
-                for (ch = 0; ch < chans; ch++)
-                    memcpy(s->cpe[i].ch[ch].coeffs, s->cpe[i].ch[ch].pcoeffs,
-                           sizeof(s->cpe[i].ch[ch].coeffs));
-            }
             its++;
             continue;
         }

-        frame_bits = put_bits_count(&s->pb);
-
         /* The NMR coder rate-controls itself (global-lambda reservoir servo):
          * per-frame bits intentionally float around the nominal rate, so skip
          * the lambda rate loop and only intervene on a hard overflow. */
@@ -1608,9 +1628,10 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,

         /* When strict bit-rate control is demanded */
         if (avctx->bit_rate_tolerance == 0) {
-            if (rate_bits < frame_bits) {
+            if (rate_bits < frame_bits && its < 16) {
                 float ratio = ((float)rate_bits) / frame_bits;
                 s->lambda *= FFMIN(0.9f, ratio);
+                its++;
                 continue;
             }
             /* reset lambda when solution is found */
@@ -1624,7 +1645,7 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,

         if (   its == 0 /* for steady-state Q-scale tracking */
             || (its < 5 && (frame_bits < too_few_bits || frame_bits > too_many_bits))
-            || frame_bits >= 6144 * s->channels - 3  )
+            || (frame_bits >= 6144 * s->channels - 3 && its < 16))
         {
             float ratio = ((float)rate_bits) / frame_bits;

@@ -1641,28 +1662,25 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
                 /* Not so fast though */
                 ratio = sqrtf(ratio);
             }
+            if (frame_bits >= 6144 * s->channels - 3) {
+                /* lambda winds up over quiet passages, far above where the
+                 * coder responds: restart an overflow from the nominal one,
+                 * and shrink at least in proportion to the overshoot (the
+                 * steady-state clamp above would allow 0.9 per retry) */
+                s->lambda = FFMIN(s->lambda, avctx->global_quality > 0 ? avctx->global_quality : 120);
+                ratio = FFMIN(ratio, FFMIN(0.9f, (6144.0f * s->channels - 3) / frame_bits));
+            }
             s->lambda = av_clipf(s->lambda * ratio, FLT_EPSILON, 65536.f);

             /* Keep iterating if we must reduce and lambda is in the sky */
-            if (ratio > 0.9f && ratio < 1.1f) {
+            if (ratio > 0.9f && ratio < 1.1f)
                 break;
-            } else {
-                if (is_mode || ms_mode || tns_mode || pred_mode) {
-                    for (i = 0; i < s->chan_map[0]; i++) {
-                        // Must restore coeffs
-                        chans = s->chan_map[i + 1] == TYPE_CPE ? 2 : 1;
-                        cpe = &s->cpe[i];
-                        for (ch = 0; ch < chans; ch++)
-                            memcpy(cpe->ch[ch].coeffs, cpe->ch[ch].pcoeffs, sizeof(cpe->ch[ch].coeffs));
-                    }
-                }
-                its++;
-            }
+            its++;
         } else {
             break;
         }
     } while (1);
-    if (avctx->flags & AV_CODEC_FLAG_QSCALE)
+    if ((avctx->flags & AV_CODEC_FLAG_QSCALE) || cutoff < 1024)
         s->lambda = avctx->global_quality > 0 ? avctx->global_quality : 120;

     /* tool-usage stats over the final per-band decisions of this frame */