PR #21572 opened by James Almer (jamrial) URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21572 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21572.patch
Supersedes #21553 >From c6015ed5edf7d7605134d4cb68f30146bdd54fd0 Mon Sep 17 00:00:00 2001 From: James Almer <[email protected]> Date: Sat, 24 Jan 2026 14:02:58 -0300 Subject: [PATCH 1/3] avcodec/opus/enc: set avctx->frame_size to a better guess based on encoder configuration Signed-off-by: James Almer <[email protected]> --- 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; -- 2.52.0 >From 9c76f2a017bd5bcfc07bc8d3317d78fa406030da Mon Sep 17 00:00:00 2001 From: James Almer <[email protected]> Date: Sat, 24 Jan 2026 14:04:31 -0300 Subject: [PATCH 2/3] 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 <[email protected]> --- libavformat/cafdec.c | 21 +++++++++++++++++++-- tests/ref/fate/caf-alac-remux | 6 +++--- tests/ref/fate/caf-qdm2-remux | 6 +++--- 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/libavformat/cafdec.c b/libavformat/cafdec.c index 99ae041364..0a67141773 100644 --- a/libavformat/cafdec.c +++ b/libavformat/cafdec.c @@ -50,6 +50,8 @@ typedef struct CafContext { 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) @@ -254,8 +256,8 @@ 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 */ + st->start_time = -(int64_t)avio_rb32(pb); /* priming frames */ + caf->remainder = avio_rb32(pb); /* remainder frames */ if (caf->bytes_per_packet > 0 && caf->frames_per_packet > 0) { st->duration = caf->frames_per_packet * num_packets; @@ -272,6 +274,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"); @@ -433,6 +438,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,6 +467,7 @@ 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; } @@ -473,6 +480,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 -- 2.52.0 >From 82a91f1d5cca40bc39d51b7831a1b20b5725c440 Mon Sep 17 00:00:00 2001 From: James Almer <[email protected]> Date: Sat, 24 Jan 2026 14:09:20 -0300 Subject: [PATCH 3/3] 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 <[email protected]> --- libavformat/cafenc.c | 17 +++++++++++------ tests/ref/fate/caf-alac-remux | 2 +- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/libavformat/cafenc.c b/libavformat/cafenc.c index 89ecb51e53..df9520a91b 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,12 @@ 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; 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 +268,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..72ad90998a 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 +4d616f58fea0c39ee725a85eab4e67b6 *tests/data/fate/caf-alac-remux.caf 1292684 tests/data/fate/caf-alac-remux.caf #extradata 0: 36, 0x562b05d8 #tb 0: 1/44100 -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
