1
0
mirror of https://git.ffmpeg.org/ffmpeg.git synced 2026-10-24 02:09:03 +03:00

avcodec/aaccoder_nmr, aacenc, aacpsy: -aac_rc abr

-aac_rc cbr|abr (default cbr). ABR runs the nd-target quality solve with
the set-point owned by a slow rate servo, and joins VBR as a
quality-target mode in the psy model (fixed-reference PE reduction,
quality attack map, broadband mask floor).

The servo integrates the log rate error but applies it to the nd
set-point in rare, discrete, calm-gated steps. The set-point must be
quasi-static: any drift on content timescales moves lambda, and with it
band/PNS/scalefactor state, tracking sections in antiphase and
coarsening exactly what needs bits - measured 2x worse than a fixed
target at equal mean rate. Locally this mode IS fixed-target VBR; rate
honesty converges on the minutes scale.

Bootstrap. The set-point is seeded from the VBR calibration anchor (one
constant, NMR_VBR_ANCHOR: the two are required to agree, and moving only
one copy made ABR overshoot its rate target by up to 9%). After ~2s of
fast rate measurement off a representative window (an all-transient
head reads over-target and would coarsen the very content that needs
bits), an open-loop jump over the measured loop gain (~ -0.24 log2 rate
per target unit) corrects the seed's per-content error, applied at
1.2x - the estimator's own inverse warm-up factor, since the EMA is
seeded on target (a cold start must not read as a fake deficit) and so
recovers only ~82% of the error. One correction is not enough whatever
the gain estimate, because the 0.24 loop gain is only nominal: the boot
re-arms while the rate is still off, up to a bounded number of times,
re-measuring each time, and re-seeds the estimator on target rather than
to zero (a zero estimate pins the integrator at its clip via log2f(0)
and reads as a 100% deficit to the fill in the same frame). Its settle
window sits below the stepper's hold, or the stepper resets the shared
counter first and the re-arm never fires.

Every set-point correction is glided in at ~0.5 log2-units/s rather than
stepped: a one-frame noise-floor jump at a fixed stream time (the boot
lands at ~2s in every stream) is audible against revealing content even
at step sizes the corpus cannot see.

Bits-fill. Under the long-run target, an easy frame is topped up toward
the ask by moving lambda finer only - the quality target is a floor,
never traded away. It spends the rate the user asked for on sub-mask
margin the nd statistic cannot see (it clips at -4/band); without it,
stat-transparent content caps the rate below any ask. The fill runs from
frame one and fades continuously as the rate EMA converges (a boot-gated
fill flipped regimes at ~2s, an audible quality step), follows the psy
PE demand shape, and is slew-bounded, writing the lambda continuity
state from long frames only instead of free-diving up to 64x per frame.
The un-booted stream head behaves CBR-like until the servo takes over
(love.flac: >6k energy had swung 0.61-1.83x vs the source at frame rate
while the head ran 25% under the ask).

The reachable-range clamps do not track the calibration anchor: their
floors are set by the stat's -4/band sub-mask clip. A floor at -1.65
railed the servo on easy content (male_speech at a 128k ask pinned at
the clamp with a 10% standing deficit); -3.0 keeps 384k asks reachable
without the stall. Easy content can still fall short of very high asks
(main_theme: 196k at a 256k ask) - there is no padding. The coarse
clamp is a quality guard: set-points past it buy little rate for a lot
of quality (2.5 -> 6.0 at a 48k ask: -5% rate, +32% Zimtohrli), so asks
below about 56 kbps stereo land above the ask (24k/32k asks: ~40k).
The documentation points those rates at CBR.

Rate accuracy against the -b:a ask:
  corpus       bias    mean|err|  worst
  IgorC-3      -1.3%   2.2%       -11.8%
  IgorC-1      +1.1%   2.0%        +5.0%
  32 random    -0.3%   2.2%       -10.0%
A 4.5-minute concatenation of the IgorC-3 samples lands at 128.2 kbps
on a 128k ask. castanets/velvet ABR beat CBR; ABR corpus 0.00060 at
126k.

-aac_rc is documented, and fate-aac-nmr-abr-encode pins the per-packet
sizes through the servo's boot.
This commit is contained in:
Lynne
2026-09-23 20:32:59 +09:00
parent a86dc8bd2a
commit 98afaae587
7 changed files with 367 additions and 15 deletions

View File

