fix(sync): pace webcam timestamps by frame duration

This commit is contained in:
Brad Stein 2026-04-26 13:22:52 -03:00
parent 71b44521ef
commit 38ead8c1e9
7 changed files with 22 additions and 10 deletions

6
Cargo.lock generated
View File

@ -1642,7 +1642,7 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
[[package]]
name = "lesavka_client"
version = "0.14.2"
version = "0.14.3"
dependencies = [
"anyhow",
"async-stream",
@ -1676,7 +1676,7 @@ dependencies = [
[[package]]
name = "lesavka_common"
version = "0.14.2"
version = "0.14.3"
dependencies = [
"anyhow",
"base64",
@ -1688,7 +1688,7 @@ dependencies = [
[[package]]
name = "lesavka_server"
version = "0.14.2"
version = "0.14.3"
dependencies = [
"anyhow",
"base64",

View File

@ -4,7 +4,7 @@ path = "src/main.rs"
[package]
name = "lesavka_client"
version = "0.14.2"
version = "0.14.3"
edition = "2024"
[dependencies]

View File

@ -50,7 +50,8 @@ pub struct CameraCapture {
pipeline: gst::Pipeline,
sink: gst_app::AppSink,
preview_tap_running: Option<Arc<AtomicBool>>,
pts_rebaser: crate::live_capture_clock::SourcePtsRebaser,
pts_rebaser: crate::live_capture_clock::DurationPacedSourcePtsRebaser,
frame_duration_us: u64,
}
include!("camera/capture_pipeline.rs");

View File

@ -227,7 +227,8 @@ impl CameraCapture {
pipeline,
sink,
preview_tap_running,
pts_rebaser: crate::live_capture_clock::SourcePtsRebaser::default(),
pts_rebaser: crate::live_capture_clock::DurationPacedSourcePtsRebaser::default(),
frame_duration_us: (1_000_000u64 / u64::from(fps.max(1))).max(1),
})
}
@ -236,7 +237,15 @@ impl CameraCapture {
let buf = sample.buffer()?;
let map = buf.map_readable().ok()?;
let source_pts_us = buf.pts().map(|ts| ts.nseconds() / 1_000);
let timing = self.pts_rebaser.rebase_or_now(source_pts_us, 1);
let packet_duration_us = buf
.duration()
.map(|ts| (ts.nseconds() / 1_000).max(1))
.unwrap_or(self.frame_duration_us);
let timing = self.pts_rebaser.rebase_with_packet_duration(
source_pts_us,
packet_duration_us,
crate::live_capture_clock::upstream_source_lag_cap(),
);
let pts = timing.packet_pts_us;
static CAMERA_PACKET_COUNT: std::sync::atomic::AtomicU64 =
std::sync::atomic::AtomicU64::new(0);
@ -278,6 +287,7 @@ fn log_camera_timing_sample(
packet_pts_us = timing.packet_pts_us,
pull_path_delay_us = timing.capture_now_us as i128 - timing.packet_pts_us as i128,
used_source_pts = timing.used_source_pts,
lag_clamped = timing.lag_clamped,
bytes,
"📸 upstream webcam timing sample"
);

View File

@ -94,7 +94,8 @@ impl CameraCapture {
pipeline,
sink,
preview_tap_running: None,
pts_rebaser: crate::live_capture_clock::SourcePtsRebaser::default(),
pts_rebaser: crate::live_capture_clock::DurationPacedSourcePtsRebaser::default(),
frame_duration_us: 1,
}
}

View File

@ -1,6 +1,6 @@
[package]
name = "lesavka_common"
version = "0.14.2"
version = "0.14.3"
edition = "2024"
build = "build.rs"

View File

@ -10,7 +10,7 @@ bench = false
[package]
name = "lesavka_server"
version = "0.14.2"
version = "0.14.3"
edition = "2024"
autobins = false