PR #24844 opened by dalecurtis URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24844 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24844.patch
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. >From 5f878cd0665be7dffaf00fb3c8ab2eb22ffd1d17 Mon Sep 17 00:00:00 2001 From: Dale Curtis <[email protected]> Date: Thu, 1 Oct 2026 22:23:56 +0000 Subject: [PATCH] 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. --- libavformat/oggparsevorbis.c | 29 ++++++++++++++++++++++++++--- tests/ref/fate/ogg-vorbis-ts-seek | 30 +++++++++++++++--------------- 2 files changed, 41 insertions(+), 18 deletions(-) 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] -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
