PR #24935 opened by ffmpeg-devel
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24935
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24935.patch

**Backport:** https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24903

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 27b46f0fbcf8d4ef8ba68f7bdc67f14f246de07a 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]>
(cherry picked from commit 7ef5a794c42abcb4a62e1ab22f4ae3ce40aee729)
---
 libavcodec/vorbisenc.c | 65 ++++++------------------------------------
 1 file changed, 9 insertions(+), 56 deletions(-)

diff --git a/libavcodec/vorbisenc.c b/libavcodec/vorbisenc.c
index 0290d38680..e3efe97b1e 100644
--- a/libavcodec/vorbisenc.c
+++ b/libavcodec/vorbisenc.c
@@ -1035,39 +1035,12 @@ static int apply_window_and_mdct(vorbis_enc_context 
*venc)
     return 1;
 }
 
-/* Used for padding the last encoded packet */
-static AVFrame *spawn_empty_frame(AVCodecContext *avctx, int channels)
-{
-    AVFrame *f = av_frame_alloc();
-    int ch;
-
-    if (!f)
-        return NULL;
-
-    f->format = avctx->sample_fmt;
-    f->nb_samples = avctx->frame_size;
-    f->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
-    f->ch_layout.nb_channels = channels;
-
-    if (av_frame_get_buffer(f, 4)) {
-        av_frame_free(&f);
-        return NULL;
-    }
-
-    for (ch = 0; ch < channels; ch++) {
-        size_t bps = av_get_bytes_per_sample(f->format);
-        memset(f->extended_data[ch], 0, bps * f->nb_samples);
-    }
-    return f;
-}
-
 /* 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;
+    int ch;
 
     /* Copy samples from last frame into current frame */
     if (venc->have_saved)
@@ -1078,8 +1051,9 @@ 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++) {
+    if (venc->bufqueue.available) {
         cur = ff_bufqueue_get(&venc->bufqueue);
+        av_assert0(!venc->bufqueue.available);
 
         for (ch = 0; ch < venc->channels; ch++) {
             float *offset = venc->samples + 2 * ch * frame_size + frame_size;
@@ -1087,8 +1061,8 @@ 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);
     }
@@ -1100,7 +1074,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,28 +1092,7 @@ 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;
-            int i;
-
-            for (i = 0; i < frames_needed; i++) {
-               AVFrame *empty = spawn_empty_frame(avctx, venc->channels);
-               if (!empty)
-                   return AVERROR(ENOMEM);
-
-               ff_bufqueue_add(avctx, &venc->bufqueue, empty);
-            }
-        }
-    }
-
-    move_audio(venc, avctx->frame_size);
+    move_audio(venc);
 
     if (!apply_window_and_mdct(venc))
         return 0;
@@ -1295,7 +1248,7 @@ static av_cold int vorbis_encode_init(AVCodecContext 
*avctx)
         return ret;
     avctx->extradata_size = ret;
 
-    avctx->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