Skip to content

Commit bd75425

Browse files
committed
Fix PTS underflow collapsing base_decode_time to zero
base_pts90k is set from the first published sample. When a subsequent sample arrives with a lower PTS the offset was silently clamped to 0, producing tfdt=0 in the moof. Two scenarios trigger this: - Small underflow (audio pre-roll / jitter): one or two frames at t=0 is harmless; keep the zero-clamp for this case. - 33-bit PTS rollover (~26.5 h): sample.pts90k wraps from near 2^33 back to zero while base_pts90k remains large, so every subsequent sample gets tfdt=0 and the decoder timeline collapses permanently. Fix: if the backward jump exceeds 2^32 ticks (~13 h, impossible as normal jitter) treat it as a rollover and reset base_pts90k to the new PTS. Duration tracking recovers naturally on the next frame via the existing last_pts / 500 ms clamp logic.
1 parent e465834 commit bd75425

1 file changed

Lines changed: 12 additions & 4 deletions

File tree

src/live_srt_ingest.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1400,11 +1400,19 @@ MediaFragment build_fragment_from_sample(const LiveSrtCallerRuntimeConfig& confi
14001400
state.base_pts90k = sample.pts90k;
14011401
}
14021402

1403-
// Compute base_decode_time from PTS relative to shared origin, converted
1404-
// to the track's timescale. This keeps audio and video in sync.
1403+
// Compute PTS offset from origin. Two cases where sample.pts90k < base_pts90k:
1404+
// Small underflow (audio pre-roll / jitter): clamp to 0 — one or two
1405+
// frames at t=0 is harmless.
1406+
// Large backward jump (>2^32 ticks, ~13 h): 33-bit PTS rollover or
1407+
// encoder restart — reset the origin so subsequent base_decode_time
1408+
// values stay non-zero and monotonically increasing.
14051409
const std::uint32_t timescale = sample.is_video ? state.video_timescale : state.audio_timescale;
1406-
const std::uint64_t pts_offset90k = sample.pts90k >= *state.base_pts90k
1407-
? sample.pts90k - *state.base_pts90k : 0;
1410+
std::uint64_t pts_offset90k = 0;
1411+
if (sample.pts90k >= *state.base_pts90k) {
1412+
pts_offset90k = sample.pts90k - *state.base_pts90k;
1413+
} else if (*state.base_pts90k - sample.pts90k > (1ULL << 32)) {
1414+
state.base_pts90k = sample.pts90k;
1415+
}
14081416
const std::uint64_t base_decode_time = (pts_offset90k * timescale + 45000ULL) / 90000ULL;
14091417

14101418
// AAC audio: always use exactly 1024 samples per frame in the audio timescale.

0 commit comments

Comments
 (0)