Commit b863390a8d for ffmpeg

commit b863390a8dab1c76d5ba07a38348f6330e31591e
Author: Dale Curtis <dalecurtis@chromium.org>
Date:   Mon Oct 12 18:52:50 2026 +0000

    lavf/oggparsevorbis: restore page-start timestamp calculation after seek

    Commit 63b7e4cefa91 removed the page duration scan in vorbis_packet()
    that ran when os->lastpts was unset. While that scan previously ran on
    every packet of a page and reset parser blocksize state during normal
    playback, removing it entirely left os->lastpts unset at the start of
    non-BOS pages after ogg_reset().

    As a result, ogg_read_timestamp() could not determine a page's start
    timestamp until advancing to the following page, and packets read from
    the start of a page after a seek were stamped with the seek target's
    cur_dts rather than the page start's timestamp.

    When os->lastpts is AV_NOPTS_VALUE at os->page_start on a non-BOS,
    non-EOS page, scan the remaining packets on the page to set os->lastpts
    to os->granule minus the page duration, and restore the parser blocksize
    state to the first packet afterwards.

    Fixes #24768.

diff --git a/libavformat/oggparsevorbis.c b/libavformat/oggparsevorbis.c
index a344081527..b4a1cfb509 100644
--- a/libavformat/oggparsevorbis.c
+++ b/libavformat/oggparsevorbis.c
@@ -478,10 +478,10 @@ static int vorbis_packet(AVFormatContext *s, int idx)

     bos = os->page_start && os->page_pos == priv->bos_page_pos;

-    if (bos) {
+    if (bos || (os->page_start && os->lastpts == AV_NOPTS_VALUE))
         av_vorbis_parse_reset(priv->vp);
+    if (bos)
         priv->last_page_granule = 0;
-    }

     duration = av_vorbis_parse_frame_flags(priv->vp, os->buf + os->pstart, 1, &flags);
     if (duration < 0) {
@@ -497,12 +497,35 @@ static int vorbis_packet(AVFormatContext *s, int idx)
     if (!priv->ts_offset)
         priv->ts_offset = os->pduration;

-    /* Initial position shift to account for encoder delay. */
+    /* Initial position shift to account for encoder delay, or page scan
+     * to recover the page start timestamp after a seek. */
     if (bos) {
         if (os->lastpts != AV_NOPTS_VALUE)
             os->lastpts -= priv->ts_offset;
         if (os->lastdts != AV_NOPTS_VALUE)
             os->lastdts -= priv->ts_offset;
+    } else if (os->page_start && os->lastpts == AV_NOPTS_VALUE &&
+               !(os->flags & OGG_FLAG_EOS) && (int64_t)os->granule >= 0) {
+        int seg, page_duration = os->pduration;
+        uint8_t *last_pkt = os->buf + os->pstart + os->psize;
+        uint8_t *next_pkt = last_pkt;
+
+        for (seg = os->segp; seg < os->nsegs; seg++) {
+            next_pkt += os->segments[seg];
+            if (os->segments[seg] < 255 && next_pkt != last_pkt) {
+                int pkt_flags = 0;
+                int d = av_vorbis_parse_frame_flags(priv->vp, last_pkt, 1, &pkt_flags);
+                if (d < 0) {
+                    page_duration = os->granule;
+                    break;
+                }
+                page_duration += d;
+                last_pkt = next_pkt;
+            }
+        }
+        av_vorbis_parse_frame_flags(priv->vp, os->buf + os->pstart, 1, &flags);
+        os->lastpts =
+        os->lastdts = os->granule - page_duration;
     }

     /* Broken files may have granule=0 on pages that contain audio data.
diff --git a/tests/ref/fate/ogg-vorbis-ts-seek b/tests/ref/fate/ogg-vorbis-ts-seek
index 00fd55dcdf..779dd1e995 100644
--- a/tests/ref/fate/ogg-vorbis-ts-seek
+++ b/tests/ref/fate/ogg-vorbis-ts-seek
@@ -1,31 +1,31 @@
 [PACKET]
-pts=89536
-dts=89536
-duration=128
+pts=44608
+dts=44608
+duration=1024
 flags=K__
 [/PACKET]
 [PACKET]
-pts=89664
-dts=89664
-duration=128
+pts=45632
+dts=45632
+duration=1024
 flags=K__
 [/PACKET]
 [PACKET]
-pts=89792
-dts=89792
-duration=128
+pts=46656
+dts=46656
+duration=1024
 flags=K__
 [/PACKET]
 [PACKET]
-pts=89920
-dts=89920
-duration=128
+pts=47680
+dts=47680
+duration=1024
 flags=K__
 [/PACKET]
 [PACKET]
-pts=90048
-dts=90048
-duration=128
+pts=48704
+dts=48704
+duration=1024
 flags=K__
 [/PACKET]
 [STREAM]
diff --git a/tests/ref/fate/ogg-vorbis-ts-seek-1.5s b/tests/ref/fate/ogg-vorbis-ts-seek-1.5s
index e5b6cd9a16..779dd1e995 100644
--- a/tests/ref/fate/ogg-vorbis-ts-seek-1.5s
+++ b/tests/ref/fate/ogg-vorbis-ts-seek-1.5s
@@ -1,30 +1,30 @@
 [PACKET]
-pts=66112
-dts=66112
+pts=44608
+dts=44608
 duration=1024
 flags=K__
 [/PACKET]
 [PACKET]
-pts=67136
-dts=67136
+pts=45632
+dts=45632
 duration=1024
 flags=K__
 [/PACKET]
 [PACKET]
-pts=68160
-dts=68160
+pts=46656
+dts=46656
 duration=1024
 flags=K__
 [/PACKET]
 [PACKET]
-pts=69184
-dts=69184
+pts=47680
+dts=47680
 duration=1024
 flags=K__
 [/PACKET]
 [PACKET]
-pts=70208
-dts=70208
+pts=48704
+dts=48704
 duration=1024
 flags=K__
 [/PACKET]