Files

85 lines
2.7 KiB
C++

// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (C) 2026 steredbits and Pelagia contributors
// Tests of the PTS -> media position realignment after a seek.
//
// The "network" scenarios simulate a mocked source: the stream is
// reopened on the server side with startTimeTicks, and we do NOT assume the PTS
// restart from 0 - the offset is frozen at the first PTS received of the new
// generation.
#include "player/seek_offset.h"
#include "test_framework.h"
using player::SeekOffsetTracker;
// Local file: absolute PTS, the offset stays fixed whatever the seek.
static void test_absolute_source() {
SeekOffsetTracker tr;
tr.init(/*timestamps_absolute=*/true, /*static_offset_ms=*/0);
tr.on_seek(0);
CHECK_EQ(tr.media_time(0), 0);
CHECK_EQ(tr.media_time(40), 40);
// Seek to 600 s: av_seek_frame lands on the previous keyframe (598.2 s),
// the media position remains the PTS itself.
tr.on_seek(600000);
CHECK_EQ(tr.media_time(598200), 598200);
CHECK_EQ(tr.offset_ms(), 0);
}
// Local file whose container does not start at 0 (MPEG-TS, start_time
// 1.4 s): static offset -start_time to display a 0-based position.
static void test_absolute_source_with_start_time() {
SeekOffsetTracker tr;
tr.init(true, -1400);
tr.on_seek(0);
CHECK_EQ(tr.media_time(1400), 0);
CHECK_EQ(tr.media_time(1440), 40);
}
// Mocked "network" source, PTS restarting from 0 after the seek.
static void test_network_pts_restart_at_zero() {
SeekOffsetTracker tr;
tr.init(/*timestamps_absolute=*/false, 0);
tr.on_seek(0);
CHECK_EQ(tr.media_time(0), 0);
CHECK_EQ(tr.media_time(40), 40);
// Seek to 600 s: the server restarts the transcoding, first PTS = 0.
tr.on_seek(600000);
CHECK_EQ(tr.media_time(0), 600000);
CHECK_EQ(tr.media_time(40), 600040);
CHECK_EQ(tr.offset_ms(), 600000);
}
// Mocked "network" source, NON-zero PTS after the seek (TS muxer offset,
// transcoding that does not restart exactly from the target, etc.).
static void test_network_pts_nonzero_after_seek() {
SeekOffsetTracker tr;
tr.init(false, 0);
tr.on_seek(0);
CHECK_EQ(tr.media_time(1400), 0); // even the opening is realigned
CHECK_EQ(tr.media_time(1440), 40);
// Seek to 600 s: first PTS received 1.4 s -> offset 598.6 s.
tr.on_seek(600000);
CHECK_EQ(tr.media_time(1400), 600000);
CHECK_EQ(tr.media_time(1480), 600080);
CHECK_EQ(tr.offset_ms(), 598600);
// Second seek: the offset is frozen again on the new first PTS.
tr.on_seek(120000);
CHECK_EQ(tr.media_time(10000), 120000);
CHECK_EQ(tr.media_time(10040), 120040);
CHECK_EQ(tr.offset_ms(), 110000);
}
int main() {
test_absolute_source();
test_absolute_source_with_start_time();
test_network_pts_restart_at_zero();
test_network_pts_nonzero_after_seek();
return testfw::test_failures();
}