screencapturekit/cm/
time.rs1use std::ffi::c_void;
4use std::fmt;
5
6#[repr(C)]
26#[derive(Debug, Clone, Copy, PartialEq, Eq)]
27pub struct CMTime {
28 pub value: i64,
29 pub timescale: i32,
30 pub flags: u32,
31 pub epoch: i64,
32}
33
34impl std::hash::Hash for CMTime {
35 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
36 self.value.hash(state);
37 self.timescale.hash(state);
38 self.flags.hash(state);
39 self.epoch.hash(state);
40 }
41}
42
43#[repr(C)]
62#[derive(Debug, Clone, Copy, PartialEq, Eq)]
63pub struct CMSampleTimingInfo {
64 pub duration: CMTime,
65 pub presentation_time_stamp: CMTime,
66 pub decode_time_stamp: CMTime,
67}
68
69impl std::hash::Hash for CMSampleTimingInfo {
70 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
71 self.duration.hash(state);
72 self.presentation_time_stamp.hash(state);
73 self.decode_time_stamp.hash(state);
74 }
75}
76
77impl CMSampleTimingInfo {
78 pub const fn new() -> Self {
89 Self {
90 duration: CMTime::INVALID,
91 presentation_time_stamp: CMTime::INVALID,
92 decode_time_stamp: CMTime::INVALID,
93 }
94 }
95
96 pub const fn with_times(
98 duration: CMTime,
99 presentation_time_stamp: CMTime,
100 decode_time_stamp: CMTime,
101 ) -> Self {
102 Self {
103 duration,
104 presentation_time_stamp,
105 decode_time_stamp,
106 }
107 }
108
109 pub const fn is_valid(&self) -> bool {
111 self.duration.is_valid()
112 && self.presentation_time_stamp.is_valid()
113 && self.decode_time_stamp.is_valid()
114 }
115
116 pub const fn has_valid_presentation_time(&self) -> bool {
118 self.presentation_time_stamp.is_valid()
119 }
120
121 pub const fn has_valid_decode_time(&self) -> bool {
123 self.decode_time_stamp.is_valid()
124 }
125
126 pub const fn has_valid_duration(&self) -> bool {
128 self.duration.is_valid()
129 }
130
131 pub fn presentation_seconds(&self) -> Option<f64> {
133 self.presentation_time_stamp.as_seconds()
134 }
135
136 pub fn decode_seconds(&self) -> Option<f64> {
138 self.decode_time_stamp.as_seconds()
139 }
140
141 pub fn duration_seconds(&self) -> Option<f64> {
143 self.duration.as_seconds()
144 }
145}
146
147impl Default for CMSampleTimingInfo {
148 fn default() -> Self {
149 Self::new()
150 }
151}
152
153impl fmt::Display for CMSampleTimingInfo {
154 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
155 write!(
156 f,
157 "CMSampleTimingInfo(pts: {}, dts: {}, duration: {})",
158 self.presentation_time_stamp, self.decode_time_stamp, self.duration
159 )
160 }
161}
162
163impl CMTime {
164 pub const ZERO: Self = Self {
165 value: 0,
166 timescale: 0,
167 flags: 1,
168 epoch: 0,
169 };
170
171 pub const INVALID: Self = Self {
172 value: 0,
173 timescale: 0,
174 flags: 0,
175 epoch: 0,
176 };
177
178 pub const fn new(value: i64, timescale: i32) -> Self {
179 Self {
180 value,
181 timescale,
182 flags: 1,
183 epoch: 0,
184 }
185 }
186
187 pub const fn is_valid(&self) -> bool {
188 self.flags & 0x1 != 0
189 }
190
191 pub const fn is_zero(&self) -> bool {
193 self.value == 0 && self.is_valid()
194 }
195
196 pub const fn is_indefinite(&self) -> bool {
198 self.flags & 0x2 != 0
199 }
200
201 pub const fn is_positive_infinity(&self) -> bool {
203 self.flags & 0x4 != 0
204 }
205
206 pub const fn is_negative_infinity(&self) -> bool {
208 self.flags & 0x8 != 0
209 }
210
211 pub const fn has_been_rounded(&self) -> bool {
213 self.flags & 0x10 != 0
214 }
215
216 pub const fn equals(&self, other: &Self) -> bool {
218 if !self.is_valid() || !other.is_valid() {
219 return false;
220 }
221 self.value == other.value && self.timescale == other.timescale
222 }
223
224 pub const fn positive_infinity() -> Self {
226 Self {
227 value: 0,
228 timescale: 0,
229 flags: 0x5, epoch: 0,
231 }
232 }
233
234 pub const fn negative_infinity() -> Self {
236 Self {
237 value: 0,
238 timescale: 0,
239 flags: 0x9, epoch: 0,
241 }
242 }
243
244 pub const fn indefinite() -> Self {
246 Self {
247 value: 0,
248 timescale: 0,
249 flags: 0x3, epoch: 0,
251 }
252 }
253
254 pub fn as_seconds(&self) -> Option<f64> {
255 if self.is_valid() && self.timescale != 0 {
256 #[allow(clippy::cast_precision_loss)]
258 Some(self.value as f64 / f64::from(self.timescale))
259 } else {
260 None
261 }
262 }
263}
264
265impl Default for CMTime {
266 fn default() -> Self {
267 Self::INVALID
268 }
269}
270
271impl fmt::Display for CMTime {
272 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
273 if let Some(seconds) = self.as_seconds() {
274 write!(f, "{seconds:.3}s")
275 } else {
276 write!(f, "invalid")
277 }
278 }
279}
280
281pub struct CMClock {
286 ptr: *const c_void,
287}
288
289impl PartialEq for CMClock {
290 fn eq(&self, other: &Self) -> bool {
291 self.ptr == other.ptr
292 }
293}
294
295impl Eq for CMClock {}
296
297impl std::hash::Hash for CMClock {
298 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
299 self.ptr.hash(state);
300 }
301}
302
303impl CMClock {
304 pub fn from_raw(ptr: *const c_void) -> Option<Self> {
306 if ptr.is_null() {
307 None
308 } else {
309 Some(Self { ptr })
310 }
311 }
312
313 #[allow(dead_code)]
318 pub(crate) fn from_ptr(ptr: *const c_void) -> Self {
319 Self { ptr }
320 }
321
322 pub fn as_ptr(&self) -> *const c_void {
324 self.ptr
325 }
326
327 pub fn time(&self) -> CMTime {
332 CMTime::INVALID
335 }
336}
337
338impl Drop for CMClock {
339 fn drop(&mut self) {
340 if !self.ptr.is_null() {
341 extern "C" {
343 fn CFRelease(cf: *const c_void);
344 }
345 unsafe {
346 CFRelease(self.ptr);
347 }
348 }
349 }
350}
351
352impl Clone for CMClock {
353 fn clone(&self) -> Self {
354 if self.ptr.is_null() {
355 Self {
356 ptr: std::ptr::null(),
357 }
358 } else {
359 extern "C" {
360 fn CFRetain(cf: *const c_void) -> *const c_void;
361 }
362 unsafe {
363 Self {
364 ptr: CFRetain(self.ptr),
365 }
366 }
367 }
368 }
369}
370
371impl std::fmt::Debug for CMClock {
372 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
373 f.debug_struct("CMClock").field("ptr", &self.ptr).finish()
374 }
375}
376
377impl fmt::Display for CMClock {
378 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
379 if self.ptr.is_null() {
380 write!(f, "CMClock(null)")
381 } else {
382 write!(f, "CMClock({:p})", self.ptr)
383 }
384 }
385}
386
387unsafe impl Send for CMClock {}
389unsafe impl Sync for CMClock {}