lesavka: tighten eye stream latency and fit

This commit is contained in:
Brad Stein 2026-04-17 13:51:26 -03:00
parent 69c71fb793
commit 545bda5a96
7 changed files with 41 additions and 9 deletions

View File

@ -4,7 +4,7 @@ path = "src/main.rs"
[package] [package]
name = "lesavka_client" name = "lesavka_client"
version = "0.11.5" version = "0.11.6"
edition = "2024" edition = "2024"
[dependencies] [dependencies]
@ -37,6 +37,7 @@ base64 = "0.22"
prost-build = "0.13" prost-build = "0.13"
[dev-dependencies] [dev-dependencies]
serial_test = { workspace = true }
temp-env = { workspace = true } temp-env = { workspace = true }
tempfile = { workspace = true } tempfile = { workspace = true }

View File

@ -1054,12 +1054,26 @@ fn build_display_pane(title: &str, capture_path: &str) -> DisplayPaneWidgets {
let picture = gtk::Picture::new(); let picture = gtk::Picture::new();
picture.set_hexpand(true); picture.set_hexpand(true);
picture.set_vexpand(true); picture.set_vexpand(true);
picture.set_halign(gtk::Align::Fill);
picture.set_valign(gtk::Align::Fill);
picture.set_can_shrink(true); picture.set_can_shrink(true);
picture.set_keep_aspect_ratio(true); picture.set_keep_aspect_ratio(true);
picture.set_size_request(220, 124); picture.set_size_request(220, 124);
let preview_box = gtk::Box::new(gtk::Orientation::Vertical, 0); let preview_box = gtk::Box::new(gtk::Orientation::Vertical, 0);
preview_box.append(&picture); preview_box.set_hexpand(true);
preview_box.set_vexpand(true);
preview_box.set_halign(gtk::Align::Fill);
preview_box.set_valign(gtk::Align::Fill);
preview_box.set_size_request(220, 124);
let preview_frame = gtk::AspectFrame::new(0.5, 0.5, 16.0 / 9.0, false);
preview_frame.set_hexpand(true);
preview_frame.set_vexpand(true);
preview_frame.set_halign(gtk::Align::Fill);
preview_frame.set_valign(gtk::Align::Fill);
preview_frame.set_size_request(220, 124);
preview_frame.set_child(Some(&picture));
preview_box.append(&preview_frame);
let placeholder = gtk::Label::new(Some( let placeholder = gtk::Label::new(Some(
"This feed is running in its own window.\nUse Return To Preview to dock it back here.", "This feed is running in its own window.\nUse Return To Preview to dock it back here.",

View File

@ -237,12 +237,25 @@ pub fn open_popout_window(
let picture = gtk::Picture::new(); let picture = gtk::Picture::new();
picture.set_hexpand(true); picture.set_hexpand(true);
picture.set_vexpand(true); picture.set_vexpand(true);
picture.set_halign(gtk::Align::Fill);
picture.set_valign(gtk::Align::Fill);
picture.set_can_shrink(true); picture.set_can_shrink(true);
picture.set_keep_aspect_ratio(true); picture.set_keep_aspect_ratio(true);
picture.set_size_request(breakout_size.width, breakout_size.height); picture.set_size_request(breakout_size.width, breakout_size.height);
let root = gtk::Box::new(gtk::Orientation::Vertical, 0); let root = gtk::Box::new(gtk::Orientation::Vertical, 0);
root.set_hexpand(true);
root.set_vexpand(true);
root.set_halign(gtk::Align::Fill);
root.set_valign(gtk::Align::Fill);
root.set_size_request(breakout_size.width, breakout_size.height); root.set_size_request(breakout_size.width, breakout_size.height);
root.append(&picture); let frame = gtk::AspectFrame::new(0.5, 0.5, 16.0 / 9.0, false);
frame.set_hexpand(true);
frame.set_vexpand(true);
frame.set_halign(gtk::Align::Fill);
frame.set_valign(gtk::Align::Fill);
frame.set_size_request(breakout_size.width, breakout_size.height);
frame.set_child(Some(&picture));
root.append(&frame);
let stream_status = gtk::Label::new(Some("")); let stream_status = gtk::Label::new(Some(""));
@ -1138,6 +1151,7 @@ mod tests {
devices::DeviceCatalog, preview::PreviewBinding, state::LauncherState, devices::DeviceCatalog, preview::PreviewBinding, state::LauncherState,
ui_components::build_launcher_view, ui_components::build_launcher_view,
}; };
use serial_test::serial;
use std::{cell::RefCell, rc::Rc}; use std::{cell::RefCell, rc::Rc};
#[test] #[test]
@ -1168,6 +1182,7 @@ mod tests {
} }
#[gtk::test] #[gtk::test]
#[serial]
fn dock_all_displays_to_preview_closes_popouts_and_resets_surfaces() { fn dock_all_displays_to_preview_closes_popouts_and_resets_surfaces() {
if gtk::gdk::Display::default().is_none() { if gtk::gdk::Display::default().is_none() {
return; return;
@ -1226,6 +1241,7 @@ mod tests {
} }
#[gtk::test] #[gtk::test]
#[serial]
fn dock_all_displays_to_preview_handles_reentrant_close_callbacks() { fn dock_all_displays_to_preview_handles_reentrant_close_callbacks() {
if gtk::gdk::Display::default().is_none() { if gtk::gdk::Display::default().is_none() {
return; return;
@ -1278,6 +1294,7 @@ mod tests {
} }
#[gtk::test] #[gtk::test]
#[serial]
fn shutdown_launcher_runtime_closes_preview_bindings_and_popouts() { fn shutdown_launcher_runtime_closes_preview_bindings_and_popouts() {
if gtk::gdk::Display::default().is_none() { if gtk::gdk::Display::default().is_none() {
return; return;

View File

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

View File

@ -17,6 +17,6 @@ mod tests {
#[test] #[test]
fn banner_includes_version() { fn banner_includes_version() {
assert_eq!(banner("0.11.5"), "lesavka-common CLI (v0.11.5)"); assert_eq!(banner("0.11.6"), "lesavka-common CLI (v0.11.6)");
} }
} }

View File

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

View File

@ -445,8 +445,8 @@ pub async fn eye_ball_with_request(
let last_telemetry_sec = Arc::new(AtomicU64::new(0)); let last_telemetry_sec = Arc::new(AtomicU64::new(0));
let packet_seq = Arc::new(AtomicU64::new(0)); let packet_seq = Arc::new(AtomicU64::new(0));
let queue_buffers = env_u32("LESAVKA_EYE_QUEUE_BUFFERS", 8).max(1); let queue_buffers = env_u32("LESAVKA_EYE_QUEUE_BUFFERS", 4).max(1);
let appsink_buffers = env_u32("LESAVKA_EYE_APPSINK_BUFFERS", 8).max(1); let appsink_buffers = env_u32("LESAVKA_EYE_APPSINK_BUFFERS", 4).max(1);
let keyframe_interval = env_u32( let keyframe_interval = env_u32(
"LESAVKA_EYE_KEYFRAME_INTERVAL", "LESAVKA_EYE_KEYFRAME_INTERVAL",
request.requested_fps.max(1).min(5), request.requested_fps.max(1).min(5),
@ -513,7 +513,7 @@ pub async fn eye_ball_with_request(
.dynamic_cast::<gst_app::AppSink>() .dynamic_cast::<gst_app::AppSink>()
.expect("appsink down-cast"); .expect("appsink down-cast");
let chan_capacity = env_usize("LESAVKA_EYE_CHAN_CAPACITY", 256).max(16); let chan_capacity = env_usize("LESAVKA_EYE_CHAN_CAPACITY", 32).max(8);
let (tx, rx) = tokio::sync::mpsc::channel(chan_capacity); let (tx, rx) = tokio::sync::mpsc::channel(chan_capacity);
if let Some(src_pad) = pipeline if let Some(src_pad) = pipeline