Skip to content

Commit 5a318b4

Browse files
committed
perf(desktop-gpui): keep bubble-sized camera preview widths even for swscale
1 parent 4394baf commit 5a318b4

2 files changed

Lines changed: 42 additions & 16 deletions

File tree

‎apps/desktop-gpui/kernels/src/camera_preview.rs‎

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,12 @@ pub fn cover_dimensions(source: (usize, usize), target: (usize, usize)) -> (usiz
2121
if scale >= 1.0 {
2222
return source;
2323
}
24-
(
25-
((width as f64 * scale).round() as usize).clamp(1, width),
26-
((height as f64 * scale).round() as usize).clamp(1, height),
27-
)
24+
// Even sizes: swscale forces full-resolution chroma interpolation for an
25+
// odd output width, which measured 2-4x slower than the even width beside
26+
// it (camera_preview_scale_benchmark, Windows and Linux CI).
27+
let even =
28+
|extent: usize| ((extent as f64 * scale / 2.0).round() as usize * 2).clamp(2, extent);
29+
(even(width), even(height))
2830
}
2931

3032
#[cfg(test)]
@@ -57,11 +59,12 @@ mod tests {
5759

5860
#[test]
5961
fn cover_dimensions_fill_the_target_and_keep_the_source_aspect() {
60-
assert_eq!(cover_dimensions((1920, 1080), (480, 480)), (853, 480));
61-
assert_eq!(cover_dimensions((3840, 2160), (480, 480)), (853, 480));
62+
assert_eq!(cover_dimensions((1920, 1080), (480, 480)), (854, 480));
63+
assert_eq!(cover_dimensions((3840, 2160), (480, 480)), (854, 480));
64+
assert_eq!(cover_dimensions((1920, 1080), (960, 960)), (1706, 960));
6265
assert_eq!(cover_dimensions((1920, 1080), (960, 540)), (960, 540));
6366
assert_eq!(cover_dimensions((1440, 1080), (960, 540)), (960, 720));
64-
assert_eq!(cover_dimensions((1080, 1920), (480, 480)), (480, 853));
67+
assert_eq!(cover_dimensions((1080, 1920), (480, 480)), (480, 854));
6568
for source in [
6669
(1280, 720),
6770
(1920, 1080),
@@ -71,6 +74,9 @@ mod tests {
7174
] {
7275
for target in [(270, 270), (480, 480), (960, 540), (1080, 1080)] {
7376
let (width, height) = cover_dimensions(source, target);
77+
if (width, height) != source {
78+
assert_eq!((width % 2, height % 2), (0, 0));
79+
}
7480
assert!(width >= target.0.min(source.0));
7581
assert!(height >= target.1.min(source.1));
7682
let aspect = source.0 as f64 / source.1 as f64;

‎apps/desktop-gpui/src/feeds.rs‎

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -573,8 +573,12 @@ fn run_camera_preview_worker(config: CameraPreviewWorkerConfig) {
573573
// alone may be shrunk to the bubble.
574574
#[cfg(target_os = "linux")]
575575
let preview_target = preview_target.filter(|_| recording.is_none());
576-
let max_dims = match blur_mode {
577-
Some(_) => Some(crate::camera_blur_portable::MAX_DIMS),
576+
let output = match blur_mode {
577+
Some(_) => crate::camera_blur_portable::fitted_dimensions(
578+
frame.inner.width(),
579+
frame.inner.height(),
580+
crate::camera_blur_portable::MAX_DIMS,
581+
),
578582
None => preview_target.map(|visible| {
579583
let (width, height) =
580584
cap_gpui_kernels::camera_preview::cover_dimensions(source_dims, visible);
@@ -583,7 +587,7 @@ fn run_camera_preview_worker(config: CameraPreviewWorkerConfig) {
583587
};
584588
let layout_dims = blur_mode.is_none().then_some(source_dims);
585589
let Some((mut image, dims)) =
586-
camera_preview_image(&frame.inner, &mut scaler, requested_mirror, max_dims)
590+
camera_preview_image_at(&frame.inner, &mut scaler, requested_mirror, output)
587591
else {
588592
#[cfg(target_os = "linux")]
589593
if let Some(recording) = &recording {
@@ -1438,19 +1442,35 @@ impl Feeds {
14381442
}
14391443
}
14401444

1441-
#[cfg(any(not(target_os = "macos"), test))]
1445+
#[cfg(test)]
14421446
pub(crate) fn camera_preview_image(
14431447
frame: &ffmpeg::frame::Video,
14441448
scaler: &mut Option<ffmpeg::software::scaling::Context>,
14451449
mirrored: bool,
14461450
max_dims: Option<(u32, u32)>,
1451+
) -> Option<(Arc<gpui::RenderImage>, (usize, usize))> {
1452+
let output = match max_dims {
1453+
Some(max) => Some(crate::camera_blur_portable::fitted_dimensions(
1454+
frame.width(),
1455+
frame.height(),
1456+
max,
1457+
)?),
1458+
None => None,
1459+
};
1460+
camera_preview_image_at(frame, scaler, mirrored, output)
1461+
}
1462+
1463+
#[cfg(any(not(target_os = "macos"), test))]
1464+
pub(crate) fn camera_preview_image_at(
1465+
frame: &ffmpeg::frame::Video,
1466+
scaler: &mut Option<ffmpeg::software::scaling::Context>,
1467+
mirrored: bool,
1468+
output: Option<(u32, u32)>,
14471469
) -> Option<(Arc<gpui::RenderImage>, (usize, usize))> {
14481470
let source_width = frame.width();
14491471
let source_height = frame.height();
1450-
let (width, height) = match max_dims {
1451-
Some(max) => {
1452-
crate::camera_blur_portable::fitted_dimensions(source_width, source_height, max)?
1453-
}
1472+
let (width, height) = match output {
1473+
Some(output) => output,
14541474
None if source_width > 0 && source_height > 0 => (source_width, source_height),
14551475
None => return None,
14561476
};
@@ -2259,7 +2279,7 @@ mod tests {
22592279
let mut dims = (0, 0);
22602280
for iteration in 0..WARMUP + ITERATIONS {
22612281
let started = Instant::now();
2262-
let (image, output) = camera_preview_image(
2282+
let (image, output) = camera_preview_image_at(
22632283
&frames[iteration % frames.len()],
22642284
&mut scaler,
22652285
mirrored,

0 commit comments

Comments
 (0)