Skip to main content

Timestamp

Struct Timestamp 

Source
pub struct Timestamp { /* private fields */ }
Expand description

A presentation timestamp, expressed as a PTS value in units of an associated Timebase.

§Equality and ordering

Comparison is value-based (same instant compares equal even across different timebases): Timestamp(1000, 1/1000) equals Timestamp(90_000, 1/90_000). Hash hashes the reduced-form rational instant (pts · num, den), so equal timestamps hash the same.

Cross-timebase comparisons use 128-bit cross-multiplication — no division, no rounding error. Same-timebase comparisons take a fast path on pts, except under a degenerate 0/den timebase, where every PTS names instant zero and the counts therefore say nothing about the instants: those fall back to the cross-multiply, and all of them compare equal.

This type is the one of the three that has an Ord, and it is Self::cmp_semantic — instants are totally ordered by when they are, which is the only reading of “before” a timestamp has, so there is nothing for a derived order to disagree with. SignedDuration and TimeRange each have a second reading and therefore no Ord at all.

Implementations§

Source§

impl Timestamp

Source

pub fn parse_seconds( text: &str, timebase: Timebase, rounding: Rounding, ) -> Result<Timestamp, ParseSecondsError>

Reads decimal seconds — 12.5, -0.040, 3 — as an instant counted in timebase, from PTS zero.

The digits are read exactly, as integers, never through a float: 0.1 is one tenth of a second, not the double nearest it. Seconds that land on a tick of timebase are that tick under every rounding; seconds between two ticks go where rounding says — or, under Rounding::Exact, are refused by name, with ParseSecondsError::BetweenTicks.

use mediatime::{ParseSecondsError, Rounding, Timebase, Timestamp};

let ntsc = Timebase::NTSC_VIDEO; // 1001/30000 s per frame
// 1.001 s is 30 frames exactly; 1 s is 29.97 frames.
let at = Timestamp::parse_seconds("1.001", ntsc, Rounding::Exact);
assert_eq!(at, Ok(Timestamp::new(30, ntsc)));
let start = Timestamp::parse_seconds("1", ntsc, Rounding::Ceil);
assert_eq!(start, Ok(Timestamp::new(30, ntsc)));
assert_eq!(
  Timestamp::parse_seconds("1", ntsc, Rounding::Exact),
  Err(ParseSecondsError::BetweenTicks)
);

The grammar is one decimal number: an optional + or -, one or more ASCII digits, and optionally a . followed by one or more digits. Surrounding whitespace is trimmed. There is no exponent, no digit separator, no bare .5 or 5., and no inf or NaN.

Nor is there a clock. The H:MM:SS.mmm form Timestamp’s Display writes is truncated to the millisecond and names no timebase, so it has no inverse — here or on the FromStr door — and a clock a person typed is a second grammar, sexagesimal, which a caller can turn into seconds before it gets here.

§Errors
Source§

impl Timestamp

Source

pub const fn new(pts: i64, timebase: Timebase) -> Timestamp

Creates a new Timestamp with the given PTS and timebase.

Source

pub const fn pts(&self) -> i64

Returns the presentation timestamp, in units of Self::timebase.

To obtain a StdDuration, use Self::duration_since against a reference timestamp, or rescale via Self::rescale_to.

Source

pub const fn timebase(&self) -> Timebase

Returns the timebase of the timestamp.

Source

pub const fn with_pts(self, pts: i64) -> Timestamp

Set the value of the presentation timestamp.

Source

pub const fn set_pts(&mut self, pts: i64) -> &mut Timestamp

Set the value of the presentation timestamp in place.

Source

pub const fn rescale_to(self, target: Timebase) -> Timestamp

Returns a new Timestamp representing the same instant in a different timebase.

Converts through Timebase::saturating_rescale, so the new PTS is the nearest tick of target (halfway cases away from zero); round-tripping through a coarser timebase can still lose precision.

§Panics

Panics if target.num() == 0, as Timebase::saturating_rescale does: a degenerate timebase names one instant, and cannot receive another.

Source

pub const fn checked_rescale_with( self, target: Timebase, rounding: Rounding, ) -> Option<Timestamp>

The same instant counted in target, rounded as rounding says, or None where Timebase::checked_rescale_with has no answer.

The road a trim takes: a start rescaled with Rounding::Ceil lands on the first tick of target at or after it, an end rescaled with Rounding::Floor on the last tick at or before it, so the trimmed stretch stays inside the one asked for. None for a PTS outside i64 in target, and for a degenerate target, which can count no instant — the refusals Self::rescale_to answers with a clamp and a panic.

Source

pub const fn saturating_sub_duration(self, d: Duration) -> Timestamp

Returns a new Timestamp representing this instant shifted backward by d, in the same timebase. Saturates at i64::MIN if the subtraction would underflow (pathological for real video).

Useful for “virtual past” seeding: e.g., initializing a warmup-filter state to ts - min_duration so the first detected cut can fire immediately.

§Panics

Panics if self.timebase().num() == 0, as Timebase::saturating_duration_to_pts does: a degenerate timebase spans no time per tick, so no tick count stands for d.

