lesavka/testing/tests/support/live_capture_clock_shim.rs

83 lines
2.5 KiB
Rust
Raw Normal View History

use std::sync::{Mutex, OnceLock};
use std::time::{Duration, Instant};
fn capture_clock_origin() -> &'static Instant {
static ORIGIN: OnceLock<Instant> = OnceLock::new();
ORIGIN.get_or_init(Instant::now)
}
pub fn capture_pts_us() -> u64 {
capture_clock_origin().elapsed().as_micros() as u64
}
pub fn upstream_timing_trace_enabled() -> bool {
std::env::var("LESAVKA_UPSTREAM_TIMING_TRACE")
.ok()
.map(|value| {
let trimmed = value.trim();
!(trimmed.eq_ignore_ascii_case("0")
|| trimmed.eq_ignore_ascii_case("false")
|| trimmed.eq_ignore_ascii_case("no")
|| trimmed.eq_ignore_ascii_case("off"))
})
.unwrap_or(false)
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub struct RebasedSourcePts {
pub packet_pts_us: u64,
pub capture_now_us: u64,
pub source_pts_us: Option<u64>,
pub source_base_us: Option<u64>,
pub capture_base_us: Option<u64>,
pub used_source_pts: bool,
}
#[derive(Debug, Default)]
struct SourcePtsRebaserState {
source_base_us: Option<u64>,
capture_base_us: Option<u64>,
last_packet_pts_us: Option<u64>,
}
#[derive(Debug, Default)]
pub struct SourcePtsRebaser {
state: Mutex<SourcePtsRebaserState>,
}
impl SourcePtsRebaser {
pub fn rebase_or_now(&self, source_pts_us: Option<u64>, min_step_us: u64) -> RebasedSourcePts {
let capture_now_us = capture_pts_us();
let mut state = self
.state
.lock()
.expect("source pts rebaser mutex poisoned");
let mut packet_pts_us = capture_now_us;
let mut used_source_pts = false;
if let Some(source_pts_us) = source_pts_us {
let source_base_us = *state.source_base_us.get_or_insert(source_pts_us);
let capture_base_us = *state.capture_base_us.get_or_insert(capture_now_us);
packet_pts_us =
capture_base_us.saturating_add(source_pts_us.saturating_sub(source_base_us));
used_source_pts = true;
}
if let Some(last_packet_pts_us) = state.last_packet_pts_us
&& packet_pts_us <= last_packet_pts_us
{
packet_pts_us = last_packet_pts_us.saturating_add(min_step_us.max(1));
}
state.last_packet_pts_us = Some(packet_pts_us);
RebasedSourcePts {
packet_pts_us,
capture_now_us,
source_pts_us,
source_base_us: state.source_base_us,
capture_base_us: state.capture_base_us,
used_source_pts,
}
}
}