@@ -85,6 +85,22 @@ and much faster at higher bitrates.
@end table
@item aac_rc
Rate-control mode of the @samp{nmr} coder when a bitrate is set with @option{b}
(other coders ignore it; @option{q} takes precedence). Possible values:
@table @samp
@item cbr
Constant bitrate within the decoder's bit reservoir. This is the default.
@item abr
Average bitrate: a constant-quality target, as in VBR, whose set-point a slow
servo moves to meet @option{b} over the length of the stream. Local quality
stays constant, so short files and individual passages can deviate from the
requested rate; the average converges over minutes rather than seconds. Below
roughly 56 kbps stereo the rate lands above the request; use @samp{cbr} there.
@end table
@item aac_ms
Sets mid/side coding mode. The default value of "auto" will automatically use
M/S with bands which will benefit from such coding. Can be forced for all bands

View File

@@ -91,18 +91,45 @@
/* Quality-target calibration anchor: the nd set-point of -q:a 1, which lands
* near 128-136 kbps stereo on the tuning corpora with the q ladder's own
* bandwidth. It moved -2.1 -> -0.75 with the quality-target mask floor
* (PSY_THRFL_QUALITY), which lowers thr_real and so lifts the whole statistic.
* The reachable-range clamp is set by the stat's -4/band sub-mask clip, which
* the mask floor does not touch: targets below it are asymptotically
* unreachable - the bisect rails at the finest lambda, the frame exceeds the
* decoder buffer and the outer re-encode loop never converges. */
* bandwidth. The ABR servo seeds off the same constant (referenced to 81.5
* kbps/ch, where it measured before the bandwidth retune; the boot corrects
* the per-content seed error), so they are one constant. It moved
* -2.1 -> -0.75 with the quality-target mask floor (PSY_THRFL_QUALITY), which
* lowers thr_real and so lifts the whole statistic.
* The reachable-range clamps did NOT move
* with it: their floors are set by the stat's -4/band sub-mask clip, which the
* mask floor does not touch. Targets below them are asymptotically unreachable
* - the bisect rails at the finest lambda, the frame exceeds the decoder buffer
* and the outer re-encode loop never converges (the 384k stall). Raising them
* with the anchor railed the ABR servo instead: it wanted a finer target to
* meet its rate ask on easy content and could not ask for one. */
#define NMR_VBR_ANCHOR (-0.75f)
#define NMR_VBR_TMIN (-3.8f)
/* ABR set-point range. The coarse end is a quality guard: set-points past it
* buy little rate for a lot of quality (2.5 -> 6.0 at a 48k ask: -5% rate,
* +32% Zimtohrli), so asks below ~56 kbps stereo land above the ask - CBR
* is the mode for those rates. At the fine end, easy content can fall short
* of very high asks (no padding). */
#define NMR_ABR_TMIN (-3.0f)
#define NMR_ABR_TMAX 2.5f
/* ABR servo: integrator gain on the log rate error, rate EMA weight after the
* boot, set-point step size and minimum frames between steps */
#define NMR_ABR_K 0.003f
#define NMR_ABR_EMA 0.0023f
#define NMR_ABR_STEP 0.15f
#define NMR_ABR_HOLD 120
/* ABR boot: open-loop correction gain over the nominal loop gain, the rate
* error that re-arms it, the re-arm budget and the settle time before one */
#define NMR_ABR_BOOT_GAIN 1.2f
#define NMR_ABR_TOL 0.02f
#define NMR_ABR_BOOTS 6
#define NMR_ABR_SETTLE 100
/* VBR shorts: the measured stat inflation counts fully once this share of
* the frame's energy sits above 6 kHz */
#define NMR_INFL_HF 0.10f
/* Reservoir half-window (bits/ch); swept 512/1536/3072, 1536 optimal. */
#define NMR_CBR_BUF 1536
/* Slew limit on the FINAL operating lambda per frame; bits deviate instead,
@@ -754,9 +781,14 @@ static void nmr_solve_group(AVCodecContext *avctx, AACEncContext *s,
}
int vbr = (avctx->flags & AV_CODEC_FLAG_QSCALE) && s->nmr;
int abr = !vbr && s->options.rc == 1 && avctx->bit_rate > 0 && s->nmr;
int vbr_subst = 1;
float vbr_t = 0.0f;
if (vbr) {
if (abr) {
/* ABR: same quality-target solve, set-point owned by the rate servo */
vbr_t = s->nmr->abr_t;
vbr = 1;
} else if (vbr) {
/* nd-target VBR: constant achieved noise-to-mask, bits float. */
/* target in log2(dist/real-mask), anchored so -q:a 1 lands near
* 128 kbps stereo on the tuning corpus; higher q is finer, each q
@@ -1011,6 +1043,48 @@ static void nmr_solve_group(AVCodecContext *avctx, AACEncContext *s,
hardcap = FFMAX(hardcap - (int)(FFMAX(s->nmr->side_ema, 0.0f) * chans / s->channels), 256);
for (int k = 0; k < nsl; k++)
tot += nmr_slot_bits(sl[k], s->nmr->nb[sl[k]->si], NMR_STEP);
if (abr && s->nmr->abr_ema < rc_rate_frame) {
/* bits-fill: under the long-run target, top an easy frame up
* toward the ask by moving lambda FINER only - the quality
* target is a floor, never traded away. Spends the rate the
* user asked for on sub-mask margin the nd statistic cannot
* see (it clips at -4/band); without this, stat-transparent
* content caps the rate below any ask. Active from frame one
* (the immature EMA reads as a deficit, so the stream head is
* held near the ask) and fades continuously as the EMA
* converges - a boot-gated fill flips regimes at ~2s, an
* audible quality step.
* The fill target follows the psy PE demand shape: per-frame
* demand carries perceptual information the nd model does not
* (the constant-lambda lesson) - and routing it through the
* fill keeps the quality floor intact. */
float dshape = 1.0f;
int fill;
if (s->psy.bitres.alloc > 0) {
float *aema = &s->nmr->abr_alloc_ema;
if (*aema <= 0.0f) *aema = s->psy.bitres.alloc;
else *aema += 0.01f * (s->psy.bitres.alloc - *aema);
dshape = av_clipf(s->psy.bitres.alloc / *aema, 0.6f, 1.7f);
}
fill = (int)((rc_rate_frame + (rc_rate_frame - (int)s->nmr->abr_ema)) * dshape) *
chans / s->channels;
fill = FFMIN3(fill, 3 * rc_rate_frame * chans / s->channels / 2, hardcap);
if (tot < fill) {
/* the fill dive is the easy-frame operating point: slew it
* like any other lambda move and let it carry the
* continuity state, or per-frame depth variation reads as
* frame-rate HF wobble */
float flo = lam / 64.0f;
if (*vslew_st > 0.0f)
flo = FFMIN(FFMAX(flo, *vslew_st / NMR_SLEW), lam);
lam = nmr_solve_slots(s, sl, nsl, NMR_STEP, fill, flo, lam, NMR_RC_ITERS);
if (!is8_any)
*vslew_st = s->nmr->lam_slew = lam;
tot = 0;
for (int k = 0; k < nsl; k++)
tot += nmr_slot_bits(sl[k], s->nmr->nb[sl[k]->si], NMR_STEP);
}
}
if (tot > hardcap) {
lam = nmr_solve_slots(s, sl, nsl, NMR_STEP, hardcap, lam, 1e4f, NMR_RC_ITERS);
tot = 0;
@@ -1280,7 +1354,7 @@ static void search_for_quantizers_nmr(AVCodecContext *avctx,
/* Global-lambda RC: one solve per frame at a servoed centre lambda; the reservoir
* holds the long-run mean rate. Bypassed for VBR (-q:a) and the bootstrap frame. */
int rc_eligible = !(avctx->flags & AV_CODEC_FLAG_QSCALE) && avctx->bit_rate > 0 &&
avctx->bit_rate_tolerance != 0;
avctx->bit_rate_tolerance != 0 && s->options.rc == 0;
/* Signed reservoir; soft steering (bounded repay + rc_off), hard cap =
* legality only. */
int rc_rate_frame = avctx->bit_rate * 1024.0 / avctx->sample_rate;
@@ -1291,6 +1365,108 @@ static void search_for_quantizers_nmr(AVCodecContext *avctx,
s->nmr->counted[s->cur_channel] = 0;
if (s->options.rc == 1 && !(avctx->flags & AV_CODEC_FLAG_QSCALE) &&
avctx->bit_rate > 0 && avctx->frame_num != n->abr_frame_num) {
/* ABR servo: integrate the log rate error, but apply it to the nd
* set-point in RARE, DISCRETE steps. The set-point must be
* quasi-static: any drift on content timescales moves lambda, and
* with it band/PNS/scalefactor state - measured 2x worse than a
* fixed target at equal mean rate. Locally this mode IS fixed-target
* VBR; rate honesty converges on the minutes scale. */
if (n->abr_frame_num == 0 && n->abr_ema <= 0.0f) {
/* seed the set-point from the VBR calibration anchor (see
* NMR_VBR_ANCHOR for the 81.5 kbps/ch reference); the servo
* trims the rest */
n->abr_t = av_clipf(NMR_VBR_ANCHOR - 2.5f * log2f(avctx->bit_rate /
(81500.0f * s->channels)), NMR_ABR_TMIN, NMR_ABR_TMAX);
n->abr_ema = rc_rate_frame;
} else if (s->last_frame_pb_count > 0) {
/* bootstrap: fast rate measurement for ~2s, then one open-loop
* jump over the measured loop gain (~ -0.24 log2 rate per target
* unit) corrects the seed's per-content error; the quasi-static
* stepper handles drift from there */
/* seed on-target: an EMA warming up from zero reads as a fake
* deficit and the fill overspends the whole stream head */
if (n->abr_ema <= 0.0f)
n->abr_ema = rc_rate_frame;
n->abr_ema += (n->abr_booted ? NMR_ABR_EMA : 0.02f) *
(s->last_frame_pb_count - n->abr_ema);
n->abr_hold++;
if (!n->abr_booted) {
n->abr_longs += sce->ics.window_sequence[0] != EIGHT_SHORT_SEQUENCE;
/* boot only off a REPRESENTATIVE window: an all-transient
* head (castanets roll) reads over-target and would coarsen
* the very content that needs bits. Time out eventually. */
if ((n->abr_hold >= 86 && n->abr_longs >= n->abr_hold / 2) ||
n->abr_hold >= 400) {
/* glide the seed correction in, never step it: a
* one-frame noise-floor jump at a fixed stream time is
* audible against revealing content */
n->abr_glide = NMR_ABR_BOOT_GAIN * log2f(n->abr_ema / rc_rate_frame) / 0.24f;
n->abr_booted = 1;
n->abr_boots++;
n->abr_hold = 0;
}
} else {
/* Re-arm the open-loop correction while the rate is still
* off. One boot leaves a residual whenever the real loop gain
* differs from the nominal 0.24, and the estimator is biased
* toward the ask by construction (the EMA is seeded ON target
* so a cold start cannot read as a deficit), so it understates
* the error it is correcting. The quasi-static stepper cannot
* drain that inside a track - measured, male_speech ended a
* 774-frame file 23% short and still moving. Re-measuring and
* firing again converges regardless of the gain estimate, and
* keeps the set-point quasi-static: corrections stay rare,
* glided, and bounded in number. */
if (n->abr_boots < NMR_ABR_BOOTS && n->abr_glide == 0.0f &&
n->abr_hold >= NMR_ABR_SETTLE &&
fabsf(log2f(n->abr_ema / rc_rate_frame)) > NMR_ABR_TOL) {
/* Re-seed the estimator ON target, exactly as the cold
* start does - never to zero. The value is read again
* before anything re-seeds it: by the integrator below
* (log2f(0) is -inf, which pinned the accumulator at its
* clip) and by the bits-fill later in this same frame
* (a zero EMA reads as a 100% deficit and authorises a
* one-frame overspend). Drop the residual integral with
* it: it describes the regime being left, and the boot
* is about to re-measure that same error open-loop. */
n->abr_booted = 0;
n->abr_ema = rc_rate_frame;
n->abr_acc = 0.0f;
n->abr_hold = 0;
n->abr_longs = 0;
} else {
n->abr_acc = av_clipf(n->abr_acc + NMR_ABR_K * log2f(n->abr_ema / rc_rate_frame),
-4.0f * NMR_ABR_STEP, 4.0f * NMR_ABR_STEP);
/* step in calm stretches (a set-point move during a transient
* section coarsens exactly what needs the bits) - but dense
* content must not deadlock the servo: after 3x the hold the
* step fires regardless. Large errors step at double size;
* the remainder carries over instead of being discarded. */
if (fabsf(n->abr_acc) >= NMR_ABR_STEP && n->abr_hold >= NMR_ABR_HOLD &&
(n->frames_since_short >= 12 || n->abr_hold >= 3 * NMR_ABR_HOLD)) {
float ms = NMR_ABR_STEP * (fabsf(n->abr_acc) > 3.0f * NMR_ABR_STEP ? 2.0f : 1.0f);
float step = av_clipf(n->abr_acc, -ms, ms);
n->abr_glide += step;
n->abr_acc -= step;
n->abr_hold = 0;
}
}
}
if (n->abr_glide != 0.0f) {
/* drain pending set-point corrections smoothly (~0.5
* log2-units/s): the decision stays quasi-static and
* calm-gated, only the application glides */
float d = av_clipf(n->abr_glide, -0.012f, 0.012f);
n->abr_t = av_clipf(n->abr_t + d, NMR_ABR_TMIN, NMR_ABR_TMAX);
n->abr_glide -= d;
if (fabsf(n->abr_glide) < 1e-4f)
n->abr_glide = 0.0f;
}
}
n->abr_frame_num = avctx->frame_num;
}
if (rc_eligible && !n->rc_fill_seeded) {
/* the decoder bit reservoir starts FULL: seed it so the head may frontload */
n->rc_fill = rc_bmax;

View File

@@ -1692,12 +1692,12 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
avpkt->size = put_bytes_output(&s->pb);
/* NMR reports its real operating lambda: the corridor centre in CBR,
* the quality-mode slew state in VBR - the lambda of the last long
* the quality-mode slew state in VBR/ABR - the lambda of the last long
* operating-point solve, which short frames and legality re-solves do
* not update (the outer-loop s->lambda is never touched for this coder
* and would pin Qavg at its 120 init) */
s->lambda_sum += (s->nmr && s->nmr->lam_slew > 0.0f &&
(avctx->flags & AV_CODEC_FLAG_QSCALE)) ?
((avctx->flags & AV_CODEC_FLAG_QSCALE) || s->options.rc == 1)) ?
s->nmr->lam_slew :
(s->nmr && s->nmr->lam_rc > 0.0f) ? s->nmr->lam_rc : s->lambda;
s->lambda_count++;
@@ -1964,7 +1964,7 @@ static av_cold int aac_encode_init(AVCodecContext *avctx)
lengths[1] = ff_aac_num_swb_128[s->samplerate_index];
for (i = 0; i < s->chan_map[0]; i++)
grouping[i] = s->chan_map[i + 1] == TYPE_CPE;
s->psy.unbounded_pe = (avctx->flags & AV_CODEC_FLAG_QSCALE) &&
s->psy.unbounded_pe = ((avctx->flags & AV_CODEC_FLAG_QSCALE) || s->options.rc == 1) &&
s->options.coder == AAC_CODER_NMR;
if ((ret = ff_psy_init(&s->psy, avctx, 2, sizes, lengths,
s->chan_map[0], grouping, s->bandwidth)) < 0)
@@ -1991,6 +1991,9 @@ static const AVOption aacenc_options[] = {
{"aac_pns", "Perceptual noise substitution", offsetof(AACEncContext, options.pns), AV_OPT_TYPE_BOOL, {.i64 = 1}, -1, 1, AACENC_FLAGS},
{"aac_tns", "Temporal noise shaping", offsetof(AACEncContext, options.tns), AV_OPT_TYPE_BOOL, {.i64 = 1}, -1, 1, AACENC_FLAGS},
{"aac_pce", "Forces the use of PCEs", offsetof(AACEncContext, options.pce), AV_OPT_TYPE_BOOL, {.i64 = 0}, -1, 1, AACENC_FLAGS},
{"aac_rc", "Rate-control mode (NMR coder)", offsetof(AACEncContext, options.rc), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, AACENC_FLAGS, .unit = "aac_rc"},
{"cbr", "Constant bitrate (corridor + leaky bucket)", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, INT_MIN, INT_MAX, AACENC_FLAGS, .unit = "aac_rc"},
{"abr", "Average bitrate (constant-quality target, slow rate servo)", 0, AV_OPT_TYPE_CONST, {.i64 = 1}, INT_MIN, INT_MAX, AACENC_FLAGS, .unit = "aac_rc"},
{"aac_nmr_speed", "NMR coder speed level: 0 = slowest/best, higher trades quality for speed", offsetof(AACEncContext, options.nmr_speed), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 4, AACENC_FLAGS},
{"aac_allow_71wide", "Allow non-PCE use of 7.1(wide) channel layout", offsetof(AACEncContext, options.allow_71wide), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AACENC_FLAGS},
FF_AAC_PROFILE_OPTS

View File

@@ -72,6 +72,7 @@ typedef struct AACEncOptions {
int intensity_stereo;
int nmr_speed; ///< NMR coder speed level: 0 = slowest/best, higher is faster
int allow_71wide;
int rc; ///< rate-control mode: 0 = cbr (corridor+bucket), 1 = abr (nd-target + slow servo)
} AACEncOptions;
/**
@@ -248,6 +249,18 @@ typedef struct AACNMRCurves {
float lam_short_ema; ///< smoothed operating lambda of short frames
float lam_long_ema; ///< smoothed operating lambda of long frames
float lam_floor; ///< lambda min-tracker (snaps down, +2%/frame up): sustained-strain floor; bursty spikes at a comfortable rate cannot raise it
/* ABR: nd-target set-point servoed to hold the long-run mean rate */
float abr_t; ///< current nd target (log2 dist/mask)
float abr_glide; ///< pending set-point correction, drained per-frame (no discrete quality steps)
float abr_ema; ///< EMA of real frame bits
float abr_acc; ///< accumulated set-point correction
int abr_hold; ///< frames since the target last stepped
int abr_booted; ///< seed correction applied (re-armed while the rate is still off)
int abr_boots; ///< open-loop corrections fired so far
float abr_alloc_ema; ///< EMA of psy bit demand (fill shaping)
int abr_longs; ///< long frames seen during bootstrap
int64_t abr_frame_num; ///< once-per-frame servo guard
} AACNMRCurves;
typedef struct AACPCEInfo {

View File

@@ -332,14 +332,16 @@ static float lame_calc_attack_threshold(int bitrate)
/**
* LAME psy model specific initialization
*/
static av_cold void lame_window_init(AacPsyContext *ctx, AVCodecContext *avctx)
static av_cold void lame_window_init(FFPsyContext *fctx, AacPsyContext *ctx, AVCodecContext *avctx)
{
int i, j;
for (i = 0; i < avctx->ch_layout.nb_channels; i++) {
AacPsyChannel *pch = &ctx->ch[i];
if (avctx->flags & AV_CODEC_FLAG_QSCALE)
if ((avctx->flags & AV_CODEC_FLAG_QSCALE) || fctx->unbounded_pe)
/* quality-target coders (VBR and ABR) switch windows for quality,
* not rate: use the quality attack map regardless of bit_rate */
pch->attack_threshold = psy_vbr_map[av_clip(avctx->global_quality / FF_QP2LAMBDA, 0, 10)].st_lrm;
else
pch->attack_threshold = lame_calc_attack_threshold(avctx->bit_rate / avctx->ch_layout.nb_channels / 1000);
@@ -456,7 +458,7 @@ static av_cold int psy_3gpp_init(FFPsyContext *ctx) {
for (i = 0; i < ctx->avctx->ch_layout.nb_channels; i++)
pctx->ch[i].rc_frame_num = -1;
lame_window_init(pctx, ctx->avctx);
lame_window_init(ctx, pctx, ctx->avctx);
return 0;
}
@@ -953,7 +955,7 @@ static void psy_3gpp_analyze_channel(FFPsyContext *ctx, int channel,
* it cannot fail. A band we still choose to code must never be allowed
* noise within PSY_THRFL_* dB of its own energy, whatever the hole logic said. */
{
int qmode = !!(ctx->avctx->flags & AV_CODEC_FLAG_QSCALE);
int qmode = ctx->unbounded_pe || (ctx->avctx->flags & AV_CODEC_FLAG_QSCALE);
float lim = qmode ? PSY_THRFL_QUALITY : PSY_THRFL_CBR;
float knee = qmode ? 0.0f : PSY_THRFL_CBR_KNEE;
float lo = ff_exp10f(-lim / 10.0f);

View File

@@ -268,6 +268,10 @@ fate-aac-yoraw-encode: FUZZ = 17
FATE_AAC_ENCODE_TRANSCODE += fate-aac-nmr-vbr-encode
fate-aac-nmr-vbr-encode: CMD = transcode wav $(TARGET_SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav adts "-af aresample -c:a aac -q:a 8 -t 2" "-c copy"
# ABR through the rate servo's boot (~2s)
FATE_AAC_ENCODE_TRANSCODE += fate-aac-nmr-abr-encode
fate-aac-nmr-abr-encode: CMD = transcode wav $(TARGET_SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav adts "-af aresample -c:a aac -aac_rc abr -b:a 96k -t 3" "-c copy"
tests/data/fate/aac-5_1_2.adts: TAG = GEN
tests/data/fate/aac-5_1_2.adts: tests/data/asynth-44100-8.wav
tests/data/fate/aac-5_1_2.adts: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data/fate

View File

@@ -0,0 +1,138 @@
8a93613d6b0acab3fc863fda864a48e5 *tests/data/fate/aac-nmr-abr-encode.adts
31792 tests/data/fate/aac-nmr-abr-encode.adts
#tb 0: 1/28224000
#media_type 0: audio
#codec_id 0: aac
#sample_rate 0: 44100
#channel_layout_name 0: stereo
0, 0, 0, 655360, 269, 0xfa9b83e0
0, 655360, 655360, 655360, 464, 0xa230e9b1
0, 1310720, 1310720, 655360, 260, 0x549a7ba3
0, 1966080, 1966080, 655360, 262, 0xe5ce7d83
0, 2621440, 2621440, 655360, 259, 0x26067677
0, 3276800, 3276800, 655360, 261, 0x2bdc7bc4
0, 3932160, 3932160, 655360, 244, 0xc16d750e
0, 4587520, 4587520, 655360, 252, 0xb09d7762
0, 5242880, 5242880, 655360, 263, 0x91157965
0, 5898240, 5898240, 655360, 259, 0xb3e972f4
0, 6553600, 6553600, 655360, 268, 0xcbe9813d
0, 7208960, 7208960, 655360, 252, 0xf9c076f3
0, 7864320, 7864320, 655360, 398, 0x2851be3c
0, 8519680, 8519680, 655360, 320, 0x166d991d
0, 9175040, 9175040, 655360, 408, 0xca4cd36f
0, 9830400, 9830400, 655360, 239, 0x78c2742b
0, 10485760, 10485760, 655360, 246, 0xca377334
0, 11141120, 11141120, 655360, 240, 0x635e7250
0, 11796480, 11796480, 655360, 220, 0x3bbd66ae
0, 12451840, 12451840, 655360, 210, 0xf244638d
0, 13107200, 13107200, 655360, 209, 0x64a6563b
0, 13762560, 13762560, 655360, 221, 0xa96762cd
0, 14417920, 14417920, 655360, 226, 0x749f66c4
0, 15073280, 15073280, 655360, 226, 0xd0eb6387
0, 15728640, 15728640, 655360, 223, 0xc3826574
0, 16384000, 16384000, 655360, 220, 0x78a86d47
0, 17039360, 17039360, 655360, 230, 0xb4446dc3
0, 17694720, 17694720, 655360, 215, 0x306f7104
0, 18350080, 18350080, 655360, 229, 0x91de69c3
0, 19005440, 19005440, 655360, 219, 0x078e672d
0, 19660800, 19660800, 655360, 214, 0xb5b766a4
0, 20316160, 20316160, 655360, 220, 0x7023610b
0, 20971520, 20971520, 655360, 210, 0x182a5ee8
0, 21626880, 21626880, 655360, 203, 0xdf3655a9
0, 22282240, 22282240, 655360, 231, 0x13d565d0
0, 22937600, 22937600, 655360, 229, 0x5e0063f5
0, 23592960, 23592960, 655360, 232, 0xf03468e7
0, 24248320, 24248320, 655360, 244, 0x882a7785
0, 24903680, 24903680, 655360, 236, 0xf8bd7012
0, 25559040, 25559040, 655360, 228, 0x1956677a
0, 26214400, 26214400, 655360, 266, 0x3e6b81a9
0, 26869760, 26869760, 655360, 233, 0x5ab66d73
0, 27525120, 27525120, 655360, 244, 0x25b56b66
0, 28180480, 28180480, 655360, 184, 0xd9695100
0, 28835840, 28835840, 655360, 229, 0x22f771cd
0, 29491200, 29491200, 655360, 260, 0xc6fa8312
0, 30146560, 30146560, 655360, 256, 0x48197e58
0, 30801920, 30801920, 655360, 247, 0xea997935
0, 31457280, 31457280, 655360, 239, 0xa22f7015
0, 32112640, 32112640, 655360, 259, 0x8b2384c0
0, 32768000, 32768000, 655360, 252, 0xd23e790d
0, 33423360, 33423360, 655360, 240, 0x25056b8c
0, 34078720, 34078720, 655360, 256, 0xab1077f8
0, 34734080, 34734080, 655360, 238, 0xd99a6cc5
0, 35389440, 35389440, 655360, 223, 0x4ffe6c3f
0, 36044800, 36044800, 655360, 222, 0x8c7c5f7a
0, 36700160, 36700160, 655360, 231, 0xcc3172bf
0, 37355520, 37355520, 655360, 224, 0xc23b68cf
0, 38010880, 38010880, 655360, 222, 0xf0986a4d
0, 38666240, 38666240, 655360, 233, 0x92a36bc9
0, 39321600, 39321600, 655360, 251, 0x11516fb9
0, 39976960, 39976960, 655360, 263, 0x0f0b7e11
0, 40632320, 40632320, 655360, 408, 0xbf1ccc26
0, 41287680, 41287680, 655360, 531, 0xa5690ccd
0, 41943040, 41943040, 655360, 308, 0x5eed9716
0, 42598400, 42598400, 655360, 277, 0x3668903e
0, 43253760, 43253760, 655360, 239, 0x2bab729b
0, 43909120, 43909120, 655360, 227, 0x3c8b7095
0, 44564480, 44564480, 655360, 190, 0x6c3257ab
0, 45219840, 45219840, 655360, 209, 0x19125f77
0, 45875200, 45875200, 655360, 196, 0xcec25cec
0, 46530560, 46530560, 655360, 250, 0x3e2875d4
0, 47185920, 47185920, 655360, 276, 0x37138362
0, 47841280, 47841280, 655360, 210, 0x77d55f66
0, 48496640, 48496640, 655360, 202, 0x88c06283
0, 49152000, 49152000, 655360, 201, 0x364a5f76
0, 49807360, 49807360, 655360, 218, 0x38ee6916
0, 50462720, 50462720, 655360, 205, 0x017c6140
0, 51118080, 51118080, 655360, 205, 0xba40628e
0, 51773440, 51773440, 655360, 211, 0x3ab1628d
0, 52428800, 52428800, 655360, 208, 0x9b636846
0, 53084160, 53084160, 655360, 207, 0xcbd06506
0, 53739520, 53739520, 655360, 207, 0x487f6291
0, 54394880, 54394880, 655360, 218, 0x7aa870d9
0, 55050240, 55050240, 655360, 256, 0x3495754e
0, 55705600, 55705600, 655360, 335, 0xd95aa995
0, 56360960, 56360960, 655360, 196, 0x54e75268
0, 57016320, 57016320, 655360, 209, 0x04de5e1e
0, 57671680, 57671680, 655360, 206, 0xa2f463a5
0, 58327040, 58327040, 655360, 204, 0xad526074
0, 58982400, 58982400, 655360, 209, 0xde2e5aec
0, 59637760, 59637760, 655360, 209, 0x8c6d6905
0, 60293120, 60293120, 655360, 202, 0x44ca5964
0, 60948480, 60948480, 655360, 206, 0xd8685ef3
0, 61603840, 61603840, 655360, 209, 0xff6360ce
0, 62259200, 62259200, 655360, 207, 0xa9fc61b1
0, 62914560, 62914560, 655360, 209, 0x312d6796
0, 63569920, 63569920, 655360, 218, 0x4c9f695f
0, 64225280, 64225280, 655360, 224, 0x34996723
0, 64880640, 64880640, 655360, 234, 0x02096ec5
0, 65536000, 65536000, 655360, 246, 0xa63a70c2
0, 66191360, 66191360, 655360, 277, 0x8559914c
0, 66846720, 66846720, 655360, 240, 0xa2087438
0, 67502080, 67502080, 655360, 245, 0xc61a826b
0, 68157440, 68157440, 655360, 248, 0xd92a7776
0, 68812800, 68812800, 655360, 244, 0xa4517d63
0, 69468160, 69468160, 655360, 258, 0x79cb75e2
0, 70123520, 70123520, 655360, 274, 0x98708776
0, 70778880, 70778880, 655360, 239, 0xcd83750c
0, 71434240, 71434240, 655360, 232, 0x05336d82
0, 72089600, 72089600, 655360, 234, 0x55847ac8
0, 72744960, 72744960, 655360, 234, 0x76da6e4c
0, 73400320, 73400320, 655360, 221, 0x919969bf
0, 74055680, 74055680, 655360, 223, 0xfbfb69c2
0, 74711040, 74711040, 655360, 228, 0xf9e373d7
0, 75366400, 75366400, 655360, 224, 0xd0975f50
0, 76021760, 76021760, 655360, 234, 0xa66d6e10
0, 76677120, 76677120, 655360, 249, 0x2a276d92
0, 77332480, 77332480, 655360, 239, 0x53516e65
0, 77987840, 77987840, 655360, 270, 0xa6b77886
0, 78643200, 78643200, 655360, 274, 0x076d7c58
0, 79298560, 79298560, 655360, 269, 0x93fc811b
0, 79953920, 79953920, 655360, 239, 0x9dfc73de
0, 80609280, 80609280, 655360, 255, 0x6aa47d01
0, 81264640, 81264640, 655360, 236, 0x755271f0
0, 81920000, 81920000, 655360, 241, 0x8bab73ea
0, 82575360, 82575360, 655360, 246, 0xa0ac7c7a
0, 83230720, 83230720, 655360, 251, 0x74447d8a
0, 83886080, 83886080, 655360, 223, 0xefc36a30
0, 84541440, 84541440, 655360, 241, 0x88ab6e54
0, 85196800, 85196800, 655360, 191, 0x89b45c00