PR #24903 opened by James Almer (jamrial)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24903
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24903.patch

It was set to a sub-frame value so the caller would then pass such small frames 
to the encoder, which would then get buffered internally before being 
processed. Because of this, the actual frame size would not end up being 
propagated back to the caller, which resulted in said bogus internal value 
being used by muxers.
Set frame_size to the actual final value and adapt the encoder to expect full 
frames.

Fixes issue #24899.


>From 5dc8a1e1a440e8fd1564bcd6a5e3f0e6fa01d074 Mon Sep 17 00:00:00 2001
From: James Almer <[email protected]>
Date: Tue, 6 Oct 2026 11:28:55 -0300
Subject: [PATCH] avcodec/vorbisenc: fix setting frame_size

It was set to a sub-frame value so the caller would then pass such small frames
to the encoder, which would then get buffered internally before being
processed. Because of this, the actual frame size would not end up being
propagated back to the caller, which resulted in said bogus internal value
being used by muxers.
Set frame_size to the actual final value and adapt the encoder to expect full
frames.

Fixes issue #24899.

Signed-off-by: James Almer <[email protected]>
---
 libavcodec/vorbisenc.c | 31 ++++++++++++++-----------------
 1 file changed, 14 insertions(+), 17 deletions(-)

diff --git a/libavcodec/vorbisenc.c b/libavcodec/vorbisenc.c
index 7e72c19c5d..c2f2685733 100644
--- a/libavcodec/vorbisenc.c
+++ b/libavcodec/vorbisenc.c
@@ -107,6 +107,7 @@ typedef struct vorbis_enc_mode {
 typedef struct vorbis_enc_context {
     int channels;
     int sample_rate;
+    int frame_size;
     int log2_blocksize[2];
     AVTXContext *mdct[2];
     av_tx_fn mdct_fn[2];
@@ -1038,6 +1039,7 @@ static int apply_window_and_mdct(vorbis_enc_context *venc)
 /* Used for padding the last encoded packet */
 static AVFrame *spawn_empty_frame(AVCodecContext *avctx, int channels)
 {
+    vorbis_enc_context *venc = avctx->priv_data;
     AVFrame *f = av_frame_alloc();
     int ch;
 
@@ -1045,7 +1047,7 @@ static AVFrame *spawn_empty_frame(AVCodecContext *avctx, 
int channels)
         return NULL;
 
     f->format = avctx->sample_fmt;
-    f->nb_samples = avctx->frame_size;
+    f->nb_samples = venc->frame_size;
     f->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
     f->ch_layout.nb_channels = channels;
 
@@ -1062,11 +1064,10 @@ static AVFrame *spawn_empty_frame(AVCodecContext 
*avctx, int channels)
 }
 
 /* Set up audio samples for psy analysis and window/mdct */
-static void move_audio(vorbis_enc_context *venc, int sf_size)
+static void move_audio(vorbis_enc_context *venc)
 {
     AVFrame *cur = NULL;
     int frame_size = 1 << (venc->log2_blocksize[1] - 1);
-    int subframes = frame_size / sf_size;
     int sf, ch;
 
     /* Copy samples from last frame into current frame */
@@ -1078,7 +1079,7 @@ static void move_audio(vorbis_enc_context *venc, int 
sf_size)
         for (ch = 0; ch < venc->channels; ch++)
             memset(venc->samples + 2 * ch * frame_size, 0, sizeof(float) * 
frame_size);
 
-    for (sf = 0; sf < subframes; sf++) {
+
         cur = ff_bufqueue_get(&venc->bufqueue);
 
         for (ch = 0; ch < venc->channels; ch++) {
@@ -1087,11 +1088,11 @@ static void move_audio(vorbis_enc_context *venc, int 
sf_size)
             const float *input = (float *) cur->extended_data[ch];
             const size_t len  = cur->nb_samples * sizeof(float);
 
-            memcpy(offset + sf*sf_size, input, len);
-            memcpy(save + sf*sf_size, input, len);   // Move samples for next 
frame
+            memcpy(offset, input, len);
+            memcpy(save, input, len);   // Move samples for next frame
         }
         av_frame_free(&cur);
-    }
+
     venc->have_saved = 1;
     memcpy(venc->scratch, venc->samples, 2 * venc->channels * frame_size);
 }
@@ -1100,7 +1101,7 @@ static int vorbis_encode_frame(AVCodecContext *avctx, 
AVPacket *avpkt,
                                const AVFrame *frame, int *got_packet_ptr)
 {
     vorbis_enc_context *venc = avctx->priv_data;
-    int i, ret, need_more;
+    int i, ret;
     int frame_size = 1 << (venc->log2_blocksize[1] - 1);
     vorbis_enc_mode *mode;
     vorbis_enc_mapping *mapping;
@@ -1118,15 +1119,10 @@ static int vorbis_encode_frame(AVCodecContext *avctx, 
AVPacket *avpkt,
         if (!venc->afq.remaining_samples)
             return 0;
 
-    need_more = venc->bufqueue.available * avctx->frame_size < frame_size;
-    need_more = frame && need_more;
-    if (need_more)
-        return 0;
-
     /* Pad the bufqueue with empty frames for encoding the last packet. */
     if (!frame) {
-        if (venc->bufqueue.available * avctx->frame_size < frame_size) {
-            int frames_needed = (frame_size/avctx->frame_size) - 
venc->bufqueue.available;
+        if (venc->bufqueue.available * venc->frame_size < frame_size) {
+            int frames_needed = (frame_size/venc->frame_size) - 
venc->bufqueue.available;
             int i;
 
             for (i = 0; i < frames_needed; i++) {
@@ -1139,7 +1135,7 @@ static int vorbis_encode_frame(AVCodecContext *avctx, 
AVPacket *avpkt,
         }
     }
 
-    move_audio(venc, avctx->frame_size);
+    move_audio(venc);
 
     if (!apply_window_and_mdct(venc))
         return 0;
@@ -1297,7 +1293,8 @@ static av_cold int vorbis_encode_init(AVCodecContext 
*avctx)
         return ret;
     avctx->extradata_size = ret;
 
-    avctx->frame_size = 64;
+    venc->frame_size = 64;
+    avctx->frame_size = 1 << (venc->log2_blocksize[1] - 1);
     avctx->initial_padding = 1 << (venc->log2_blocksize[1] - 1);
 
     ff_af_queue_init(avctx, &venc->afq);
-- 
2.52.0

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

Reply via email to