#![forbid(unsafe_code)] use std::sync::OnceLock; use std::time::{Duration, Instant}; static CAPTURE_ORIGIN: OnceLock = OnceLock::new(); fn origin() -> Instant { *CAPTURE_ORIGIN.get_or_init(Instant::now) } /// Return the shared live-capture timestamp for upstream camera/mic packets. /// /// Inputs: none. /// Outputs: microseconds elapsed since the relay child first stamped live media. /// Why: camera and microphone capture pipelines run independently, so they need /// one explicit common origin before the server can keep them on the same live /// call timeline. #[must_use] pub fn capture_pts_us() -> u64 { origin().elapsed().as_micros().min(u64::MAX as u128) as u64 } /// Measure how old one shared capture timestamp is right now. /// /// Inputs: a packet timestamp previously produced by `capture_pts_us`. /// Outputs: the elapsed age as a `Duration`. /// Why: upstream freshness telemetry should use the same shared live clock as /// packet timestamps so queue-age calculations stay honest. #[must_use] pub fn packet_age(pts_us: u64) -> Duration { Duration::from_micros(capture_pts_us().saturating_sub(pts_us)) } #[cfg(test)] mod tests { use super::{capture_pts_us, packet_age}; use std::time::Duration; #[test] fn capture_pts_us_monotonically_advances() { let first = capture_pts_us(); std::thread::sleep(Duration::from_millis(2)); let second = capture_pts_us(); assert!(second >= first); } #[test] fn packet_age_is_small_for_recent_packets() { let pts = capture_pts_us(); std::thread::sleep(Duration::from_millis(2)); let age = packet_age(pts); assert!(age >= Duration::from_millis(1)); assert!(age < Duration::from_secs(1)); } }