Skip to content

Commit fd30b14

Browse files
committed
Add checked_duration_since for timestamp types
1 parent 05f39bb commit fd30b14

File tree

4 files changed

+49
-4
lines changed

4 files changed

+49
-4
lines changed

crates/recording/src/output_pipeline/core.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -464,10 +464,12 @@ fn spawn_video_encoder<TMutex: VideoMuxer<VideoFrame = TVideo::Frame>, TVideo: V
464464
let _ = first_tx.send(timestamp);
465465
}
466466

467+
let duration = timestamp.checked_duration_since(timestamps).unwrap_or(Duration::ZERO);
468+
467469
muxer
468470
.lock()
469471
.await
470-
.send_video_frame(frame, timestamp.duration_since(timestamps))
472+
.send_video_frame(frame, duration)
471473
.map_err(|e| anyhow!("Error queueing video frame: {e}"))?;
472474
}
473475

@@ -476,12 +478,16 @@ fn spawn_video_encoder<TMutex: VideoMuxer<VideoFrame = TVideo::Frame>, TVideo: V
476478
})
477479
.await;
478480

481+
muxer.lock().await.stop();
482+
483+
if let Some(Err(e)) = res {
484+
return Err(e);
485+
}
486+
479487
if res.is_none() {
480488
info!("mux-video cancelled");
481489
}
482490

483-
muxer.lock().await.stop();
484-
485491
Ok(())
486492
});
487493
}
@@ -512,7 +518,7 @@ impl PreparedAudioSources {
512518
let _ = first_tx.send(frame.timestamp);
513519
}
514520

515-
let timestamp = frame.timestamp.duration_since(timestamps);
521+
let timestamp = frame.timestamp.checked_duration_since(timestamps).unwrap_or(Duration::ZERO);
516522
if let Err(e) = muxer.lock().await.send_audio_frame(frame, timestamp) {
517523
error!("Audio encoder: {e}");
518524
}

crates/timestamp/src/lib.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,17 @@ impl Timestamp {
3232
}
3333
}
3434

35+
pub fn checked_duration_since(&self, start: Timestamps) -> Option<Duration> {
36+
match self {
37+
Self::Instant(instant) => instant.checked_duration_since(start.instant),
38+
Self::SystemTime(time) => time.duration_since(start.system_time).ok(),
39+
#[cfg(windows)]
40+
Self::PerformanceCounter(counter) => counter.checked_duration_since(start.performance_counter),
41+
#[cfg(target_os = "macos")]
42+
Self::MachAbsoluteTime(time) => time.checked_duration_since(start.mach_absolute_time),
43+
}
44+
}
45+
3546
pub fn from_cpal(instant: cpal::StreamInstant) -> Self {
3647
#[cfg(windows)]
3748
{

crates/timestamp/src/macos.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,15 @@ impl MachAbsoluteTimestamp {
3030
Duration::from_nanos((diff as f64 * freq) as u64)
3131
}
3232

33+
pub fn checked_duration_since(&self, other: Self) -> Option<Duration> {
34+
let info = TimeBaseInfo::new();
35+
let freq = info.numer as f64 / info.denom as f64;
36+
37+
let diff = self.0.checked_sub(other.0)?;
38+
39+
Some(Duration::from_nanos((diff as f64 * freq) as u64))
40+
}
41+
3342
pub fn from_cpal(instant: cpal::StreamInstant) -> Self {
3443
use cpal::host::coreaudio::StreamInstantExt;
3544

crates/timestamp/src/win.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,25 @@ impl PerformanceCounterTimestamp {
4646
}
4747
}
4848

49+
pub fn checked_duration_since(&self, other: Self) -> Option<Duration> {
50+
let freq = perf_freq() as i128;
51+
debug_assert!(freq > 0);
52+
53+
let diff = self.0 as i128 - other.0 as i128;
54+
55+
if diff < 0 {
56+
None
57+
} else {
58+
let diff = diff as u128;
59+
let freq = freq as u128;
60+
61+
let secs = diff / freq;
62+
let nanos = ((diff % freq) * 1_000_000_000u128) / freq;
63+
64+
Some(Duration::new(secs as u64, nanos as u32))
65+
}
66+
}
67+
4968
pub fn now() -> Self {
5069
let mut value = 0;
5170
unsafe { QueryPerformanceCounter(&mut value).unwrap() };

0 commit comments

Comments
 (0)