sheathe_core/time.rs
1//! Media timing primitives.
2//!
3//! All timestamps in sheathe are integers expressed in a per-stream
4//! [`Timescale`] (ticks per second), matching how ISO-BMFF and MPEG-TS carry
5//! time. Avoiding floating point keeps segment boundaries exact.
6
7/// Ticks-per-second for a stream's timeline (e.g. 90_000 for MPEG-TS video).
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
9pub struct Timescale(pub u32);
10
11impl Timescale {
12 /// A common video timescale (90 kHz), as used by MPEG-2 transport streams.
13 pub const MPEG_TS: Timescale = Timescale(90_000);
14
15 /// Convert a duration in this timescale to whole milliseconds (truncating).
16 pub fn to_millis(self, ticks: u64) -> u64 {
17 ticks.saturating_mul(1_000) / u64::from(self.0.max(1))
18 }
19}
20
21/// A value (timestamp or duration) paired with the [`Timescale`] it lives in.
22#[derive(Debug, Clone, Copy, PartialEq, Eq)]
23pub struct Scaled {
24 /// The raw tick count.
25 pub ticks: u64,
26 /// The timescale `ticks` are expressed in.
27 pub scale: Timescale,
28}
29
30impl Scaled {
31 /// Pair a tick count with its timescale.
32 pub fn new(ticks: u64, scale: Timescale) -> Self {
33 Self { ticks, scale }
34 }
35
36 /// Seconds as an `f64`, for display only — never for boundary math.
37 pub fn seconds(self) -> f64 {
38 self.ticks as f64 / f64::from(self.scale.0.max(1))
39 }
40}