Source

pub const fn saturating_add_duration(self, d: Duration) -> Timestamp

Returns a new Timestamp representing this instant shifted forward by d, in the same timebase. Saturates at i64::MAX if the addition would overflow (pathological for real video).

The forward twin of Self::saturating_sub_duration: use it to close a window opened at self, e.g. ts + max_gap for the deadline a detector will stop waiting at.

Saturating in both steps, and only the second is visible in the result: Timebase::saturating_duration_to_pts itself saturates when d is enormous for this timebase, so a saturated answer can mean either “the duration did not fit” or “the sum did not”. Both say the same thing about the instant — it is past the end of what an i64 PTS can name.

§Panics

Panics if self.timebase().num() == 0, as Timebase::saturating_duration_to_pts does: a degenerate timebase spans no time per tick, so no tick count stands for d.

Source

pub const fn signed_duration_since(&self, other: &Timestamp) -> SignedDuration

The span from other to self, counted in self’s timebase — negative when other is the later instant.

Point minus point is a vector, which is why this is the subtraction two timestamps have and addition is not: an instant plus an instant names nothing. Self::duration_since is the same difference through the unsigned StdDuration, and refuses the direction this one reports.

Saturating in both steps: an other in a different timebase is rescaled into self’s first, to the nearest tick, and the difference clamps at i64::MIN/i64::MAX rather than wrapping. Self::checked_signed_duration_since is the rung that refuses instead of clamping.

§Panics

Panics if the timebases differ and self’s is degenerate, as Timebase::saturating_rescale does. Two instants counted in the same degenerate timebase are subtracted without a rescale, and without a panic.

Source

pub const fn checked_signed_duration_since( &self, other: &Timestamp, ) -> Option<SignedDuration>

The span from other to self in self’s timebase, or None if it is not an exact i64 count of its ticks.

The checked rung of Self::signed_duration_since: None where that one clamps or panics — other outside what self’s timebase can count, a difference outside i64, or a degenerate self timebase with a differing other.

Source

pub const fn checked_add_signed(self, d: SignedDuration) -> Option<Timestamp>

This instant shifted forward by the signed span d, or None if the result is not an i64 PTS in this timebase.

A d counted in another timebase is rescaled into this one first, so None also covers a span this timebase cannot count and a degenerate timebase that can count none. Shifting backward is Self::checked_sub_signed rather than a negated d, which i64::MIN ticks has no room for.

Named as u64::checked_add_signed is, and for the same reason: the operand is a signed offset, the receiver is not one.

Source

pub const fn saturating_add_signed(self, d: SignedDuration) -> Timestamp

This instant shifted forward by d, clamping at i64::MIN/i64::MAX instead of overflowing — the saturating rung of Self::checked_add_signed, saturating in the rescale of d as well as in the addition.

§Panics

Panics if d is counted in a different timebase and this one is degenerate, as Timebase::saturating_rescale does.

Source

pub const fn checked_sub_signed(self, d: SignedDuration) -> Option<Timestamp>

This instant shifted backward by the signed span d, or None if the result is not an i64 PTS in this timebase.

The mirror of Self::checked_add_signed, and not a negation of d: the most negative count has no positive twin, so subtracting it is reachable where negating it is not.

Source

pub const fn saturating_sub_signed(self, d: SignedDuration) -> Timestamp

This instant shifted backward by d, clamping at i64::MIN/i64::MAX instead of overflowing — the saturating rung of Self::checked_sub_signed.

§Panics

Panics if d is counted in a different timebase and this one is degenerate, as Timebase::saturating_rescale does.

Source

pub const fn cmp_semantic(&self, other: &Timestamp) -> Ordering

const fn form of Ord::cmp. Compares two timestamps by the instant they represent, rescaling if timebases differ.

Uses a 128-bit cross-multiply for the mixed-timebase case; no division, so no rounding error. Same-timebase comparisons take a direct fast path, the degenerate timebase excepted — see the guard at the site.

Source

pub const fn duration(&self) -> Option<Duration>

Returns the StdDuration from PTS zero (in this timebase) to self, or None if self.pts() < 0 (pre-roll / edit-list cases can produce negative PTS, which has no StdDuration representation).

Equivalent to self.duration_since(&Timestamp::new(0, self.timebase())). Under a degenerate 0/den timebase every PTS names instant zero, so the answer is StdDuration::ZERO for any count, a negative one included.

Source

pub const fn duration_since(&self, earlier: &Timestamp) -> Option<Duration>

Returns the elapsed StdDuration from earlier to self, or None if earlier is after self.

Works across different timebases. Computes the exact rational difference first using a common denominator, then truncates once when converting to nanoseconds for the returned StdDuration. If the result would exceed StdDuration::MAX (pathological: seconds don’t fit in u64), saturates to StdDuration::MAX rather than wrapping.

Trait Implementations§

Source§

impl Arbitrary for Timestamp

Source§

fn arbitrary(__quickcheck_g: &mut Gen) -> Timestamp

Return an arbitrary value. Read more
Source§

