This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch master in repository ffmpeg.
commit 6ff12c4f6c8904e7f7d48388ee84cc9fcbc5104f Author: James Almer <[email protected]> AuthorDate: Sat Jan 24 18:58:21 2026 -0300 Commit: James Almer <[email protected]> CommitDate: Thu Jan 29 21:09:02 2026 -0300 avformat/cafenc: add support for variable frame size codecs Signed-off-by: James Almer <[email protected]> --- libavformat/cafenc.c | 105 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 75 insertions(+), 30 deletions(-) diff --git a/libavformat/cafenc.c b/libavformat/cafenc.c index c6369f0b62..b1e7555aca 100644 --- a/libavformat/cafenc.c +++ b/libavformat/cafenc.c @@ -34,12 +34,14 @@ typedef struct { int64_t data; int64_t total_duration; int64_t packets; + uint32_t frame_size; } CAFContext; typedef struct { - uint8_t *byte_size_buffer; - int byte_size_buffer_sz; - int nb_byte_size_buffer; + uint32_t *byte_size_buffer; + uint32_t *frame_size_buffer; + unsigned byte_size_buffer_sz; + unsigned frame_size_buffer_sz; } CAFStreamContext; static uint32_t codec_flags(enum AVCodecID codec_id) { @@ -123,7 +125,7 @@ static int caf_write_header(AVFormatContext *s) const AVDictionaryEntry *t = NULL; unsigned int codec_tag = ff_codec_get_tag(ff_codec_caf_tags, par->codec_id); int64_t chunk_size = 0; - int frame_size = par->frame_size, sample_rate = par->sample_rate; + int sample_rate = par->sample_rate; switch (par->codec_id) { case AV_CODEC_ID_AAC: @@ -146,16 +148,22 @@ static int caf_write_header(AVFormatContext *s) return AVERROR_INVALIDDATA; } - st->priv_data = av_mallocz(sizeof(CAFStreamContext)); - if (!st->priv_data) - return AVERROR(ENOMEM); + caf->frame_size = par->frame_size; + if (par->codec_id != AV_CODEC_ID_MP3 || caf->frame_size != 576) + caf->frame_size = samples_per_packet(par); - if (par->codec_id != AV_CODEC_ID_MP3 || frame_size != 576) - frame_size = samples_per_packet(par); + if (!caf->frame_size && !(pb->seekable & AVIO_SEEKABLE_NORMAL)) { + av_log(s, AV_LOG_ERROR, "Muxing variable frame size not supported on non seekable output\n"); + return AVERROR_INVALIDDATA; + } if (par->codec_id == AV_CODEC_ID_OPUS) sample_rate = 48000; + st->priv_data = av_mallocz(sizeof(CAFStreamContext)); + if (!st->priv_data) + return AVERROR(ENOMEM); + ffio_wfourcc(pb, "caff"); //< mFileType avio_wb16(pb, 1); //< mFileVersion avio_wb16(pb, 0); //< mFileFlags @@ -166,7 +174,7 @@ static int caf_write_header(AVFormatContext *s) avio_wl32(pb, codec_tag); //< mFormatID avio_wb32(pb, codec_flags(par->codec_id)); //< mFormatFlags avio_wb32(pb, par->block_align); //< mBytesPerPacket - avio_wb32(pb, frame_size); //< mFramesPerPacket + avio_wb32(pb, caf->frame_size); //< mFramesPerPacket avio_wb32(pb, par->ch_layout.nb_channels); //< mChannelsPerFrame avio_wb32(pb, av_get_bits_per_sample(par->codec_id)); //< mBitsPerChannel @@ -226,25 +234,36 @@ static int caf_write_packet(AVFormatContext *s, AVPacket *pkt) CAFContext *caf = s->priv_data; AVStream *const st = s->streams[0]; - if (!st->codecpar->block_align) { + if (!st->codecpar->block_align || !caf->frame_size) { CAFStreamContext *caf_st = st->priv_data; - uint8_t *pkt_sizes; - int i, alloc_size = caf_st->nb_byte_size_buffer + 5U; - if (alloc_size < 0) + void *pkt_sizes; + unsigned alloc_size = caf->packets + 1; + + if (!st->codecpar->block_align) { + if (UINT_MAX / sizeof(*caf_st->byte_size_buffer) < alloc_size) return AVERROR(ERANGE); pkt_sizes = av_fast_realloc(caf_st->byte_size_buffer, &caf_st->byte_size_buffer_sz, - alloc_size); + alloc_size * sizeof(*caf_st->byte_size_buffer)); if (!pkt_sizes) return AVERROR(ENOMEM); caf_st->byte_size_buffer = pkt_sizes; - for (i = 4; i > 0; i--) { - unsigned top = pkt->size >> i * 7; - if (top) - pkt_sizes[caf_st->nb_byte_size_buffer++] = 128 | top; + caf_st->byte_size_buffer[caf->packets] = pkt->size; + } + if (!caf->frame_size) { + if (UINT_MAX / sizeof(*caf_st->frame_size_buffer) < alloc_size) + return AVERROR(ERANGE); + + pkt_sizes = av_fast_realloc(caf_st->frame_size_buffer, + &caf_st->frame_size_buffer_sz, + alloc_size * sizeof(*caf_st->frame_size_buffer)); + if (!pkt_sizes) + return AVERROR(ENOMEM); + caf_st->frame_size_buffer = pkt_sizes; + caf_st->frame_size_buffer[caf->packets] = pkt->duration; } - pkt_sizes[caf_st->nb_byte_size_buffer++] = pkt->size & 127; + caf->packets++; caf->total_duration += pkt->duration; } @@ -265,30 +284,56 @@ static int caf_write_trailer(AVFormatContext *s) avio_seek(pb, caf->data, SEEK_SET); avio_wb64(pb, file_size - caf->data - 8); - if (!par->block_align) { - unsigned packet_size = samples_per_packet(par); - int64_t valid_frames = (packet_size ? caf->packets * packet_size : caf->total_duration); + if (!par->block_align || !caf->frame_size) { + int64_t valid_frames = caf->frame_size ? caf->packets * caf->frame_size : caf->total_duration; unsigned remainder_frames = valid_frames > caf->total_duration ? valid_frames - caf->total_duration : 0; + int64_t size = 24; + valid_frames -= par->initial_padding; valid_frames -= remainder_frames; - if (!packet_size) { - packet_size = caf->total_duration / (caf->packets - 1); - avio_seek(pb, FRAME_SIZE_OFFSET, SEEK_SET); - avio_wb32(pb, packet_size); - } + avio_seek(pb, file_size, SEEK_SET); ffio_wfourcc(pb, "pakt"); - avio_wb64(pb, caf_st->nb_byte_size_buffer + 24U); + avio_wb64(pb, 0); // size, to be replaced avio_wb64(pb, caf->packets); ///< mNumberPackets avio_wb64(pb, valid_frames); ///< mNumberValidFrames avio_wb32(pb, par->initial_padding); ///< mPrimingFrames avio_wb32(pb, remainder_frames); ///< mRemainderFrames - avio_write(pb, caf_st->byte_size_buffer, caf_st->nb_byte_size_buffer); + for (int i = 0; i < caf->packets; i++) { + if (!par->block_align) { + for (int j = 4; j > 0; j--) { + unsigned top = caf_st->byte_size_buffer[i] >> j * 7; + if (top) { + avio_w8(pb, 128 | top); + size++; + } + } + avio_w8(pb, caf_st->byte_size_buffer[i] & 127); + size++; + } + if (!caf->frame_size) { + for (int j = 4; j > 0; j--) { + unsigned top = caf_st->frame_size_buffer[i] >> j * 7; + if (top) { + avio_w8(pb, 128 | top); + size++; + } + } + avio_w8(pb, caf_st->frame_size_buffer[i] & 127); + size++; + } + } + + int64_t end = avio_tell(pb); + avio_seek(pb, file_size + 4, SEEK_SET); + avio_wb64(pb, size); + avio_seek(pb, end, SEEK_SET); } } av_freep(&caf_st->byte_size_buffer); + av_freep(&caf_st->frame_size_buffer); return 0; } _______________________________________________ ffmpeg-cvslog mailing list -- [email protected] To unsubscribe send an email to [email protected]
