PR #25363 opened by Forgejo_Fairy
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25363
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25363.patch

Seeking after probing a small DASH fragment can duplicate the selected segment. 
Probing may reach EOF and set `is_restart_needed`; `dash_seek()` resets the 
selected sequence number and read offsets but retains this flag. At the next 
segment EOF, `read_data()` consequently skips advancing the sequence number and 
the same segment is opened again.

Clear the pending restart before reopening the component. Clearing it before 
reopening also preserves a new restart legitimately requested while probing the 
selected segment.

A generated 15-second Opus input produces 751 packets without seeking and 1,001 
with `-ss 0` before this fix. The duplicated packets have backward timestamps, 
which FFmpeg adjusts to one-tick increments when writing MP4. With the fix, 
seek-to-zero packet timestamps and payload hashes match the no-seek baseline 
exactly.

Validation:

- Added portable generated-media FATE tests `fate-dash-seek-zero` and 
`fate-dash-seek-reference`, sharing an expected packet-checksum/timestamp 
reference. The seek test fails with 14 duplicate MP2 packets before the fix; 
both pass with 42 packets afterward.
- Verified that Opus seeks to 0, 5, 7, 10, and 14 seconds no longer duplicate 
250 packets or produce non-monotonic DTS warnings.
- Verified the fix with generated H.264/Opus DASH input as well.
- Reproduced the underlying bug on master and release/9.0, 8.1, 8.0, 7.1, 6.1, 
5.1, and 4.4. The patch itself was tested on master on Linux ARM64.
- No additional FATE sample upload is needed.

Fixes #25247.


>From 2e3196a7089e099bb6e768740218ac3d2e55edd4 Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Thu, 22 Oct 2026 16:42:29 +0000
Subject: [PATCH] avformat/dashdec: clear pending segment restart when seeking

Probing a small fragment can reach EOF and set is_restart_needed before a
seek. dash_seek selects a new segment but leaves this flag set, so
read_data does not advance cur_seq_no at the next EOF. The selected
segment is then opened a second time.

Clear the pending restart along with the other segment read state before
reopening the component. Do this before probing the new segment, which
may legitimately set the flag again.

Add generated MP2 DASH tests comparing seek-to-zero and sequential packet
checksums and timestamps. The seek test emits 14 duplicate packets without
the reset; both tests produce the same 42 packets with it.

Fixes #25247

Assisted-by: Fairy
---
 libavformat/dashdec.c         |  1 +
 tests/fate/dashenc.mak        | 13 ++++++++++
 tests/ref/fate/dash-seek-zero | 47 +++++++++++++++++++++++++++++++++++
 3 files changed, 61 insertions(+)
 create mode 100644 tests/ref/fate/dash-seek-zero

diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c
index 8b0fb0361d8..654c0535db8 100644
--- a/libavformat/dashdec.c
+++ b/libavformat/dashdec.c
@@ -2516,6 +2516,7 @@ set_seq_num:
     pls->cur_timestamp = 0;
     pls->cur_seg_offset = 0;
     pls->init_sec_buf_read_offset = 0;
+    pls->is_restart_needed = 0;
     ret = dry_run ? 0 : reopen_demux_for_component(s, pls);
 
     return ret;
diff --git a/tests/fate/dashenc.mak b/tests/fate/dashenc.mak
index a1c00e74021..0f1cca3341c 100644
--- a/tests/fate/dashenc.mak
+++ b/tests/fate/dashenc.mak
@@ -43,5 +43,18 @@ fate-dash-big-init: tests/data/dash_big_init.mpd
 fate-dash-big-init: CLEANFILES = tests/data/dash_big_init.mpd 
tests/data/dash_big_init.m3u8 tests/data/dash_big_init.mp4 
tests/data/dash_big_init_*.m4s
 fate-dash-big-init: CMD = framecrc -i 
$(TARGET_PATH)/tests/data/dash_big_init.mpd -map 0:a:99 -c copy
 
