Commit 7ef5a794c4 for ffmpeg
commit 7ef5a794c42abcb4a62e1ab22f4ae3ce40aee729
Author: James Almer <jamrial@gmail.com>
Date: Tue Oct 6 11:28:55 2026 -0300
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 <jamrial@gmail.com>
diff --git a/libavcodec/vorbisenc.c b/libavcodec/vorbisenc.c
index 7e72c19c5d..74539c9993 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;
@@ -1297,7 +1250,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);