screencapturekit/cm/
time.rs1use std::fmt;
4
5#[repr(C)]
25#[derive(Debug, Clone, Copy, PartialEq, Eq)]
26pub struct CMTime {
27 pub value: i64,
28 pub timescale: i32,
29 pub flags: u32,
30 pub epoch: i64,
31}
32
33impl std::hash::Hash for CMTime {
34 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
35 self.value.hash(state);
36 self.timescale.hash(state);
37 self.flags.hash(state);
38 self.epoch.hash(state);
39 }
40}
41
42#[repr(C)]
61#[derive(Debug, Clone, Copy, PartialEq, Eq)]
62pub struct CMSampleTimingInfo {
63 pub duration: CMTime,
64 pub presentation_time_stamp: CMTime,
65 pub decode_time_stamp: CMTime,
66}
67
68impl std::hash::Hash for CMSampleTimingInfo {
69 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
70 self.duration.hash(state);
71 self.presentation_time_stamp.hash(state);
72 self.decode_time_stamp.hash(state);
73 }
74}
75
76impl CMSampleTimingInfo {
77 pub const fn new() -> Self {
88 Self {
89 duration: CMTime::INVALID,
90 presentation_time_stamp: CMTime::INVALID,
91 decode_time_stamp: CMTime::INVALID,
92 }
93 }
94
95 pub const fn with_times(
97 duration: CMTime,
98 presentation_time_stamp: CMTime,
99 decode_time_stamp: CMTime,
100 ) -> Self {
101 Self {
102 duration,
103 presentation_time_stamp,
104 decode_time_stamp,
105 }
106 }
107
108 pub const fn is_valid(&self) -> bool {
110 self.duration.is_valid()
111 && self.presentation_time_stamp.is_valid()
112 && self.decode_time_stamp.is_valid()
113 }
114
115 pub const fn has_valid_presentation_time(&self) -> bool {
117 self.presentation_time_stamp.is_valid()
118 }
119
120 pub const fn has_valid_decode_time(&self) -> bool {
122 self.decode_time_stamp.is_valid()
123 }
124
125 pub const fn has_valid_duration(&self) -> bool {
127 self.duration.is_valid()
128 }
129
130 pub fn presentation_seconds(&self) -> Option<f64> {
132 self.presentation_time_stamp.as_seconds()
133 }
134
135 pub fn decode_seconds(&self) -> Option<f64> {
137 self.decode_time_stamp.as_seconds()
138 }
139
140 pub fn duration_seconds(&self) -> Option<f64> {
142 self.duration.as_seconds()
143 }
144}
145
146impl Default for CMSampleTimingInfo {
147 fn default() -> Self {
148 Self::new()
149 }
150}
151
152impl fmt::Display for CMSampleTimingInfo {
153 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
154 write!(
155 f,
156 "CMSampleTimingInfo(pts: {}, dts: {}, duration: {})",
157 self.presentation_time_stamp, self.decode_time_stamp, self.duration
158 )
159 }
160}
161
162impl CMTime {
163 pub const ZERO: Self = Self {
164 value: 0,
165 timescale: 0,
166 flags: 1,
167 epoch: 0,
168 };
169
170 pub const INVALID: Self = Self {
171 value: 0,
172 timescale: 0,
173 flags: 0,
174 epoch: 0,
175 };
176
177 pub const fn new(value: i64, timescale: i32) -> Self {
178 Self {
179 value,
180 timescale,
181 flags: 1,
182 epoch: 0,
183 }
184 }
185
186 pub const fn is_valid(&self) -> bool {
187 self.flags & 0x1 != 0
188 }
189
190 pub const fn is_zero(&self) -> bool {
192 self.value == 0 && self.is_valid()
193 }
194
195 pub const fn is_indefinite(&self) -> bool {
197 self.flags & 0x2 != 0
198 }
199
200 pub const fn is_positive_infinity(&self) -> bool {
202 self.flags & 0x4 != 0
203 }
204
205 pub const fn is_negative_infinity(&self) -> bool {
207 self.flags & 0x8 != 0
208 }
209
210 pub const fn has_been_rounded(&self) -> bool {
212 self.flags & 0x10 != 0
213 }
214
215 pub const fn equals(&self, other: &Self) -> bool {
217 if !self.is_valid() || !other.is_valid() {
218 return false;
219 }
220 self.value == other.value && self.timescale == other.timescale
221 }
222
223 pub const fn positive_infinity() -> Self {
225 Self {
226 value: 0,
227 timescale: 0,
228 flags: 0x5, epoch: 0,
230 }
231 }
232
233 pub const fn negative_infinity() -> Self {
235 Self {
236 value: 0,
237 timescale: 0,
238 flags: 0x9, epoch: 0,
240 }
241 }
242
243 pub const fn indefinite() -> Self {
245 Self {
246 value: 0,
247 timescale: 0,
248 flags: 0x3, epoch: 0,
250 }
251 }
252
253 pub fn as_seconds(&self) -> Option<f64> {
254 if self.is_valid() && self.timescale != 0 {
255 #[allow(clippy::cast_precision_loss)]
257 Some(self.value as f64 / f64::from(self.timescale))
258 } else {
259 None
260 }
261 }
262}
263
264impl Default for CMTime {
265 fn default() -> Self {
266 Self::INVALID
267 }
268}
269
270impl fmt::Display for CMTime {
271 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
272 if let Some(seconds) = self.as_seconds() {
273 write!(f, "{seconds:.3}s")
274 } else {
275 write!(f, "invalid")
276 }
277 }
278}