Skip to content

Commit

Permalink
MediaTime: document the interface
Browse files Browse the repository at this point in the history
  • Loading branch information
david-flok authored and algesten committed Nov 27, 2023
1 parent d4b0c70 commit 7565523
Showing 1 changed file with 35 additions and 8 deletions.
43 changes: 35 additions & 8 deletions src/rtp/mtime.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#![allow(missing_docs)]

use std::cmp::Ordering;
use std::fmt::Display;
use std::num::{NonZeroU32, TryFromIntError};
Expand All @@ -10,8 +8,9 @@ use std::time::Instant;

use serde::{Deserialize, Serialize};

use crate::util::InstantExt;

/// Media timeline frequency as represented by a non-zero unsigned integer.
///
///
#[derive(Debug, Clone, Copy, Serialize)]
pub struct Frequency(NonZeroU32);

Expand All @@ -37,26 +36,30 @@ impl Frequency {
/// Seconds in a second.
pub const SECONDS: Frequency = Self::make(1);

/// Private unconditional non-zero constructor for use with constants
/// Private unconditional non-zero constructor for use with constants.
const fn make(v: u32) -> Frequency {
match NonZeroU32::new(v) {
Some(v) => Self(v),
None => panic!("assured non-zero value is zero"),
}
}

/// Any non-zero u32 is a valid media timeline frequency.
pub const fn from_nonzero(v: NonZeroU32) -> Self {
Self(v)
}

/// Every u32 is a valid media timeline frequency except zero.
pub fn new(v: u32) -> Option<Self> {
NonZeroU32::new(v).map(Self)
}

/// The frequency as a u32.
pub const fn get(&self) -> u32 {
self.0.get()
}

/// The frequency as a [`std::num::NonZeroU32`] i.e. including a positivity proof.
pub const fn nonzero(&self) -> NonZeroU32 {
self.0
}
Expand Down Expand Up @@ -104,85 +107,105 @@ impl<'de> Deserialize<'de> for Frequency {
}
}

/// Media time represented by a numerator / denominator.
/// Media timeline offset represented by a count (numerator) /
/// frequency (denominator) in seconds.
///
/// The numerator is typically the packet time of an Rtp header. The denominator is the
/// clock frequency of the media source (typically 90kHz for video and 48kHz for audio).
/// The numerator is typically the packet time of an Rtp header. The
/// denominator is the clock frequency of the media source (typically
/// 90kHz for video and 48kHz for audio). The denominator is
/// guaranteed to be a positive integer while the numerator could be
/// positive, negative, or zero.
#[derive(Debug, Clone, Copy)]
pub struct MediaTime(i64, Frequency);

impl MediaTime {
/// The additive identity: 0/1.
pub const ZERO: MediaTime = MediaTime::from_secs(0);

/// Construct a [`MediaTime`] from a guaranteed non-zero [`Frequency`].
pub const fn new(numer: i64, denom: Frequency) -> Self {
Self(numer, denom)
}

/// The numerator of the offset time.
#[inline(always)]
pub const fn numer(&self) -> i64 {
self.0
}

/// The denominator of the offset time.
#[inline(always)]
pub const fn denom(&self) -> u32 {
self.1.get()
}

/// The [`Frequency`] of the offset time.
#[inline(always)]
pub const fn frequency(&self) -> Frequency {
self.1
}

/// Convenience constructor for numbers of microseconds (v/1_000_000).
#[inline(always)]
pub const fn from_micros(v: i64) -> MediaTime {
MediaTime(v, Frequency::MICROS)
}

/// Convenience constructor for numbers of 24-bit 6.18 fixed point units (v/2^18).
#[inline(always)]
pub const fn from_fixed_point_6_18(v: i64) -> MediaTime {
MediaTime(v, Frequency::FIXED_POINT_6_18)
}

/// Convenience constructor for numbers of 90kHz units (v/90_000).
#[inline(always)]
pub const fn from_90khz(v: i64) -> MediaTime {
MediaTime(v, Frequency::NINETY_KHZ)
}

/// Convenience constructor for numbers of milliseconds (v/1000).
#[inline(always)]
pub const fn from_millis(v: i64) -> MediaTime {
MediaTime(v, Frequency::MILLIS)
}

/// Convenience constructor for numbers of hundredths of seconds (v/100).
#[inline(always)]
pub const fn from_hundredths(v: i64) -> MediaTime {
MediaTime(v, Frequency::HUNDREDTHS)
}

/// Convenience constructor for numbers of seconds (v/1).
#[inline(always)]
pub const fn from_secs(v: i64) -> MediaTime {
MediaTime(v, Frequency::SECONDS)
}

/// Convenience constructor for floating point fractions of seconds as microsecond units.
#[inline(always)]
pub fn from_seconds(v: impl Into<f64>) -> MediaTime {
Self::from_micros((v.into() * 1_000_000.0_f64) as i64)
}

/// A floating point fraction second representation.
#[inline(always)]
pub fn as_seconds(&self) -> f64 {
let denom: f64 = self.1.get().into();
self.0 as f64 / denom
}

/// A microsecond representation.
pub const fn as_micros(&self) -> i64 {
self.rebase(Frequency::MICROS).numer()
}

/// Predicate for checking that the numerator is 0.
#[inline(always)]
pub const fn is_zero(&self) -> bool {
self.0 == 0
}

/// The absolute value of the offset time.
#[inline(always)]
pub const fn abs(mut self) -> MediaTime {
if self.0 < 0 {
Expand All @@ -191,6 +214,10 @@ impl MediaTime {
self
}

/// Convert this offset time to have a different denominator
/// (frequency). This conversion may lose precision and, after
/// arithmetic operations with other times of higher frequencies,
/// may have a higher frequency.
#[inline(always)]
pub const fn rebase(self, denom: Frequency) -> MediaTime {
if denom.get() == self.1.get() {
Expand Down

0 comments on commit 7565523

Please sign in to comment.