|
3 | 3 | use std::ffi::c_void; |
4 | 4 | use std::fmt; |
5 | 5 |
|
6 | | -/// `CMTime` representation matching Core Media's `CMTime` |
7 | | -/// |
8 | | -/// Represents a rational time value with a 64-bit numerator and 32-bit denominator. |
9 | | -/// |
10 | | -/// # Examples |
11 | | -/// |
12 | | -/// ``` |
13 | | -/// use screencapturekit::cm::CMTime; |
14 | | -/// |
15 | | -/// // Create a time of 1 second (30/30) |
16 | | -/// let time = CMTime::new(30, 30); |
17 | | -/// assert_eq!(time.as_seconds(), Some(1.0)); |
18 | | -/// |
19 | | -/// // Create a time of 2.5 seconds at 1000 Hz timescale |
20 | | -/// let time = CMTime::new(2500, 1000); |
21 | | -/// assert_eq!(time.value, 2500); |
22 | | -/// assert_eq!(time.timescale, 1000); |
23 | | -/// assert_eq!(time.as_seconds(), Some(2.5)); |
24 | | -/// ``` |
25 | | -#[repr(C)] |
26 | | -#[derive(Debug, Clone, Copy, PartialEq, Eq)] |
27 | | -pub struct CMTime { |
28 | | - pub value: i64, |
29 | | - pub timescale: i32, |
30 | | - pub flags: u32, |
31 | | - pub epoch: i64, |
32 | | -} |
33 | | - |
34 | | -impl 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 | | -} |
| 6 | +pub use apple_cf::cm::CMTime; |
42 | 7 |
|
43 | 8 | /// Sample timing information |
44 | 9 | /// |
@@ -160,124 +125,6 @@ impl fmt::Display for CMSampleTimingInfo { |
160 | 125 | } |
161 | 126 | } |
162 | 127 |
|
163 | | -impl 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 | | - /// Check if this time represents zero |
192 | | - pub const fn is_zero(&self) -> bool { |
193 | | - self.value == 0 && self.is_valid() |
194 | | - } |
195 | | - |
196 | | - /// Check if this time is indefinite |
197 | | - pub const fn is_indefinite(&self) -> bool { |
198 | | - self.flags & 0x2 != 0 |
199 | | - } |
200 | | - |
201 | | - /// Check if this time is positive infinity |
202 | | - pub const fn is_positive_infinity(&self) -> bool { |
203 | | - self.flags & 0x4 != 0 |
204 | | - } |
205 | | - |
206 | | - /// Check if this time is negative infinity |
207 | | - pub const fn is_negative_infinity(&self) -> bool { |
208 | | - self.flags & 0x8 != 0 |
209 | | - } |
210 | | - |
211 | | - /// Check if this time has been rounded |
212 | | - pub const fn has_been_rounded(&self) -> bool { |
213 | | - self.flags & 0x10 != 0 |
214 | | - } |
215 | | - |
216 | | - /// Compare two times for equality (value and timescale) |
217 | | - 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 | | - /// Create a time representing positive infinity |
225 | | - pub const fn positive_infinity() -> Self { |
226 | | - Self { |
227 | | - value: 0, |
228 | | - timescale: 0, |
229 | | - flags: 0x5, // kCMTimeFlags_Valid | kCMTimeFlags_PositiveInfinity |
230 | | - epoch: 0, |
231 | | - } |
232 | | - } |
233 | | - |
234 | | - /// Create a time representing negative infinity |
235 | | - pub const fn negative_infinity() -> Self { |
236 | | - Self { |
237 | | - value: 0, |
238 | | - timescale: 0, |
239 | | - flags: 0x9, // kCMTimeFlags_Valid | kCMTimeFlags_NegativeInfinity |
240 | | - epoch: 0, |
241 | | - } |
242 | | - } |
243 | | - |
244 | | - /// Create an indefinite time |
245 | | - pub const fn indefinite() -> Self { |
246 | | - Self { |
247 | | - value: 0, |
248 | | - timescale: 0, |
249 | | - flags: 0x3, // kCMTimeFlags_Valid | kCMTimeFlags_Indefinite |
250 | | - epoch: 0, |
251 | | - } |
252 | | - } |
253 | | - |
254 | | - pub fn as_seconds(&self) -> Option<f64> { |
255 | | - if self.is_valid() && self.timescale != 0 { |
256 | | - // Precision loss is acceptable for time conversion to seconds |
257 | | - #[allow(clippy::cast_precision_loss)] |
258 | | - Some(self.value as f64 / f64::from(self.timescale)) |
259 | | - } else { |
260 | | - None |
261 | | - } |
262 | | - } |
263 | | -} |
264 | | - |
265 | | -impl Default for CMTime { |
266 | | - fn default() -> Self { |
267 | | - Self::INVALID |
268 | | - } |
269 | | -} |
270 | | - |
271 | | -impl 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 | | - |
281 | 128 | /// `CMClock` wrapper for synchronization clock |
282 | 129 | /// |
283 | 130 | /// Represents a Core Media clock used for time synchronization. |
|
0 commit comments