mirror of
https://github.com/rustdesk/rustdesk.git
synced 2024-12-27 23:28:03 +08:00
112 lines
2.7 KiB
Rust
112 lines
2.7 KiB
Rust
use std::ptr;
|
|
|
|
use block::{Block, ConcreteBlock};
|
|
use libc::c_void;
|
|
use std::sync::{Arc, Mutex};
|
|
|
|
use super::config::Config;
|
|
use super::display::Display;
|
|
use super::ffi::*;
|
|
use super::frame::Frame;
|
|
|
|
pub struct Capturer {
|
|
stream: CGDisplayStreamRef,
|
|
queue: DispatchQueue,
|
|
|
|
width: usize,
|
|
height: usize,
|
|
format: PixelFormat,
|
|
display: Display,
|
|
stopped: Arc<Mutex<bool>>,
|
|
}
|
|
|
|
impl Capturer {
|
|
pub fn new<F: Fn(Frame) + 'static>(
|
|
display: Display,
|
|
width: usize,
|
|
height: usize,
|
|
format: PixelFormat,
|
|
config: Config,
|
|
handler: F,
|
|
) -> Result<Capturer, CGError> {
|
|
let stopped = Arc::new(Mutex::new(false));
|
|
let cloned_stopped = stopped.clone();
|
|
let handler: FrameAvailableHandler = ConcreteBlock::new(move |status, _, surface, _| {
|
|
use self::CGDisplayStreamFrameStatus::*;
|
|
if status == Stopped {
|
|
let mut lock = cloned_stopped.lock().unwrap();
|
|
*lock = true;
|
|
return;
|
|
}
|
|
if status == FrameComplete {
|
|
handler(unsafe { Frame::new(surface) });
|
|
}
|
|
})
|
|
.copy();
|
|
|
|
let queue = unsafe {
|
|
dispatch_queue_create(
|
|
b"quadrupleslap.scrap\0".as_ptr() as *const i8,
|
|
ptr::null_mut(),
|
|
)
|
|
};
|
|
|
|
let stream = unsafe {
|
|
let config = config.build();
|
|
let stream = CGDisplayStreamCreateWithDispatchQueue(
|
|
display.id(),
|
|
width,
|
|
height,
|
|
format,
|
|
config,
|
|
queue,
|
|
&*handler as *const Block<_, _> as *const c_void,
|
|
);
|
|
CFRelease(config);
|
|
stream
|
|
};
|
|
|
|
match unsafe { CGDisplayStreamStart(stream) } {
|
|
CGError::Success => Ok(Capturer {
|
|
stream,
|
|
queue,
|
|
width,
|
|
height,
|
|
format,
|
|
display,
|
|
stopped,
|
|
}),
|
|
x => Err(x),
|
|
}
|
|
}
|
|
|
|
pub fn width(&self) -> usize {
|
|
self.width
|
|
}
|
|
pub fn height(&self) -> usize {
|
|
self.height
|
|
}
|
|
pub fn format(&self) -> PixelFormat {
|
|
self.format
|
|
}
|
|
pub fn display(&self) -> Display {
|
|
self.display
|
|
}
|
|
}
|
|
|
|
impl Drop for Capturer {
|
|
fn drop(&mut self) {
|
|
unsafe {
|
|
let _ = CGDisplayStreamStop(self.stream);
|
|
loop {
|
|
if *self.stopped.lock().unwrap() {
|
|
break;
|
|
}
|
|
std::thread::sleep(std::time::Duration::from_millis(30));
|
|
}
|
|
CFRelease(self.stream);
|
|
dispatch_release(self.queue);
|
|
}
|
|
}
|
|
}
|