Commit 60204fe890 for ffmpeg
commit 60204fe890613e642164d4a0c2f137484d254cff
Author: Furkan Efe Can <caglarf646@gmail.com>
Date: Fri Oct 16 02:22:09 2026 +0300
tests/fate/mov: Test the stsd version 2 sample rate
A version 2 SoundDescription carries the sample rate as a double, so the
muxer is asked for a rate that does not fit the legacy 16.16 field and
empty_moov places the description ahead of mdat, which puts the double at
a fixed offset of the generated file. run_with_patched_temp then replaces
it, so these tests need no sample either.
Measured with libavformat/mov.c restored from the parent of 3be6c2d943,
i.e. with the double converted before being checked, and these tests kept
in place:
fate-mov-stsd-v2-sample-rate-nan fails (reports -2147483648)
fate-mov-stsd-v2-sample-rate-overflow fails (reports -2147483648)
fate-mov-stsd-v2-sample-rate-negative passes
fate-mov-stsd-v2-sample-rate-zero passes
The first two compare the diagnostic rather than only the exit status:
on this x86-64 build the conversion happens to produce INT_MIN, which the
later sample_rate check rejects as well, so the rejection alone does not
show which check fired, and the value it reports is undefined anyway.
The zero test fixes the opposite direction. Zero must stay accepted,
because mov_finalize_stsd_codec() then falls back to the media timescale;
a check rejecting it as invalid would break that fallback.
The generator decodes the lavfi input device's s16 output, which the
device describes with the native-endian PCM codec id, so the decoder
dependency follows the host endianness.
Signed-off-by: Furkan Efe Can <caglarf646@gmail.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
diff --git a/tests/fate/mov.mak b/tests/fate/mov.mak
index e36ddff7ed..3550e1d7b8 100644
--- a/tests/fate/mov.mak
+++ b/tests/fate/mov.mak
@@ -405,6 +405,62 @@ fate-mov-trun-zero-sample-size: CMD = run_with_patched_temp \
-show_entries packet=pts,dts,duration,size,pos -print_format compact \
-select_streams v -v 0" mp4 927 "\\0000\\0000\\0000\\0000"
+FATE_MOV_FFMPEG_FFPROBE-$(call ALLYES, LAVFI_INDEV ANULLSRC_FILTER AFORMAT_FILTER \
+ PCM_S16$(if $(filter yes,$(HAVE_BIGENDIAN)),BE,LE)_DECODER \
+ PCM_S16BE_ENCODER \
+ MOV_MUXER MOV_DEMUXER FILE_PROTOCOL) \
+ += fate-mov-stsd-v2-sample-rate-nan \
+ fate-mov-stsd-v2-sample-rate-overflow \
+ fate-mov-stsd-v2-sample-rate-negative \
+ fate-mov-stsd-v2-sample-rate-zero
+
+# A version 2 SoundDescription stores the sample rate as a double. Requesting
+# a rate that does not fit the legacy 16.16 field makes the muxer write one,
+# and empty_moov puts it ahead of mdat, so the double always starts at offset
+# 489 of the generated file. The tests below replace it with values that must
+# not be converted to codecpar->sample_rate.
+#
+# The diagnostic also identifies which check rejected the file: it prints the
+# double, while the later sample_rate check runs after the conversion and can
+# only report its result.
+#
+# The decoder dependency follows the host endianness, because the lavfi input
+# device describes its s16 output with the native-endian PCM codec id.
+MOV_STSD_V2_GEN = $(FFMPEG) -nostdin -v error \
+ -f lavfi -i anullsrc=cl=stereo:r=96000,aformat=sample_fmts=s16 \
+ -t 0.01 -c:a pcm_s16be -threads 1 \
+ -flags +bitexact -fflags +bitexact -movflags empty_moov+frag_keyframe \
+ -f mov -y
+MOV_STSD_V2_PROBE = ffprobe$(PROGSSUF)$(EXESUF) -v error \
+ -show_entries stream=sample_rate -print_format compact
+
+# NaN: converting it to an integer is undefined.
+fate-mov-stsd-v2-sample-rate-nan: CMD = run_with_patched_temp \
+ "$(MOV_STSD_V2_GEN)" "$(MOV_STSD_V2_PROBE)" mov \
+ 489 "\\0177\\0370\\0000\\0000\\0000\\0000\\0000\\0000" ; test $$? -ne 0
+fate-mov-stsd-v2-sample-rate-nan: CMP = grep
+fate-mov-stsd-v2-sample-rate-nan: REF = Invalid sample rate nan
+
+# INT_MAX + 1: the smallest positive double that does not fit an int.
+fate-mov-stsd-v2-sample-rate-overflow: CMD = run_with_patched_temp \
+ "$(MOV_STSD_V2_GEN)" "$(MOV_STSD_V2_PROBE)" mov \
+ 489 "\\0101\\0340\\0000\\0000\\0000\\0000\\0000\\0000" ; test $$? -ne 0
+fate-mov-stsd-v2-sample-rate-overflow: CMP = grep
+fate-mov-stsd-v2-sample-rate-overflow: REF = Invalid sample rate 2.14748e+09
+
+# A negative rate fits an int, and is rejected for being negative.
+fate-mov-stsd-v2-sample-rate-negative: CMD = run_with_patched_temp \
+ "$(MOV_STSD_V2_GEN)" "$(MOV_STSD_V2_PROBE)" mov \
+ 489 "\\0277\\0360\\0000\\0000\\0000\\0000\\0000\\0000" ; test $$? -ne 0
+fate-mov-stsd-v2-sample-rate-negative: CMP = grep
+fate-mov-stsd-v2-sample-rate-negative: REF = Invalid sample rate -1
+
+# Zero must stay accepted: mov_finalize_stsd_codec() then falls back to the
+# media timescale, which is 96000 here.
+fate-mov-stsd-v2-sample-rate-zero: CMD = run_with_patched_temp \
+ "$(MOV_STSD_V2_GEN)" "$(MOV_STSD_V2_PROBE)" mov \
+ 489 "\\0000\\0000\\0000\\0000\\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-stsd-v2-sample-rate-zero b/tests/ref/fate/mov-stsd-v2-sample-rate-zero
new file mode 100644
index 0000000000..a39c5a26f4
--- /dev/null
+++ b/tests/ref/fate/mov-stsd-v2-sample-rate-zero
@@ -0,0 +1 @@
+stream|sample_rate=96000