rustdesk/libs/scrap/src/common/quartz.rs
21pages 534bfad50f opt codec
1. use src width/height to convert yuv
2. align dst yuv to avoid illegal memory access
3. init yuvfmt when new codec
4. move remote reset calls from empty conns judge to emtpy remote conns
   judge

Signed-off-by: 21pages <pages21@163.com>
2023-11-03 11:52:41 +08:00

148 lines
3.5 KiB
Rust

use crate::{quartz, Pixfmt};
use std::marker::PhantomData;
use std::sync::{Arc, Mutex, TryLockError};
use std::{io, mem};
pub struct Capturer {
inner: quartz::Capturer,
frame: Arc<Mutex<Option<quartz::Frame>>>,
saved_raw_data: Vec<u8>, // for faster compare and copy
}
impl Capturer {
pub fn new(display: Display) -> io::Result<Capturer> {
let frame = Arc::new(Mutex::new(None));
let f = frame.clone();
let inner = quartz::Capturer::new(
display.0,
display.width(),
display.height(),
quartz::PixelFormat::Argb8888,
Default::default(),
move |inner| {
if let Ok(mut f) = f.lock() {
*f = Some(inner);
}
},
)
.map_err(|_| io::Error::from(io::ErrorKind::Other))?;
Ok(Capturer {
inner,
frame,
saved_raw_data: Vec::new(),
})
}
pub fn width(&self) -> usize {
self.inner.width()
}
pub fn height(&self) -> usize {
self.inner.height()
}
}
impl crate::TraitCapturer for Capturer {
fn frame<'a>(&'a mut self, _timeout_ms: std::time::Duration) -> io::Result<Frame<'a>> {
match self.frame.try_lock() {
Ok(mut handle) => {
let mut frame = None;
mem::swap(&mut frame, &mut handle);
match frame {
Some(mut frame) => {
crate::would_block_if_equal(&mut self.saved_raw_data, frame.inner())?;
frame.surface_to_bgra(self.height());
Ok(Frame {
frame,
data: PhantomData,
width: self.width(),
height: self.height(),
})
}
None => Err(io::ErrorKind::WouldBlock.into()),
}
}
Err(TryLockError::WouldBlock) => Err(io::ErrorKind::WouldBlock.into()),
Err(TryLockError::Poisoned(..)) => Err(io::ErrorKind::Other.into()),
}
}
}
pub struct Frame<'a> {
frame: quartz::Frame,
data: PhantomData<&'a [u8]>,
width: usize,
height: usize,
}
impl<'a> crate::TraitFrame for Frame<'a> {
fn data(&self) -> &[u8] {
&*self.frame
}
fn width(&self) -> usize {
self.width
}
fn height(&self) -> usize {
self.height
}
fn stride(&self) -> Vec<usize> {
let mut v = Vec::new();
v.push(self.frame.stride());
v
}
fn pixfmt(&self) -> Pixfmt {
Pixfmt::BGRA
}
}
pub struct Display(quartz::Display);
impl Display {
pub fn primary() -> io::Result<Display> {
Ok(Display(quartz::Display::primary()))
}
pub fn all() -> io::Result<Vec<Display>> {
Ok(quartz::Display::online()
.map_err(|_| io::Error::from(io::ErrorKind::Other))?
.into_iter()
.map(Display)
.collect())
}
pub fn width(&self) -> usize {
self.0.width()
}
pub fn height(&self) -> usize {
self.0.height()
}
pub fn name(&self) -> String {
self.0.id().to_string()
}
pub fn is_online(&self) -> bool {
self.0.is_online()
}
pub fn origin(&self) -> (i32, i32) {
let o = self.0.bounds().origin;
(o.x as _, o.y as _)
}
pub fn is_primary(&self) -> bool {
self.0.is_primary()
}
}