diff --git a/Cargo.lock b/Cargo.lock index 01f6570dc..2d3de8743 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2973,8 +2973,8 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hwcodec" -version = "0.1.1" -source = "git+https://github.com/21pages/hwcodec?branch=stable#82cdc15457e42feaf14e1b38622506b2d54baf76" +version = "0.1.3" +source = "git+https://github.com/21pages/hwcodec?branch=stable#83300549075158e5a3fa6c59ea527af3330e48ff" dependencies = [ "bindgen 0.59.2", "cc", diff --git a/flutter/lib/common/widgets/dialog.dart b/flutter/lib/common/widgets/dialog.dart index d1e14d2fb..d45509096 100644 --- a/flutter/lib/common/widgets/dialog.dart +++ b/flutter/lib/common/widgets/dialog.dart @@ -1248,25 +1248,41 @@ customImageQualityDialog(SessionID sessionId, String id, FFI ffi) async { double fpsInitValue = 30; bool qualitySet = false; bool fpsSet = false; + + bool? direct; + try { + direct = + ConnectionTypeState.find(id).direct.value == ConnectionType.strDirect; + } catch (_) {} + bool hideFps = (await bind.mainIsUsingPublicServer() && direct != true) || + versionCmp(ffi.ffiModel.pi.version, '1.2.0') < 0; + bool hideMoreQuality = + (await bind.mainIsUsingPublicServer() && direct != true) || + versionCmp(ffi.ffiModel.pi.version, '1.2.2') < 0; + setCustomValues({double? quality, double? fps}) async { if (quality != null) { qualitySet = true; await bind.sessionSetCustomImageQuality( sessionId: sessionId, value: quality.toInt()); + print("quality:$quality"); } if (fps != null) { fpsSet = true; await bind.sessionSetCustomFps(sessionId: sessionId, fps: fps.toInt()); + print("fps:$fps"); } if (!qualitySet) { qualitySet = true; await bind.sessionSetCustomImageQuality( sessionId: sessionId, value: qualityInitValue.toInt()); + print("qualityInitValue:$qualityInitValue"); } - if (!fpsSet) { + if (!hideFps && !fpsSet) { fpsSet = true; await bind.sessionSetCustomFps( sessionId: sessionId, fps: fpsInitValue.toInt()); + print("fpsInitValue:$fpsInitValue"); } } @@ -1279,7 +1295,9 @@ customImageQualityDialog(SessionID sessionId, String id, FFI ffi) async { final quality = await bind.sessionGetCustomImageQuality(sessionId: sessionId); qualityInitValue = quality != null && quality.isNotEmpty ? quality[0].toDouble() : 50.0; - if (qualityInitValue < 10 || qualityInitValue > 2000) { + if ((hideMoreQuality && qualityInitValue > 100) || + qualityInitValue < 10 || + qualityInitValue > 2000) { qualityInitValue = 50; } // fps @@ -1289,20 +1307,14 @@ customImageQualityDialog(SessionID sessionId, String id, FFI ffi) async { if (fpsInitValue < 5 || fpsInitValue > 120) { fpsInitValue = 30; } - bool? direct; - try { - direct = - ConnectionTypeState.find(id).direct.value == ConnectionType.strDirect; - } catch (_) {} - bool notShowFps = (await bind.mainIsUsingPublicServer() && direct != true) || - versionCmp(ffi.ffiModel.pi.version, '1.2.0') < 0; final content = customImageQualityWidget( initQuality: qualityInitValue, initFps: fpsInitValue, setQuality: (v) => setCustomValues(quality: v), setFps: (v) => setCustomValues(fps: v), - showFps: !notShowFps); + showFps: !hideFps, + showMoreQuality: !hideMoreQuality); msgBoxCommon(ffi.dialogManager, 'Custom Image Quality', content, [btnClose]); } diff --git a/flutter/lib/common/widgets/setting_widgets.dart b/flutter/lib/common/widgets/setting_widgets.dart index 771b65ab5..b0a4f1a92 100644 --- a/flutter/lib/common/widgets/setting_widgets.dart +++ b/flutter/lib/common/widgets/setting_widgets.dart @@ -10,7 +10,11 @@ customImageQualityWidget( required double initFps, required Function(double) setQuality, required Function(double) setFps, - required bool showFps}) { + required bool showFps, + required bool showMoreQuality}) { + if (!showMoreQuality && initQuality > 100) { + initQuality = 50; + } final qualityValue = initQuality.obs; final fpsValue = initFps.obs; @@ -69,7 +73,7 @@ customImageQualityWidget( style: const TextStyle(fontSize: 15), )), // mobile doesn't have enough space - if (!isMobile) + if (showMoreQuality && !isMobile) Expanded( flex: 1, child: Row( @@ -85,7 +89,7 @@ customImageQualityWidget( )) ], )), - if (isMobile) + if (showMoreQuality && isMobile) Obx(() => Row( children: [ Expanded( @@ -160,7 +164,8 @@ customImageQualitySetting() { setFps: (v) { bind.mainSetUserDefaultOption(key: fpsKey, value: v.toString()); }, - showFps: true); + showFps: true, + showMoreQuality: true); } Future setServerConfig( diff --git a/flutter/lib/desktop/widgets/tabbar_widget.dart b/flutter/lib/desktop/widgets/tabbar_widget.dart index 7f1449ca4..67931d353 100644 --- a/flutter/lib/desktop/widgets/tabbar_widget.dart +++ b/flutter/lib/desktop/widgets/tabbar_widget.dart @@ -583,32 +583,19 @@ class WindowActionPanelState extends State void onWindowClose() async { mainWindowClose() async => await windowManager.hide(); notMainWindowClose(WindowController controller) async { - if (widget.tabController.length == 0) { - debugPrint("close emtpy multiwindow, hide"); - await controller.hide(); - await rustDeskWinManager - .call(WindowType.Main, kWindowEventHide, {"id": kWindowId!}); - } else { + if (widget.tabController.length != 0) { debugPrint("close not emtpy multiwindow from taskbar"); if (Platform.isWindows) { await controller.show(); await controller.focus(); final res = await widget.onClose?.call() ?? true; - if (res) { - Future.delayed(Duration.zero, () async { - // onWindowClose will be called again to hide - await WindowController.fromWindowId(kWindowId!).close(); - }); - } - } else { - // ubuntu22.04 windowOnTop not work from taskbar - widget.tabController.clear(); - Future.delayed(Duration.zero, () async { - // onWindowClose will be called again to hide - await WindowController.fromWindowId(kWindowId!).close(); - }); + if (!res) return; } + widget.tabController.clear(); } + await controller.hide(); + await rustDeskWinManager + .call(WindowType.Main, kWindowEventHide, {"id": kWindowId!}); } macOSWindowClose( diff --git a/libs/scrap/src/common/android.rs b/libs/scrap/src/common/android.rs index ffbf4353a..538b52b69 100644 --- a/libs/scrap/src/common/android.rs +++ b/libs/scrap/src/common/android.rs @@ -43,7 +43,7 @@ impl crate::TraitCapturer for Capturer { unsafe { std::ptr::copy_nonoverlapping(buf.as_ptr(), self.rgba.as_mut_ptr(), buf.len()) }; - Ok(Frame::new(&self.rgba, self.height())) + Ok(Frame::new(&self.rgba, self.width(), self.height())) } else { return Err(io::ErrorKind::WouldBlock.into()); } @@ -51,16 +51,23 @@ impl crate::TraitCapturer for Capturer { } pub struct Frame<'a> { - pub data: &'a [u8], - pub stride: Vec, + data: &'a [u8], + width: usize, + height: usize, + stride: Vec, } impl<'a> Frame<'a> { - pub fn new(data: &'a [u8], h: usize) -> Self { - let stride = data.len() / h; - let mut v = Vec::new(); - v.push(stride); - Frame { data, stride: v } + pub fn new(data: &'a [u8], width: usize, height: usize) -> Self { + let stride0 = data.len() / height; + let mut stride = Vec::new(); + stride.push(stride0); + Frame { + data, + width, + height, + stride, + } } } @@ -69,6 +76,14 @@ impl<'a> crate::TraitFrame for Frame<'a> { self.data } + fn width(&self) -> usize { + self.width + } + + fn height(&self) -> usize { + self.height + } + fn stride(&self) -> Vec { self.stride.clone() } diff --git a/libs/scrap/src/common/aom.rs b/libs/scrap/src/common/aom.rs index c75106a6e..975a82d64 100644 --- a/libs/scrap/src/common/aom.rs +++ b/libs/scrap/src/common/aom.rs @@ -7,9 +7,9 @@ include!(concat!(env!("OUT_DIR"), "/aom_ffi.rs")); use crate::codec::{base_bitrate, codec_thread_num, Quality}; -use crate::Pixfmt; use crate::{codec::EncoderApi, EncodeFrame, STRIDE_ALIGN}; use crate::{common::GoogleImage, generate_call_macro, generate_call_ptr_macro, Error, Result}; +use crate::{EncodeYuvFormat, Pixfmt}; use hbb_common::{ anyhow::{anyhow, Context}, bytes::Bytes, @@ -54,6 +54,7 @@ pub struct AomEncoder { width: usize, height: usize, i444: bool, + yuvfmt: EncodeYuvFormat, } // https://webrtc.googlesource.com/src/+/refs/heads/main/modules/video_coding/codecs/av1/libaom_av1_encoder.cc @@ -241,6 +242,7 @@ impl EncoderApi for AomEncoder { width: config.width as _, height: config.height as _, i444, + yuvfmt: Self::get_yuvfmt(config.width, config.height, i444), }) } _ => Err(anyhow!("encoder type mismatch")), @@ -263,35 +265,7 @@ impl EncoderApi for AomEncoder { } fn yuvfmt(&self) -> crate::EncodeYuvFormat { - let mut img = Default::default(); - let fmt = if self.i444 { - aom_img_fmt::AOM_IMG_FMT_I444 - } else { - aom_img_fmt::AOM_IMG_FMT_I420 - }; - unsafe { - aom_img_wrap( - &mut img, - fmt, - self.width as _, - self.height as _, - crate::STRIDE_ALIGN as _, - 0x1 as _, - ); - } - let pixfmt = if self.i444 { - Pixfmt::I444 - } else { - Pixfmt::I420 - }; - crate::EncodeYuvFormat { - pixfmt, - w: img.w as _, - h: img.h as _, - stride: img.stride.map(|s| s as usize).to_vec(), - u: img.planes[1] as usize - img.planes[0] as usize, - v: img.planes[2] as usize - img.planes[0] as usize, - } + self.yuvfmt.clone() } fn set_quality(&mut self, quality: Quality) -> ResultType<()> { @@ -400,6 +374,34 @@ impl AomEncoder { (q_min, q_max) } + + fn get_yuvfmt(width: u32, height: u32, i444: bool) -> EncodeYuvFormat { + let mut img = Default::default(); + let fmt = if i444 { + aom_img_fmt::AOM_IMG_FMT_I444 + } else { + aom_img_fmt::AOM_IMG_FMT_I420 + }; + unsafe { + aom_img_wrap( + &mut img, + fmt, + width as _, + height as _, + crate::STRIDE_ALIGN as _, + 0x1 as _, + ); + } + let pixfmt = if i444 { Pixfmt::I444 } else { Pixfmt::I420 }; + EncodeYuvFormat { + pixfmt, + w: img.w as _, + h: img.h as _, + stride: img.stride.map(|s| s as usize).to_vec(), + u: img.planes[1] as usize - img.planes[0] as usize, + v: img.planes[2] as usize - img.planes[0] as usize, + } + } } impl Drop for AomEncoder { diff --git a/libs/scrap/src/common/convert.rs b/libs/scrap/src/common/convert.rs index 0ef3bc362..3bf0e7a03 100644 --- a/libs/scrap/src/common/convert.rs +++ b/libs/scrap/src/common/convert.rs @@ -202,17 +202,31 @@ pub fn convert_to_yuv( ) -> ResultType<()> { let src = captured.data(); let src_stride = captured.stride(); - let captured_pixfmt = captured.pixfmt(); - if captured_pixfmt == crate::Pixfmt::BGRA || captured_pixfmt == crate::Pixfmt::RGBA { - if src.len() < src_stride[0] * dst_fmt.h { + let src_pixfmt = captured.pixfmt(); + let src_width = captured.width(); + let src_height = captured.height(); + if src_width > dst_fmt.w || src_height > dst_fmt.h { + bail!( + "src rect > dst rect: ({src_width}, {src_height}) > ({},{})", + dst_fmt.w, + dst_fmt.h + ); + } + if src_pixfmt == crate::Pixfmt::BGRA || src_pixfmt == crate::Pixfmt::RGBA { + if src.len() < src_stride[0] * src_height { bail!( - "length not enough: {} < {}", + "wrong src len, {} < {} * {}", src.len(), - src_stride[0] * dst_fmt.h + src_stride[0], + src_height ); } } - match (captured_pixfmt, dst_fmt.pixfmt) { + let align = |x:usize| { + (x + 63) / 64 * 64 + }; + + match (src_pixfmt, dst_fmt.pixfmt) { (crate::Pixfmt::BGRA, crate::Pixfmt::I420) | (crate::Pixfmt::RGBA, crate::Pixfmt::I420) => { let dst_stride_y = dst_fmt.stride[0]; let dst_stride_uv = dst_fmt.stride[1]; @@ -220,7 +234,7 @@ pub fn convert_to_yuv( let dst_y = dst.as_mut_ptr(); let dst_u = dst[dst_fmt.u..].as_mut_ptr(); let dst_v = dst[dst_fmt.v..].as_mut_ptr(); - let f = if captured_pixfmt == crate::Pixfmt::BGRA { + let f = if src_pixfmt == crate::Pixfmt::BGRA { ARGBToI420 } else { ABGRToI420 @@ -234,17 +248,20 @@ pub fn convert_to_yuv( dst_stride_uv as _, dst_v, dst_stride_uv as _, - dst_fmt.w as _, - dst_fmt.h as _, + src_width as _, + src_height as _, )); } (crate::Pixfmt::BGRA, crate::Pixfmt::NV12) | (crate::Pixfmt::RGBA, crate::Pixfmt::NV12) => { let dst_stride_y = dst_fmt.stride[0]; let dst_stride_uv = dst_fmt.stride[1]; - dst.resize(dst_fmt.h * (dst_stride_y + dst_stride_uv / 2), 0); + dst.resize( + align(dst_fmt.h) * (align(dst_stride_y) + align(dst_stride_uv / 2)), + 0, + ); let dst_y = dst.as_mut_ptr(); let dst_uv = dst[dst_fmt.u..].as_mut_ptr(); - let f = if captured_pixfmt == crate::Pixfmt::BGRA { + let f = if src_pixfmt == crate::Pixfmt::BGRA { ARGBToNV12 } else { ABGRToNV12 @@ -256,19 +273,22 @@ pub fn convert_to_yuv( dst_stride_y as _, dst_uv, dst_stride_uv as _, - dst_fmt.w as _, - dst_fmt.h as _, + src_width as _, + src_height as _, )); } (crate::Pixfmt::BGRA, crate::Pixfmt::I444) | (crate::Pixfmt::RGBA, crate::Pixfmt::I444) => { let dst_stride_y = dst_fmt.stride[0]; let dst_stride_u = dst_fmt.stride[1]; let dst_stride_v = dst_fmt.stride[2]; - dst.resize(dst_fmt.h * (dst_stride_y + dst_stride_u + dst_stride_v), 0); + dst.resize( + align(dst_fmt.h) * (align(dst_stride_y) + align(dst_stride_u) + align(dst_stride_v)), + 0, + ); let dst_y = dst.as_mut_ptr(); let dst_u = dst[dst_fmt.u..].as_mut_ptr(); let dst_v = dst[dst_fmt.v..].as_mut_ptr(); - let src = if captured_pixfmt == crate::Pixfmt::BGRA { + let src = if src_pixfmt == crate::Pixfmt::BGRA { src } else { mid_data.resize(src.len(), 0); @@ -277,8 +297,8 @@ pub fn convert_to_yuv( src_stride[0] as _, mid_data.as_mut_ptr(), src_stride[0] as _, - dst_fmt.w as _, - dst_fmt.h as _, + src_width as _, + src_height as _, )); mid_data }; @@ -291,13 +311,13 @@ pub fn convert_to_yuv( dst_stride_u as _, dst_v, dst_stride_v as _, - dst_fmt.w as _, - dst_fmt.h as _, + src_width as _, + src_height as _, )); } _ => { bail!( - "convert not support, {captured_pixfmt:?} -> {:?}", + "convert not support, {src_pixfmt:?} -> {:?}", dst_fmt.pixfmt ); } diff --git a/libs/scrap/src/common/dxgi.rs b/libs/scrap/src/common/dxgi.rs index cfec42195..3bf1783a8 100644 --- a/libs/scrap/src/common/dxgi.rs +++ b/libs/scrap/src/common/dxgi.rs @@ -41,7 +41,7 @@ impl Capturer { impl TraitCapturer for Capturer { fn frame<'a>(&'a mut self, timeout: Duration) -> io::Result> { match self.inner.frame(timeout.as_millis() as _) { - Ok(frame) => Ok(Frame::new(frame, self.height)), + Ok(frame) => Ok(Frame::new(frame, self.width, self.height)), Err(ref error) if error.kind() == TimedOut => Err(WouldBlock.into()), Err(error) => Err(error), } @@ -58,15 +58,22 @@ impl TraitCapturer for Capturer { pub struct Frame<'a> { data: &'a [u8], + width: usize, + height: usize, stride: Vec, } impl<'a> Frame<'a> { - pub fn new(data: &'a [u8], h: usize) -> Self { - let stride = data.len() / h; - let mut v = Vec::new(); - v.push(stride); - Frame { data, stride: v } + pub fn new(data: &'a [u8], width: usize, height: usize) -> Self { + let stride0 = data.len() / height; + let mut stride = Vec::new(); + stride.push(stride0); + Frame { + data, + width, + height, + stride, + } } } @@ -75,6 +82,14 @@ impl<'a> crate::TraitFrame for Frame<'a> { self.data } + fn width(&self) -> usize { + self.width + } + + fn height(&self) -> usize { + self.height + } + fn stride(&self) -> Vec { self.stride.clone() } @@ -167,7 +182,11 @@ impl CapturerMag { impl TraitCapturer for CapturerMag { fn frame<'a>(&'a mut self, _timeout_ms: Duration) -> io::Result> { self.inner.frame(&mut self.data)?; - Ok(Frame::new(&self.data, self.inner.get_rect().2)) + Ok(Frame::new( + &self.data, + self.inner.get_rect().1, + self.inner.get_rect().2, + )) } fn is_gdi(&self) -> bool { diff --git a/libs/scrap/src/common/mod.rs b/libs/scrap/src/common/mod.rs index f1cc9ab0e..4433e512f 100644 --- a/libs/scrap/src/common/mod.rs +++ b/libs/scrap/src/common/mod.rs @@ -112,6 +112,10 @@ pub trait TraitCapturer { pub trait TraitFrame { fn data(&self) -> &[u8]; + fn width(&self) -> usize; + + fn height(&self) -> usize; + fn stride(&self) -> Vec; fn pixfmt(&self) -> Pixfmt; @@ -125,6 +129,7 @@ pub enum Pixfmt { I444, } +#[derive(Debug, Clone)] pub struct EncodeYuvFormat { pub pixfmt: Pixfmt, pub w: usize, diff --git a/libs/scrap/src/common/quartz.rs b/libs/scrap/src/common/quartz.rs index 9aad7ee09..d84913999 100644 --- a/libs/scrap/src/common/quartz.rs +++ b/libs/scrap/src/common/quartz.rs @@ -55,7 +55,12 @@ impl crate::TraitCapturer for Capturer { Some(mut frame) => { crate::would_block_if_equal(&mut self.saved_raw_data, frame.inner())?; frame.surface_to_bgra(self.height()); - Ok(Frame(frame, PhantomData)) + Ok(Frame { + frame, + data: PhantomData, + width: self.width(), + height: self.height(), + }) } None => Err(io::ErrorKind::WouldBlock.into()), @@ -69,16 +74,29 @@ impl crate::TraitCapturer for Capturer { } } -pub struct Frame<'a>(pub quartz::Frame, PhantomData<&'a [u8]>); +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.0 + &*self.frame + } + + fn width(&self) -> usize { + self.width + } + + fn height(&self) -> usize { + self.height } fn stride(&self) -> Vec { let mut v = Vec::new(); - v.push(self.0.stride()); + v.push(self.frame.stride()); v } diff --git a/libs/scrap/src/common/vpxcodec.rs b/libs/scrap/src/common/vpxcodec.rs index d3fb9c7d3..19ede9bba 100644 --- a/libs/scrap/src/common/vpxcodec.rs +++ b/libs/scrap/src/common/vpxcodec.rs @@ -8,7 +8,7 @@ use hbb_common::message_proto::{Chroma, EncodedVideoFrame, EncodedVideoFrames, V use hbb_common::ResultType; use crate::codec::{base_bitrate, codec_thread_num, EncoderApi, Quality}; -use crate::{GoogleImage, Pixfmt, STRIDE_ALIGN}; +use crate::{EncodeYuvFormat, GoogleImage, Pixfmt, STRIDE_ALIGN}; use super::vpx::{vp8e_enc_control_id::*, vpx_codec_err_t::*, *}; use crate::{generate_call_macro, generate_call_ptr_macro, Error, Result}; @@ -40,6 +40,7 @@ pub struct VpxEncoder { height: usize, id: VpxVideoCodecId, i444: bool, + yuvfmt: EncodeYuvFormat, } pub struct VpxDecoder { @@ -175,6 +176,7 @@ impl EncoderApi for VpxEncoder { height: config.height as _, id: config.codec, i444, + yuvfmt: Self::get_yuvfmt(config.width, config.height, i444), }) } _ => Err(anyhow!("encoder type mismatch")), @@ -202,35 +204,7 @@ impl EncoderApi for VpxEncoder { } fn yuvfmt(&self) -> crate::EncodeYuvFormat { - let mut img = Default::default(); - let fmt = if self.i444 { - vpx_img_fmt::VPX_IMG_FMT_I444 - } else { - vpx_img_fmt::VPX_IMG_FMT_I420 - }; - unsafe { - vpx_img_wrap( - &mut img, - fmt, - self.width as _, - self.height as _, - crate::STRIDE_ALIGN as _, - 0x1 as _, - ); - } - let pixfmt = if self.i444 { - Pixfmt::I444 - } else { - Pixfmt::I420 - }; - crate::EncodeYuvFormat { - pixfmt, - w: img.w as _, - h: img.h as _, - stride: img.stride.map(|s| s as usize).to_vec(), - u: img.planes[1] as usize - img.planes[0] as usize, - v: img.planes[2] as usize - img.planes[0] as usize, - } + self.yuvfmt.clone() } fn set_quality(&mut self, quality: Quality) -> ResultType<()> { @@ -362,6 +336,34 @@ impl VpxEncoder { (q_min, q_max) } + + fn get_yuvfmt(width: u32, height: u32, i444: bool) -> EncodeYuvFormat { + let mut img = Default::default(); + let fmt = if i444 { + vpx_img_fmt::VPX_IMG_FMT_I444 + } else { + vpx_img_fmt::VPX_IMG_FMT_I420 + }; + unsafe { + vpx_img_wrap( + &mut img, + fmt, + width as _, + height as _, + crate::STRIDE_ALIGN as _, + 0x1 as _, + ); + } + let pixfmt = if i444 { Pixfmt::I444 } else { Pixfmt::I420 }; + EncodeYuvFormat { + pixfmt, + w: img.w as _, + h: img.h as _, + stride: img.stride.map(|s| s as usize).to_vec(), + u: img.planes[1] as usize - img.planes[0] as usize, + v: img.planes[2] as usize - img.planes[0] as usize, + } + } } impl Drop for VpxEncoder { diff --git a/libs/scrap/src/common/wayland.rs b/libs/scrap/src/common/wayland.rs index 5c5b74e5b..cf36a83a4 100644 --- a/libs/scrap/src/common/wayland.rs +++ b/libs/scrap/src/common/wayland.rs @@ -62,8 +62,8 @@ impl Capturer { impl TraitCapturer for Capturer { 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::new(x, crate::Pixfmt::BGRA, h)), - PixelProvider::RGB0(_w, h, x) => Ok(Frame::new(x, crate::Pixfmt::RGBA, h)), + PixelProvider::BGR0(w, h, x) => Ok(Frame::new(x, crate::Pixfmt::BGRA, w, h)), + PixelProvider::RGB0(w, h, x) => Ok(Frame::new(x, crate::Pixfmt::RGBA, w,h)), PixelProvider::NONE => Err(std::io::ErrorKind::WouldBlock.into()), _ => Err(map_err("Invalid data")), } diff --git a/libs/scrap/src/common/x11.rs b/libs/scrap/src/common/x11.rs index f5009095e..08ec5e1f1 100644 --- a/libs/scrap/src/common/x11.rs +++ b/libs/scrap/src/common/x11.rs @@ -1,4 +1,4 @@ -use crate::{common::TraitCapturer, x11, TraitFrame, Pixfmt}; +use crate::{common::TraitCapturer, x11, Pixfmt, TraitFrame}; use std::{io, time::Duration}; pub struct Capturer(x11::Capturer); @@ -25,26 +25,42 @@ impl TraitCapturer for Capturer { } } -pub struct Frame<'a>{ +pub struct Frame<'a> { pub data: &'a [u8], - pub pixfmt:Pixfmt, - pub stride:Vec, + pub pixfmt: Pixfmt, + pub width: usize, + pub height: usize, + pub stride: Vec, } -impl<'a> Frame<'a> { - pub fn new(data:&'a [u8], pixfmt:Pixfmt, h:usize) -> Self { - let stride = data.len() / h; - let mut v = Vec::new(); - v.push(stride); - Self { data, pixfmt, stride: v } +impl<'a> Frame<'a> { + pub fn new(data: &'a [u8], pixfmt: Pixfmt, width: usize, height: usize) -> Self { + let stride0 = data.len() / height; + let mut stride = Vec::new(); + stride.push(stride0); + Self { + data, + pixfmt, + width, + height, + stride, + } } } -impl<'a> TraitFrame for Frame<'a> { +impl<'a> TraitFrame for Frame<'a> { fn data(&self) -> &[u8] { self.data } + fn width(&self) -> usize { + self.width + } + + fn height(&self) -> usize { + self.height + } + fn stride(&self) -> Vec { self.stride.clone() } diff --git a/libs/scrap/src/x11/capturer.rs b/libs/scrap/src/x11/capturer.rs index 52b882bbf..308df1651 100644 --- a/libs/scrap/src/x11/capturer.rs +++ b/libs/scrap/src/x11/capturer.rs @@ -102,7 +102,7 @@ impl Capturer { let result = unsafe { slice::from_raw_parts(self.buffer, self.size) }; crate::would_block_if_equal(&mut self.saved_raw_data, result)?; Ok( - Frame::new(result, crate::Pixfmt::BGRA, self.display.h()) + Frame::new(result, crate::Pixfmt::BGRA, self.display.w(), self.display.h()) ) } } diff --git a/src/server/connection.rs b/src/server/connection.rs index a31fcb8d4..da12f6fee 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -670,7 +670,6 @@ impl Connection { conn.lr.my_id.clone(), ); video_service::notify_video_frame_fetched(id, None); - scrap::codec::Encoder::update(id, scrap::codec::EncodingUpdate::Remove); if conn.authorized { password::update_temporary_password(); } @@ -1173,7 +1172,7 @@ impl Connection { sub_service = true; } } - Self::on_remote_authorized(); + self.on_remote_authorized(); } let mut msg_out = Message::new(); msg_out.set_login_response(res); @@ -1212,9 +1211,10 @@ impl Connection { } } - fn on_remote_authorized() { + fn on_remote_authorized(&self) { use std::sync::Once; static _ONCE: Once = Once::new(); + self.update_codec_on_login(); #[cfg(any(target_os = "windows", target_os = "linux"))] if !Config::get_option("allow-remove-wallpaper").is_empty() { // multi connections set once @@ -1412,8 +1412,8 @@ impl Connection { return Config::get_option(enable_prefix_option).is_empty(); } - fn update_codec_on_login(&self, lr: &LoginRequest) { - if let Some(o) = lr.option.as_ref() { + fn update_codec_on_login(&self) { + if let Some(o) = self.lr.clone().option.as_ref() { if let Some(q) = o.supported_decoding.clone().take() { scrap::codec::Encoder::update( self.inner.id(), @@ -1438,9 +1438,6 @@ impl Connection { if let Some(o) = lr.option.as_ref() { self.options_in_login = Some(o.clone()); } - if lr.union.is_none() { - self.update_codec_on_login(&lr); - } self.video_ack_required = lr.video_ack_required; } @@ -2969,18 +2966,6 @@ mod raii { fn drop(&mut self) { let mut active_conns_lock = ALIVE_CONNS.lock().unwrap(); active_conns_lock.retain(|&c| c != self.0); - #[cfg(not(any(target_os = "android", target_os = "ios")))] - if active_conns_lock.is_empty() { - display_service::reset_resolutions(); - } - #[cfg(all(windows, feature = "virtual_display_driver"))] - if active_conns_lock.is_empty() { - let _ = virtual_display_manager::reset_all(); - } - #[cfg(all(windows))] - if active_conns_lock.is_empty() { - crate::privacy_win_mag::stop(); - } video_service::VIDEO_QOS .lock() .unwrap() @@ -2988,17 +2973,20 @@ mod raii { } } - pub struct AuthedConnID(i32); + pub struct AuthedConnID(i32, AuthConnType); impl AuthedConnID { pub fn new(id: i32, conn_type: AuthConnType) -> Self { AUTHED_CONNS.lock().unwrap().push((id, conn_type)); - Self(id) + Self(id, conn_type) } } impl Drop for AuthedConnID { fn drop(&mut self) { + if self.1 == AuthConnType::Remote { + scrap::codec::Encoder::update(self.0, scrap::codec::EncodingUpdate::Remove); + } let mut lock = AUTHED_CONNS.lock().unwrap(); lock.retain(|&c| c.0 != self.0); if lock.iter().filter(|c| c.1 == AuthConnType::Remote).count() == 0 { @@ -3006,6 +2994,12 @@ mod raii { { *WALLPAPER_REMOVER.lock().unwrap() = None; } + #[cfg(not(any(target_os = "android", target_os = "ios")))] + display_service::reset_resolutions(); + #[cfg(all(windows, feature = "virtual_display_driver"))] + let _ = virtual_display_manager::reset_all(); + #[cfg(all(windows))] + crate::privacy_win_mag::stop(); } } } diff --git a/src/server/portable_service.rs b/src/server/portable_service.rs index 65d861bea..51d665d0a 100644 --- a/src/server/portable_service.rs +++ b/src/server/portable_service.rs @@ -704,7 +704,7 @@ pub mod client { } let frame_ptr = base.add(ADDR_CAPTURE_FRAME); let data = slice::from_raw_parts(frame_ptr, (*frame_info).length); - Ok(Frame::new(data, self.height)) + Ok(Frame::new(data, self.width, self.height)) } else { let ptr = base.add(ADDR_CAPTURE_WOULDBLOCK); let wouldblock = utils::ptr_to_i32(ptr);