lesavka: lighten inline preview feeds
This commit is contained in:
parent
57cd7aac33
commit
2f11cfa483
@ -4,7 +4,7 @@ path = "src/main.rs"
|
|||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "lesavka_client"
|
name = "lesavka_client"
|
||||||
version = "0.11.3"
|
version = "0.11.4"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|||||||
@ -32,6 +32,14 @@ const PREVIEW_WIDTH: i32 = 640;
|
|||||||
#[cfg(not(coverage))]
|
#[cfg(not(coverage))]
|
||||||
const PREVIEW_HEIGHT: i32 = 360;
|
const PREVIEW_HEIGHT: i32 = 360;
|
||||||
#[cfg(not(coverage))]
|
#[cfg(not(coverage))]
|
||||||
|
const INLINE_PREVIEW_REQUEST_WIDTH: i32 = 960;
|
||||||
|
#[cfg(not(coverage))]
|
||||||
|
const INLINE_PREVIEW_REQUEST_HEIGHT: i32 = 540;
|
||||||
|
#[cfg(not(coverage))]
|
||||||
|
const INLINE_PREVIEW_REQUEST_FPS: u32 = 24;
|
||||||
|
#[cfg(not(coverage))]
|
||||||
|
const INLINE_PREVIEW_MAX_KBIT: u32 = 4_000;
|
||||||
|
#[cfg(not(coverage))]
|
||||||
const DEFAULT_EYE_SOURCE_WIDTH: i32 = 1920;
|
const DEFAULT_EYE_SOURCE_WIDTH: i32 = 1920;
|
||||||
#[cfg(not(coverage))]
|
#[cfg(not(coverage))]
|
||||||
const DEFAULT_EYE_SOURCE_HEIGHT: i32 = 1080;
|
const DEFAULT_EYE_SOURCE_HEIGHT: i32 = 1080;
|
||||||
@ -105,14 +113,20 @@ impl PreviewSurface {
|
|||||||
display_height: preview_dimension("LESAVKA_PREVIEW_HEIGHT", PREVIEW_HEIGHT),
|
display_height: preview_dimension("LESAVKA_PREVIEW_HEIGHT", PREVIEW_HEIGHT),
|
||||||
requested_width: preview_dimension(
|
requested_width: preview_dimension(
|
||||||
"LESAVKA_PREVIEW_REQUEST_WIDTH",
|
"LESAVKA_PREVIEW_REQUEST_WIDTH",
|
||||||
DEFAULT_EYE_SOURCE_WIDTH,
|
INLINE_PREVIEW_REQUEST_WIDTH,
|
||||||
),
|
),
|
||||||
requested_height: preview_dimension(
|
requested_height: preview_dimension(
|
||||||
"LESAVKA_PREVIEW_REQUEST_HEIGHT",
|
"LESAVKA_PREVIEW_REQUEST_HEIGHT",
|
||||||
DEFAULT_EYE_SOURCE_HEIGHT,
|
INLINE_PREVIEW_REQUEST_HEIGHT,
|
||||||
|
),
|
||||||
|
requested_fps: preview_bitrate(
|
||||||
|
"LESAVKA_PREVIEW_REQUEST_FPS",
|
||||||
|
INLINE_PREVIEW_REQUEST_FPS,
|
||||||
|
),
|
||||||
|
max_bitrate_kbit: preview_bitrate(
|
||||||
|
"LESAVKA_PREVIEW_MAX_KBIT",
|
||||||
|
INLINE_PREVIEW_MAX_KBIT,
|
||||||
),
|
),
|
||||||
requested_fps: preview_bitrate("LESAVKA_PREVIEW_REQUEST_FPS", 30),
|
|
||||||
max_bitrate_kbit: preview_bitrate("LESAVKA_PREVIEW_MAX_KBIT", 12_000),
|
|
||||||
prefer_reencode: true,
|
prefer_reencode: true,
|
||||||
},
|
},
|
||||||
Self::Window => PreviewProfile {
|
Self::Window => PreviewProfile {
|
||||||
@ -267,15 +281,28 @@ impl LauncherPreview {
|
|||||||
max_bitrate_kbit: u32,
|
max_bitrate_kbit: u32,
|
||||||
prefer_reencode: bool,
|
prefer_reencode: bool,
|
||||||
) {
|
) {
|
||||||
|
let (
|
||||||
|
inline_requested_width,
|
||||||
|
inline_requested_height,
|
||||||
|
inline_requested_fps,
|
||||||
|
inline_max_bitrate_kbit,
|
||||||
|
inline_prefer_reencode,
|
||||||
|
) = adapt_inline_preview_request(
|
||||||
|
requested_width,
|
||||||
|
requested_height,
|
||||||
|
requested_fps,
|
||||||
|
max_bitrate_kbit,
|
||||||
|
prefer_reencode,
|
||||||
|
);
|
||||||
self.rebuild_feed(
|
self.rebuild_feed(
|
||||||
&self.inline_feeds,
|
&self.inline_feeds,
|
||||||
monitor_id,
|
monitor_id,
|
||||||
Some((
|
Some((
|
||||||
requested_width,
|
inline_requested_width,
|
||||||
requested_height,
|
inline_requested_height,
|
||||||
requested_fps,
|
inline_requested_fps,
|
||||||
max_bitrate_kbit,
|
inline_max_bitrate_kbit,
|
||||||
prefer_reencode,
|
inline_prefer_reencode,
|
||||||
)),
|
)),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
@ -1307,6 +1334,80 @@ fn preview_dimension(var: &str, default: i32) -> i32 {
|
|||||||
.unwrap_or(default)
|
.unwrap_or(default)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(coverage))]
|
||||||
|
fn adapt_inline_preview_request(
|
||||||
|
requested_width: i32,
|
||||||
|
requested_height: i32,
|
||||||
|
requested_fps: u32,
|
||||||
|
max_bitrate_kbit: u32,
|
||||||
|
prefer_reencode: bool,
|
||||||
|
) -> (i32, i32, u32, u32, bool) {
|
||||||
|
let bounded_width = requested_width.max(2).min(preview_dimension(
|
||||||
|
"LESAVKA_PREVIEW_REQUEST_WIDTH",
|
||||||
|
INLINE_PREVIEW_REQUEST_WIDTH,
|
||||||
|
));
|
||||||
|
let bounded_height = requested_height.max(2).min(preview_dimension(
|
||||||
|
"LESAVKA_PREVIEW_REQUEST_HEIGHT",
|
||||||
|
INLINE_PREVIEW_REQUEST_HEIGHT,
|
||||||
|
));
|
||||||
|
let (inline_width, inline_height) = fit_preview_within_bounds(
|
||||||
|
requested_width.max(2),
|
||||||
|
requested_height.max(2),
|
||||||
|
bounded_width,
|
||||||
|
bounded_height,
|
||||||
|
);
|
||||||
|
let inline_fps = requested_fps.max(1).min(preview_bitrate(
|
||||||
|
"LESAVKA_PREVIEW_REQUEST_FPS",
|
||||||
|
INLINE_PREVIEW_REQUEST_FPS,
|
||||||
|
));
|
||||||
|
let inline_bitrate = max_bitrate_kbit.max(800).min(preview_bitrate(
|
||||||
|
"LESAVKA_PREVIEW_MAX_KBIT",
|
||||||
|
INLINE_PREVIEW_MAX_KBIT,
|
||||||
|
));
|
||||||
|
let adapted = inline_width != requested_width.max(2)
|
||||||
|
|| inline_height != requested_height.max(2)
|
||||||
|
|| inline_fps != requested_fps.max(1)
|
||||||
|
|| inline_bitrate != max_bitrate_kbit.max(800);
|
||||||
|
(
|
||||||
|
inline_width,
|
||||||
|
inline_height,
|
||||||
|
inline_fps,
|
||||||
|
inline_bitrate,
|
||||||
|
prefer_reencode || adapted,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(coverage))]
|
||||||
|
fn fit_preview_within_bounds(
|
||||||
|
requested_width: i32,
|
||||||
|
requested_height: i32,
|
||||||
|
max_width: i32,
|
||||||
|
max_height: i32,
|
||||||
|
) -> (i32, i32) {
|
||||||
|
let requested_width = round_down_even_i32(requested_width.max(2));
|
||||||
|
let requested_height = round_down_even_i32(requested_height.max(2));
|
||||||
|
let max_width = round_down_even_i32(max_width.max(2));
|
||||||
|
let max_height = round_down_even_i32(max_height.max(2));
|
||||||
|
if requested_width <= max_width && requested_height <= max_height {
|
||||||
|
return (requested_width, requested_height);
|
||||||
|
}
|
||||||
|
let width_limited_height =
|
||||||
|
round_down_even_i32((requested_height * max_width) / requested_width);
|
||||||
|
if width_limited_height <= max_height {
|
||||||
|
(max_width, width_limited_height.max(2))
|
||||||
|
} else {
|
||||||
|
let height_limited_width =
|
||||||
|
round_down_even_i32((requested_width * max_height) / requested_height);
|
||||||
|
(height_limited_width.max(2), max_height)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(coverage))]
|
||||||
|
fn round_down_even_i32(value: i32) -> i32 {
|
||||||
|
let value = value.max(2);
|
||||||
|
value - (value & 1)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(not(coverage))]
|
#[cfg(not(coverage))]
|
||||||
fn events_per_second(events: &VecDeque<Instant>, now: Instant) -> f32 {
|
fn events_per_second(events: &VecDeque<Instant>, now: Instant) -> f32 {
|
||||||
let Some(oldest) = events.front().copied() else {
|
let Some(oldest) = events.front().copied() else {
|
||||||
@ -1362,20 +1463,22 @@ fn compute_peak_gap_ms(samples: &VecDeque<(Instant, f32)>) -> f32 {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::{
|
use super::{
|
||||||
DEFAULT_EYE_SOURCE_HEIGHT, DEFAULT_EYE_SOURCE_WIDTH, PREVIEW_HEIGHT, PREVIEW_WIDTH,
|
DEFAULT_EYE_SOURCE_HEIGHT, DEFAULT_EYE_SOURCE_WIDTH, INLINE_PREVIEW_MAX_KBIT,
|
||||||
PreviewSurface, PreviewTelemetry,
|
INLINE_PREVIEW_REQUEST_FPS, INLINE_PREVIEW_REQUEST_HEIGHT, INLINE_PREVIEW_REQUEST_WIDTH,
|
||||||
|
PREVIEW_HEIGHT, PREVIEW_WIDTH, PreviewSurface, PreviewTelemetry,
|
||||||
|
adapt_inline_preview_request,
|
||||||
};
|
};
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn inline_preview_profile_uses_existing_defaults() {
|
fn inline_preview_profile_uses_lightweight_defaults() {
|
||||||
let profile = PreviewSurface::Inline.profile();
|
let profile = PreviewSurface::Inline.profile();
|
||||||
assert_eq!(profile.display_width, PREVIEW_WIDTH);
|
assert_eq!(profile.display_width, PREVIEW_WIDTH);
|
||||||
assert_eq!(profile.display_height, PREVIEW_HEIGHT);
|
assert_eq!(profile.display_height, PREVIEW_HEIGHT);
|
||||||
assert_eq!(profile.requested_width, DEFAULT_EYE_SOURCE_WIDTH);
|
assert_eq!(profile.requested_width, INLINE_PREVIEW_REQUEST_WIDTH);
|
||||||
assert_eq!(profile.requested_height, DEFAULT_EYE_SOURCE_HEIGHT);
|
assert_eq!(profile.requested_height, INLINE_PREVIEW_REQUEST_HEIGHT);
|
||||||
assert_eq!(profile.requested_fps, 30);
|
assert_eq!(profile.requested_fps, INLINE_PREVIEW_REQUEST_FPS);
|
||||||
assert_eq!(profile.max_bitrate_kbit, 12_000);
|
assert_eq!(profile.max_bitrate_kbit, INLINE_PREVIEW_MAX_KBIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -1389,6 +1492,12 @@ mod tests {
|
|||||||
assert_eq!(profile.max_bitrate_kbit, 12_000);
|
assert_eq!(profile.max_bitrate_kbit, 12_000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn inline_preview_request_caps_large_full_quality_streams() {
|
||||||
|
let adapted = adapt_inline_preview_request(1920, 1080, 30, 12_000, false);
|
||||||
|
assert_eq!(adapted, (960, 540, 24, 4_000, true));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn preview_telemetry_reports_fps_jitter_loss_and_drop_metrics() {
|
fn preview_telemetry_reports_fps_jitter_loss_and_drop_metrics() {
|
||||||
let mut telemetry = PreviewTelemetry::default();
|
let mut telemetry = PreviewTelemetry::default();
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "lesavka_common"
|
name = "lesavka_common"
|
||||||
version = "0.11.3"
|
version = "0.11.4"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
|
|
||||||
|
|||||||
@ -17,6 +17,6 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn banner_includes_version() {
|
fn banner_includes_version() {
|
||||||
assert_eq!(banner("0.11.3"), "lesavka-common CLI (v0.11.3)");
|
assert_eq!(banner("0.11.4"), "lesavka-common CLI (v0.11.4)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,7 +10,7 @@ bench = false
|
|||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "lesavka_server"
|
name = "lesavka_server"
|
||||||
version = "0.11.3"
|
version = "0.11.4"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
autobins = false
|
autobins = false
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user