diff --git a/src/server/portable_service.rs b/src/server/portable_service.rs index 617763bb3..1b60d59b6 100644 --- a/src/server/portable_service.rs +++ b/src/server/portable_service.rs @@ -37,8 +37,8 @@ const ADDR_CURSOR_PARA: usize = 0; const ADDR_CURSOR_COUNTER: usize = ADDR_CURSOR_PARA + size_of::(); const ADDR_CAPTURER_PARA: usize = ADDR_CURSOR_COUNTER + SIZE_COUNTER; -const ADDR_CAPTURE_FRAME_SIZE: usize = ADDR_CAPTURER_PARA + size_of::(); -const ADDR_CAPTURE_WOULDBLOCK: usize = ADDR_CAPTURE_FRAME_SIZE + size_of::(); +const ADDR_CAPTURE_FRAME_INFO: usize = ADDR_CAPTURER_PARA + size_of::(); +const ADDR_CAPTURE_WOULDBLOCK: usize = ADDR_CAPTURE_FRAME_INFO + size_of::(); const ADDR_CAPTURE_FRAME_COUNTER: usize = ADDR_CAPTURE_WOULDBLOCK + size_of::(); const ADDR_CAPTURE_FRAME: usize = @@ -134,10 +134,16 @@ mod utils { use core::slice; use std::mem::size_of; + use super::{ + CapturerPara, FrameInfo, SharedMemory, ADDR_CAPTURER_PARA, ADDR_CAPTURE_FRAME_INFO, + }; + + #[inline] pub fn i32_to_vec(i: i32) -> Vec { i.to_ne_bytes().to_vec() } + #[inline] pub fn ptr_to_i32(ptr: *const u8) -> i32 { unsafe { let v = slice::from_raw_parts(ptr, size_of::()); @@ -145,6 +151,7 @@ mod utils { } } + #[inline] pub fn counter_ready(counter: *const u8) -> bool { unsafe { let wptr = counter; @@ -160,6 +167,7 @@ mod utils { } } + #[inline] pub fn counter_equal(counter: *const u8) -> bool { unsafe { let wptr = counter; @@ -170,6 +178,7 @@ mod utils { } } + #[inline] pub fn increase_counter(counter: *mut u8) { unsafe { let wptr = counter; @@ -185,9 +194,30 @@ mod utils { } } + #[inline] pub fn align(v: usize, align: usize) -> usize { (v + align - 1) / align * align } + + #[inline] + pub fn set_para(shmem: &SharedMemory, para: CapturerPara) { + let para_ptr = ¶ as *const CapturerPara as *const u8; + let para_data; + unsafe { + para_data = slice::from_raw_parts(para_ptr, size_of::()); + } + shmem.write(ADDR_CAPTURER_PARA, para_data); + } + + #[inline] + pub fn set_frame_info(shmem: &SharedMemory, info: FrameInfo) { + let ptr = &info as *const FrameInfo as *const u8; + let data; + unsafe { + data = slice::from_raw_parts(ptr, size_of::()); + } + shmem.write(ADDR_CAPTURE_FRAME_INFO, data); + } } // functions called in separate SYSTEM user process. @@ -257,6 +287,8 @@ pub mod server { let mut spf = Duration::from_millis(last_timeout_ms as _); let mut first_frame_captured = false; let mut dxgi_failed_times = 0; + let mut display_width = 0; + let mut display_height = 0; loop { if EXIT.lock().unwrap().clone() { break; @@ -264,6 +296,7 @@ pub mod server { unsafe { let para_ptr = shmem.as_ptr().add(ADDR_CAPTURER_PARA); let para = para_ptr as *const CapturerPara; + let recreate = (*para).recreate; let current_display = (*para).current_display; let use_yuv = (*para).use_yuv; let use_yuv_set = (*para).use_yuv_set; @@ -276,6 +309,8 @@ pub mod server { if c.is_none() { *crate::video_service::CURRENT_DISPLAY.lock().unwrap() = current_display; let (_, _current, display) = get_current_display().unwrap(); + display_width = display.width(); + display_height = display.height(); match Capturer::new(display, use_yuv) { Ok(mut v) => { c = { @@ -286,6 +321,16 @@ pub mod server { dxgi_failed_times = 0; v.set_gdi(); } + utils::set_para( + &shmem, + CapturerPara { + recreate: false, + current_display: (*para).current_display, + use_yuv: (*para).use_yuv, + use_yuv_set: (*para).use_yuv_set, + timeout_ms: (*para).timeout_ms, + }, + ); Some(v) } } @@ -296,9 +341,12 @@ pub mod server { } } } else { - if current_display != last_current_display || use_yuv != last_use_yuv { + if recreate + || current_display != last_current_display + || use_yuv != last_use_yuv + { log::info!( - "display:{}->{}, use_yuv:{}->{}", + "create capturer, display:{}->{}, use_yuv:{}->{}", last_current_display, current_display, last_use_yuv, @@ -323,9 +371,14 @@ pub mod server { } match c.as_mut().unwrap().frame(spf) { Ok(f) => { - let len = f.0.len(); - let len_slice = utils::i32_to_vec(len as _); - shmem.write(ADDR_CAPTURE_FRAME_SIZE, &len_slice); + utils::set_frame_info( + &shmem, + FrameInfo { + length: f.0.len(), + width: display_width, + height: display_height, + }, + ); shmem.write(ADDR_CAPTURE_FRAME, f.0); shmem.write(ADDR_CAPTURE_WOULDBLOCK, &utils::i32_to_vec(TRUE)); utils::increase_counter(shmem.as_ptr().add(ADDR_CAPTURE_FRAME_COUNTER)); @@ -554,7 +607,10 @@ pub mod client { *QUICK_SUPPORT.lock().unwrap() = v; } - pub struct CapturerPortable; + pub struct CapturerPortable { + width: usize, + height: usize, + } impl CapturerPortable { pub fn new(current_display: usize, use_yuv: bool) -> Self @@ -563,9 +619,13 @@ pub mod client { { let mut option = SHMEM.lock().unwrap(); if let Some(shmem) = option.as_mut() { - Self::set_para( + unsafe { + libc::memset(shmem.as_ptr() as _, 0, shmem.len() as _); + } + utils::set_para( shmem, CapturerPara { + recreate: true, current_display, use_yuv, use_yuv_set: false, @@ -574,16 +634,14 @@ pub mod client { ); shmem.write(ADDR_CAPTURE_WOULDBLOCK, &utils::i32_to_vec(TRUE)); } - CapturerPortable {} - } - - fn set_para(shmem: &mut SharedMemory, para: CapturerPara) { - let para_ptr = ¶ as *const CapturerPara as *const u8; - let para_data; - unsafe { - para_data = slice::from_raw_parts(para_ptr, size_of::()); + let (mut width, mut height) = (0, 0); + if let Ok((_, current, display)) = get_current_display() { + if current_display == current { + width = display.width(); + height = display.height(); + } } - shmem.write(ADDR_CAPTURER_PARA, para_data); + CapturerPortable { width, height } } } @@ -594,9 +652,10 @@ pub mod client { unsafe { let para_ptr = shmem.as_ptr().add(ADDR_CAPTURER_PARA); let para = para_ptr as *const CapturerPara; - Self::set_para( + utils::set_para( shmem, CapturerPara { + recreate: (*para).recreate, current_display: (*para).current_display, use_yuv, use_yuv_set: true, @@ -618,9 +677,10 @@ pub mod client { let para_ptr = base.add(ADDR_CAPTURER_PARA); let para = para_ptr as *const CapturerPara; if timeout.as_millis() != (*para).timeout_ms as _ { - Self::set_para( + utils::set_para( shmem, CapturerPara { + recreate: (*para).recreate, current_display: (*para).current_display, use_yuv: (*para).use_yuv, use_yuv_set: (*para).use_yuv_set, @@ -629,10 +689,23 @@ pub mod client { ); } if utils::counter_ready(base.add(ADDR_CAPTURE_FRAME_COUNTER)) { - let frame_len_ptr = base.add(ADDR_CAPTURE_FRAME_SIZE); - let frame_len = utils::ptr_to_i32(frame_len_ptr); + let frame_info_ptr = shmem.as_ptr().add(ADDR_CAPTURE_FRAME_INFO); + let frame_info = frame_info_ptr as *const FrameInfo; + if (*frame_info).width != self.width || (*frame_info).height != self.height { + log::info!( + "skip frame, ({},{}) != ({},{})", + (*frame_info).width, + (*frame_info).height, + self.width, + self.height, + ); + return Err(std::io::Error::new( + std::io::ErrorKind::WouldBlock, + "wouldblock error".to_string(), + )); + } let frame_ptr = base.add(ADDR_CAPTURE_FRAME); - let data = slice::from_raw_parts(frame_ptr, frame_len as usize); + let data = slice::from_raw_parts(frame_ptr, (*frame_info).length); Ok(Frame(data)) } else { let ptr = base.add(ADDR_CAPTURE_WOULDBLOCK); @@ -839,9 +912,17 @@ pub mod client { } #[repr(C)] -struct CapturerPara { +pub struct CapturerPara { + recreate: bool, current_display: usize, use_yuv: bool, use_yuv_set: bool, timeout_ms: i32, } + +#[repr(C)] +pub struct FrameInfo { + length: usize, + width: usize, + height: usize, +}