avcodec: add a flag to force encoders to use fixed size frames

Signed-off-by: James Almer <jamrial@gmail.com>
This commit is contained in:
James Almer
2026-05-16 13:55:22 -03:00
parent bf2695e876
commit b1120b1ed8
9 changed files with 29 additions and 9 deletions
+3
View File
@@ -2,6 +2,9 @@ The last version increases of all libraries were on 2025-03-28
API changes, most recent first:
2026-05-16 - xxxxxxxxxxx - lavc 62.33.100 - avcodec.h
Add AV_CODEC_FLAG2_FIXED_FRAME_SIZE.
2026-05-12 - xxxxxxxxxx - lavu 60.31.100 - frame.h
Add IAMF frame side data types to enum AVFrameSideDataType:
- AV_FRAME_DATA_IAMF_MIX_GAIN_PARAM
+2
View File
@@ -646,6 +646,8 @@ Do not skip samples and export skip information as frame side data.
Do not reset ASS ReadOrder field on flush.
@item icc_profiles
Generate/parse embedded ICC profiles from/to colorimetry tags.
@item fixed_frame_size
Force audio encoders to use a fixed frame size.
@end table
@item export_side_data @var{flags} (@emph{decoding/encoding,audio,video,subtitles})
+8
View File
@@ -354,6 +354,14 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code
if (!avctx->bit_rate)
avctx->bit_rate = get_bit_rate(avctx);
if (avctx->codec_type == AVMEDIA_TYPE_AUDIO &&
!avctx->frame_size && (avctx->flags2 & AV_CODEC_FLAG2_FIXED_FRAME_SIZE)) {
av_log(avctx, AV_LOG_ERROR, "Fixed frame size requested but no frame_size value set\n");
ret = AVERROR(EINVAL);
goto free_and_end;
}
avci->skip_samples = avctx->delay;
/* validate channel layout from the decoder */
+11 -4
View File
@@ -353,6 +353,10 @@ typedef struct RcOverride{
* Discard cropping information from SPS.
*/
#define AV_CODEC_FLAG2_IGNORE_CROP (1 << 16)
/**
* Force audio encoders to use a fixed frame size.
*/
#define AV_CODEC_FLAG2_FIXED_FRAME_SIZE (1 << 17)
/**
* Show all frames before the first keyframe
@@ -1050,18 +1054,20 @@ typedef struct AVCodecContext {
*/
AVChannelLayout ch_layout;
/* The following data should not be initialized. */
/**
* Number of samples per channel in an audio frame.
*
* - encoding: set by libavcodec in avcodec_open2(). Each submitted frame
* - encoding: may be set by the user before calling avcodec_open2(), and
* libavcodec may then overwrite it if needed. Each submitted frame
* except the last must contain exactly frame_size samples per channel.
* May be 0 when the codec has AV_CODEC_CAP_VARIABLE_FRAME_SIZE set, then the
* May be 0 when the codec has AV_CODEC_CAP_VARIABLE_FRAME_SIZE set, except
* when AV_CODEC_FLAG2_FIXED_FRAME_SIZE is requested, then the
* frame size is not restricted.
* - decoding: may be set by some decoders to indicate constant frame size
*/
int frame_size;
/* The following data should not be initialized. */
/**
* number of bytes per packet if constant and known or 0
* Used by some WAV based audio codecs.
@@ -2414,7 +2420,8 @@ int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame);
* For audio:
* If AV_CODEC_CAP_VARIABLE_FRAME_SIZE is set, then each frame
* can have any number of samples.
* If it is not set, frame->nb_samples must be equal to
* If it is not set, or AV_CODEC_FLAG2_FIXED_FRAME_SIZE was
* requested, then frame->nb_samples must be equal to
* avctx->frame_size for all frames except the last.
* The final frame may be smaller than avctx->frame_size.
* @retval 0 success
+3 -2
View File
@@ -439,7 +439,7 @@ static int encode_send_frame_internal(AVCodecContext *avctx, const AVFrame *src)
avctx->audio_service_type = *(enum AVAudioServiceType*)sd->data;
/* check for valid frame size */
if (!(avctx->codec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE)) {
if (avctx->frame_size) {
/* if we already got an undersized frame, that must have been the last */
if (ec->last_audio_frame) {
av_log(avctx, AV_LOG_ERROR, "frame_size (%d) was not respected for a non-last frame\n", avctx->frame_size);
@@ -451,7 +451,8 @@ static int encode_send_frame_internal(AVCodecContext *avctx, const AVFrame *src)
}
if (src->nb_samples < avctx->frame_size) {
ec->last_audio_frame = 1;
if (!(avctx->codec->capabilities & AV_CODEC_CAP_SMALL_LAST_FRAME)) {
if (!(avctx->codec->capabilities & AV_CODEC_CAP_SMALL_LAST_FRAME) ||
(avctx->flags2 & AV_CODEC_FLAG2_FIXED_FRAME_SIZE)) {
int pad_samples = avci->pad_samples ? avci->pad_samples : avctx->frame_size;
int out_samples = (src->nb_samples + pad_samples - 1) / pad_samples * pad_samples;
+1
View File
@@ -85,6 +85,7 @@ static const AVOption avcodec_options[] = {
{"skip_manual", "do not skip samples and export skip information as frame side data", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG2_SKIP_MANUAL}, INT_MIN, INT_MAX, A|D, .unit = "flags2"},
{"ass_ro_flush_noop", "do not reset ASS ReadOrder field on flush", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG2_RO_FLUSH_NOOP}, INT_MIN, INT_MAX, S|D, .unit = "flags2"},
{"icc_profiles", "generate/parse embedded ICC profiles from/to colorimetry tags", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG2_ICC_PROFILES}, INT_MIN, INT_MAX, S|D, .unit = "flags2"},
{"fixed_frame_size", "Force a fixed frame size", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG2_FIXED_FRAME_SIZE}, INT_MIN, INT_MAX, A|E, .unit = "flags2"},
{"export_side_data", "Export metadata as side data", OFFSET(export_side_data), AV_OPT_TYPE_FLAGS, {.i64 = DEFAULT}, 0, UINT_MAX, A|V|S|D|E, .unit = "export_side_data"},
{"mvs", "export motion vectors through frame side data", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_EXPORT_DATA_MVS}, INT_MIN, INT_MAX, V|D, .unit = "export_side_data"},
{"prft", "export Producer Reference Time through packet side data", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_EXPORT_DATA_PRFT}, INT_MIN, INT_MAX, A|V|S|E, .unit = "export_side_data"},
-1
View File
@@ -40,7 +40,6 @@
av_unused av_cold static int pcm_encode_init(AVCodecContext *avctx)
{
avctx->frame_size = 0;
#if !CONFIG_HARDCODED_TABLES
switch (avctx->codec->id) {
#if CONFIG_PCM_ALAW_ENCODER
-1
View File
@@ -61,7 +61,6 @@ static av_cold int s302m_encode_init(AVCodecContext *avctx)
}
}
avctx->frame_size = 0;
avctx->bit_rate = 48000 * avctx->ch_layout.nb_channels *
(avctx->bits_per_raw_sample + 4);
s->framing_index = 0;
+1 -1
View File
@@ -29,7 +29,7 @@
#include "version_major.h"
#define LIBAVCODEC_VERSION_MINOR 32
#define LIBAVCODEC_VERSION_MINOR 33
#define LIBAVCODEC_VERSION_MICRO 100
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \