[ffmpeg] branch master updated (5b4ba2e1ac -> 277f9cb5d8)
This is an automated email from the git hooks/post-receive script. Git pushed a change to branch master in repository ffmpeg. from 5b4ba2e1ac avfilter/vsrc_amf: Remove unused-but-set variable new c3aea7628c avcodec/opus/enc: set avctx->frame_size to a better guess based on encoder configuration new 041d108958 avcodec/opus/enc: don't remove more samples than needed from the last packet new c52b287ba9 avformat/cafdec: fix setting stream and packet durations new f5ea09afe8 avformat/cafdec: export frame size when present new 8d1f247ec1 avformat/cafenc: fix setting frame count fields in Packet Table Description new 7600d12383 avformat/cafenc: define a structure to store stream private fields new 6ff12c4f6c avformat/cafenc: add support for variable frame size codecs new 7581abdcb1 avformat/cafenc: support writing Packet Table Chunk Header if there are priming or remainder frames new 2d5556b082 avformat/cafenc: reindent after the previous changes new 277f9cb5d8 avformat/cafenc: add init and deinit callbacks The 10 revisions listed above as "new" are entirely new to this repository and will be described in separate emails. The revisions listed as "add" were already present in the repository and have only been added to this reference. Summary of changes: libavcodec/opus/enc.c | 10 +-- libavformat/cafdec.c | 37 ++++++++- libavformat/cafenc.c | 175 +++++++++++++++++++++++++++++++----------- tests/ref/fate/caf-alac-remux | 8 +- tests/ref/fate/caf-qdm2-remux | 10 +-- 5 files changed, 179 insertions(+), 61 deletions(-)
This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch master in repository ffmpeg. commit c3aea7628c179dc512b2da18ac6cd4c4260618e2 Author: James Almer <jamrial@gmail.com> AuthorDate: Sat Jan 24 14:02:58 2026 -0300 Commit: James Almer <jamrial@gmail.com> CommitDate: Thu Jan 29 21:09:02 2026 -0300 avcodec/opus/enc: set avctx->frame_size to a better guess based on encoder configuration Signed-off-by: James Almer <jamrial@gmail.com> --- libavcodec/opus/enc.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/libavcodec/opus/enc.c b/libavcodec/opus/enc.c index 8d20b6c192..1bbeb4bf6e 100644 --- a/libavcodec/opus/enc.c +++ b/libavcodec/opus/enc.c @@ -638,12 +638,8 @@ static av_cold int opus_encode_init(AVCodecContext *avctx) s->avctx = avctx; s->channels = avctx->ch_layout.nb_channels; - /* Opus allows us to change the framesize on each packet (and each packet may - * have multiple frames in it) but we can't change the codec's frame size on - * runtime, so fix it to the lowest possible number of samples and use a queue - * to accumulate AVFrames until we have enough to encode whatever the encoder - * decides is the best */ - avctx->frame_size = 120; + int max_delay_samples = (s->options.max_delay_ms * s->avctx->sample_rate) / 1000; + avctx->frame_size = OPUS_BLOCK_SIZE(FFMIN(OPUS_SAMPLES_TO_BLOCK_SIZE(max_delay_samples), CELT_BLOCK_960)); /* Initial padding will change if SILK is ever supported */ avctx->initial_padding = 120;
This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch master in repository ffmpeg. commit 041d10895884b64ba412485d5b3faa0a13a2a4e3 Author: James Almer <jamrial@gmail.com> AuthorDate: Tue Jan 27 10:42:59 2026 -0300 Commit: James Almer <jamrial@gmail.com> CommitDate: Thu Jan 29 21:09:02 2026 -0300 avcodec/opus/enc: don't remove more samples than needed from the last packet The hardcoded extra 120 samples results in the side data reporting the need to discard the entire packet rather than the padding samples. This is in line with the behavior of the libopus encoder. Signed-off-by: James Almer <jamrial@gmail.com> --- libavcodec/opus/enc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/opus/enc.c b/libavcodec/opus/enc.c index 1bbeb4bf6e..65e6a09575 100644 --- a/libavcodec/opus/enc.c +++ b/libavcodec/opus/enc.c @@ -604,7 +604,7 @@ static int opus_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, uint8_t *side = av_packet_new_side_data(avpkt, AV_PKT_DATA_SKIP_SAMPLES, 10); if (!side) return AVERROR(ENOMEM); - AV_WL32(&side[4], s->packet.frames*frame_size - avpkt->duration + 120); + AV_WL32(&side[4], s->packet.frames*frame_size - avpkt->duration); } *got_packet_ptr = 1;
This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch master in repository ffmpeg. commit c52b287ba9e4d23bab6e9401fd860a4dd4f31f32 Author: James Almer <jamrial@gmail.com> AuthorDate: Sat Jan 24 14:04:31 2026 -0300 Commit: James Almer <jamrial@gmail.com> CommitDate: Thu Jan 29 21:09:02 2026 -0300 avformat/cafdec: fix setting stream and packet durations Take into account priming frames, exported as start time, and remainder frames, substracted from the stream duration as well as exported as discard padding side data in the last packet. Signed-off-by: James Almer <jamrial@gmail.com> --- libavformat/cafdec.c | 36 ++++++++++++++++++++++++++++++++++-- tests/ref/fate/caf-alac-remux | 6 +++--- tests/ref/fate/caf-qdm2-remux | 6 +++--- 3 files changed, 40 insertions(+), 8 deletions(-) diff --git a/libavformat/cafdec.c b/libavformat/cafdec.c index 99ae041364..081fc9d06c 100644 --- a/libavformat/cafdec.c +++ b/libavformat/cafdec.c @@ -45,11 +45,14 @@ typedef struct CafContext { int frames_per_packet; ///< frames in a packet, or 0 if variable int64_t num_bytes; ///< total number of bytes in stream + int64_t num_packets; ///< packet amount int64_t packet_cnt; ///< packet counter int64_t frame_cnt; ///< frame counter int64_t data_start; ///< data start position, in bytes int64_t data_size; ///< raw data size, in bytes + + unsigned remainder; ///< frames to discard from the last packet } CafContext; static int probe(const AVProbeData *p) @@ -244,6 +247,7 @@ static int read_pakt_chunk(AVFormatContext *s, int64_t size) AVStream *st = s->streams[0]; CafContext *caf = s->priv_data; int64_t pos = 0, ccount, num_packets; + unsigned priming; int i; int ret; @@ -254,10 +258,19 @@ static int read_pakt_chunk(AVFormatContext *s, int64_t size) return AVERROR_INVALIDDATA; st->nb_frames = avio_rb64(pb); /* valid frames */ - st->nb_frames += avio_rb32(pb); /* priming frames */ - st->nb_frames += avio_rb32(pb); /* remainder frames */ + priming = avio_rb32(pb); /* priming frames */ + caf->remainder = avio_rb32(pb); /* remainder frames */ + + st->codecpar->initial_padding = priming; + st->nb_frames += priming; + st->nb_frames += caf->remainder; if (caf->bytes_per_packet > 0 && caf->frames_per_packet > 0) { + if (!num_packets) { + if (caf->data_size < 0) + return AVERROR_INVALIDDATA; + num_packets = caf->data_size / caf->bytes_per_packet; + } st->duration = caf->frames_per_packet * num_packets; pos = caf-> bytes_per_packet * num_packets; } else { @@ -272,6 +285,9 @@ static int read_pakt_chunk(AVFormatContext *s, int64_t size) st->duration += caf->frames_per_packet ? caf->frames_per_packet : ff_mp4_read_descr_len(pb); } } + st->duration -= caf->remainder; + if (st->duration < 0) + return AVERROR_INVALIDDATA; if (avio_tell(pb) - ccount > size || size > INT64_MAX - ccount) { av_log(s, AV_LOG_ERROR, "error reading packet table\n"); @@ -279,6 +295,7 @@ static int read_pakt_chunk(AVFormatContext *s, int64_t size) } avio_seek(pb, ccount + size, SEEK_SET); + caf->num_packets = num_packets; caf->num_bytes = pos; return 0; } @@ -433,6 +450,7 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt) FFStream *const sti = ffstream(st); CafContext *caf = s->priv_data; int res, pkt_size = 0, pkt_frames = 0; + unsigned remainder = 0; int64_t left = CAF_MAX_PKT_SIZE; if (avio_feof(pb)) @@ -461,9 +479,13 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt) } else if (caf->packet_cnt == sti->nb_index_entries - 1) { pkt_size = caf->num_bytes - sti->index_entries[caf->packet_cnt].pos; pkt_frames = st->duration - sti->index_entries[caf->packet_cnt].timestamp; + remainder = caf->remainder; } else { return AVERROR_INVALIDDATA; } + } else if (caf->packet_cnt + 1 == caf->num_packets) { + pkt_frames -= caf->remainder; + remainder = caf->remainder; } if (pkt_size == 0 || pkt_frames == 0 || pkt_size > left) @@ -473,6 +495,16 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt) if (res < 0) return res; + if (remainder > 0) { + uint8_t* side_data = av_packet_new_side_data(pkt, + AV_PKT_DATA_SKIP_SAMPLES, + 10); + if (!side_data) + return AVERROR(ENOMEM); + AV_WL32(side_data + 4, caf->remainder); + } + + pkt->duration = pkt_frames; pkt->size = res; pkt->stream_index = 0; pkt->dts = pkt->pts = caf->frame_cnt; diff --git a/tests/ref/fate/caf-alac-remux b/tests/ref/fate/caf-alac-remux index f33182b721..2a1d24092b 100644 --- a/tests/ref/fate/caf-alac-remux +++ b/tests/ref/fate/caf-alac-remux @@ -6,9 +6,9 @@ #codec_id 0: alac #sample_rate 0: 44100 #channel_layout_name 0: stereo -0, 0, 0, 0, 32, 0xa0af0dfe -0, 4096, 4096, 0, 6701, 0xa9ddc14e -0, 8192, 8192, 0, 6639, 0x3ccda8d6 +0, 0, 0, 4096, 32, 0xa0af0dfe +0, 4096, 4096, 4096, 6701, 0xa9ddc14e +0, 8192, 8192, 4096, 6639, 0x3ccda8d6 [FORMAT] TAG:track=5/13 TAG:minor_version=0 diff --git a/tests/ref/fate/caf-qdm2-remux b/tests/ref/fate/caf-qdm2-remux index d4f658c163..e0e96eaf5e 100644 --- a/tests/ref/fate/caf-qdm2-remux +++ b/tests/ref/fate/caf-qdm2-remux @@ -6,6 +6,6 @@ #codec_id 0: qdm2 #sample_rate 0: 44100 #channel_layout_name 0: stereo -0, 0, 0, 0, 370, 0x4d1897fc -0, 4096, 4096, 0, 370, 0xea999da0 -0, 8192, 8192, 0, 370, 0xca259462 +0, 0, 0, 4096, 370, 0x4d1897fc +0, 4096, 4096, 4096, 370, 0xea999da0 +0, 8192, 8192, 4096, 370, 0xca259462
This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch master in repository ffmpeg. commit f5ea09afe802732b0d62dedc3a7dad2beac8dd79 Author: James Almer <jamrial@gmail.com> AuthorDate: Mon Jan 26 10:29:01 2026 -0300 Commit: James Almer <jamrial@gmail.com> CommitDate: Thu Jan 29 21:09:02 2026 -0300 avformat/cafdec: export frame size when present Signed-off-by: James Almer <jamrial@gmail.com> --- libavformat/cafdec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavformat/cafdec.c b/libavformat/cafdec.c index 081fc9d06c..f0f307177b 100644 --- a/libavformat/cafdec.c +++ b/libavformat/cafdec.c @@ -89,6 +89,7 @@ static int read_desc_chunk(AVFormatContext *s) caf->bytes_per_packet = avio_rb32(pb); st->codecpar->block_align = caf->bytes_per_packet; caf->frames_per_packet = avio_rb32(pb); + st->codecpar->frame_size = caf->frames_per_packet != 1 ? caf->frames_per_packet : 0; st->codecpar->ch_layout.nb_channels = avio_rb32(pb); st->codecpar->bits_per_coded_sample = avio_rb32(pb);
This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch master in repository ffmpeg. commit 8d1f247ec11d16774675b218c9442af1ac5cd0da Author: James Almer <jamrial@gmail.com> AuthorDate: Sat Jan 24 14:09:20 2026 -0300 Commit: James Almer <jamrial@gmail.com> CommitDate: Thu Jan 29 21:09:02 2026 -0300 avformat/cafenc: fix setting frame count fields in Packet Table Description st->duration is not guaranteed to be set, so store the sum of packet durations instead. Also, set mPrimingFrames and mRemainderFrames to correct values. Based on a patch by Jun Zhao. Signed-off-by: James Almer <jamrial@gmail.com> --- libavformat/cafenc.c | 19 +++++++++++++------ tests/ref/fate/caf-alac-remux | 2 +- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/libavformat/cafenc.c b/libavformat/cafenc.c index 89ecb51e53..e229358970 100644 --- a/libavformat/cafenc.c +++ b/libavformat/cafenc.c @@ -32,9 +32,10 @@ typedef struct { int64_t data; + int64_t total_duration; + int64_t packets; int size_buffer_size; int size_entries_used; - int packets; } CAFContext; static uint32_t codec_flags(enum AVCodecID codec_id) { @@ -235,6 +236,7 @@ static int caf_write_packet(AVFormatContext *s, AVPacket *pkt) } pkt_sizes[caf->size_entries_used++] = pkt->size & 127; caf->packets++; + caf->total_duration += pkt->duration; } avio_write(s->pb, pkt->data, pkt->size); return 0; @@ -253,9 +255,14 @@ 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) { - int packet_size = samples_per_packet(par); + unsigned packet_size = samples_per_packet(par); + int64_t valid_frames = (packet_size ? caf->packets * packet_size : caf->total_duration); + unsigned remainder_frames = valid_frames > caf->total_duration + ? valid_frames - caf->total_duration : 0; + valid_frames -= par->initial_padding; + valid_frames -= remainder_frames; if (!packet_size) { - packet_size = st->duration / (caf->packets - 1); + packet_size = caf->total_duration / (caf->packets - 1); avio_seek(pb, FRAME_SIZE_OFFSET, SEEK_SET); avio_wb32(pb, packet_size); } @@ -263,9 +270,9 @@ static int caf_write_trailer(AVFormatContext *s) ffio_wfourcc(pb, "pakt"); avio_wb64(pb, caf->size_entries_used + 24U); avio_wb64(pb, caf->packets); ///< mNumberPackets - avio_wb64(pb, caf->packets * packet_size); ///< mNumberValidFrames - avio_wb32(pb, 0); ///< mPrimingFrames - avio_wb32(pb, 0); ///< mRemainderFrames + avio_wb64(pb, valid_frames); ///< mNumberValidFrames + avio_wb32(pb, par->initial_padding); ///< mPrimingFrames + avio_wb32(pb, remainder_frames); ///< mRemainderFrames avio_write(pb, st->priv_data, caf->size_entries_used); } } diff --git a/tests/ref/fate/caf-alac-remux b/tests/ref/fate/caf-alac-remux index 2a1d24092b..63987239db 100644 --- a/tests/ref/fate/caf-alac-remux +++ b/tests/ref/fate/caf-alac-remux @@ -1,4 +1,4 @@ -9ef40186fb3e24789df03f8c08110486 *tests/data/fate/caf-alac-remux.caf +1f3ac6e905aa6bfee0d35c19a2400c26 *tests/data/fate/caf-alac-remux.caf 1292684 tests/data/fate/caf-alac-remux.caf #extradata 0: 36, 0x562b05d8 #tb 0: 1/44100
This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch master in repository ffmpeg. commit 7600d12383c276681ed02b9871b88659eee62dee Author: James Almer <jamrial@gmail.com> AuthorDate: Sat Jan 24 18:37:40 2026 -0300 Commit: James Almer <jamrial@gmail.com> CommitDate: Thu Jan 29 21:09:02 2026 -0300 avformat/cafenc: define a structure to store stream private fields Will be useful in the following commit. Signed-off-by: James Almer <jamrial@gmail.com> --- libavformat/cafenc.c | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/libavformat/cafenc.c b/libavformat/cafenc.c index e229358970..c6369f0b62 100644 --- a/libavformat/cafenc.c +++ b/libavformat/cafenc.c @@ -34,10 +34,14 @@ typedef struct { int64_t data; int64_t total_duration; int64_t packets; - int size_buffer_size; - int size_entries_used; } CAFContext; +typedef struct { + uint8_t *byte_size_buffer; + int byte_size_buffer_sz; + int nb_byte_size_buffer; +} CAFStreamContext; + static uint32_t codec_flags(enum AVCodecID codec_id) { switch (codec_id) { case AV_CODEC_ID_PCM_F32BE: @@ -113,6 +117,7 @@ static uint32_t samples_per_packet(const AVCodecParameters *par) { static int caf_write_header(AVFormatContext *s) { AVIOContext *pb = s->pb; + AVStream *const st = s->streams[0]; AVCodecParameters *par = s->streams[0]->codecpar; CAFContext *caf = s->priv_data; const AVDictionaryEntry *t = NULL; @@ -141,6 +146,10 @@ static int caf_write_header(AVFormatContext *s) return AVERROR_INVALIDDATA; } + st->priv_data = av_mallocz(sizeof(CAFStreamContext)); + if (!st->priv_data) + return AVERROR(ENOMEM); + if (par->codec_id != AV_CODEC_ID_MP3 || frame_size != 576) frame_size = samples_per_packet(par); @@ -218,23 +227,24 @@ static int caf_write_packet(AVFormatContext *s, AVPacket *pkt) AVStream *const st = s->streams[0]; if (!st->codecpar->block_align) { + CAFStreamContext *caf_st = st->priv_data; uint8_t *pkt_sizes; - int i, alloc_size = caf->size_entries_used + 5U; + int i, alloc_size = caf_st->nb_byte_size_buffer + 5U; if (alloc_size < 0) return AVERROR(ERANGE); - pkt_sizes = av_fast_realloc(st->priv_data, - &caf->size_buffer_size, + pkt_sizes = av_fast_realloc(caf_st->byte_size_buffer, + &caf_st->byte_size_buffer_sz, alloc_size); if (!pkt_sizes) return AVERROR(ENOMEM); - st->priv_data = pkt_sizes; + caf_st->byte_size_buffer = pkt_sizes; for (i = 4; i > 0; i--) { unsigned top = pkt->size >> i * 7; if (top) - pkt_sizes[caf->size_entries_used++] = 128 | top; + pkt_sizes[caf_st->nb_byte_size_buffer++] = 128 | top; } - pkt_sizes[caf->size_entries_used++] = pkt->size & 127; + pkt_sizes[caf_st->nb_byte_size_buffer++] = pkt->size & 127; caf->packets++; caf->total_duration += pkt->duration; } @@ -247,6 +257,7 @@ static int caf_write_trailer(AVFormatContext *s) CAFContext *caf = s->priv_data; AVIOContext *pb = s->pb; AVStream *st = s->streams[0]; + CAFStreamContext *caf_st = st->priv_data; AVCodecParameters *par = st->codecpar; if (pb->seekable & AVIO_SEEKABLE_NORMAL) { @@ -268,14 +279,17 @@ static int caf_write_trailer(AVFormatContext *s) } avio_seek(pb, file_size, SEEK_SET); ffio_wfourcc(pb, "pakt"); - avio_wb64(pb, caf->size_entries_used + 24U); + avio_wb64(pb, caf_st->nb_byte_size_buffer + 24U); 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, st->priv_data, caf->size_entries_used); + avio_write(pb, caf_st->byte_size_buffer, caf_st->nb_byte_size_buffer); } } + + av_freep(&caf_st->byte_size_buffer); + return 0; }
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 <jamrial@gmail.com> AuthorDate: Sat Jan 24 18:58:21 2026 -0300 Commit: James Almer <jamrial@gmail.com> CommitDate: Thu Jan 29 21:09:02 2026 -0300 avformat/cafenc: add support for variable frame size codecs Signed-off-by: James Almer <jamrial@gmail.com> --- 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; }
This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch master in repository ffmpeg. commit 7581abdcb1602b9fb7e54ea65868473105ed8ee0 Author: James Almer <jamrial@gmail.com> AuthorDate: Sun Jan 25 23:45:12 2026 -0300 Commit: James Almer <jamrial@gmail.com> CommitDate: Thu Jan 29 21:09:02 2026 -0300 avformat/cafenc: support writing Packet Table Chunk Header if there are priming or remainder frames If a codec has fixed block_align and frame_size but a given sample has either priming or remainder frames, a pakt chunk can be written declaring zero packets and no table, reporting only the samples to be discarded. Signed-off-by: James Almer <jamrial@gmail.com> --- libavformat/cafenc.c | 18 ++++++++++-------- tests/ref/fate/caf-qdm2-remux | 4 ++-- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/libavformat/cafenc.c b/libavformat/cafenc.c index b1e7555aca..6f44e2a2b0 100644 --- a/libavformat/cafenc.c +++ b/libavformat/cafenc.c @@ -263,10 +263,10 @@ static int caf_write_packet(AVFormatContext *s, AVPacket *pkt) caf_st->frame_size_buffer = pkt_sizes; caf_st->frame_size_buffer[caf->packets] = pkt->duration; } - + } caf->packets++; caf->total_duration += pkt->duration; - } + avio_write(s->pb, pkt->data, pkt->size); return 0; } @@ -281,13 +281,15 @@ static int caf_write_trailer(AVFormatContext *s) if (pb->seekable & AVIO_SEEKABLE_NORMAL) { int64_t file_size = avio_tell(pb); - - avio_seek(pb, caf->data, SEEK_SET); - avio_wb64(pb, file_size - caf->data - 8); - if (!par->block_align || !caf->frame_size) { + int64_t packets = (!par->block_align || !caf->frame_size) ? caf->packets : 0; 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; + + avio_seek(pb, caf->data, SEEK_SET); + avio_wb64(pb, file_size - caf->data - 8); + + if (!par->block_align || !caf->frame_size || par->initial_padding || remainder_frames) { int64_t size = 24; valid_frames -= par->initial_padding; @@ -296,11 +298,11 @@ static int caf_write_trailer(AVFormatContext *s) avio_seek(pb, file_size, SEEK_SET); ffio_wfourcc(pb, "pakt"); avio_wb64(pb, 0); // size, to be replaced - avio_wb64(pb, caf->packets); ///< mNumberPackets + avio_wb64(pb, packets); ///< mNumberPackets avio_wb64(pb, valid_frames); ///< mNumberValidFrames avio_wb32(pb, par->initial_padding); ///< mPrimingFrames avio_wb32(pb, remainder_frames); ///< mRemainderFrames - for (int i = 0; i < caf->packets; i++) { + for (int i = 0; i < packets; i++) { if (!par->block_align) { for (int j = 4; j > 0; j--) { unsigned top = caf_st->byte_size_buffer[i] >> j * 7; diff --git a/tests/ref/fate/caf-qdm2-remux b/tests/ref/fate/caf-qdm2-remux index e0e96eaf5e..d14e298d5d 100644 --- a/tests/ref/fate/caf-qdm2-remux +++ b/tests/ref/fate/caf-qdm2-remux @@ -1,5 +1,5 @@ -2b71d78aa6c9d13a3c0dbbbebe885227 *tests/data/fate/caf-qdm2-remux.caf -51228 tests/data/fate/caf-qdm2-remux.caf +fa896705e19dccfef00734f1e8f614c8 *tests/data/fate/caf-qdm2-remux.caf +51264 tests/data/fate/caf-qdm2-remux.caf #extradata 0: 64, 0x10d20603 #tb 0: 1/44100 #media_type 0: audio
This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch master in repository ffmpeg. commit 2d5556b082b93d6d29de944b46b82dc3fed90d69 Author: James Almer <jamrial@gmail.com> AuthorDate: Sun Jan 25 23:47:05 2026 -0300 Commit: James Almer <jamrial@gmail.com> CommitDate: Thu Jan 29 21:09:03 2026 -0300 avformat/cafenc: reindent after the previous changes Signed-off-by: James Almer <jamrial@gmail.com> --- libavformat/cafenc.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/libavformat/cafenc.c b/libavformat/cafenc.c index 6f44e2a2b0..ada03836bc 100644 --- a/libavformat/cafenc.c +++ b/libavformat/cafenc.c @@ -240,16 +240,16 @@ static int caf_write_packet(AVFormatContext *s, AVPacket *pkt) 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 * sizeof(*caf_st->byte_size_buffer)); - if (!pkt_sizes) - return AVERROR(ENOMEM); - caf_st->byte_size_buffer = pkt_sizes; - caf_st->byte_size_buffer[caf->packets] = pkt->size; + 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 * sizeof(*caf_st->byte_size_buffer)); + if (!pkt_sizes) + return AVERROR(ENOMEM); + caf_st->byte_size_buffer = pkt_sizes; + caf_st->byte_size_buffer[caf->packets] = pkt->size; } if (!caf->frame_size) { if (UINT_MAX / sizeof(*caf_st->frame_size_buffer) < alloc_size) @@ -264,8 +264,8 @@ static int caf_write_packet(AVFormatContext *s, AVPacket *pkt) caf_st->frame_size_buffer[caf->packets] = pkt->duration; } } - caf->packets++; - caf->total_duration += pkt->duration; + caf->packets++; + caf->total_duration += pkt->duration; avio_write(s->pb, pkt->data, pkt->size); return 0; @@ -282,9 +282,9 @@ static int caf_write_trailer(AVFormatContext *s) if (pb->seekable & AVIO_SEEKABLE_NORMAL) { int64_t file_size = avio_tell(pb); int64_t packets = (!par->block_align || !caf->frame_size) ? caf->packets : 0; - 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 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; avio_seek(pb, caf->data, SEEK_SET); avio_wb64(pb, file_size - caf->data - 8);
This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch master in repository ffmpeg. commit 277f9cb5d8f1b1de4839ea729fa7fa39569c312f Author: James Almer <jamrial@gmail.com> AuthorDate: Sat Jan 24 21:48:17 2026 -0300 Commit: James Almer <jamrial@gmail.com> CommitDate: Thu Jan 29 21:09:03 2026 -0300 avformat/cafenc: add init and deinit callbacks Signed-off-by: James Almer <jamrial@gmail.com> --- libavformat/cafenc.c | 45 +++++++++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/libavformat/cafenc.c b/libavformat/cafenc.c index ada03836bc..5bee5f74bb 100644 --- a/libavformat/cafenc.c +++ b/libavformat/cafenc.c @@ -116,16 +116,11 @@ static uint32_t samples_per_packet(const AVCodecParameters *par) { } } -static int caf_write_header(AVFormatContext *s) +static int caf_write_init(struct AVFormatContext *s) { - AVIOContext *pb = s->pb; AVStream *const st = s->streams[0]; AVCodecParameters *par = s->streams[0]->codecpar; - CAFContext *caf = s->priv_data; - 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 sample_rate = par->sample_rate; switch (par->codec_id) { case AV_CODEC_ID_AAC: @@ -143,6 +138,28 @@ static int caf_write_header(AVFormatContext *s) return AVERROR_INVALIDDATA; } + st->priv_data = av_mallocz(sizeof(CAFStreamContext)); + if (!st->priv_data) + return AVERROR(ENOMEM); + + // if either block_align or frame_size are 0, we need to check that the output + // is seekable. Postpone reporting init as complete until caf_write_header() + if (!par->block_align || !par->frame_size) + return 1; + + return 0; +} + +static int caf_write_header(AVFormatContext *s) +{ + AVIOContext *pb = s->pb; + AVCodecParameters *par = s->streams[0]->codecpar; + CAFContext *caf = s->priv_data; + 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 sample_rate = par->sample_rate; + if (!par->block_align && !(pb->seekable & AVIO_SEEKABLE_NORMAL)) { av_log(s, AV_LOG_ERROR, "Muxing variable packet size not supported on non seekable output\n"); return AVERROR_INVALIDDATA; @@ -160,10 +177,6 @@ static int caf_write_header(AVFormatContext *s) 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 @@ -334,10 +347,16 @@ static int caf_write_trailer(AVFormatContext *s) } } + return 0; +} + +static void caf_write_deinit(AVFormatContext *s) +{ + AVStream *st = s->streams[0]; + CAFStreamContext *caf_st = st->priv_data; + av_freep(&caf_st->byte_size_buffer); av_freep(&caf_st->frame_size_buffer); - - return 0; } const FFOutputFormat ff_caf_muxer = { @@ -350,8 +369,10 @@ const FFOutputFormat ff_caf_muxer = { .p.video_codec = AV_CODEC_ID_NONE, .p.subtitle_codec = AV_CODEC_ID_NONE, .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, + .init = caf_write_init, .write_header = caf_write_header, .write_packet = caf_write_packet, .write_trailer = caf_write_trailer, + .deinit = caf_write_deinit, .p.codec_tag = ff_caf_codec_tags_list, };
participants (2)
-
ffmpeg-git -
James Almer