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]