ndi_sdk_sys/
timecode.rs

1use std::time::{Duration, SystemTime};
2
3use static_assertions::{const_assert, const_assert_eq};
4
5use crate::bindings;
6
7/// This is the timecode of this frame in 100 ns intervals.
8/// This is generally not used internally by the SDK but is passed through to applications which may interpret it as they wish.
9/// When sending data, a value of [NDITime::SYNTHESIZE] (C: `NDIlib_send_timecode_synthesize`) can be specified (and should be the default), the operation of this value is documented in the sending section of this documentation.
10///
11/// [NDITime::SYNTHESIZE] will yield UTC time in 100 ns intervals since the Unix Time Epoch 1/1/1970 00:00.
12/// When interpreting this timecode, a receiving application may choose to localize the time of day based on time zone offset, which can optionally be communicated by the sender in connection metadata.
13///
14/// Since the timecode is stored in UTC within NDI, communicating timecode time of day for non-UTC time zones requires a translation.
15#[repr(transparent)]
16#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
17pub struct NDITime(i64);
18
19const NDI_TIME_DEFAULT: i64 = i64::MAX;
20
21const_assert_eq!(NDI_TIME_DEFAULT, bindings::NDIlib_recv_timestamp_undefined);
22const_assert_eq!(NDI_TIME_DEFAULT, bindings::NDIlib_send_timecode_synthesize);
23
24impl Default for NDITime {
25    fn default() -> Self {
26        Self(NDI_TIME_DEFAULT)
27    }
28}
29
30impl NDITime {
31    #[inline]
32    pub fn to_ffi(self) -> i64 {
33        self.0
34    }
35
36    #[inline]
37    pub fn from_ffi(time: i64) -> Self {
38        Self(time)
39    }
40
41    /// **This API is unstable**
42    ///
43    /// Converts this timestamp to [SystemTime]
44    pub fn to_utc(self) -> Option<SystemTime> {
45        fn to_duration(time: u64) -> Duration {
46            let secs = time / 10_000_000;
47            let sub_100ns = time % 10_000_000;
48
49            const_assert!(10_000_000 < i32::MAX);
50
51            let nanos = (sub_100ns * 100) as u32;
52
53            Duration::new(secs, nanos)
54        }
55
56        if self.is_default() {
57            None
58        } else {
59            Some(if self.0 >= 0 {
60                SystemTime::UNIX_EPOCH + to_duration(self.0 as u64)
61            } else {
62                SystemTime::UNIX_EPOCH - to_duration(self.0.saturating_abs() as u64)
63            })
64        }
65    }
66
67    pub fn is_default(self) -> bool {
68        self.0 == NDI_TIME_DEFAULT
69    }
70
71    pub const UNDEFINED: Self = Self(NDI_TIME_DEFAULT);
72    /// Advises the SDK to automatically generate a timecode for this frame from the system clock
73    pub const SYNTHESIZE: Self = Self(NDI_TIME_DEFAULT);
74}