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 */