fn shrink(&self) -> Box<dyn Iterator<Item = Timestamp>>

Return an iterator of values that are smaller than itself. Read more
Source§

impl<'a> Arbitrary<'a> for Timestamp

Source§

fn arbitrary(u: &mut Unstructured<'a>) -> Result<Timestamp, Error>

Generate an arbitrary value of Self from the given unstructured data. Read more
Source§

fn arbitrary_take_rest(u: Unstructured<'a>) -> Result<Self, Error>

Generate an arbitrary value of Self from the entirety of the given unstructured data. Read more
Source§

fn size_hint(depth: usize) -> (usize, Option<usize>)

Get a size hint for how many bytes out of an Unstructured this type needs to construct itself. Read more
Source§

fn try_size_hint( depth: usize, ) -> Result<(usize, Option<usize>), MaxRecursionReached>

Get a size hint for how many bytes out of an Unstructured this type needs to construct itself. Read more
Source§

impl Clone for Timestamp

Source§

fn clone(&self) -> Timestamp

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for Timestamp

Source§

impl Debug for Timestamp

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Default for Timestamp

Source§

fn default() -> Timestamp

Returns the “default value” for a type. Read more
Source§

impl<'de> Deserialize<'de> for Timestamp

Source§

fn deserialize<__D>( __deserializer: __D, ) -> Result<Timestamp, <__D as Deserializer<'de>>::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Display for Timestamp

Writes the instant on the clock as H:MM:SS.mmm — 0:00:00.137 — so a log line reads as a time instead of as a division to carry out. video-rs prints the unreduced rational (12345/90000 secs) in the same position; the readable form is the default here because readable log messages are what the request this impl answers asked for, and the rational is still one # away.

Hours are unpadded and unbounded — 123:45:06.789 is a normal rendering, not an overflow. Minutes and seconds are two digits, milliseconds three. A negative PTS (pre-roll, or an edit list) signs the whole rendering: -0:00:01.500.

The instant is truncated toward zero at millisecond resolution, and deliberately not rounded the way the rescale ladder rounds (see Timebase::checked_rescale): a clock is read as elapsed time, and must not name an instant the stream has not reached yet. So this form is lossy twice over: below a millisecond nothing survives, and the timebase the PTS was counted in is not shown at all. One consequence is worth stating outright — a PTS smaller in magnitude than one millisecond renders 0:00:00.000 without a sign, because the value being printed is zero and a signed zero would claim a precision this form does not have.

{:#} is the exact form: the stored PTS beside its timebase, as 12345 @ 1/90000. So is the derived Debug. Being the exact one, {:#} is also the form FromStr reads back; the clock is lossy and has no inverse.

Width and alignment flags ({:>12}) are ignored, so this will not line a log up into columns: honouring them means measuring the finished string, and this crate has no alloc to build one in.

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Eq for Timestamp

Source§

impl FromStr for Timestamp

Parses pts @ num/den — the form Timestamp’s Display writes under {:#}.

Whitespace around each part is trimmed, so 12345@1/90000 parses as well as 12345 @ 1/90000. The default {} clock is not accepted: it is truncated to milliseconds and names no timebase, so it cannot name back the instant it was printed from.

§Errors

Returns ParseTimestampError if the @ is missing, if the PTS is not an i64, or if the timebase half is not one Timebase accepts.

Source§

type Err = ParseTimestampError

The associated error which can be returned from parsing.
Source§

fn from_str(s: &str) -> Result<Timestamp, <Timestamp as FromStr>::Err>

Parses a string s to return a value of this type. Read more
Source§

impl Hash for Timestamp

Source§

fn hash<H>(&self, state: &mut H)
where H: Hasher,

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl Ord for Timestamp

Source§

fn cmp(&self, other: &Timestamp) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 (const: unstable) · Source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 (const: unstable) · Source§

fn min(self, other: Self) -> Self
where Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 (const: unstable) · Source§

fn clamp(self, min: Self, max: Self) -> Self
where Self: Sized,

Restrict a value to a certain interval. Read more
Source§

fn clamp_to<R>(self, range: R) -> Self
where Self: Sized, R: ClampBounds<Self>,

🔬This is a nightly-only experimental API. (clamp_to)
Restrict a value to a certain range. Read more
Source§

impl PartialEq for Timestamp

Source§

fn eq(&self, other: &Timestamp) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl PartialOrd for Timestamp

Source§

fn partial_cmp(&self, other: &Timestamp) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 (const: unstable) · Source§

fn lt(&self, other: &Rhs) -> bool

Tests less than (for self and other) and is used by the < operator. Read more
1.0.0 (const: unstable) · Source§

fn le(&self, other: &Rhs) -> bool

Tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 (const: unstable) · Source§

fn gt(&self, other: &Rhs) -> bool

Tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 (const: unstable) · Source§

fn ge(&self, other: &Rhs) -> bool

Tests greater than or equal to (for self and other) and is used by the >= operator. Read more
Source§

impl Serialize for Timestamp

Source§

fn serialize<__S>( &self, __serializer: __S, ) -> Result<<__S as Serializer>::Ok, <__S as Serializer>::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.