diff --git a/Cargo.lock b/Cargo.lock index c91272112..be6c13915 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -378,9 +378,12 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" +checksum = "f0b3de4a0c5e67e16066a0715723abd91edc2f9001d09c46e1dca929351e130e" +dependencies = [ + "serde 1.0.139", +] [[package]] name = "cache-padded" @@ -3964,6 +3967,7 @@ dependencies = [ "async-process", "async-trait", "base64", + "bytes", "cc", "cfg-if 1.0.0", "clap 3.2.12", diff --git a/libs/scrap/examples/capture_mag.rs b/libs/scrap/examples/capture_mag.rs index c0505141e..81b2d8573 100644 --- a/libs/scrap/examples/capture_mag.rs +++ b/libs/scrap/examples/capture_mag.rs @@ -4,7 +4,7 @@ extern crate scrap; use std::fs::File; #[cfg(windows)] -use scrap::CapturerMag; +use scrap::{CapturerMag, TraitCapturer}; use scrap::{i420_to_rgb, Display}; fn main() { diff --git a/libs/scrap/examples/ffplay.rs b/libs/scrap/examples/ffplay.rs index 2c685b931..b8fe16e35 100644 --- a/libs/scrap/examples/ffplay.rs +++ b/libs/scrap/examples/ffplay.rs @@ -3,7 +3,7 @@ use std::time::Duration; extern crate scrap; fn main() { - use scrap::{Capturer, Display}; + use scrap::{Capturer, Display, TraitCapturer}; use std::io::ErrorKind::WouldBlock; use std::io::Write; use std::process::{Command, Stdio}; diff --git a/libs/scrap/examples/record-screen.rs b/libs/scrap/examples/record-screen.rs index e099a8d1e..5df97838e 100644 --- a/libs/scrap/examples/record-screen.rs +++ b/libs/scrap/examples/record-screen.rs @@ -18,7 +18,7 @@ use webm::mux; use webm::mux::Track; use scrap::vpxcodec as vpx_encode; -use scrap::{Capturer, Display, STRIDE_ALIGN}; +use scrap::{TraitCapturer, Capturer, Display, STRIDE_ALIGN}; const USAGE: &'static str = " Simple WebM screen capture. diff --git a/libs/scrap/examples/screenshot.rs b/libs/scrap/examples/screenshot.rs index b6bf8a1d9..636768eb8 100644 --- a/libs/scrap/examples/screenshot.rs +++ b/libs/scrap/examples/screenshot.rs @@ -6,7 +6,7 @@ use std::io::ErrorKind::WouldBlock; use std::thread; use std::time::Duration; -use scrap::{i420_to_rgb, Capturer, Display}; +use scrap::{i420_to_rgb, Capturer, Display, TraitCapturer}; fn main() { let n = Display::all().unwrap().len(); diff --git a/libs/scrap/src/common/android.rs b/libs/scrap/src/common/android.rs index 8322da3cd..e15752d8e 100644 --- a/libs/scrap/src/common/android.rs +++ b/libs/scrap/src/common/android.rs @@ -32,8 +32,12 @@ impl Capturer { pub fn height(&self) -> usize { self.display.height() as usize } +} - pub fn frame<'a>(&'a mut self, _timeout: Duration) -> io::Result> { +impl TraitCapturer for Capturer { + fn set_use_yuv(&mut self, _use_yuv: bool) {} + + fn frame<'a>(&'a mut self, _timeout: Duration) -> io::Result> { if let Some(buf) = get_video_raw() { crate::would_block_if_equal(&mut self.saved_raw_data, buf)?; rgba_to_i420(self.width(), self.height(), buf, &mut self.bgra); diff --git a/libs/scrap/src/common/dxgi.rs b/libs/scrap/src/common/dxgi.rs index 855ac7ac3..963f39de1 100644 --- a/libs/scrap/src/common/dxgi.rs +++ b/libs/scrap/src/common/dxgi.rs @@ -1,7 +1,12 @@ -use crate::dxgi; -use std::io::ErrorKind::{NotFound, TimedOut, WouldBlock}; -use std::time::Duration; -use std::{io, ops}; +use crate::{common::TraitCapturer, dxgi}; +use std::{ + io::{ + self, + ErrorKind::{NotFound, TimedOut, WouldBlock}, + }, + ops, + time::Duration, +}; pub struct Capturer { inner: dxgi::Capturer, @@ -21,18 +26,6 @@ impl Capturer { }) } - pub fn set_use_yuv(&mut self, use_yuv: bool) { - self.inner.set_use_yuv(use_yuv); - } - - pub fn is_gdi(&self) -> bool { - self.inner.is_gdi() - } - - pub fn set_gdi(&mut self) -> bool { - self.inner.set_gdi() - } - pub fn cancel_gdi(&mut self) { self.inner.cancel_gdi() } @@ -44,14 +37,28 @@ impl Capturer { pub fn height(&self) -> usize { self.height } +} - pub fn frame<'a>(&'a mut self, timeout: Duration) -> io::Result> { +impl TraitCapturer for Capturer { + fn set_use_yuv(&mut self, use_yuv: bool) { + self.inner.set_use_yuv(use_yuv); + } + + fn frame<'a>(&'a mut self, timeout: Duration) -> io::Result> { match self.inner.frame(timeout.as_millis() as _) { Ok(frame) => Ok(Frame(frame)), Err(ref error) if error.kind() == TimedOut => Err(WouldBlock.into()), Err(error) => Err(error), } } + + fn is_gdi(&self) -> bool { + self.inner.is_gdi() + } + + fn set_gdi(&mut self) -> bool { + self.inner.set_gdi() + } } pub struct Frame<'a>(&'a [u8]); @@ -134,10 +141,6 @@ impl CapturerMag { }) } - pub fn set_use_yuv(&mut self, use_yuv: bool) { - self.inner.set_use_yuv(use_yuv) - } - pub fn exclude(&mut self, cls: &str, name: &str) -> io::Result { self.inner.exclude(cls, name) } @@ -145,8 +148,23 @@ impl CapturerMag { pub fn get_rect(&self) -> ((i32, i32), usize, usize) { self.inner.get_rect() } - pub fn frame<'a>(&'a mut self, _timeout_ms: Duration) -> io::Result> { +} + +impl TraitCapturer for CapturerMag { + fn set_use_yuv(&mut self, use_yuv: bool) { + self.inner.set_use_yuv(use_yuv) + } + + fn frame<'a>(&'a mut self, _timeout_ms: Duration) -> io::Result> { self.inner.frame(&mut self.data)?; Ok(Frame(&self.data)) } + + fn is_gdi(&self) -> bool { + false + } + + fn set_gdi(&mut self) -> bool { + false + } } diff --git a/libs/scrap/src/common/linux.rs b/libs/scrap/src/common/linux.rs index 8498ab7ff..866fb851a 100644 --- a/libs/scrap/src/common/linux.rs +++ b/libs/scrap/src/common/linux.rs @@ -1,6 +1,7 @@ use crate::common::{ wayland, x11::{self, Frame}, + TraitCapturer, }; use std::{io, time::Duration}; @@ -17,13 +18,6 @@ impl Capturer { }) } - pub fn set_use_yuv(&mut self, use_yuv: bool) { - match self { - Capturer::X11(d) => d.set_use_yuv(use_yuv), - Capturer::WAYLAND(d) => d.set_use_yuv(use_yuv), - } - } - pub fn width(&self) -> usize { match self { Capturer::X11(d) => d.width(), @@ -37,8 +31,17 @@ impl Capturer { Capturer::WAYLAND(d) => d.height(), } } +} - pub fn frame<'a>(&'a mut self, timeout: Duration) -> io::Result> { +impl TraitCapturer for Capturer { + fn set_use_yuv(&mut self, use_yuv: bool) { + match self { + Capturer::X11(d) => d.set_use_yuv(use_yuv), + Capturer::WAYLAND(d) => d.set_use_yuv(use_yuv), + } + } + + fn frame<'a>(&'a mut self, timeout: Duration) -> io::Result> { match self { Capturer::X11(d) => d.frame(timeout), Capturer::WAYLAND(d) => d.frame(timeout), diff --git a/libs/scrap/src/common/mod.rs b/libs/scrap/src/common/mod.rs index 9115bfd3a..4a9ade58d 100644 --- a/libs/scrap/src/common/mod.rs +++ b/libs/scrap/src/common/mod.rs @@ -49,3 +49,13 @@ pub fn would_block_if_equal(old: &mut Vec, b: &[u8]) -> std::io::Result<() old.copy_from_slice(b); Ok(()) } + +pub trait TraitCapturer { + fn set_use_yuv(&mut self, use_yuv: bool); + fn frame<'a>(&'a mut self, timeout: std::time::Duration) -> std::io::Result>; + + #[cfg(windows)] + fn is_gdi(&self) -> bool; + #[cfg(windows)] + fn set_gdi(&mut self) -> bool; +} diff --git a/libs/scrap/src/common/quartz.rs b/libs/scrap/src/common/quartz.rs index 46ac1b56d..b4ecf898b 100644 --- a/libs/scrap/src/common/quartz.rs +++ b/libs/scrap/src/common/quartz.rs @@ -50,8 +50,14 @@ impl Capturer { pub fn height(&self) -> usize { self.inner.height() } +} - pub fn frame<'a>(&'a mut self, _timeout_ms: std::time::Duration) -> io::Result> { +impl TraitCapturer for Capturer { + fn set_use_yuv(&mut self, use_yuv: bool) { + self.use_yuv = use_yuv; + } + + fn frame<'a>(&'a mut self, _timeout_ms: std::time::Duration) -> io::Result> { match self.frame.try_lock() { Ok(mut handle) => { let mut frame = None; diff --git a/libs/scrap/src/common/wayland.rs b/libs/scrap/src/common/wayland.rs index 05bb08744..e33cbe745 100644 --- a/libs/scrap/src/common/wayland.rs +++ b/libs/scrap/src/common/wayland.rs @@ -1,4 +1,4 @@ -use crate::common::x11::Frame; +use crate::common::{x11::Frame, TraitCapturer}; use crate::wayland::{capturable::*, *}; use std::{io, time::Duration}; @@ -14,10 +14,6 @@ impl Capturer { Ok(Capturer(display, r, yuv, Default::default())) } - pub fn set_use_yuv(&mut self, use_yuv: bool) { - self.2 = use_yuv; - } - pub fn width(&self) -> usize { self.0.width() } @@ -25,8 +21,14 @@ impl Capturer { pub fn height(&self) -> usize { self.0.height() } +} - pub fn frame<'a>(&'a mut self, timeout: Duration) -> io::Result> { +impl TraitCapturer for Capturer { + fn set_use_yuv(&mut self, use_yuv: bool) { + self.2 = use_yuv; + } + + fn frame<'a>(&'a mut self, timeout: Duration) -> io::Result> { match self.1.capture(timeout.as_millis() as _).map_err(map_err)? { PixelProvider::BGR0(w, h, x) => Ok(Frame(if self.2 { crate::common::bgra_to_i420(w as _, h as _, &x, &mut self.3); diff --git a/libs/scrap/src/common/x11.rs b/libs/scrap/src/common/x11.rs index c1a25c8d6..791514deb 100644 --- a/libs/scrap/src/common/x11.rs +++ b/libs/scrap/src/common/x11.rs @@ -1,4 +1,4 @@ -use crate::x11; +use crate::{x11, common::TraitCapturer}; use std::{io, ops, time::Duration}; pub struct Capturer(x11::Capturer); @@ -8,10 +8,6 @@ impl Capturer { x11::Capturer::new(display.0, yuv).map(Capturer) } - pub fn set_use_yuv(&mut self, use_yuv: bool) { - self.0.set_use_yuv(use_yuv); - } - pub fn width(&self) -> usize { self.0.display().rect().w as usize } @@ -19,8 +15,14 @@ impl Capturer { pub fn height(&self) -> usize { self.0.display().rect().h as usize } +} - pub fn frame<'a>(&'a mut self, _timeout: Duration) -> io::Result> { +impl TraitCapturer for Capturer { + fn set_use_yuv(&mut self, use_yuv: bool) { + self.0.set_use_yuv(use_yuv); + } + + fn frame<'a>(&'a mut self, _timeout: Duration) -> io::Result> { Ok(Frame(self.0.frame()?)) } } diff --git a/src/server/video_service.rs b/src/server/video_service.rs index e6ea713a1..2fb9f3dcd 100644 --- a/src/server/video_service.rs +++ b/src/server/video_service.rs @@ -26,11 +26,11 @@ use hbb_common::tokio::sync::{ use scrap::{ codec::{Encoder, EncoderCfg, HwEncoderConfig}, vpxcodec::{VpxEncoderConfig, VpxVideoCodecId}, - Capturer, Display, Frame, + Capturer, Display, TraitCapturer, }; use std::{ collections::HashSet, - io::{ErrorKind::WouldBlock, Result}, + io::ErrorKind::WouldBlock, ops::{Deref, DerefMut}, time::{self, Duration, Instant}, }; @@ -128,56 +128,6 @@ impl VideoFrameController { } } -pub(super) trait TraitCapturer { - fn frame<'a>(&'a mut self, timeout: Duration) -> Result>; - - fn set_use_yuv(&mut self, use_yuv: bool); - - #[cfg(windows)] - fn is_gdi(&self) -> bool; - #[cfg(windows)] - fn set_gdi(&mut self) -> bool; -} - -impl TraitCapturer for Capturer { - fn frame<'a>(&'a mut self, timeout: Duration) -> Result> { - self.frame(timeout) - } - - fn set_use_yuv(&mut self, use_yuv: bool) { - self.set_use_yuv(use_yuv); - } - - #[cfg(windows)] - fn is_gdi(&self) -> bool { - self.is_gdi() - } - - #[cfg(windows)] - fn set_gdi(&mut self) -> bool { - self.set_gdi() - } -} - -#[cfg(windows)] -impl TraitCapturer for scrap::CapturerMag { - fn frame<'a>(&'a mut self, _timeout_ms: Duration) -> Result> { - self.frame(_timeout_ms) - } - - fn set_use_yuv(&mut self, use_yuv: bool) { - self.set_use_yuv(use_yuv); - } - - fn is_gdi(&self) -> bool { - false - } - - fn set_gdi(&mut self) -> bool { - false - } -} - pub fn new() -> GenericService { let sp = GenericService::new(NAME, true); sp.run(run); diff --git a/src/server/wayland.rs b/src/server/wayland.rs index e84be3f7c..1ac2c18be 100644 --- a/src/server/wayland.rs +++ b/src/server/wayland.rs @@ -1,30 +1,39 @@ use super::*; use hbb_common::allow_err; -use scrap::{Capturer, Display, Frame}; -use std::{io::Result, time::Duration}; +use scrap::{Capturer, Display, Frame, TraitCapturer}; +use std::io::Result; lazy_static::lazy_static! { static ref CAP_DISPLAY_INFO: RwLock = RwLock::new(0); } + +struct CapturerPtr(*mut Capturer); + +impl Clone for CapturerPtr { + fn clone(&self) -> Self { + Self(self.0) + } +} + +impl TraitCapturer for CapturerPtr { + fn frame<'a>(&'a mut self, timeout: Duration) -> Result> { + unsafe { (*self.0).frame(timeout) } + } + + fn set_use_yuv(&mut self, use_yuv: bool) { + unsafe { + (*self.0).set_use_yuv(use_yuv); + } + } +} + struct CapDisplayInfo { rects: Vec<((i32, i32), usize, usize)>, displays: Vec, num: usize, primary: usize, current: usize, - capturer: *mut Capturer, -} - -impl super::video_service::TraitCapturer for *mut Capturer { - fn frame<'a>(&'a mut self, timeout: Duration) -> Result> { - unsafe { (**self).frame(timeout) } - } - - fn set_use_yuv(&mut self, use_yuv: bool) { - unsafe { - (**self).set_use_yuv(use_yuv); - } - } + capturer: CapturerPtr, } async fn check_init() -> ResultType<()> { @@ -68,6 +77,7 @@ async fn check_init() -> ResultType<()> { let capturer = Box::into_raw(Box::new( Capturer::new(display, true).with_context(|| "Failed to create capturer")?, )); + let capturer = CapturerPtr(capturer); let cap_display_info = Box::into_raw(Box::new(CapDisplayInfo { rects, displays, @@ -104,7 +114,7 @@ pub fn clear() { if *lock != 0 { unsafe { let cap_display_info = Box::from_raw(*lock as *mut CapDisplayInfo); - let _ = Box::from_raw(cap_display_info.capturer); + let _ = Box::from_raw(cap_display_info.capturer.0); } *lock = 0; } @@ -170,7 +180,7 @@ pub(super) fn get_capturer() -> ResultType { current: cap_display_info.current, privacy_mode_id: 0, _captuerer_privacy_mode_id: 0, - capturer: Box::new(cap_display_info.capturer), + capturer: Box::new(cap_display_info.capturer.clone()), }) } } else {