PR #22234 opened by Daniil Cherednik (dcherednik)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22234
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22234.patch

Commit c3aea7628c changes frame size. But the encoder and psy code
expected frame size was 120 samples.


>From 2eac3c5ce7a3ea956b8231a6246fcbfd781a4b27 Mon Sep 17 00:00:00 2001
From: Daniil Cherednik <[email protected]>
Date: Fri, 20 Feb 2026 00:40:14 +0200
Subject: [PATCH] Fix regration after c3aea7628c

Commit c3aea7628c changes frame size. But the encoder and psy code
expected frame size was 120 samples.
---
 libavcodec/opus/enc.c     |  7 +++++--
 libavcodec/opus/enc_psy.c | 23 ++++++++++++++---------
 2 files changed, 19 insertions(+), 11 deletions(-)

diff --git a/libavcodec/opus/enc.c b/libavcodec/opus/enc.c
index 587e4ed69d..f1775bc653 100644
--- a/libavcodec/opus/enc.c
+++ b/libavcodec/opus/enc.c
@@ -130,9 +130,12 @@ static void celt_frame_setup_input(OpusEncContext *s, 
CeltFrame *f)
 
     for (int ch = 0; ch < f->channels; ch++) {
         CeltBlock *b = &f->block[ch];
-        const void *input = cur->extended_data[ch];
+        const char *input = cur->extended_data[ch];
         size_t bps = av_get_bytes_per_sample(cur->format);
-        memcpy(b->overlap, input, bps*cur->nb_samples);
+        /* The MDCT overlap is always CELT_OVERLAP samples taken from the end 
of
+         * the previous frame, regardless of the encoder's frame_size. */
+        memcpy(b->overlap, input+(cur->nb_samples - CELT_OVERLAP)*bps,
+               CELT_OVERLAP*bps);
     }
 
     av_frame_free(&cur);
diff --git a/libavcodec/opus/enc_psy.c b/libavcodec/opus/enc_psy.c
index 250cfb567a..08f1ec57c9 100644
--- a/libavcodec/opus/enc_psy.c
+++ b/libavcodec/opus/enc_psy.c
@@ -258,7 +258,8 @@ int ff_opus_psy_process(OpusPsyContext *s, OpusPacketInfo 
*p)
 void ff_opus_psy_celt_frame_init(OpusPsyContext *s, CeltFrame *f, int index)
 {
     int i, neighbouring_points = 0, start_offset = 0;
-    int radius = (1 << s->p.framesize), step_offset = radius*index;
+    int steps_per_frame = OPUS_BLOCK_SIZE(s->p.framesize) / 
s->avctx->frame_size;
+    int step_offset = steps_per_frame*index;
     int silence = 1;
 
     f->start_band = (s->p.mode == OPUS_MODE_HYBRID) ? 17 : 0;
@@ -266,8 +267,8 @@ void ff_opus_psy_celt_frame_init(OpusPsyContext *s, 
CeltFrame *f, int index)
     f->channels   = s->avctx->ch_layout.nb_channels;
     f->size       = s->p.framesize;
 
-    for (i = 0; i < (1 << f->size); i++)
-        silence &= s->steps[index*(1 << f->size) + i]->silence;
+    for (i = 0; i < steps_per_frame; i++)
+        silence &= s->steps[index*steps_per_frame + i]->silence;
 
     f->silence = silence;
     if (f->silence) {
@@ -282,8 +283,8 @@ void ff_opus_psy_celt_frame_init(OpusPsyContext *s, 
CeltFrame *f, int index)
         }
     }
 
-    for (i = start_offset; i < FFMIN(radius, s->inflection_points_count - 
start_offset); i++) {
-        if (s->inflection_points[i] < (step_offset + radius)) {
+    for (i = start_offset; i < FFMIN(steps_per_frame, 
s->inflection_points_count - start_offset); i++) {
+        if (s->inflection_points[i] < (step_offset + steps_per_frame)) {
             neighbouring_points++;
         }
     }
@@ -316,6 +317,7 @@ static void celt_gauge_psy_weight(OpusPsyContext *s, 
OpusPsyStep **start,
 {
     int i, f, ch;
     int frame_size = OPUS_BLOCK_SIZE(s->p.framesize);
+    int steps_per_frame = frame_size / s->avctx->frame_size;
     float rate, frame_bits = 0;
 
     /* Used for the global ROTATE flag */
@@ -329,7 +331,7 @@ static void celt_gauge_psy_weight(OpusPsyContext *s, 
OpusPsyStep **start,
     for (i = 0; i < CELT_MAX_BANDS; i++) {
         float weight = 0.0f;
         float tonal_contrib = 0.0f;
-        for (f = 0; f < (1 << s->p.framesize); f++) {
+        for (f = 0; f < steps_per_frame; f++) {
             weight = start[f]->stereo[i];
             for (ch = 0; ch < s->avctx->ch_layout.nb_channels; ch++) {
                 weight += start[f]->change_amp[ch][i] + start[f]->tone[ch][i] 
+ start[f]->energy[ch][i];
@@ -425,6 +427,7 @@ static void celt_search_for_intensity(OpusPsyContext *s, 
CeltFrame *f)
 static int celt_search_for_tf(OpusPsyContext *s, OpusPsyStep **start, 
CeltFrame *f)
 {
     int i, j, k, cway, config[2][CELT_MAX_BANDS] = { { 0 } };
+    int steps_per_frame = OPUS_BLOCK_SIZE(f->size) / s->avctx->frame_size;
     float score[2] = { 0 };
 
     for (cway = 0; cway < 2; cway++) {
@@ -439,7 +442,7 @@ static int celt_search_for_tf(OpusPsyContext *s, 
OpusPsyStep **start, CeltFrame
         for (i = 0; i < CELT_MAX_BANDS; i++) {
             float iscore0 = 0.0f;
             float iscore1 = 0.0f;
-            for (j = 0; j < (1 << f->size); j++) {
+            for (j = 0; j < steps_per_frame; j++) {
                 for (k = 0; k < s->avctx->ch_layout.nb_channels; k++) {
                     iscore0 += 
start[j]->tone[k][i]*start[j]->change_amp[k][i]/mag[0];
                     iscore1 += 
start[j]->tone[k][i]*start[j]->change_amp[k][i]/mag[1];
@@ -480,7 +483,7 @@ int ff_opus_psy_celt_frame_process(OpusPsyContext *s, 
CeltFrame *f, int index)
 void ff_opus_psy_postencode_update(OpusPsyContext *s, CeltFrame *f)
 {
     int i, frame_size = OPUS_BLOCK_SIZE(s->p.framesize);
-    int steps_out = s->p.frames*(frame_size/120);
+    int steps_out = s->p.frames*(frame_size/s->avctx->frame_size);
     void *tmp[FF_BUFQUEUE_SIZE];
     float ideal_fbits;
 
@@ -522,7 +525,9 @@ av_cold int ff_opus_psy_init(OpusPsyContext *s, 
AVCodecContext *avctx,
     s->options = options;
     s->avctx = avctx;
     s->bufqueue = bufqueue;
-    s->max_steps = ceilf(s->options->max_delay_ms/2.5f);
+    s->max_steps = ceilf(s->options->max_delay_ms * avctx->sample_rate /
+        (1000.0f * avctx->frame_size));
+
     s->bsize_analysis = CELT_BLOCK_960;
     s->avg_is_band = CELT_MAX_BANDS - 1;
     s->inflection_points_count = 0;
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to