From 55786aaa5709ac0a450aabcf06f9d1fee3119908 Mon Sep 17 00:00:00 2001 From: RustDesk <71636191+rustdesk@users.noreply.github.com> Date: Tue, 3 Nov 2026 12:26:12 +0800 Subject: [PATCH] perf(android): hand the captured frame over instead of copying it again (#16835) #16827 made FrameRaw copy each frame while the Image is still valid, and then copy it a second time into the capturer in take(). Swap the owned buffer into dst instead: both callers own dst and only read it until their next call, so the two buffers alternate and take() holds the lock for constant time. A taken frame is copied once, as before #16827. Release the buffer whenever capture is enabled or disabled. FrameRaw is global, so it would otherwise keep a full frame after capture stops. Note why the would_block_if_equal check never fires, so that nobody revives it by accident. Co-authored-by: Claude Opus 5.5 --- libs/scrap/src/android/ffi.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libs/scrap/src/android/ffi.rs b/libs/scrap/src/android/ffi.rs index 9f0573456..2bb248a1c 100644 --- a/libs/scrap/src/android/ffi.rs +++ b/libs/scrap/src/android/ffi.rs @@ -59,6 +59,7 @@ impl FrameRaw { fn set_enable(&mut self, value: bool) { self.enable = value; self.ready = false; + self.data = Vec::new(); } fn update(&mut self, data: *mut u8, len: usize) { @@ -81,12 +82,13 @@ impl FrameRaw { return None; } self.ready = false; + // Never true: `last` starts empty and only `would_block_if_equal` fills it. Left off on + // purpose: Android sends a frame only when the screen recomposes, so repeats are rare. if last.len() == self.data.len() && crate::would_block_if_equal(last, &self.data).is_err() { return None; } - dst.clear(); - dst.extend_from_slice(&self.data); + std::mem::swap(dst, &mut self.data); Some(()) } }