+tests/data/dash_seek.mpd: TAG = GEN
+tests/data/dash_seek.mpd: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data
+       $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin -loglevel error \
+       -f lavfi -i "sine=sample_rate=16000:duration=3" \
+       -c:a mp2fixed -b:a 8k -bitexact -f dash -seg_duration 1 \
+       -init_seg_name dash_seek_init.mp4 -media_seg_name 
'dash_seek_$$Number$$.m4s' $(TARGET_PATH)/$@
+
+FATE_DASHENC_LAVFI-$(call ALLYES, SINE_FILTER ARESAMPLE_FILTER LAVFI_INDEV 
PCM_S16LE_DECODER MP2FIXED_ENCODER DASH_MUXER MP4_MUXER DASH_DEMUXER 
MOV_DEMUXER MP3_DECODER FILE_PROTOCOL FRAMECRC_MUXER PIPE_PROTOCOL) += 
fate-dash-seek-zero fate-dash-seek-reference
+fate-dash-seek-zero fate-dash-seek-reference: tests/data/dash_seek.mpd
+fate-dash-seek-zero: CMD = framecrc -ss 0 -i 
$(TARGET_PATH)/tests/data/dash_seek.mpd -c copy
+fate-dash-seek-reference: CMD = framecrc -i 
$(TARGET_PATH)/tests/data/dash_seek.mpd -c copy
+fate-dash-seek-reference: REF = $(SRC_PATH)/tests/ref/fate/dash-seek-zero
+
 FATE_FFMPEG += $(FATE_DASHENC_LAVFI-yes)
 fate-dashenc: $(FATE_DASHENC_LAVFI-yes)
diff --git a/tests/ref/fate/dash-seek-zero b/tests/ref/fate/dash-seek-zero
new file mode 100644
index 00000000000..c2190258fd4
--- /dev/null
+++ b/tests/ref/fate/dash-seek-zero
@@ -0,0 +1,47 @@
+#tb 0: 1/16000
+#media_type 0: audio
+#codec_id 0: mp3
+#sample_rate 0: 16000
+#channel_layout_name 0: mono
+0,          0,          0,     1152,       72, 0x76b21f9b
+0,       1152,       1152,     1152,       72, 0x9e131900
+0,       2304,       2304,     1152,       72, 0xaa621ba7
+0,       3456,       3456,     1152,       72, 0x76ab1842
+0,       4608,       4608,     1152,       72, 0xcc1f1c52
+0,       5760,       5760,     1152,       72, 0xd1991af3
+0,       6912,       6912,     1152,       72, 0x88301bf2
+0,       8064,       8064,     1152,       72, 0x9e8f1bb3
+0,       9216,       9216,     1152,       72, 0xc2911b4d
+0,      10368,      10368,     1152,       72, 0xd44d1b0b
+0,      11520,      11520,     1152,       72, 0x5d3f1906
+0,      12672,      12672,     1152,       72, 0xc5cb1bae
+0,      13824,      13824,     1152,       72, 0x60fa18f9
+0,      14976,      14976,     1152,       72, 0xb0e01be3
+0,      16128,      16128,     1152,       72, 0x4ccf1a2b
+0,      17280,      17280,     1152,       72, 0x96ba1b53
+0,      18432,      18432,     1152,       72, 0xc8db1a81
+0,      19584,      19584,     1152,       72, 0xb5161cc4
+0,      20736,      20736,     1152,       72, 0x166a16a6
+0,      21888,      21888,     1152,       72, 0xd6631b63
+0,      23040,      23040,     1152,       72, 0x8a9019e5
+0,      24192,      24192,     1152,       72, 0xb9851c35
+0,      25344,      25344,     1152,       72, 0x81d51936
+0,      26496,      26496,     1152,       72, 0xd0671c45
+0,      27648,      27648,     1152,       72, 0x9ce119d9
+0,      28800,      28800,     1152,       72, 0xbde81b9f
+0,      29952,      29952,     1152,       72, 0x9e131900
+0,      31104,      31104,     1152,       72, 0xaa621ba7
+0,      32256,      32256,     1152,       72, 0x76ab1842
+0,      33408,      33408,     1152,       72, 0xcc1f1c52
+0,      34560,      34560,     1152,       72, 0xd1991af3
+0,      35712,      35712,     1152,       72, 0x88301bf2
+0,      36864,      36864,     1152,       72, 0x9e8f1bb3
+0,      38016,      38016,     1152,       72, 0xc2911b4d
+0,      39168,      39168,     1152,       72, 0xd44d1b0b
+0,      40320,      40320,     1152,       72, 0x5d3f1906
+0,      41472,      41472,     1152,       72, 0xc5cb1bae
+0,      42624,      42624,     1152,       72, 0x60fa18f9
+0,      43776,      43776,     1152,       72, 0xb0e01be3
+0,      44928,      44928,     1152,       72, 0x4ccf1a2b
+0,      46080,      46080,     1152,       72, 0x96ba1b53
+0,      47232,      47232,     1152,       72, 0x832d1ae9
-- 
2.54.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to