[PR] avformat/oggdec: keep timestamps monotonic across a chain (PR #23987)
Romain Beauxis via ffmpeg-devel <[email protected]> Sun, 02 Aug 2026 19:16:53 -0000
| Newsgroups | gmane.comp.video.ffmpeg.devel |
|---|---|
| Message-ID | <178569821379.59.16995331196588308187@29965ddac10e> |
PR #23987 opened by Romain Beauxis (toots) URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23987 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23987.patch Granule positions restart at zero in every link, and ogg_replace_stream() dropped the timestamp the previous link had reached, so a packet taking its timestamp from its own page came out placed within its link rather than within the file. Carry that timestamp forward as the offset the new link starts at, and apply it where timestamps are handed out, since codec parsers derive lastpts from the raw granule and parseopus.c reads a value of exactly zero as the mark of a link having begun. >From bdbd98afbb00746d1fa0270c416d5cc89567cf9a Mon Sep 17 00:00:00 2001 From: Romain Beauxis <[email protected]> Date: Wed, 29 Jul 2026 08:57:43 -0500 Subject: [PATCH] avformat/oggdec: keep timestamps monotonic across a chain Granule positions restart at zero in every link, and ogg_replace_stream() dropped the timestamp the previous link had reached, so a packet taking its timestamp from its own page came out placed within its link rather than within the file. Carry that timestamp forward as the offset the new link starts at, and apply it where timestamps are handed out, since codec parsers derive lastpts from the raw granule and parseopus.c reads a value of exactly zero as the mark of a link having begun. --- libavformat/oggdec.c | 21 +++++++++++++++++---- libavformat/oggdec.h | 1 + 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/libavformat/oggdec.c b/libavformat/oggdec.c index 48279f2928..ba92754eae 100644 --- a/libavformat/oggdec.c +++ b/libavformat/oggdec.c @@ -239,6 +239,10 @@ static int ogg_replace_stream(AVFormatContext *s, uint32_t serial, char *magic, os->serial = serial; os->codec = codec; os->serial = serial; + /* Granule positions restart at zero in every link, so what the link that + * just ended reached is where the new one begins. */ + if (os->lastpts != AV_NOPTS_VALUE) + os->link_offset += os->lastpts; os->lastpts = 0; os->lastdts = 0; os->flags = 0; @@ -782,24 +786,33 @@ static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts) struct ogg *ogg = s->priv_data; struct ogg_stream *os = ogg->streams + idx; int64_t pts = AV_NOPTS_VALUE; + /* Shifting here, where timestamps are handed out, rather than where they + * are stored: codec parsers derive os->lastpts from the raw granule + * themselves, and parseopus.c reads a value of exactly zero as the mark of + * a link having begun. */ + int64_t offset = os->link_offset; if (dts) *dts = AV_NOPTS_VALUE; if (os->lastpts != AV_NOPTS_VALUE) { - pts = os->lastpts; + pts = os->lastpts + offset; os->lastpts = AV_NOPTS_VALUE; } if (os->lastdts != AV_NOPTS_VALUE) { if (dts) - *dts = os->lastdts; + *dts = os->lastdts + offset; os->lastdts = AV_NOPTS_VALUE; } if (os->page_end) { if (os->granule != -1LL) { - if (os->codec && os->codec->granule_is_start) + if (os->codec && os->codec->granule_is_start) { pts = ogg_gptopts(s, idx, os->granule, dts); - else + if (pts != AV_NOPTS_VALUE) + pts += offset; + if (dts && *dts != AV_NOPTS_VALUE) + *dts += offset; + } else os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts); os->granule = -1LL; } diff --git a/libavformat/oggdec.h b/libavformat/oggdec.h index 72f3d40c5a..337b625605 100644 --- a/libavformat/oggdec.h +++ b/libavformat/oggdec.h @@ -77,6 +77,7 @@ struct ogg_stream { uint64_t start_granule; int64_t lastpts; int64_t lastdts; + int64_t link_offset; ///< start of the current link on the file timeline int64_t sync_pos; ///< file offset of the first page needed to reconstruct the current packet int64_t page_pos; ///< file offset of the current page int flags; -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]