Commit be65e08c18 for ffmpeg

commit be65e08c1873541932b43938858aa8d50a5efc41
Author: Romain Beauxis <romain.beauxis@gmail.com>
Date:   Mon Nov 2 23:45:02 2026 -0600

    avformat/mov: ignore discarded streams when placing the fragment position on seek

    With seek_individually, the last stream seeked sets next_root_atom, so a chapter track whose samples all sit in the first fragment makes mov_read_packet() read every fragment from the start of the file before it reaches the seeked sample.

    Resume reading from the earliest fragment any stream that is read landed in, which keeps the fragments that a lagging audio track still needs and ignores the chapter track.

    The seek in fate-mov-mp4-frag-chapters-seek no longer restarts from the beginning of the file.

diff --git a/libavformat/mov.c b/libavformat/mov.c
index 786994699e..c7e6164d5e 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -13196,21 +13196,31 @@ static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_ti
     if (mc->seek_individually) {
         /* adjust seek timestamp to found sample timestamp */
         int64_t seek_timestamp = sti->index_entries[sample].timestamp;
+        int64_t next_root_atom = mc->next_root_atom;
         sti->skip_samples = mov_get_skip_samples(st, sample);

         for (i = 0; i < s->nb_streams; i++) {
             AVStream *const st  = s->streams[i];
             FFStream *const sti = ffstream(st);
+            const MOVStreamContext *sc = st->priv_data;
             int64_t timestamp;

             if (stream_index == i)
                 continue;

+            mc->next_root_atom = 0;
             timestamp = av_rescale_q(seek_timestamp, s->streams[stream_index]->time_base, st->time_base);
             sample = mov_seek_stream(s, st, timestamp, flags);
             if (sample >= 0)
                 sti->skip_samples = mov_get_skip_samples(st, sample);
+
+            /* Reading resumes from the earliest fragment a read stream landed
+             * in; a discarded chapter track would send it back to the start. */
+            if ((st->discard != AVDISCARD_ALL || sc->iamf) && mc->next_root_atom &&
+                (!next_root_atom || mc->next_root_atom < next_root_atom))
+                next_root_atom = mc->next_root_atom;
         }
+        mc->next_root_atom = next_root_atom;
     } else {
         for (i = 0; i < s->nb_streams; i++) {
             MOVStreamContext *sc;
diff --git a/tests/ref/fate/mov-mp4-frag-chapters-seek b/tests/ref/fate/mov-mp4-frag-chapters-seek
index efe720ef6a..5ce82fc604 100644
--- a/tests/ref/fate/mov-mp4-frag-chapters-seek
+++ b/tests/ref/fate/mov-mp4-frag-chapters-seek
@@ -19,43 +19,43 @@
 1,       3072,       3072,     1024,     2048, 0x487e06b5
 0,       1024,       1024,      512,      829, 0x46b18019, F=0x0
 1,       4096,       4096,     1024,     2048, 0xb0abfcca
-packet|stream_index=0|pts=25600|dts=25600|pos=236536
-packet|stream_index=0|pts=26112|dts=26112|pos=237272
-packet|stream_index=0|pts=28160|dts=26624|pos=238079
-packet|stream_index=0|pts=27136|dts=27136|pos=239352
-packet|stream_index=0|pts=27648|dts=27648|pos=240188
-packet|stream_index=0|pts=29696|dts=28160|pos=241118
-packet|stream_index=0|pts=28672|dts=28672|pos=242466
-packet|stream_index=0|pts=29184|dts=29184|pos=243607
-packet|stream_index=0|pts=31232|dts=29696|pos=273736
-packet|stream_index=0|pts=30208|dts=30208|pos=276635
-packet|stream_index=0|pts=30720|dts=30720|pos=277656
-packet|stream_index=0|pts=32768|dts=31232|pos=278485
-packet|stream_index=0|pts=31744|dts=31744|pos=279502
-packet|stream_index=0|pts=32256|dts=32256|pos=280107
-packet|stream_index=0|pts=34304|dts=32768|pos=280520
-packet|stream_index=0|pts=33280|dts=33280|pos=281788
-packet|stream_index=0|pts=33792|dts=33792|pos=282441
-packet|stream_index=0|pts=35840|dts=34304|pos=282996
-packet|stream_index=0|pts=34816|dts=34816|pos=284827
-packet|stream_index=0|pts=35328|dts=35328|pos=285896
-packet|stream_index=0|pts=37376|dts=35840|pos=286902
-packet|stream_index=0|pts=36352|dts=36352|pos=288215
-packet|stream_index=0|pts=36864|dts=36864|pos=288973
-packet|stream_index=0|pts=38912|dts=37376|pos=289697
-packet|stream_index=0|pts=37888|dts=37888|pos=290988
-packet|stream_index=0|pts=38400|dts=38400|pos=291953
-packet|stream_index=0|pts=40448|dts=38912|pos=292850
-packet|stream_index=0|pts=39424|dts=39424|pos=294160
-packet|stream_index=0|pts=39936|dts=39936|pos=295139
-packet|stream_index=0|pts=41984|dts=40448|pos=296050
-packet|stream_index=0|pts=40960|dts=40960|pos=297337
-packet|stream_index=0|pts=41472|dts=41472|pos=298167
-packet|stream_index=0|pts=43520|dts=41984|pos=298944
-packet|stream_index=0|pts=42496|dts=42496|pos=388626
-packet|stream_index=0|pts=43008|dts=43008|pos=389534
-packet|stream_index=0|pts=45056|dts=43520|pos=390336
-packet|stream_index=0|pts=44032|dts=44032|pos=391448
-packet|stream_index=0|pts=44544|dts=44544|pos=392241
-packet|stream_index=0|pts=46592|dts=45056|pos=392933
-packet|stream_index=0|pts=45568|dts=45568|pos=394492
+packet|stream_index=0|pts=86016|dts=86016|pos=770777
+packet|stream_index=0|pts=88064|dts=86528|pos=771287
+packet|stream_index=0|pts=87040|dts=87040|pos=772624
+packet|stream_index=0|pts=87552|dts=87552|pos=773343
+packet|stream_index=0|pts=89600|dts=88064|pos=774048
+packet|stream_index=0|pts=88576|dts=88576|pos=775481
+packet|stream_index=0|pts=89088|dts=89088|pos=776166
+packet|stream_index=0|pts=91136|dts=89600|pos=776721
+packet|stream_index=0|pts=90112|dts=90112|pos=778386
+packet|stream_index=0|pts=90624|dts=90624|pos=779165
+packet|stream_index=1|pts=313060|dts=313060|pos=812468
+packet|stream_index=0|pts=92672|dts=91136|pos=814920
+packet|stream_index=0|pts=91648|dts=91648|pos=817387
+packet|stream_index=0|pts=92160|dts=92160|pos=818621
+packet|stream_index=0|pts=94208|dts=92672|pos=819771
+packet|stream_index=0|pts=93184|dts=93184|pos=821113
+packet|stream_index=0|pts=93696|dts=93696|pos=821708
+packet|stream_index=0|pts=95744|dts=94208|pos=822434
+packet|stream_index=0|pts=94720|dts=94720|pos=823800
+packet|stream_index=0|pts=95232|dts=95232|pos=824674
+packet|stream_index=0|pts=97280|dts=95744|pos=825469
+packet|stream_index=0|pts=96256|dts=96256|pos=826649
+packet|stream_index=0|pts=96768|dts=96768|pos=827376
+packet|stream_index=0|pts=98816|dts=97280|pos=828106
+packet|stream_index=0|pts=97792|dts=97792|pos=829733
+packet|stream_index=0|pts=98304|dts=98304|pos=830385
+packet|stream_index=0|pts=100352|dts=98816|pos=831077
+packet|stream_index=0|pts=99328|dts=99328|pos=832570
+packet|stream_index=0|pts=99840|dts=99840|pos=833090
+packet|stream_index=0|pts=101888|dts=100352|pos=833645
+packet|stream_index=0|pts=100864|dts=100864|pos=835372
+packet|stream_index=0|pts=101376|dts=101376|pos=836222
+packet|stream_index=0|pts=103424|dts=101888|pos=837066
+packet|stream_index=0|pts=102400|dts=102400|pos=838452
+packet|stream_index=0|pts=102912|dts=102912|pos=838979
+packet|stream_index=0|pts=104960|dts=103424|pos=839752
+packet|stream_index=1|pts=314084|dts=314084|pos=841267
+packet|stream_index=1|pts=315108|dts=315108|pos=843315
+packet|stream_index=1|pts=316132|dts=316132|pos=845363
+packet|stream_index=1|pts=317156|dts=317156|pos=847411