57 lines
1.7 KiB
Rust
57 lines
1.7 KiB
Rust
|
|
#![forbid(unsafe_code)]
|
||
|
|
|
||
|
|
use std::sync::OnceLock;
|
||
|
|
use std::time::{Duration, Instant};
|
||
|
|
|
||
|
|
static CAPTURE_ORIGIN: OnceLock<Instant> = 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));
|
||
|
|
}
|
||
|
|
}
|