PR #24581 opened by Forgejo_Fairy URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24581 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24581.patch
Fragmented MP4 recordings with occasional explicitly zero-sized samples fail during input opening after 03d81a044ad5. The sample in #23807 contains two such video samples; the immediate parent of that commit remuxes it successfully. Allow explicit zero sample sizes, whose count is bounded by the existing trun payload checks. Continue rejecting nonempty runs that inherit a zero default size, but perform that check before allocating or modifying the sample index. Retain empty samples in the index to preserve sample numbering and timing. Add `fate-mov-trun-zero-sample-size`, which generates a small fragmented MP4, sets the last sample size in its first fragment to zero, and checks packet sizes, positions, and timestamps through the following fragment. It requires no external sample. Validation on Linux/AArch64: - The generated regression input fails on unmodified master and passes with the patch. - The full #23807 recording remuxes without warnings. Its 35,677 video packets and 55,782 audio packets match the working parent revision's remux in packet sizes and SHA-256 payload hashes. - All 12 enabled MOV FATE tests and `fate-api-movenc` pass. - Generated zero-default-size runs remain rejected, including a large-count case; a run with zero entries remains accepted. Fixes #23807. >From 7ce7c8c2c99ab6f13c39b6e7ee571dfbe06a2376 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Sun, 20 Sep 2026 12:44:33 +0000 Subject: [PATCH] avformat/mov: allow explicit zero sample sizes in trun 03d81a044ad587ea83567f75dc36bc3d64278199 rejected every zero-sized sample to avoid pathological runs of empty samples. This also prevents opening fragmented recordings with occasional explicit zero sizes. Allow explicit zero sample sizes, whose count is bounded by the trun payload checks. Continue rejecting nonempty runs that inherit a zero default size, but do so before allocating or updating the sample index. Keep empty samples in the index to preserve sample numbering and timing. Add a generated FATE test with an empty sample at the end of one fragment followed by another fragment. No external sample is needed. Fixes #23807. Assisted-by: Fairy --- libavformat/mov.c | 7 +++++-- tests/fate/mov.mak | 16 +++++++++++++++- tests/ref/fate/mov-trun-zero-sample-size | 10 ++++++++++ 3 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 tests/ref/fate/mov-trun-zero-sample-size diff --git a/libavformat/mov.c b/libavformat/mov.c index 6abd3f3513..968ac0a090 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -6255,6 +6255,11 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) entries = avio_rb32(pb); av_log(c->fc, AV_LOG_TRACE, "flags 0x%x entries %u\n", flags, entries); + /* Explicit zero sizes are bounded by the trun payload. Reject a zero + * default size before allocating or updating the sample index. */ + if (entries && !frag->size && !(flags & MOV_TRUN_SAMPLE_SIZE)) + return AVERROR_INVALIDDATA; + if ((uint64_t)entries+sc->tts_count >= UINT_MAX/sizeof(*sc->tts_data)) return AVERROR_INVALIDDATA; if (flags & MOV_TRUN_DATA_OFFSET) data_offset = avio_rb32(pb); @@ -6465,8 +6470,6 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) distance++; if (av_sat_add64(dts, sample_duration) != dts + (uint64_t)sample_duration) return AVERROR_INVALIDDATA; - if (!sample_size) - return AVERROR_INVALIDDATA; dts += sample_duration; offset += sample_size; sc->data_size += sample_size; diff --git a/tests/fate/mov.mak b/tests/fate/mov.mak index ecbf686814..b2c5b0a0e9 100644 --- a/tests/fate/mov.mak +++ b/tests/fate/mov.mak @@ -340,7 +340,8 @@ FATE_MOV_FFMPEG_FFPROBE-$(call ALLYES, COLOR_FILTER SETPTS_FILTER MPEG4_ENCODER FATE_MOV_FFMPEG_FFPROBE-$(call ALLYES, COLOR_FILTER SETPTS_FILTER MPEG4_ENCODER \ MP4_MUXER MOV_DEMUXER FILE_PROTOCOL) \ - += fate-mov-trun-large-sample-duration + += fate-mov-trun-large-sample-duration \ + fate-mov-trun-zero-sample-size # Generate a fragmented VFR file, then replace the last sample duration in # its first trun with UINT32_MAX. @@ -354,6 +355,19 @@ fate-mov-trun-large-sample-duration: CMD = run_with_patched_temp \ -show_entries packet=pts,dts,duration -print_format compact \ -select_streams v -v 0" mp4 923 "\\0377\\0377\\0377\\0377" +# An explicitly empty sample must not prevent reading the following fragment. +# Set the last sample size in the first trun to zero; its unreferenced payload +# remains in mdat. Disable parsing to observe the empty sample and its duration. +fate-mov-trun-zero-sample-size: CMD = run_with_patched_temp \ + "$(FFMPEG) -nostdin -v error \ + -filter_complex color=c=black:s=2x2:r=1,setpts=N*N \ + -frames:v 10 -fps_mode vfr -c:v mpeg4 -g 5 -bf 0 -q:v 2 -threads 1 \ + -flags +bitexact -fflags +bitexact \ + -movflags empty_moov+frag_keyframe+default_base_moof -f mp4 -y" \ + "ffprobe$(PROGSSUF)$(EXESUF) -fflags +noparse+nofillin -show_packets \ + -show_entries packet=pts,dts,duration,size,pos -print_format compact \ + -select_streams v -v 0" mp4 927 "\\0000\\0000\\0000\\0000" + # Create VFR B-frames whose presentation durations are not a permutation of # the STTS sample deltas. tests/data/mov-vfr-bframes-derived-duration.mov: TAG = GEN diff --git a/tests/ref/fate/mov-trun-zero-sample-size b/tests/ref/fate/mov-trun-zero-sample-size new file mode 100644 index 0000000000..7838fa6b93 --- /dev/null +++ b/tests/ref/fate/mov-trun-zero-sample-size @@ -0,0 +1,10 @@ +packet|pts=0|dts=0|duration=16384|size=17|pos=939 +packet|pts=16384|dts=16384|duration=49152|size=7|pos=956 +packet|pts=65536|dts=65536|duration=81920|size=7|pos=963 +packet|pts=147456|dts=147456|duration=114688|size=8|pos=970 +packet|pts=262144|dts=262144|duration=147456|size=0|pos=978 +packet|pts=409600|dts=409600|duration=180224|size=17|pos=1138 +packet|pts=589824|dts=589824|duration=212992|size=8|pos=1155 +packet|pts=802816|dts=802816|duration=245760|size=9|pos=1163 +packet|pts=1048576|dts=1048576|duration=278528|size=9|pos=1172 +packet|pts=1327104|dts=1327104|duration=16384|size=9|pos=1181 -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
