From efa6b5972da1b4d5105a8f8a10144415655e1963 Mon Sep 17 00:00:00 2001 From: tom Date: Sat, 16 Jul 2022 00:45:23 +0800 Subject: [PATCH 01/17] update bytes(protobuf types) mapping, from Vec to bytes:Byte issues:958 --- Cargo.toml | 1 + libs/hbb_common/build.rs | 5 +++++ libs/scrap/src/common/vpxcodec.rs | 3 ++- src/client.rs | 8 ++++---- src/clipboard_file.rs | 8 ++++---- src/common.rs | 4 ++-- src/platform/windows.rs | 2 +- src/rendezvous_mediator.rs | 14 +++++++------- src/server.rs | 6 ++++-- src/server/audio_service.rs | 2 +- src/server/connection.rs | 2 +- src/server/input_service.rs | 2 +- src/ui/cm.rs | 2 +- 13 files changed, 34 insertions(+), 25 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f270f7b30..898d81da8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,6 +55,7 @@ rpassword = "6.0" base64 = "0.13" sysinfo = "0.23" num_cpus = "1.13" +bytes = "1.1" [target.'cfg(not(target_os = "linux"))'.dependencies] reqwest = { version = "0.11", features = ["json", "rustls-tls"], default-features=false } diff --git a/libs/hbb_common/build.rs b/libs/hbb_common/build.rs index 5c1c6af22..3c2a3c7a4 100644 --- a/libs/hbb_common/build.rs +++ b/libs/hbb_common/build.rs @@ -5,6 +5,11 @@ fn main() { .out_dir("src/protos") .inputs(&["protos/rendezvous.proto", "protos/message.proto"]) .include("protos") + .customize( + protobuf_codegen::Customize::default() + .tokio_bytes(true) + // .tokio_bytes_for_string(true) + ) .run() .expect("Codegen failed."); } diff --git a/libs/scrap/src/common/vpxcodec.rs b/libs/scrap/src/common/vpxcodec.rs index fc54b153c..0fda53fa3 100644 --- a/libs/scrap/src/common/vpxcodec.rs +++ b/libs/scrap/src/common/vpxcodec.rs @@ -12,6 +12,7 @@ use crate::STRIDE_ALIGN; use super::vpx::{vp8e_enc_control_id::*, vpx_codec_err_t::*, *}; use std::os::raw::{c_int, c_uint}; use std::{ptr, slice}; +use hbb_common::bytes::Bytes; #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum VpxVideoCodecId { @@ -291,7 +292,7 @@ impl VpxEncoder { #[inline] fn create_frame(frame: &EncodeFrame) -> EncodedVideoFrame { EncodedVideoFrame { - data: frame.data.to_vec(), + data: Bytes::from(frame.data.to_vec()), key: frame.key, pts: frame.pts, ..Default::default() diff --git a/src/client.rs b/src/client.rs index 33d966d2a..a1c9b2b0f 100644 --- a/src/client.rs +++ b/src/client.rs @@ -201,7 +201,7 @@ impl Client { } else { peer_nat_type = ph.nat_type(); is_local = ph.is_local(); - signed_id_pk = ph.pk; + signed_id_pk = ph.pk.as_ref().to_vec(); relay_server = ph.relay_server; peer_addr = AddrMangle::decode(&ph.socket_addr); log::info!("Hole Punched {} = {}", peer, peer_addr); @@ -393,8 +393,8 @@ impl Client { let sealed_key = box_::seal(&key.0, &nonce, &their_pk_b, &out_sk_b); let mut msg_out = Message::new(); msg_out.set_public_key(PublicKey { - asymmetric_value: our_pk_b.0.into(), - symmetric_value: sealed_key, + asymmetric_value: Vec::from(our_pk_b.0).into(), + symmetric_value: sealed_key.into(), ..Default::default() }); timeout(CONNECT_TIMEOUT, conn.send(&msg_out)).await??; @@ -1122,7 +1122,7 @@ impl LoginConfigHandler { let my_id = Config::get_id(); let mut lr = LoginRequest { username: self.id.clone(), - password, + password:password.into(), my_id, my_name: crate::username(), option: self.get_option_message(true).into(), diff --git a/src/clipboard_file.rs b/src/clipboard_file.rs index 2f35065c9..d2125010c 100644 --- a/src/clipboard_file.rs +++ b/src/clipboard_file.rs @@ -67,7 +67,7 @@ pub fn clip_2_msg(clip: ClipbaordFile) -> Message { CliprdrServerFormatDataResponse { conn_id, msg_flags, - format_data, + format_data: format_data.into(), ..Default::default() }, )), @@ -117,7 +117,7 @@ pub fn clip_2_msg(clip: ClipbaordFile) -> Message { conn_id, msg_flags, stream_id, - requested_data, + requested_data: requested_data.into(), ..Default::default() }, )), @@ -156,7 +156,7 @@ pub fn msg_2_clip(msg: Cliprdr) -> Option { Some(ClipbaordFile::ServerFormatDataResponse { conn_id: data.conn_id, msg_flags: data.msg_flags, - format_data: data.format_data, + format_data: data.format_data.as_ref().to_vec(), }) } Some(cliprdr::Union::FileContentsRequest(data)) => { @@ -177,7 +177,7 @@ pub fn msg_2_clip(msg: Cliprdr) -> Option { conn_id: data.conn_id, msg_flags: data.msg_flags, stream_id: data.stream_id, - requested_data: data.requested_data, + requested_data: data.requested_data.as_ref().to_vec(), }) } _ => None, diff --git a/src/common.rs b/src/common.rs index 9917a47f2..2930a1611 100644 --- a/src/common.rs +++ b/src/common.rs @@ -49,7 +49,7 @@ pub fn create_clipboard_msg(content: String) -> Message { let mut msg = Message::new(); msg.set_clipboard(Clipboard { compress, - content, + content:content.into(), ..Default::default() }); msg @@ -80,7 +80,7 @@ pub fn update_clipboard(clipboard: Clipboard, old: Option<&Arc>>) let content = if clipboard.compress { decompress(&clipboard.content) } else { - clipboard.content + clipboard.content.as_ref().to_vec() }; if let Ok(content) = String::from_utf8(content) { if content.is_empty() { diff --git a/src/platform/windows.rs b/src/platform/windows.rs index c9f83389a..cb0fd778f 100644 --- a/src/platform/windows.rs +++ b/src/platform/windows.rs @@ -164,7 +164,7 @@ pub fn get_cursor_data(hcursor: u64) -> ResultType { Ok(CursorData { id: hcursor, - colors: cbits, + colors: cbits.into(), hotx: ii.0.xHotspot as _, hoty: ii.0.yHotspot as _, width: width as _, diff --git a/src/rendezvous_mediator.rs b/src/rendezvous_mediator.rs index 4381fbc74..a07a096ab 100644 --- a/src/rendezvous_mediator.rs +++ b/src/rendezvous_mediator.rs @@ -263,7 +263,7 @@ impl RendezvousMediator { async fn handle_request_relay(&self, rr: RequestRelay, server: ServerPtr) -> ResultType<()> { self.create_relay( - rr.socket_addr, + rr.socket_addr.as_ref().to_vec(), rr.relay_server, rr.uuid, server, @@ -300,7 +300,7 @@ impl RendezvousMediator { let mut msg_out = Message::new(); let mut rr = RelayResponse { - socket_addr, + socket_addr: socket_addr.into(), version: crate::VERSION.to_owned(), ..Default::default() }; @@ -331,8 +331,8 @@ impl RendezvousMediator { let relay_server = self.get_relay_server(fla.relay_server); msg_out.set_local_addr(LocalAddr { id: Config::get_id(), - socket_addr: AddrMangle::encode(peer_addr), - local_addr: AddrMangle::encode(local_addr), + socket_addr: AddrMangle::encode(peer_addr).into(), + local_addr: AddrMangle::encode(local_addr).into(), relay_server, version: crate::VERSION.to_owned(), ..Default::default() @@ -350,7 +350,7 @@ impl RendezvousMediator { { let uuid = Uuid::new_v4().to_string(); return self - .create_relay(ph.socket_addr, relay_server, uuid, server, true, true) + .create_relay(ph.socket_addr.as_ref().to_vec(), relay_server, uuid, server, true, true) .await; } let peer_addr = AddrMangle::decode(&ph.socket_addr); @@ -391,8 +391,8 @@ impl RendezvousMediator { self.last_id_pk_registry = id.clone(); msg_out.set_register_pk(RegisterPk { id, - uuid, - pk, + uuid: uuid.into(), + pk: pk.into(), ..Default::default() }); socket.send(&msg_out, self.addr.to_owned()).await?; diff --git a/src/server.rs b/src/server.rs index d437ce6d4..0d2e97c67 100644 --- a/src/server.rs +++ b/src/server.rs @@ -20,6 +20,8 @@ use std::{ sync::{Arc, Mutex, RwLock, Weak}, time::Duration, }; +use bytes::Bytes; + pub mod audio_service; cfg_if::cfg_if! { if #[cfg(not(any(target_os = "android", target_os = "ios")))] { @@ -126,13 +128,13 @@ pub async fn create_tcp_connection( id: sign::sign( &IdPk { id: Config::get_id(), - pk: our_pk_b.0.to_vec(), + pk: Bytes::from(our_pk_b.0.to_vec()), ..Default::default() } .write_to_bytes() .unwrap_or_default(), &sk, - ), + ).into(), ..Default::default() }); timeout(CONNECT_TIMEOUT, stream.send(&msg_out)).await??; diff --git a/src/server/audio_service.rs b/src/server/audio_service.rs index e0974a228..02db0bffd 100644 --- a/src/server/audio_service.rs +++ b/src/server/audio_service.rs @@ -367,7 +367,7 @@ fn send_f32(data: &[f32], encoder: &mut Encoder, sp: &GenericService) { Ok(data) => { let mut msg_out = Message::new(); msg_out.set_audio_frame(AudioFrame { - data, + data: data.into(), timestamp: crate::common::get_time(), ..Default::default() }); diff --git a/src/server/connection.rs b/src/server/connection.rs index e8344c4a7..64ff6cbe9 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -1063,7 +1063,7 @@ impl Connection { self.send_fs(ipc::FS::WriteBlock { id: block.id, file_num: block.file_num, - data: block.data, + data: block.data.as_ref().to_vec(), compressed: block.compressed, }); } diff --git a/src/server/input_service.rs b/src/server/input_service.rs index 3ec9c0f70..9bae8d35b 100644 --- a/src/server/input_service.rs +++ b/src/server/input_service.rs @@ -145,7 +145,7 @@ fn run_cursor(sp: MouseCursorService, state: &mut StateCursor) -> ResultType<()> msg = cached.clone(); } else { let mut data = crate::get_cursor_data(hcursor)?; - data.colors = hbb_common::compress::compress(&data.colors[..], COMPRESS_LEVEL); + data.colors = hbb_common::compress::compress(&data.colors[..], COMPRESS_LEVEL).into(); let mut tmp = Message::new(); tmp.set_cursor_data(data); msg = Arc::new(tmp); diff --git a/src/ui/cm.rs b/src/ui/cm.rs index c1acb6926..1c2b36a93 100644 --- a/src/ui/cm.rs +++ b/src/ui/cm.rs @@ -263,7 +263,7 @@ impl ConnectionManager { FileTransferBlock { id, file_num, - data, + data: data.into(), compressed, ..Default::default() }, From ae839bd5bf0641d1709ab7aaa510e7c64b67d130 Mon Sep 17 00:00:00 2001 From: tom Date: Sun, 17 Jul 2022 00:59:56 +0800 Subject: [PATCH 02/17] update linux.rs & macos.rs with bytes:Byte issues:958 --- libs/hbb_common/build.rs | 1 - src/platform/linux.rs | 12 +++++++----- src/platform/macos.rs | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/libs/hbb_common/build.rs b/libs/hbb_common/build.rs index 3c2a3c7a4..225ec34c7 100644 --- a/libs/hbb_common/build.rs +++ b/libs/hbb_common/build.rs @@ -8,7 +8,6 @@ fn main() { .customize( protobuf_codegen::Customize::default() .tokio_bytes(true) - // .tokio_bytes_for_string(true) ) .run() .expect("Codegen failed."); diff --git a/src/platform/linux.rs b/src/platform/linux.rs index efd6476b6..f331dd6ee 100644 --- a/src/platform/linux.rs +++ b/src/platform/linux.rs @@ -109,7 +109,8 @@ pub fn get_cursor_data(hcursor: u64) -> ResultType { cd.id = (*img).cursor_serial as _; let pixels = std::slice::from_raw_parts((*img).pixels, (cd.width * cd.height) as _); - cd.colors.resize(pixels.len() * 4, 0); + // cd.colors.resize(pixels.len() * 4, 0); + let mut cd_colors = vec![0_u8; pixels.len() * 4]; for y in 0..cd.height { for x in 0..cd.width { let pos = (y * cd.width + x) as usize; @@ -122,12 +123,13 @@ pub fn get_cursor_data(hcursor: u64) -> ResultType { continue; } let pos = pos * 4; - cd.colors[pos] = r as _; - cd.colors[pos + 1] = g as _; - cd.colors[pos + 2] = b as _; - cd.colors[pos + 3] = a as _; + cd_colors[pos] = r as _; + cd_colors[pos + 1] = g as _; + cd_colors[pos + 2] = b as _; + cd_colors[pos + 3] = a as _; } } + cd.colors = cd_colors.into(); res = Some(cd); } if !img.is_null() { diff --git a/src/platform/macos.rs b/src/platform/macos.rs index dabe11e49..1a8096587 100644 --- a/src/platform/macos.rs +++ b/src/platform/macos.rs @@ -342,7 +342,7 @@ pub fn get_cursor_data(hcursor: u64) -> ResultType { } Ok(CursorData { id: hcursor, - colors, + colors: colors.into(), hotx: hotspot.x as _, hoty: hotspot.y as _, width: size.width as _, From 16b7c7c7163e7b386e29352b29828012e11ec542 Mon Sep 17 00:00:00 2001 From: tom Date: Thu, 21 Jul 2022 00:39:20 +0800 Subject: [PATCH 03/17] upgrade bytes to 1.2 --- Cargo.toml | 2 +- libs/hbb_common/Cargo.toml | 2 +- src/client.rs | 2 +- src/clipboard_file.rs | 4 ++-- src/common.rs | 2 +- src/rendezvous_mediator.rs | 4 ++-- src/server/connection.rs | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3656e8221..6237afe4e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,7 +55,7 @@ rpassword = "7.0" base64 = "0.13" sysinfo = "0.24" num_cpus = "1.13" -bytes = "1.1" +bytes = "1.2" default-net = "0.11.0" wol-rs = "0.9.1" diff --git a/libs/hbb_common/Cargo.toml b/libs/hbb_common/Cargo.toml index 6fec67193..8d34709fe 100644 --- a/libs/hbb_common/Cargo.toml +++ b/libs/hbb_common/Cargo.toml @@ -11,7 +11,7 @@ protobuf = { version = "3.1", features = ["with-bytes"] } tokio = { version = "1.20", features = ["full"] } tokio-util = { version = "0.7", features = ["full"] } futures = "0.3" -bytes = "1.1" +bytes = "1.2" log = "0.4" env_logger = "0.9" socket2 = { version = "0.3", features = ["reuseport"] } diff --git a/src/client.rs b/src/client.rs index c8a561c8d..9b4bb1814 100644 --- a/src/client.rs +++ b/src/client.rs @@ -215,7 +215,7 @@ impl Client { } else { peer_nat_type = ph.nat_type(); is_local = ph.is_local(); - signed_id_pk = ph.pk.as_ref().to_vec(); + signed_id_pk = ph.pk.into(); relay_server = ph.relay_server; peer_addr = AddrMangle::decode(&ph.socket_addr); log::info!("Hole Punched {} = {}", peer, peer_addr); diff --git a/src/clipboard_file.rs b/src/clipboard_file.rs index d2125010c..b6c0513e8 100644 --- a/src/clipboard_file.rs +++ b/src/clipboard_file.rs @@ -156,7 +156,7 @@ pub fn msg_2_clip(msg: Cliprdr) -> Option { Some(ClipbaordFile::ServerFormatDataResponse { conn_id: data.conn_id, msg_flags: data.msg_flags, - format_data: data.format_data.as_ref().to_vec(), + format_data: data.format_data.into(), }) } Some(cliprdr::Union::FileContentsRequest(data)) => { @@ -177,7 +177,7 @@ pub fn msg_2_clip(msg: Cliprdr) -> Option { conn_id: data.conn_id, msg_flags: data.msg_flags, stream_id: data.stream_id, - requested_data: data.requested_data.as_ref().to_vec(), + requested_data: data.requested_data.into(), }) } _ => None, diff --git a/src/common.rs b/src/common.rs index b2026e5ba..e4ec7cb9c 100644 --- a/src/common.rs +++ b/src/common.rs @@ -79,7 +79,7 @@ pub fn update_clipboard(clipboard: Clipboard, old: Option<&Arc>>) let content = if clipboard.compress { decompress(&clipboard.content) } else { - clipboard.content.as_ref().to_vec() + clipboard.content.into() }; if let Ok(content) = String::from_utf8(content) { if content.is_empty() { diff --git a/src/rendezvous_mediator.rs b/src/rendezvous_mediator.rs index 24e50f086..7cf059843 100644 --- a/src/rendezvous_mediator.rs +++ b/src/rendezvous_mediator.rs @@ -266,7 +266,7 @@ impl RendezvousMediator { async fn handle_request_relay(&self, rr: RequestRelay, server: ServerPtr) -> ResultType<()> { self.create_relay( - rr.socket_addr.as_ref().to_vec(), + rr.socket_addr.into(), rr.relay_server, rr.uuid, server, @@ -353,7 +353,7 @@ impl RendezvousMediator { { let uuid = Uuid::new_v4().to_string(); return self - .create_relay(ph.socket_addr.as_ref().to_vec(), relay_server, uuid, server, true, true) + .create_relay(ph.socket_addr.into(), relay_server, uuid, server, true, true) .await; } let peer_addr = AddrMangle::decode(&ph.socket_addr); diff --git a/src/server/connection.rs b/src/server/connection.rs index 677d8f238..10a1786fd 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -1063,7 +1063,7 @@ impl Connection { self.send_fs(ipc::FS::WriteBlock { id: block.id, file_num: block.file_num, - data: block.data.as_ref().to_vec(), + data: block.data.into(), compressed: block.compressed, }); } From 1fecd7168a3f9b15e0ed8e973d215e66551fd604 Mon Sep 17 00:00:00 2001 From: 21pages Date: Thu, 7 Jul 2022 20:55:19 +0800 Subject: [PATCH 04/17] hwcodec: linux compatible Signed-off-by: 21pages --- Cargo.lock | 2 +- libs/scrap/Cargo.toml | 2 +- libs/scrap/src/common/convert.rs | 3 +++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c91272112..21224012f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2209,7 +2209,7 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hwcodec" version = "0.1.0" -source = "git+https://github.com/21pages/hwcodec#91d1cd327c88490f917457072aeef0676ddb2be7" +source = "git+https://github.com/21pages/hwcodec#890204e0703a3d361fc7a45f035fe75c0575bb1d" dependencies = [ "bindgen", "cc", diff --git a/libs/scrap/Cargo.toml b/libs/scrap/Cargo.toml index 1b269d96e..d40eb0cfd 100644 --- a/libs/scrap/Cargo.toml +++ b/libs/scrap/Cargo.toml @@ -50,5 +50,5 @@ gstreamer = { version = "0.16", optional = true } gstreamer-app = { version = "0.16", features = ["v1_10"], optional = true } gstreamer-video = { version = "0.16", optional = true } -[target.'cfg(target_os = "windows")'.dependencies] +[target.'cfg(any(target_os = "windows", target_os = "linux"))'.dependencies] hwcodec = { git = "https://github.com/21pages/hwcodec", optional = true } diff --git a/libs/scrap/src/common/convert.rs b/libs/scrap/src/common/convert.rs index 306a217ea..2b0223a0a 100644 --- a/libs/scrap/src/common/convert.rs +++ b/libs/scrap/src/common/convert.rs @@ -246,6 +246,7 @@ pub unsafe fn nv12_to_i420( #[cfg(feature = "hwcodec")] pub mod hw { use hbb_common::{anyhow::anyhow, ResultType}; + #[cfg(target_os = "windows")] use hwcodec::{ffmpeg::ffmpeg_linesize_offset_length, AVPixelFormat}; pub fn hw_bgra_to_i420( @@ -381,6 +382,8 @@ pub mod hw { src_stride_y: usize, src_stride_uv: usize, dst: &mut Vec, + _i420: &mut Vec, + _align: usize, ) -> ResultType<()> { dst.resize(width * height * 4, 0); unsafe { From 1b1f28b872a32ba7220affe977d285fae35e57f4 Mon Sep 17 00:00:00 2001 From: 21pages Date: Fri, 8 Jul 2022 18:18:58 +0800 Subject: [PATCH 05/17] hwcodec: check when server or each client starts and refactor hwcodec::best() Signed-off-by: 21pages --- libs/hbb_common/src/config.rs | 4 + libs/scrap/src/common/codec.rs | 4 +- libs/scrap/src/common/hwcodec.rs | 127 +++++++++++++------------------ src/server.rs | 17 ++--- 4 files changed, 69 insertions(+), 83 deletions(-) diff --git a/libs/hbb_common/src/config.rs b/libs/hbb_common/src/config.rs index 787ffe5ee..cf657c8dc 100644 --- a/libs/hbb_common/src/config.rs +++ b/libs/hbb_common/src/config.rs @@ -978,6 +978,10 @@ impl HwCodecConfig { pub fn store(&self) { Config::store_(self, "_hwcodec"); } + + pub fn remove() { + std::fs::remove_file(Config::file_("_hwcodec")).ok(); + } } #[cfg(test)] diff --git a/libs/scrap/src/common/codec.rs b/libs/scrap/src/common/codec.rs index 1d9deba68..b48053e0b 100644 --- a/libs/scrap/src/common/codec.rs +++ b/libs/scrap/src/common/codec.rs @@ -102,7 +102,7 @@ impl Encoder { codec: Box::new(hw), }), Err(e) => { - HwEncoder::best(true, true); + check_config_process(true); Err(e) } }, @@ -132,7 +132,7 @@ impl Encoder { } let current_encoder_name = HwEncoder::current_name(); if states.len() > 0 { - let (best, _) = HwEncoder::best(false, true); + let best = HwEncoder::best(); let enabled_h264 = best.h264.is_some() && states.len() > 0 && states.iter().all(|(_, s)| s.ScoreH264 > 0); diff --git a/libs/scrap/src/common/hwcodec.rs b/libs/scrap/src/common/hwcodec.rs index ff23978de..c2c853956 100644 --- a/libs/scrap/src/common/hwcodec.rs +++ b/libs/scrap/src/common/hwcodec.rs @@ -123,40 +123,11 @@ impl EncoderApi for HwEncoder { } impl HwEncoder { - /// Get best encoders. - /// - /// # Parameter - /// `force_reset`: force to refresh config. - /// `write`: write to config file. - /// - /// # Return - /// `CodecInfos`: infos. - /// `bool`: whether the config is refreshed. - pub fn best(force_reset: bool, write: bool) -> (CodecInfos, bool) { - let config = get_config(CFG_KEY_ENCODER); - if !force_reset && config.is_ok() { - (config.unwrap(), false) - } else { - let ctx = EncodeContext { - name: String::from(""), - width: 1920, - height: 1080, - pixfmt: DEFAULT_PIXFMT, - align: HW_STRIDE_ALIGN as _, - bitrate: 0, - timebase: DEFAULT_TIME_BASE, - gop: DEFAULT_GOP, - quality: DEFAULT_HW_QUALITY, - rc: DEFAULT_RC, - }; - let encoders = CodecInfo::score(Encoder::avaliable_encoders(ctx)); - if write { - set_config(CFG_KEY_ENCODER, &encoders) - .map_err(|e| log::error!("{:?}", e)) - .ok(); - } - (encoders, true) - } + pub fn best() -> CodecInfos { + get_config(CFG_KEY_ENCODER).unwrap_or(CodecInfos { + h264: None, + h265: None, + }) } pub fn current_name() -> Arc>> { @@ -207,24 +178,15 @@ pub struct HwDecoders { } impl HwDecoder { - /// See HwEncoder::best - fn best(force_reset: bool, write: bool) -> (CodecInfos, bool) { - let config = get_config(CFG_KEY_DECODER); - if !force_reset && config.is_ok() { - (config.unwrap(), false) - } else { - let decoders = CodecInfo::score(Decoder::avaliable_decoders()); - if write { - set_config(CFG_KEY_DECODER, &decoders) - .map_err(|e| log::error!("{:?}", e)) - .ok(); - } - (decoders, true) - } + fn best() -> CodecInfos { + get_config(CFG_KEY_DECODER).unwrap_or(CodecInfos { + h264: None, + h265: None, + }) } pub fn new_decoders() -> HwDecoders { - let (best, _) = HwDecoder::best(false, true); + let best = HwDecoder::best(); let mut h264: Option = None; let mut h265: Option = None; let mut fail = false; @@ -242,7 +204,7 @@ impl HwDecoder { } } if fail { - HwDecoder::best(true, true); + check_config_process(true); } HwDecoders { h264, h265 } } @@ -314,31 +276,52 @@ fn get_config(k: &str) -> ResultType { } } -fn set_config(k: &str, v: &CodecInfos) -> ResultType<()> { - match v.serialize() { - Ok(v) => { - let mut config = HwCodecConfig::load(); - config.options.insert(k.to_owned(), v); - config.store(); - Ok(()) - } - Err(_) => Err(anyhow!("Failed to set config:{}", k)), - } -} - pub fn check_config() { - let (encoders, update_encoders) = HwEncoder::best(false, false); - let (decoders, update_decoders) = HwDecoder::best(false, false); - if update_encoders || update_decoders { - if let Ok(encoders) = encoders.serialize() { - if let Ok(decoders) = decoders.serialize() { - let mut config = HwCodecConfig::load(); - config.options.insert(CFG_KEY_ENCODER.to_owned(), encoders); - config.options.insert(CFG_KEY_DECODER.to_owned(), decoders); - config.store(); + let ctx = EncodeContext { + name: String::from(""), + width: 1920, + height: 1080, + pixfmt: DEFAULT_PIXFMT, + align: HW_STRIDE_ALIGN as _, + bitrate: 0, + timebase: DEFAULT_TIME_BASE, + gop: DEFAULT_GOP, + quality: DEFAULT_HW_QUALITY, + rc: DEFAULT_RC, + }; + let encoders = CodecInfo::score(Encoder::avaliable_encoders(ctx)); + let decoders = CodecInfo::score(Decoder::avaliable_decoders()); + + if let Ok(old_encoders) = get_config(CFG_KEY_ENCODER) { + if let Ok(old_decoders) = get_config(CFG_KEY_DECODER) { + if encoders == old_encoders && decoders == old_decoders { return; } } - log::error!("Failed to serialize codec info"); } + + if let Ok(encoders) = encoders.serialize() { + if let Ok(decoders) = decoders.serialize() { + let mut config = HwCodecConfig::load(); + config.options.insert(CFG_KEY_ENCODER.to_owned(), encoders); + config.options.insert(CFG_KEY_DECODER.to_owned(), decoders); + config.store(); + return; + } + } + log::error!("Failed to serialize codec info"); +} + +pub fn check_config_process(force_reset: bool) { + if force_reset { + HwCodecConfig::remove(); + } + if let Ok(exe) = std::env::current_exe() { + std::thread::spawn(move || { + std::process::Command::new(exe) + .arg("--check-hwcodec-config") + .status() + .ok() + }); + }; } diff --git a/src/server.rs b/src/server.rs index a71efaee2..f2d643e1c 100644 --- a/src/server.rs +++ b/src/server.rs @@ -319,6 +319,14 @@ pub async fn start_server(is_server: bool) { log::info!("DISPLAY={:?}", std::env::var("DISPLAY")); log::info!("XAUTHORITY={:?}", std::env::var("XAUTHORITY")); } + #[cfg(feature = "hwcodec")] + { + use std::sync::Once; + static ONCE: Once = Once::new(); + ONCE.call_once(|| { + scrap::hwcodec::check_config_process(false); + }) + } if is_server { std::thread::spawn(move || { @@ -327,15 +335,6 @@ pub async fn start_server(is_server: bool) { std::process::exit(-1); } }); - #[cfg(feature = "hwcodec")] - if let Ok(exe) = std::env::current_exe() { - std::thread::spawn(move || { - std::process::Command::new(exe) - .arg("--check-hwcodec-config") - .status() - .ok() - }); - } #[cfg(windows)] crate::platform::windows::bootstrap(); input_service::fix_key_down_timeout_loop(); From 7aa431d349593467fbbefb05375fbb80d4aa7dbe Mon Sep 17 00:00:00 2001 From: 21pages Date: Sat, 9 Jul 2022 20:17:10 +0800 Subject: [PATCH 06/17] hwcodec: codec preference Signed-off-by: 21pages --- libs/hbb_common/protos/message.proto | 20 +++- libs/scrap/src/common/codec.rs | 143 +++++++++++++++++++-------- src/client.rs | 21 +++- src/server/connection.rs | 16 +++ src/server/video_service.rs | 4 + src/ui/header.css | 1 + src/ui/header.tis | 20 +++- src/ui/remote.rs | 39 ++++++++ 8 files changed, 217 insertions(+), 47 deletions(-) diff --git a/libs/hbb_common/protos/message.proto b/libs/hbb_common/protos/message.proto index 2044388f8..7b4bc3787 100644 --- a/libs/hbb_common/protos/message.proto +++ b/libs/hbb_common/protos/message.proto @@ -72,6 +72,11 @@ message Features { bool privacy_mode = 1; } +message SupportedEncoding { + bool h264 = 1; + bool h265 = 2; +} + message PeerInfo { string username = 1; string hostname = 2; @@ -82,6 +87,7 @@ message PeerInfo { string version = 7; int32 conn_id = 8; Features features = 9; + SupportedEncoding encoding = 10; } message LoginResponse { @@ -434,9 +440,17 @@ enum ImageQuality { } message VideoCodecState { - int32 ScoreVpx = 1; - int32 ScoreH264 = 2; - int32 ScoreH265 = 3; + enum PerferCodec { + Auto = 0; + VPX = 1; + H264 = 2; + H265 = 3; + } + + int32 score_vpx = 1; + int32 score_h264 = 2; + int32 score_h265 = 3; + PerferCodec perfer = 4; } message OptionMessage { diff --git a/libs/scrap/src/common/codec.rs b/libs/scrap/src/common/codec.rs index b48053e0b..1a18a79c3 100644 --- a/libs/scrap/src/common/codec.rs +++ b/libs/scrap/src/common/codec.rs @@ -16,7 +16,11 @@ use hbb_common::{ ResultType, }; #[cfg(feature = "hwcodec")] -use hbb_common::{config::Config2, lazy_static}; +use hbb_common::{ + config::{Config2, PeerConfig}, + lazy_static, + message_proto::video_codec_state::PerferCodec, +}; #[cfg(feature = "hwcodec")] lazy_static::lazy_static! { @@ -113,7 +117,6 @@ impl Encoder { // TODO pub fn update_video_encoder(id: i32, update: EncoderUpdate) { - log::info!("encoder update: {:?}", update); #[cfg(feature = "hwcodec")] { let mut states = PEER_DECODER_STATES.lock().unwrap(); @@ -130,49 +133,75 @@ impl Encoder { } } } - let current_encoder_name = HwEncoder::current_name(); + let name = HwEncoder::current_name(); if states.len() > 0 { let best = HwEncoder::best(); let enabled_h264 = best.h264.is_some() && states.len() > 0 - && states.iter().all(|(_, s)| s.ScoreH264 > 0); + && states.iter().all(|(_, s)| s.score_h264 > 0); let enabled_h265 = best.h265.is_some() && states.len() > 0 - && states.iter().all(|(_, s)| s.ScoreH265 > 0); + && states.iter().all(|(_, s)| s.score_h265 > 0); - // score encoder - let mut score_vpx = SCORE_VPX; - let mut score_h264 = best.h264.as_ref().map_or(0, |c| c.score); - let mut score_h265 = best.h265.as_ref().map_or(0, |c| c.score); - - // score decoder - score_vpx += states.iter().map(|s| s.1.ScoreVpx).sum::(); - if enabled_h264 { - score_h264 += states.iter().map(|s| s.1.ScoreH264).sum::(); - } - if enabled_h265 { - score_h265 += states.iter().map(|s| s.1.ScoreH265).sum::(); + // Preference first + let mut preference = PerferCodec::Auto; + let preferences: Vec<_> = states + .iter() + .filter(|(_, s)| { + s.perfer == PerferCodec::VPX.into() + || s.perfer == PerferCodec::H264.into() && enabled_h264 + || s.perfer == PerferCodec::H265.into() && enabled_h265 + }) + .map(|(_, s)| s.perfer) + .collect(); + if preferences.len() > 0 && preferences.iter().all(|&p| p == preferences[0]) { + preference = preferences[0].enum_value_or(PerferCodec::Auto); } - if enabled_h265 && score_h265 >= score_vpx && score_h265 >= score_h264 { - *current_encoder_name.lock().unwrap() = Some(best.h265.unwrap().name); - } else if enabled_h264 && score_h264 >= score_vpx && score_h264 >= score_h265 { - *current_encoder_name.lock().unwrap() = Some(best.h264.unwrap().name); - } else { - *current_encoder_name.lock().unwrap() = None; + match preference { + PerferCodec::VPX => *name.lock().unwrap() = None, + PerferCodec::H264 => { + *name.lock().unwrap() = best.h264.map_or(None, |c| Some(c.name)) + } + PerferCodec::H265 => { + *name.lock().unwrap() = best.h265.map_or(None, |c| Some(c.name)) + } + PerferCodec::Auto => { + // score encoder + let mut score_vpx = SCORE_VPX; + let mut score_h264 = best.h264.as_ref().map_or(0, |c| c.score); + let mut score_h265 = best.h265.as_ref().map_or(0, |c| c.score); + + // score decoder + score_vpx += states.iter().map(|s| s.1.score_vpx).sum::(); + if enabled_h264 { + score_h264 += states.iter().map(|s| s.1.score_h264).sum::(); + } + if enabled_h265 { + score_h265 += states.iter().map(|s| s.1.score_h265).sum::(); + } + + if enabled_h265 && score_h265 >= score_vpx && score_h265 >= score_h264 { + *name.lock().unwrap() = best.h265.map_or(None, |c| Some(c.name)); + } else if enabled_h264 + && score_h264 >= score_vpx + && score_h264 >= score_h265 + { + *name.lock().unwrap() = best.h264.map_or(None, |c| Some(c.name)); + } else { + *name.lock().unwrap() = None; + } + } } + log::info!( - "connection count:{}, h264:{}, h265:{}, score: vpx({}), h264({}), h265({}), set current encoder name {:?}", + "connection count:{}, used preference:{:?}, encoder:{:?}", states.len(), - enabled_h264, - enabled_h265, - score_vpx, - score_h264, - score_h265, - current_encoder_name.lock().unwrap() - ) + preference, + name.lock().unwrap() + ) } else { - *current_encoder_name.lock().unwrap() = None; + *name.lock().unwrap() = None; } } #[cfg(not(feature = "hwcodec"))] @@ -192,34 +221,51 @@ impl Encoder { #[cfg(not(feature = "hwcodec"))] return None; } + + pub fn supported_encoding() -> (bool, bool) { + #[cfg(feature = "hwcodec")] + if check_hwcodec_config() { + let best = HwEncoder::best(); + ( + best.h264.as_ref().map_or(false, |c| c.score > 0), + best.h265.as_ref().map_or(false, |c| c.score > 0), + ) + } else { + (false, false) + } + #[cfg(not(feature = "hwcodec"))] + (false, false) + } } #[cfg(feature = "hwcodec")] impl Drop for Decoder { fn drop(&mut self) { *MY_DECODER_STATE.lock().unwrap() = VideoCodecState { - ScoreVpx: SCORE_VPX, + score_vpx: SCORE_VPX, ..Default::default() }; } } impl Decoder { - pub fn video_codec_state() -> VideoCodecState { + pub fn video_codec_state(_id: &str) -> VideoCodecState { // video_codec_state is mainted by creation and destruction of Decoder. // It has been ensured to use after Decoder's creation. #[cfg(feature = "hwcodec")] if check_hwcodec_config() { - return MY_DECODER_STATE.lock().unwrap().clone(); + let mut state = MY_DECODER_STATE.lock().unwrap(); + state.perfer = Self::codec_preference(_id).into(); + state.clone() } else { return VideoCodecState { - ScoreVpx: SCORE_VPX, + score_vpx: SCORE_VPX, ..Default::default() }; } #[cfg(not(feature = "hwcodec"))] VideoCodecState { - ScoreVpx: SCORE_VPX, + score_vpx: SCORE_VPX, ..Default::default() } } @@ -237,9 +283,9 @@ impl Decoder { #[cfg(feature = "hwcodec")] { let mut state = MY_DECODER_STATE.lock().unwrap(); - state.ScoreVpx = SCORE_VPX; - state.ScoreH264 = decoder.hw.h264.as_ref().map_or(0, |d| d.info.score); - state.ScoreH265 = decoder.hw.h265.as_ref().map_or(0, |d| d.info.score); + state.score_vpx = SCORE_VPX; + state.score_h264 = decoder.hw.h264.as_ref().map_or(0, |d| d.info.score); + state.score_h265 = decoder.hw.h265.as_ref().map_or(0, |d| d.info.score); } decoder @@ -316,6 +362,23 @@ impl Decoder { } return Ok(ret); } + + #[cfg(feature = "hwcodec")] + fn codec_preference(id: &str) -> PerferCodec { + let codec = PeerConfig::load(id) + .options + .get("codec-preference") + .map_or("".to_owned(), |c| c.to_owned()); + if codec == "vp9" { + PerferCodec::VPX + } else if codec == "h264" { + PerferCodec::H264 + } else if codec == "h265" { + PerferCodec::H265 + } else { + PerferCodec::Auto + } + } } #[cfg(feature = "hwcodec")] diff --git a/src/client.rs b/src/client.rs index 28101896e..dbea079ea 100644 --- a/src/client.rs +++ b/src/client.rs @@ -784,6 +784,7 @@ pub struct LoginConfigHandler { pub conn_id: i32, features: Option, session_id: u64, + pub supported_encoding: Option<(bool, bool)>, } impl Deref for LoginConfigHandler { @@ -808,6 +809,7 @@ impl LoginConfigHandler { self.remember = !config.password.is_empty(); self.config = config; self.session_id = rand::random(); + self.supported_encoding = None; } pub fn should_auto_login(&self) -> String { @@ -958,8 +960,7 @@ impl LoginConfigHandler { msg.disable_clipboard = BoolOption::Yes.into(); n += 1; } - // TODO: add option - let state = Decoder::video_codec_state(); + let state = Decoder::video_codec_state(&self.id); msg.video_codec_state = hbb_common::protobuf::MessageField::some(state); n += 1; @@ -1111,6 +1112,10 @@ impl LoginConfigHandler { self.conn_id = pi.conn_id; // no matter if change, for update file time self.save_config(config); + #[cfg(feature = "hwcodec")] + { + self.supported_encoding = Some((pi.encoding.h264, pi.encoding.h265)); + } } pub fn get_remote_dir(&self) -> String { @@ -1163,6 +1168,18 @@ impl LoginConfigHandler { msg_out.set_login_request(lr); msg_out } + + pub fn change_prefer_codec(&self) -> Message { + let state = scrap::codec::Decoder::video_codec_state(&self.id); + let mut misc = Misc::new(); + misc.set_option(OptionMessage { + video_codec_state: hbb_common::protobuf::MessageField::some(state), + ..Default::default() + }); + let mut msg_out = Message::new(); + msg_out.set_misc(misc); + msg_out + } } pub enum MediaData { diff --git a/src/server/connection.rs b/src/server/connection.rs index 869df4196..8b0b3f192 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -635,6 +635,16 @@ impl Connection { pi.hostname = MOBILE_INFO2.lock().unwrap().clone(); pi.platform = "Android".into(); } + #[cfg(feature = "hwcodec")] + { + let (h264, h265) = scrap::codec::Encoder::supported_encoding(); + pi.encoding = Some(SupportedEncoding { + h264, + h265, + ..Default::default() + }) + .into(); + } if self.port_forward_socket.is_some() { let mut msg_out = Message::new(); @@ -1351,6 +1361,12 @@ impl Connection { } } } + if let Some(q) = o.video_codec_state.clone().take() { + scrap::codec::Encoder::update_video_encoder( + self.inner.id(), + scrap::codec::EncoderUpdate::State(q), + ); + } } async fn on_close(&mut self, reason: &str, lock: bool) { diff --git a/src/server/video_service.rs b/src/server/video_service.rs index e6ea713a1..e639fbe24 100644 --- a/src/server/video_service.rs +++ b/src/server/video_service.rs @@ -483,6 +483,7 @@ fn run(sp: GenericService) -> ResultType<()> { let mut try_gdi = 1; #[cfg(windows)] log::info!("gdi: {}", c.is_gdi()); + let codec_name = Encoder::current_hw_encoder_name(); while sp.ok() { #[cfg(windows)] @@ -508,6 +509,9 @@ fn run(sp: GenericService) -> ResultType<()> { *SWITCH.lock().unwrap() = true; bail!("SWITCH"); } + if codec_name != Encoder::current_hw_encoder_name() { + bail!("SWITCH"); + } check_privacy_mode_changed(&sp, c.privacy_mode_id)?; #[cfg(windows)] { diff --git a/src/ui/header.css b/src/ui/header.css index fb7b57fda..e248b46d5 100644 --- a/src/ui/header.css +++ b/src/ui/header.css @@ -94,3 +94,4 @@ span#fullscreen.active { button:disabled { opacity: 0.3; } + diff --git a/src/ui/header.tis b/src/ui/header.tis index 35a132c90..6ee3cad01 100644 --- a/src/ui/header.tis +++ b/src/ui/header.tis @@ -145,6 +145,9 @@ class Header: Reactor.Component { } function renderDisplayPop() { + var codecs = handler.supported_hwcodec(); + var show_codec = handler.has_hwcodec() && (codecs[0] || codecs[1]); + return
  • {translate('Adjust Window')}
  • @@ -157,6 +160,13 @@ class Header: Reactor.Component {
  • {svg_checkmark}{translate('Balanced')}
  • {svg_checkmark}{translate('Optimize reaction time')}
  • {svg_checkmark}{translate('Custom')}
  • + {show_codec ?
    +
    +
  • {svg_checkmark}Auto
  • +
  • {svg_checkmark}VP9
  • + {codecs[0] ?
  • {svg_checkmark}H264
  • : ""} + {codecs[1] ?
  • {svg_checkmark}H265
  • : ""} +
    : ""}
  • {svg_checkmark}{translate('Show remote cursor')}
  • {svg_checkmark}{translate('Show quality monitor')}
  • @@ -311,7 +321,7 @@ class Header: Reactor.Component { } } - event click $(menu#display-options>li) (_, me) { + event click $(menu#display-options li) (_, me) { if (me.id == "custom") { handle_custom_image_quality(); } else if (me.id == "privacy-mode") { @@ -328,6 +338,9 @@ class Header: Reactor.Component { } else if (type == "view-style") { handler.save_view_style(me.id); adaptDisplay(); + } else if (type == "codec-preference") { + handler.set_option("codec-preference", me.id); + handler.change_prefer_codec(); } toggleMenuState(); } @@ -355,7 +368,10 @@ function toggleMenuState() { var s = handler.get_view_style(); if (!s) s = "original"; values.push(s); - for (var el in $$(menu#display-options>li)) { + var c = handler.get_option("codec-preference"); + if (!c) c = "auto"; + values.push(c); + for (var el in $$(menu#display-options li)) { el.attributes.toggleClass("selected", values.indexOf(el.id) >= 0); } for (var id in ["show-remote-cursor", "show-quality-monitor", "disable-audio", "enable-file-transfer", "disable-clipboard", "lock-after-session-end"]) { diff --git a/src/ui/remote.rs b/src/ui/remote.rs index 4d941e1f8..a738d7f8b 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -231,6 +231,9 @@ impl sciter::EventHandler for Handler { fn get_remember(); fn peer_platform(); fn set_write_override(i32, i32, bool, bool, bool); + fn has_hwcodec(); + fn supported_hwcodec(); + fn change_prefer_codec(); } } @@ -595,6 +598,42 @@ impl Handler { true } + fn has_hwcodec(&self) -> bool { + #[cfg(not(feature = "hwcodec"))] + return false; + #[cfg(feature = "hwcodec")] + return true; + } + + fn supported_hwcodec(&self) -> Value { + #[cfg(feature = "hwcodec")] + { + let mut v = Value::array(0); + let decoder = scrap::codec::Decoder::video_codec_state(&self.id); + let mut h264 = decoder.score_h264 > 0; + let mut h265 = decoder.score_h265 > 0; + if let Some((encoding_264, encoding_265)) = self.lc.read().unwrap().supported_encoding { + h264 = h264 && encoding_264; + h265 = h265 && encoding_265; + } + v.push(h264); + v.push(h265); + v + } + #[cfg(not(feature = "hwcodec"))] + { + let mut v = Value::array(0); + v.push(false); + v.push(false); + v + } + } + + fn change_prefer_codec(&self) { + let msg = self.lc.write().unwrap().change_prefer_codec(); + self.send(Data::Message(msg)); + } + fn t(&self, name: String) -> String { crate::client::translate(name) } From 23deae0e523557e9bfbb8fe0e48322a9f7505bd7 Mon Sep 17 00:00:00 2001 From: 21pages Date: Tue, 19 Jul 2022 18:14:34 +0800 Subject: [PATCH 07/17] hwcodec: remove bad MY_DECODER_STATE When reset, the new of the decoder will be after it's drop Signed-off-by: 21pages --- libs/scrap/src/common/codec.rs | 36 ++++++++------------------------ libs/scrap/src/common/hwcodec.rs | 2 +- 2 files changed, 10 insertions(+), 28 deletions(-) diff --git a/libs/scrap/src/common/codec.rs b/libs/scrap/src/common/codec.rs index 1a18a79c3..f0bd1c5f7 100644 --- a/libs/scrap/src/common/codec.rs +++ b/libs/scrap/src/common/codec.rs @@ -25,7 +25,6 @@ use hbb_common::{ #[cfg(feature = "hwcodec")] lazy_static::lazy_static! { static ref PEER_DECODER_STATES: Arc>> = Default::default(); - static ref MY_DECODER_STATE: Arc> = Default::default(); } const SCORE_VPX: i32 = 90; @@ -238,25 +237,18 @@ impl Encoder { } } -#[cfg(feature = "hwcodec")] -impl Drop for Decoder { - fn drop(&mut self) { - *MY_DECODER_STATE.lock().unwrap() = VideoCodecState { - score_vpx: SCORE_VPX, - ..Default::default() - }; - } -} - impl Decoder { pub fn video_codec_state(_id: &str) -> VideoCodecState { - // video_codec_state is mainted by creation and destruction of Decoder. - // It has been ensured to use after Decoder's creation. #[cfg(feature = "hwcodec")] if check_hwcodec_config() { - let mut state = MY_DECODER_STATE.lock().unwrap(); - state.perfer = Self::codec_preference(_id).into(); - state.clone() + let best = HwDecoder::best(); + VideoCodecState { + score_vpx: SCORE_VPX, + score_h264: best.h264.map_or(0, |c| c.score), + score_h265: best.h265.map_or(0, |c| c.score), + perfer: Self::codec_preference(_id).into(), + ..Default::default() + } } else { return VideoCodecState { score_vpx: SCORE_VPX, @@ -272,23 +264,13 @@ impl Decoder { pub fn new(config: DecoderCfg) -> Decoder { let vpx = VpxDecoder::new(config.vpx).unwrap(); - let decoder = Decoder { + Decoder { vpx, #[cfg(feature = "hwcodec")] hw: HwDecoder::new_decoders(), #[cfg(feature = "hwcodec")] i420: vec![], - }; - - #[cfg(feature = "hwcodec")] - { - let mut state = MY_DECODER_STATE.lock().unwrap(); - state.score_vpx = SCORE_VPX; - state.score_h264 = decoder.hw.h264.as_ref().map_or(0, |d| d.info.score); - state.score_h265 = decoder.hw.h265.as_ref().map_or(0, |d| d.info.score); } - - decoder } pub fn handle_video_frame( diff --git a/libs/scrap/src/common/hwcodec.rs b/libs/scrap/src/common/hwcodec.rs index c2c853956..c065d811d 100644 --- a/libs/scrap/src/common/hwcodec.rs +++ b/libs/scrap/src/common/hwcodec.rs @@ -178,7 +178,7 @@ pub struct HwDecoders { } impl HwDecoder { - fn best() -> CodecInfos { + pub fn best() -> CodecInfos { get_config(CFG_KEY_DECODER).unwrap_or(CodecInfos { h264: None, h265: None, From 9ab955bb8eaac10f01ad023113f43c9fa8a1570e Mon Sep 17 00:00:00 2001 From: tom Date: Thu, 21 Jul 2022 16:07:19 +0800 Subject: [PATCH 08/17] enable serde feature of bytes, modify struct WriteBlock using Bytes --- Cargo.toml | 2 +- libs/hbb_common/Cargo.toml | 2 +- src/ipc.rs | 3 ++- src/server/connection.rs | 6 +++--- src/ui/cm.rs | 2 +- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6237afe4e..e84875462 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,7 +55,7 @@ rpassword = "7.0" base64 = "0.13" sysinfo = "0.24" num_cpus = "1.13" -bytes = "1.2" +bytes = { version = "1.2", features = ["serde"] } default-net = "0.11.0" wol-rs = "0.9.1" diff --git a/libs/hbb_common/Cargo.toml b/libs/hbb_common/Cargo.toml index 8d34709fe..027aefe79 100644 --- a/libs/hbb_common/Cargo.toml +++ b/libs/hbb_common/Cargo.toml @@ -11,7 +11,7 @@ protobuf = { version = "3.1", features = ["with-bytes"] } tokio = { version = "1.20", features = ["full"] } tokio-util = { version = "0.7", features = ["full"] } futures = "0.3" -bytes = "1.2" +bytes = { version = "1.2", features = ["serde"] } log = "0.4" env_logger = "0.9" socket2 = { version = "0.3", features = ["reuseport"] } diff --git a/src/ipc.rs b/src/ipc.rs index 7df06cd22..532722e38 100644 --- a/src/ipc.rs +++ b/src/ipc.rs @@ -17,6 +17,7 @@ use parity_tokio_ipc::{ }; use serde_derive::{Deserialize, Serialize}; use std::{collections::HashMap, sync::atomic::Ordering}; +use bytes::Bytes; #[cfg(not(windows))] use std::{fs::File, io::prelude::*}; @@ -63,7 +64,7 @@ pub enum FS { WriteBlock { id: i32, file_num: i32, - data: Vec, + data: Bytes, compressed: bool, }, WriteDone { diff --git a/src/server/connection.rs b/src/server/connection.rs index 10a1786fd..f4ed9da2a 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -1063,7 +1063,7 @@ impl Connection { self.send_fs(ipc::FS::WriteBlock { id: block.id, file_num: block.file_num, - data: block.data.into(), + data: block.data, compressed: block.compressed, }); } @@ -1363,8 +1363,8 @@ async fn start_ipc( file_num, data, compressed}) = data { - stream.send(&Data::FS(ipc::FS::WriteBlock{id, file_num, data: Vec::new(), compressed})).await?; - stream.send_raw(data).await?; + stream.send(&Data::FS(ipc::FS::WriteBlock{id, file_num, data: Bytes::new(), compressed})).await?; + stream.send_raw(data.into()).await?; } else { stream.send(&data).await?; } diff --git a/src/ui/cm.rs b/src/ui/cm.rs index 1c2b36a93..c1acb6926 100644 --- a/src/ui/cm.rs +++ b/src/ui/cm.rs @@ -263,7 +263,7 @@ impl ConnectionManager { FileTransferBlock { id, file_num, - data: data.into(), + data, compressed, ..Default::default() }, From e811d5f18b7df0963b272f2831561e261634362a Mon Sep 17 00:00:00 2001 From: tom Date: Thu, 21 Jul 2022 17:54:07 +0800 Subject: [PATCH 09/17] modify argument of ConnectionTmpl::send_raw() --- src/ipc.rs | 4 ++-- src/server/connection.rs | 2 +- src/ui/cm.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ipc.rs b/src/ipc.rs index 532722e38..f2765ebd1 100644 --- a/src/ipc.rs +++ b/src/ipc.rs @@ -456,8 +456,8 @@ where } } - pub async fn send_raw(&mut self, data: Vec) -> ResultType<()> { - self.inner.send(bytes::Bytes::from(data)).await?; + pub async fn send_raw(&mut self, data: Bytes) -> ResultType<()> { + self.inner.send(data).await?; Ok(()) } diff --git a/src/server/connection.rs b/src/server/connection.rs index f4ed9da2a..9c326575e 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -1364,7 +1364,7 @@ async fn start_ipc( data, compressed}) = data { stream.send(&Data::FS(ipc::FS::WriteBlock{id, file_num, data: Bytes::new(), compressed})).await?; - stream.send_raw(data.into()).await?; + stream.send_raw(data).await?; } else { stream.send(&data).await?; } diff --git a/src/ui/cm.rs b/src/ui/cm.rs index c1acb6926..fe5738c31 100644 --- a/src/ui/cm.rs +++ b/src/ui/cm.rs @@ -590,7 +590,7 @@ async fn start_pa() { } else { buf.clone() }; - if let Err(err) = stream.send_raw(out).await { + if let Err(err) = stream.send_raw(out.into()).await { log::error!("Failed to send audio data:{}", err); break; } From d19a8fdc4307f44f95364eb3852af855cc6cd003 Mon Sep 17 00:00:00 2001 From: fufesou Date: Thu, 21 Jul 2022 20:04:39 +0800 Subject: [PATCH 10/17] fix_capturer_trait_name_shadowing: build win Signed-off-by: fufesou --- libs/scrap/examples/capture_mag.rs | 2 +- libs/scrap/examples/ffplay.rs | 2 +- libs/scrap/examples/record-screen.rs | 2 +- libs/scrap/examples/screenshot.rs | 2 +- libs/scrap/src/common/android.rs | 6 ++- libs/scrap/src/common/dxgi.rs | 62 ++++++++++++++++++---------- libs/scrap/src/common/linux.rs | 19 +++++---- libs/scrap/src/common/mod.rs | 10 +++++ libs/scrap/src/common/quartz.rs | 8 +++- libs/scrap/src/common/wayland.rs | 14 ++++--- libs/scrap/src/common/x11.rs | 14 ++++--- src/server/video_service.rs | 54 +----------------------- src/server/wayland.rs | 44 ++++++++++++-------- 13 files changed, 122 insertions(+), 117 deletions(-) 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 { From 04c8340b3b87c64edcb14637e9fc97b35ed1ef78 Mon Sep 17 00:00:00 2001 From: fufesou Date: Thu, 21 Jul 2022 20:53:31 +0800 Subject: [PATCH 11/17] fix_capturer_trait_name_shadowing: update Cargo.lock Signed-off-by: fufesou --- Cargo.lock | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) 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", From e06c37338914f9752a3c2e025cd0a3cb2f2697eb Mon Sep 17 00:00:00 2001 From: fufesou Date: Thu, 21 Jul 2022 21:58:42 +0800 Subject: [PATCH 12/17] fix_cmd_window: do not show cmd prompt window Signed-off-by: fufesou --- Cargo.lock | 8 ++++++-- src/server/video_service.rs | 6 ++++-- src/ui/win_privacy.rs | 6 +++++- 3 files changed, 15 insertions(+), 5 deletions(-) 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/src/server/video_service.rs b/src/server/video_service.rs index e6ea713a1..362fe15c5 100644 --- a/src/server/video_service.rs +++ b/src/server/video_service.rs @@ -393,8 +393,10 @@ fn get_capturer(use_yuv: bool) -> ResultType { #[cfg(windows)] let mut captuerer_privacy_mode_id = privacy_mode_id; #[cfg(windows)] - if crate::ui::win_privacy::is_process_consent_running()? { - captuerer_privacy_mode_id = 0; + if captuerer_privacy_mode_id != 0 { + if crate::ui::win_privacy::is_process_consent_running()? { + captuerer_privacy_mode_id = 0; + } } log::debug!( "Try create capturer with captuerer privacy mode id {}", diff --git a/src/ui/win_privacy.rs b/src/ui/win_privacy.rs index 0bbb040ec..9944bf262 100644 --- a/src/ui/win_privacy.rs +++ b/src/ui/win_privacy.rs @@ -5,6 +5,7 @@ use crate::{ use hbb_common::{allow_err, bail, lazy_static, log, tokio, ResultType}; use std::{ ffi::CString, + os::windows::process::CommandExt, sync::Mutex, time::{Duration, Instant}, }; @@ -24,7 +25,9 @@ use winapi::{ CreateProcessAsUserW, GetCurrentThreadId, QueueUserAPC, ResumeThread, PROCESS_INFORMATION, STARTUPINFOW, }, - winbase::{WTSGetActiveConsoleSessionId, CREATE_SUSPENDED, DETACHED_PROCESS}, + winbase::{ + WTSGetActiveConsoleSessionId, CREATE_NO_WINDOW, CREATE_SUSPENDED, DETACHED_PROCESS, + }, winnt::{MEM_COMMIT, PAGE_READWRITE}, winuser::*, }, @@ -317,6 +320,7 @@ fn wait_find_privacy_hwnd(msecs: u128) -> ResultType { pub fn is_process_consent_running() -> ResultType { let output = std::process::Command::new("cmd") .args(&["/C", "tasklist | findstr consent.exe"]) + .creation_flags(CREATE_NO_WINDOW) .output()?; Ok(output.status.success() && !output.stdout.is_empty()) } From 9ee2d750f82f3e672a9b6374ddfe8f548775c7a6 Mon Sep 17 00:00:00 2001 From: rustdesk Date: Thu, 21 Jul 2022 22:29:26 +0800 Subject: [PATCH 13/17] fix compile error --- libs/scrap/src/common/android.rs | 2 +- libs/scrap/src/common/quartz.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/scrap/src/common/android.rs b/libs/scrap/src/common/android.rs index e15752d8e..949188712 100644 --- a/libs/scrap/src/common/android.rs +++ b/libs/scrap/src/common/android.rs @@ -34,7 +34,7 @@ impl Capturer { } } -impl TraitCapturer for Capturer { +impl crate::TraitCapturer for Capturer { fn set_use_yuv(&mut self, _use_yuv: bool) {} fn frame<'a>(&'a mut self, _timeout: Duration) -> io::Result> { diff --git a/libs/scrap/src/common/quartz.rs b/libs/scrap/src/common/quartz.rs index b4ecf898b..6e29c2441 100644 --- a/libs/scrap/src/common/quartz.rs +++ b/libs/scrap/src/common/quartz.rs @@ -52,7 +52,7 @@ impl Capturer { } } -impl TraitCapturer for Capturer { +impl crate::TraitCapturer for Capturer { fn set_use_yuv(&mut self, use_yuv: bool) { self.use_yuv = use_yuv; } From bb1289dbc3c00267a613ac4a94be541e90e47785 Mon Sep 17 00:00:00 2001 From: Fabian Schillig Date: Thu, 21 Jul 2022 18:31:59 +0200 Subject: [PATCH 14/17] Update de.rs --- src/lang/de.rs | 284 ++++++++++++++++++++++++------------------------- 1 file changed, 142 insertions(+), 142 deletions(-) diff --git a/src/lang/de.rs b/src/lang/de.rs index c9cd243fb..671bcae98 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -6,14 +6,14 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("desk_tip", "Mit dieser ID und diesem Passwort können Sie auf Ihren Desktop zugreifen."), ("Password", "Passwort"), ("Ready", "Bereit"), - ("Established", "Etabliert"), + ("Established", "Verbunden"), ("connecting_status", "Verbinden mit dem RustDesk-Netzwerk..."), - ("Enable Service", "Verbindungsserver einschalten"), - ("Start Service", "Starte Verbindungsserver"), - ("Service is running", "Dienst läuft"), - ("Service is not running", "Der Verbindungsserver läuft nicht"), + ("Enable Service", "Verbindungsserver aktivieren"), + ("Start Service", "Starte Vermittlungsdienst"), + ("Service is running", "Vermittlungsdienst aktiv"), + ("Service is not running", "Vermittlungsdienst deaktiviert"), ("not_ready_status", "Nicht bereit. Bitte überprüfen Sie Ihre Verbindung"), - ("Control Remote Desktop", "Entfernten Desktop steuern"), + ("Control Remote Desktop", "Entfernten PC steuern"), ("Transfer File", "Datei übertragen"), ("Connect", "Verbinden"), ("Recent Sessions", "Letzte Sitzungen"), @@ -21,49 +21,49 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Confirmation", "Bestätigung"), ("TCP Tunneling", "TCP Tunneln"), ("Remove", "Entfernen"), - ("Refresh random password", "Zufälliges Passwort aktualisieren"), - ("Set your own password", "Legen Sie Ihr eigenes Passwort fest"), - ("Enable Keyboard/Mouse", "Tastatur/Maus einschalten"), - ("Enable Clipboard", "Zwischenablage einschalten"), + ("Refresh random password", "Neues zufälliges Passwort"), + ("Set your own password", "Eigenes Passwort setzen"), + ("Enable Keyboard/Mouse", "Tastatur/Maus aktivieren"), + ("Enable Clipboard", "Zwischenablage aktivieren"), ("Enable File Transfer", "Dateiübertragung aktivieren"), - ("Enable TCP Tunneling", "TCP-Tunneling einschalten"), - ("IP Whitelisting", "IP Freigabeliste"), - ("ID/Relay Server", "ID/Verbindungsserver"), - ("Stop service", "Verbindungsserver ausschalten"), - ("Change ID", "ID wechseln"), + ("Enable TCP Tunneling", "TCP-Tunneln aktivieren"), + ("IP Whitelisting", "IP-Whitelist"), + ("ID/Relay Server", "ID/Vermittlungsserver"), + ("Stop service", "Vermittlungsdienst deaktivieren"), + ("Change ID", "ID ändern"), ("Website", "Webseite"), ("About", "Über"), ("Mute", "Stummschalten"), ("Audio Input", "Audio-Eingang"), - ("Enhancements", ""), - ("Hardware Codec", ""), - ("Adaptive Bitrate", ""), + ("Enhancements", "Verbesserungen"), + ("Hardware Codec", "Hardware-Codec"), + ("Adaptive Bitrate", "Adaptive Bitrate"), ("ID Server", "ID Server"), - ("Relay Server", "Verbindungsserver Server"), - ("API Server", "API Server"), + ("Relay Server", "Vermittlungsserver"), + ("API Server", "API-Server"), ("invalid_http", "Muss mit http:// oder https:// beginnen"), ("Invalid IP", "Ungültige IP-Adresse"), - ("id_change_tip", "Nur die Zeichen a-z, A-Z, 0-9 und _ (Unterstrich) sind erlaubt. Der erste Buchstabe muss a-z, A-Z sein. Länge zwischen 6 und 16."), + ("id_change_tip", "Nur die Zeichen a-z, A-Z, 0-9 und _ (Unterstrich) sind erlaubt. Der erste Buchstabe muss a-z, A-Z sein, Länge zwischen 6 und 16."), ("Invalid format", "Ungültiges Format"), - ("server_not_support", "Noch nicht vom Server unterstützt"), + ("server_not_support", "Diese Funktion wird noch nicht vom Server unterstützt"), ("Not available", "Nicht verfügbar"), ("Too frequent", "Zu häufig"), ("Cancel", "Abbrechen"), ("Skip", "Überspringen"), ("Close", "Schließen"), - ("Retry", "Nochmal versuchen"), + ("Retry", "Erneut versuchen"), ("OK", "OK"), ("Password Required", "Passwort erforderlich"), - ("Please enter your password", "Bitte geben Sie Ihr Passwort ein"), + ("Please enter your password", "Bitte geben Sie das Passwort des entfernten PCs ein."), ("Remember password", "Passwort merken"), ("Wrong Password", "Falsches Passwort"), - ("Do you want to enter again?", "Möchten Sie erneut teilnehmen?"), + ("Do you want to enter again?", "Erneut verbinden?"), ("Connection Error", "Verbindungsfehler"), ("Error", "Fehler"), - ("Reset by the peer", "Zurücksetzen durch die Gegenstelle"), + ("Reset by the peer", "Verbindung wurde von der Gegenstelle zurückgesetzt"), ("Connecting...", "Verbinden..."), ("Connection in progress. Please wait.", "Die Verbindung wird hergestellt. Bitte warten Sie."), - ("Please try 1 minute later", "Bitte versuchen Sie es 1 Minute später"), + ("Please try 1 minute later", "Bitte versuchen Sie es später erneut"), ("Login Error", "Anmeldefehler"), ("Successful", "Erfolgreich"), ("Connected, waiting for image...", "Verbunden, warten auf Bild..."), @@ -75,92 +75,92 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Receive", "Empfangen"), ("Send", "Senden"), ("Refresh File", "Datei aktualisieren"), - ("Local", "Lokaler"), - ("Remote", "Entfernter"), + ("Local", "Lokal"), + ("Remote", "Entfernt"), ("Remote Computer", "Entfernter Computer"), - ("Local Computer", "Lokaler Computer"), + ("Local Computer", "Dieser Computer"), ("Confirm Delete", "Löschen bestätigen"), ("Delete", "Löschen"), ("Properties", "Eigenschaften"), ("Multi Select", "Mehrfachauswahl"), - ("Empty Directory", "Leeres Verzeichnis"), - ("Not an empty directory", "Kein leeres Verzeichnis"), + ("Empty Directory", "Leerer Ordner"), + ("Not an empty directory", "Ordner nicht leer"), ("Are you sure you want to delete this file?", "Sind Sie sicher, dass Sie diese Datei löschen wollen?"), - ("Are you sure you want to delete this empty directory?", "Sind Sie sicher, dass Sie dieses leere Verzeichnis löschen möchten?"), - ("Are you sure you want to delete the file of this directory?", "Sind Sie sicher, dass Sie die Datei dieses Verzeichnisses löschen möchten?"), - ("Do this for all conflicts", "Dies gilt für alle Konflikte"), + ("Are you sure you want to delete this empty directory?", "Sind Sie sicher, dass Sie diesen leeren Ordner löschen möchten?"), + ("Are you sure you want to delete the file of this directory?", "Sind Sie sicher, dass Sie die Datei dieses Ordners löschen möchten?"), + ("Do this for all conflicts", "Für alle Konflikte merken"), ("This is irreversible!", "Dies ist irreversibel!"), ("Deleting", "Löschen"), ("files", "Dateien"), ("Waiting", "Warten"), ("Finished", "Fertiggestellt"), ("Speed", "Geschwindigkeit"), - ("Custom Image Quality", "Individuelle Bildqualität"), + ("Custom Image Quality", "Benutzerdefinierte Bildqualität"), ("Privacy mode", "Datenschutz-Modus"), ("Block user input", "Benutzereingaben blockieren"), ("Unblock user input", "Benutzereingaben freigeben"), ("Adjust Window", "Fenster anpassen"), ("Original", "Original"), - ("Shrink", "Geschrumpft"), - ("Stretch", "Gestreckt"), - ("Good image quality", "Gute Bildqualität"), + ("Shrink", "Verkleinern"), + ("Stretch", "Strecken"), + ("Good image quality", "Schöner"), ("Balanced", "Ausgeglichen"), - ("Optimize reaction time", "Optimierte Reaktionszeit"), + ("Optimize reaction time", "Schneller"), ("Custom", "Benutzerdefiniert"), - ("Show remote cursor", "Ferngesteuerten Cursor anzeigen"), - ("Show quality monitor", ""), + ("Show remote cursor", "Entfernten Cursor anzeigen"), + ("Show quality monitor", "Qualitätsüberwachung anzeigen"), ("Disable clipboard", "Zwischenablage deaktivieren"), ("Lock after session end", "Sperren nach Sitzungsende"), ("Insert", "Einfügen"), - ("Insert Lock", "Sperre einfügen"), + ("Insert Lock", "Win+L (Sperren) senden"), ("Refresh", "Aktualisieren"), - ("ID does not exist", "Die ID existiert nicht"), - ("Failed to connect to rendezvous server", "Verbindung zum Verbindungsserver fehlgeschlagen"), - ("Please try later", "Bitte versuchen Sie es später"), - ("Remote desktop is offline", "Entfernter Desktop ist offline"), - ("Key mismatch", "Schlüssel nicht übereinstimmend"), + ("ID does not exist", "Diese ID existiert nicht"), + ("Failed to connect to rendezvous server", "Verbindung zum Vermittlungsserver fehlgeschlagen"), + ("Please try later", "Bitte versuchen Sie es später erneut"), + ("Remote desktop is offline", "Entfernter PC ist offline"), + ("Key mismatch", "Schlüssel stimmt nicht mit Serverschlüssel überein"), ("Timeout", "Zeitüberschreitung"), - ("Failed to connect to relay server", "Verbindung zum Verbindungsserver fehlgeschlagen"), - ("Failed to connect via rendezvous server", "Verbindung über rendezvous server fehlgeschlagen"), - ("Failed to connect via relay server", "Verbindung über den Verbindungsserver ist fehlgeschlagen"), - ("Failed to make direct connection to remote desktop", "Direkte Verbindung zum Entfernten-Desktop konnte nicht hergestellt werden"), + ("Failed to connect to relay server", "Verbindung zum Vermittlungsserver fehlgeschlagen"), + ("Failed to connect via rendezvous server", "Verbindung über Vermittlungsserver ist fehlgeschlagen"), + ("Failed to connect via relay server", "Verbindung über Relay-Server ist fehlgeschlagen"), + ("Failed to make direct connection to remote desktop", "Direkte Verbindung zum entfernten PC fehlgeschlagen"), ("Set Password", "Passwort festlegen"), ("OS Password", "Betriebssystem-Passwort"), ("install_tip", "Aufgrund der UAC kann RustDesk in manchen Fällen nicht ordnungsgemäß auf der Gegenseite funktionieren. Um UAC zu vermeiden, klicken Sie bitte auf die Schaltfläche unten, um RustDesk auf dem System zu installieren"), - ("Click to upgrade", "Zum Upgrade anklicken"), + ("Click to upgrade", "Zum Aktualisieren anklicken"), ("Click to download", "Zum Herunterladen klicken"), ("Click to update", "Zum Aktualisieren klicken"), ("Configure", "Konfigurieren"), - ("config_acc", "Um Ihren Desktop aus der Ferne zu steuern, müssen Sie RustDesk \"Zugangs\" Rechte erteilen."), - ("config_screen", "Um aus der Ferne auf Ihren Desktop zugreifen zu können, müssen Sie RustDesk \"Bildschirm-Aufnahme\" Berechtigungen erteilen."), + ("config_acc", "Um Ihren PC aus der Ferne zu steuern, müssen Sie RustDesk Zugriffsrechte erteilen."), + ("config_screen", "Um aus der Ferne auf Ihren PC zugreifen zu können, müssen Sie RustDesk \"Bildschirm-Aufnahme\"-Berechtigung erteilen."), ("Installing ...", "Installiere ..."), ("Install", "Installieren"), - ("Installation", "Einrichtung"), - ("Installation Path", "Einrichtungs Pfad"), - ("Create start menu shortcuts", "Startmenü Verknüpfungen erstellen"), - ("Create desktop icon", "Desktop Symbol erstellen"), - ("agreement_tip", "Wenn Sie die Einrichtung starten, akzeptieren Sie die Lizenzvereinbarung"), - ("Accept and Install", "Akzeptieren und installieren"), + ("Installation", "Installation"), + ("Installation Path", "Installationspfad"), + ("Create start menu shortcuts", "Verknüpfung im Startmenü erstellen"), + ("Create desktop icon", "Desktop-Verknüpfung erstellen"), + ("agreement_tip", "Durch die Installation akzeptieren Sie die Lizenzvereinbarung"), + ("Accept and Install", "Akzeptieren und Installieren"), ("End-user license agreement", "Lizenzvereinbarung für Endbenutzer"), - ("Generating ...", "Generierung ..."), - ("Your installation is lower version.", "Ihre Installation ist eine niedrigere Version."), - ("not_close_tcp_tip", "Schließen Sie dieses Fenster nicht, während Sie den Tunnel benutzen."), - ("Listening ...", "Hören ..."), - ("Remote Host", "Entfernter Rechner"), + ("Generating ...", "Generiere..."), + ("Your installation is lower version.", "Ihre Installation ist älter."), + ("not_close_tcp_tip", "Schließen Sie dieses Fenster nicht, solange Sie den Tunnel benutzen."), + ("Listening ...", "Höre..."), + ("Remote Host", "Entfernter PC"), ("Remote Port", "Entfernter Port"), ("Action", "Aktion"), ("Add", "Hinzufügen"), ("Local Port", "Lokaler Port"), - ("setup_server_tip", "Für eine schnellere Verbindung, richten Sie bitte Ihren eigenen Verbindungsserver ein"), + ("setup_server_tip", "Für eine schnellere Verbindung richten Sie bitte Ihren eigenen Verbindungsserver ein"), ("Too short, at least 6 characters.", "Zu kurz, mindestens 6 Zeichen."), - ("The confirmation is not identical.", "Die Bestätigung ist nicht identisch."), + ("The confirmation is not identical.", "Die Passwörter sind nicht identisch."), ("Permissions", "Berechtigungen"), ("Accept", "Akzeptieren"), ("Dismiss", "Ablehnen"), ("Disconnect", "Verbindung trennen"), - ("Allow using keyboard and mouse", "Erlaubt die Verwendung von Tastatur und Maus"), + ("Allow using keyboard and mouse", "Verwendung von Maus und Tastatur zulassen"), ("Allow using clipboard", "Verwendung der Zwischenablage zulassen"), - ("Allow hearing sound", "Erlaubt das Hören von Sound"), + ("Allow hearing sound", "System-Audio übertragen"), ("Allow file copy and paste", "Kopieren und Einfügen von Dateien zulassen"), ("Connected", "Verbunden"), ("Direct and encrypted connection", "Direkte und verschlüsselte Verbindung"), @@ -171,17 +171,17 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enter your password", "Geben Sie Ihr Passwort ein"), ("Logging in...", "Anmeldung..."), ("Enable RDP session sharing", "RDP-Sitzungsfreigabe aktivieren"), - ("Auto Login", "Automatisches Login (nur gültig, wenn Sie \"Sperren nach Sitzungsende\" eingestellt haben)"), + ("Auto Login", "Automatisch anmelden (nur gültig, wenn Sie \"Sperren nach Sitzungsende\" aktiviert haben)"), ("Enable Direct IP Access", "Direkten IP-Zugang aktivieren"), ("Rename", "Umbenennen"), - ("Space", "Platz"), + ("Space", "Speicherplatz"), ("Create Desktop Shortcut", "Desktop-Verknüpfung erstellen"), ("Change Path", "Pfad ändern"), ("Create Folder", "Ordner erstellen"), ("Please enter the folder name", "Bitte geben Sie den Ordnernamen ein"), ("Fix it", "Reparieren"), ("Warning", "Warnung"), - ("Login screen using Wayland is not supported", "Anmeldebildschirm mit Wayland wird nicht unterstützt"), + ("Login screen using Wayland is not supported", "Anmeldebildschirm wird mit Wayland nicht unterstützt"), ("Reboot required", "Neustart erforderlich"), ("Unsupported display server ", "Nicht unterstützter Display-Server"), ("x11 expected", "X11 erwartet"), @@ -189,14 +189,14 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Settings", "Einstellungen"), ("Username", " Benutzername"), ("Invalid port", "Ungültiger Port"), - ("Closed manually by the peer", "Vom Peer manuell geschlossen"), - ("Enable remote configuration modification", "Änderung der Fernkonfiguration zulassen"), + ("Closed manually by the peer", "Von der Gegenstelle manuell geschlossen"), + ("Enable remote configuration modification", "Änderung der Konfiguration aus der Ferne zulassen"), ("Run without install", "Ohne Installation ausführen"), - ("Always connected via relay", "Immer über Verbindungsserver verbunden"), - ("Always connect via relay", "Verbindung immer über Verbindungsserver"), - ("whitelist_tip", "Nur IPs auf der Freigabeliste können auf mich zugreifen"), - ("Login", "Anmeldung"), - ("Logout", "Abmeldung"), + ("Always connected via relay", "Immer über Relay-Server verbunden"), + ("Always connect via relay", "Immer über Relay-Server verbinden"), + ("whitelist_tip", "Nur IPs auf der Whitelist können zugreifen"), + ("Login", "Anmelden"), + ("Logout", "Abmelden"), ("Tags", "Stichworte"), ("Search ID", "Suche ID"), ("Current Wayland display server is not supported", "Der aktuelle Wayland-Anzeigeserver wird nicht unterstützt"), @@ -205,100 +205,100 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Add Tag", "Stichwort hinzufügen"), ("Unselect all tags", "Alle Stichworte abwählen"), ("Network error", "Netzwerkfehler"), - ("Username missed", "Benutzername fehlt"), + ("Username missed", "Benutzername vergessen"), ("Password missed", "Passwort vergessen"), ("Wrong credentials", "Falsche Anmeldedaten"), ("Edit Tag", "Stichwort bearbeiten"), - ("Unremember Password", "Passwort nicht merken"), + ("Unremember Password", "Passwort vergessen"), ("Favorites", "Favoriten"), ("Add to Favorites", "Zu Favoriten hinzufügen"), - ("Remove from Favorites", "Entferne von Favoriten"), + ("Remove from Favorites", "Aus Favoriten entfernen"), ("Empty", "Leer"), ("Invalid folder name", "Ungültiger Ordnername"), ("Socks5 Proxy", "Socks5 Proxy"), ("Hostname", "Rechnername"), ("Discovered", "Gefunden"), - ("install_daemon_tip", "Um beim Booten zu starten, müssen Sie den Systemdienst installieren"), + ("install_daemon_tip", "Um mit System zu starten, muss der Systemdienst installiert sein"), ("Remote ID", "Entfernte ID"), ("Paste", "Einfügen"), ("Paste here?", "Hier einfügen?"), - ("Are you sure to close the connection?", "Sind Sie sicher, dass Sie die Verbindung schließen wollen?"), + ("Are you sure to close the connection?", "Möchten Sie diese Verbindung wirklich trennen?"), ("Download new version", "Neue Version herunterladen"), ("Touch mode", "Touch-Modus"), - ("Mouse mode", "Mouse-Modus"), - ("One-Finger Tap", "Ein Fingertipp"), - ("Left Mouse", "Linke Maus"), - ("One-Long Tap", "Tippen Sie mit einem Finger lang"), - ("Two-Finger Tap", "Zwei Finger tippen"), - ("Right Mouse", "Rechte Maus"), - ("One-Finger Move", "Eine Fingerbewegung"), - ("Double Tap & Move", "Doppeltippen und verschieben"), - ("Mouse Drag", "Maus ziehen"), - ("Three-Finger vertically", "Drei Finger vertikal"), + ("Mouse mode", "Maus-Modus"), + ("One-Finger Tap", "1-Finger-Tipp"), + ("Left Mouse", "Linksklick"), + ("One-Long Tap", "1-Finger-Halten"), + ("Two-Finger Tap", "2-Finger-Tipp"), + ("Right Mouse", "Rechtsklick"), + ("One-Finger Move", "Einen Finger bewegen"), + ("Double Tap & Move", "Doppeltippen und bewegen"), + ("Mouse Drag", "Maus bewegen"), + ("Three-Finger vertically", "Drei Finger vertikal bewegen"), ("Mouse Wheel", "Mausrad"), - ("Two-Finger Move", "Zwei Finger Bewegung"), - ("Canvas Move", "Leinwand bewegen"), - ("Pinch to Zoom", "Zum Zoomen kneifen"), - ("Canvas Zoom", "Leinwand Zoom"), - ("Reset canvas", "Anzeige zurücksetzen"), - ("No permission of file transfer", "Keine Erlaubnis zur Dateiübertragung"), - ("Note", "Notiz"), + ("Two-Finger Move", "Zwei Finger bewegen"), + ("Canvas Move", "Sichtfeld bewegen"), + ("Pinch to Zoom", "2-Finger-Zoom"), + ("Canvas Zoom", "Sichtfeld-Zoom"), + ("Reset canvas", "Sichtfeld zurücksetzen"), + ("No permission of file transfer", "Keine Dateizugriff-Berechtigung"), + ("Note", "Anmerkung"), ("Connection", "Verbindung"), ("Share Screen", "Bildschirm freigeben"), - ("CLOSE", "NAH DRAN"), - ("OPEN", "OFFEN"), - ("Chat", "Plaudern"), + ("CLOSE", "DEAKTIV."), + ("OPEN", "AKTIVIER."), + ("Chat", "Chat"), ("Total", "Gesamt"), - ("items", "Artikel"), + ("items", "Einträge"), ("Selected", "Ausgewählt"), - ("Screen Capture", "Bildschirmaufnahme"), - ("Input Control", "Eingabesteuerung"), - ("Audio Capture", "Audioaufnahme"), - ("File Connection", "Dateiverbindung"), + ("Screen Capture", "Bildschirmzugr."), + ("Input Control", "Eingabezugriff"), + ("Audio Capture", "Audiozugriff"), + ("File Connection", "Dateizugriff"), ("Screen Connection", "Bildschirmanschluss"), - ("Do you accept?", "Akzeptieren Sie?"), + ("Do you accept?", "Verbindung zulassen?"), ("Open System Setting", "Systemeinstellung öffnen"), ("How to get Android input permission?", "Wie erhalte ich eine Android-Eingabeberechtigung?"), - ("android_input_permission_tip1", "Damit ein Remote-Gerät Ihr Android-Gerät per Maus oder Berührung steuern kann, müssen Sie RustDesk erlauben, den Dienst \"Barrierefreiheit\" zu verwenden."), + ("android_input_permission_tip1", "Damit ein Remote-Gerät Ihr Android-Gerät steuern kann, müssen Sie RustDesk erlauben, den Dienst \"Barrierefreiheit\" zu verwenden."), ("android_input_permission_tip2", "Bitte gehen Sie zur nächsten Systemeinstellungsseite, suchen und geben Sie [Installierte Dienste] ein, schalten Sie den Dienst [RustDesk Input] ein."), - ("android_new_connection_tip", "Es wurde eine neue Steuerungsanforderung empfangen, die Ihr aktuelles Gerät steuern möchte."), - ("android_service_will_start_tip", "Durch das Einschalten der Bildschirmaufnahme wird der Dienst automatisch gestartet, sodass andere Geräte eine Verbindung von diesem Gerät anfordern können."), - ("android_stop_service_tip", "Durch das Schließen des Dienstes werden automatisch alle hergestellten Verbindungen geschlossen."), - ("android_version_audio_tip", "Die aktuelle Android-Version unterstützt keine Audioaufnahme, bitte aktualisieren Sie auf Android 10 oder höher."), - ("android_start_service_tip", "Tippen Sie auf [Dienst starten] oder ÖFFNEN Sie die Berechtigung [Bildschirmaufnahme], um den Bildschirmfreigabedienst zu starten."), + ("android_new_connection_tip", "möchte ihr Gerät steuern."), + ("android_service_will_start_tip", "Durch das Aktivieren der Bildschirmfreigabe wird der Dienst automatisch gestartet, sodass andere Geräte dieses Android-Gerät steuern können."), + ("android_stop_service_tip", "Durch das Deaktivieren des Dienstes werden automatisch alle hergestellten Verbindungen getrennt."), + ("android_version_audio_tip", "Ihre Android-Version unterstützt keine Audioaufnahme, bitte aktualisieren Sie auf Android 10 oder höher, falls möglich."), + ("android_start_service_tip", "Tippen Sie auf [Dienst aktivieren] oder aktivieren Sie die Berechtigung [Bildschirmzugr.], um den Bildschirmfreigabedienst zu starten."), ("Account", "Konto"), ("Overwrite", "Überschreiben"), - ("This file exists, skip or overwrite this file?", "Diese Datei existiert, diese Datei überspringen oder überschreiben?"), - ("Quit", "Aufhören"), - ("doc_mac_permission", "https://rustdesk.com/docs/en/manual/mac/#enable-permissions"), + ("This file exists, skip or overwrite this file?", "Diese Datei existiert; überspringen oder überschreiben?"), + ("Quit", "Beenden"), + ("doc_mac_permission", "https://rustdesk.com/docs/de/manual/mac/#berechtigungen-aktivieren"), ("Help", "Hilfe"), - ("Failed", "Gescheitert"), + ("Failed", "Fehlgeschlagen"), ("Succeeded", "Erfolgreich"), - ("Someone turns on privacy mode, exit", "Jemand aktiviert den Datenschutzmodus, beenden"), + ("Someone turns on privacy mode, exit", "Jemand hat den Datenschutzmodus aktiviert, beende..."), ("Unsupported", "Nicht unterstützt"), - ("Peer denied", "Peer verweigert"), + ("Peer denied", "Die Gegenstelle hat die Verbindung abgelehnt"), ("Please install plugins", "Bitte installieren Sie Plugins"), - ("Peer exit", "Peer-Ausgang"), + ("Peer exit", "Die Gegenstelle hat die Verbindung getrennt"), ("Failed to turn off", "Ausschalten fehlgeschlagen"), ("Turned off", "Ausgeschaltet"), - ("In privacy mode", "im Datenschutzmodus"), - ("Out privacy mode", "Datenschutzmodus aus"), + ("In privacy mode", "Datenschutzmodus aktivieren"), + ("Out privacy mode", "Datenschutzmodus deaktivieren"), ("Language", "Sprache"), - ("Keep RustDesk background service", ""), - ("Ignore Battery Optimizations", ""), - ("android_open_battery_optimizations_tip", ""), - ("Random Password After Session", ""), - ("Keep", ""), - ("Update", ""), - ("Disable", ""), - ("Onetime Password", ""), - ("Verification Method", ""), - ("Enable security password", ""), - ("Enable random password", ""), - ("Enable onetime password", ""), - ("Disable onetime password", ""), - ("Activate onetime password", ""), - ("Set security password", ""), - ("Connection not allowed", ""), + ("Keep RustDesk background service", "RustDesk im Hintergrund ausführen"), + ("Ignore Battery Optimizations", "Batterieoptimierung ignorieren"), + ("android_open_battery_optimizations_tip", "Möchten Sie die Batterieopimierungs-Einstellungen öffnen?"), + ("Random Password After Session", "Neues zufälliges Passwort nach jeder Sitzung"), + ("Keep", "Behalten"), + ("Update", "Aktualisieren"), + ("Disable", "Deaktivieren"), + ("Onetime Password", "Einmal-Passwort"), + ("Verification Method", "Überprüfungsmethode"), + ("Enable security password", "Sicheres Passwort aktivieren"), + ("Enable random password", "Zufälliges Passwort aktivieren"), + ("Enable onetime password", "Einmal-Passwort aktivieren"), + ("Disable onetime password", "Einmal-Passwort deaktivieren"), + ("Activate onetime password", "Einmal-Passwort aktivieren"), + ("Set security password", "Sicheres Passwort setzen"), + ("Connection not allowed", "Verbindung abgelehnt"), ].iter().cloned().collect(); } From b55fc35d83e1f2bad227711dd8f1a5d4224ffc53 Mon Sep 17 00:00:00 2001 From: 21pages Date: Fri, 22 Jul 2022 09:13:40 +0800 Subject: [PATCH 15/17] hwcodec: fix compile error Signed-off-by: 21pages --- libs/scrap/src/common/hwcodec.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/scrap/src/common/hwcodec.rs b/libs/scrap/src/common/hwcodec.rs index c065d811d..7431bc952 100644 --- a/libs/scrap/src/common/hwcodec.rs +++ b/libs/scrap/src/common/hwcodec.rs @@ -7,7 +7,7 @@ use hbb_common::{ config::HwCodecConfig, lazy_static, log, message_proto::{EncodedVideoFrame, EncodedVideoFrames, Message, VideoFrame}, - ResultType, + ResultType, bytes::Bytes, }; use hwcodec::{ decode::{DecodeContext, DecodeFrame, Decoder}, @@ -91,7 +91,7 @@ impl EncoderApi for HwEncoder { let mut frames = Vec::new(); for frame in self.encode(frame).with_context(|| "Failed to encode")? { frames.push(EncodedVideoFrame { - data: frame.data, + data: Bytes::from(frame.data), pts: frame.pts as _, ..Default::default() }); From af60042e33bc1a6888b3234db0aa79a03a58937d Mon Sep 17 00:00:00 2001 From: 21pages Date: Fri, 22 Jul 2022 09:14:18 +0800 Subject: [PATCH 16/17] hwcodec: update build.py Signed-off-by: 21pages --- build.py | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) mode change 100644 => 100755 build.py diff --git a/build.py b/build.py old mode 100644 new mode 100755 index efa6f7831..f612caa22 --- a/build.py +++ b/build.py @@ -22,7 +22,7 @@ def get_version(): return '' -def get_features(feature): +def prase_rc_features(feature): available_features = { 'IddDriver': { 'zip_url': 'https://github.com/fufesou/RustDeskIddDriver/releases/download/v0.1/RustDeskIddDriver_x64.zip', @@ -94,8 +94,8 @@ def download_extract_features(features, res_dir): print(f'{feat} extract end') -def build_windows(args): - features = get_features(args.feature) +def get_rc_features(args): + features = prase_rc_features(args.feature) if features: print(f'Build with features {list(features.keys())}') res_dir = 'resources' @@ -105,12 +105,17 @@ def build_windows(args): raise Exception(f'Find file {res_dir}, not a directory') os.makedirs(res_dir, exist_ok=True) download_extract_features(features, res_dir) + return ['with_rc'] if features else [] + - with_rc = ',with_rc' if features else '' - hwcodec = ',hwcodec' if args.hwcodec else '' - cmd = 'cargo build --release --features inline' + with_rc + hwcodec - print(cmd) - os.system(cmd) +def get_features(args): + features = ['inline'] + if windows: + features.extend(get_rc_features(args)) + if args.hwcodec: + features.append('hwcodec') + print("features:", features) + return features def main(): parser = make_parser() @@ -129,8 +134,9 @@ def main(): if os.path.isfile('/usr/bin/pacman'): os.system('git checkout src/ui/common.tis') version = get_version() + features = ",".join(get_features(args)) if windows: - build_windows(args) + os.system('cargo build --release --features ' + features) # os.system('upx.exe target/release/rustdesk.exe') os.system('mv target/release/rustdesk.exe target/release/RustDesk.exe') pa = os.environ.get('P') @@ -141,7 +147,7 @@ def main(): print('Not signed') os.system(f'cp -rf target/release/RustDesk.exe rustdesk-{version}-setdown.exe') elif os.path.isfile('/usr/bin/pacman'): - os.system('cargo build --release --features inline') + os.system('cargo build --release --features ' + features) os.system('git checkout src/ui/common.tis') os.system('strip target/release/rustdesk') os.system("sed -i 's/pkgver=.*/pkgver=%s/g' PKGBUILD" % version) @@ -150,7 +156,7 @@ def main(): os.system('mv rustdesk-%s-0-x86_64.pkg.tar.zst rustdesk-%s-manjaro-arch.pkg.tar.zst' % (version, version)) # pacman -U ./rustdesk.pkg.tar.zst elif os.path.isfile('/usr/bin/yum'): - os.system('cargo build --release --features inline') + os.system('cargo build --release --features ' + features) os.system('strip target/release/rustdesk') os.system("sed -i 's/Version: .*/Version: %s/g' rpm.spec" % version) os.system('HBB=`pwd` rpmbuild -ba rpm.spec') @@ -158,14 +164,14 @@ def main(): version, version)) # yum localinstall rustdesk.rpm elif os.path.isfile('/usr/bin/zypper'): - os.system('cargo build --release --features inline') + os.system('cargo build --release --features ' + features) os.system('strip target/release/rustdesk') os.system("sed -i 's/Version: .*/Version: %s/g' rpm-suse.spec" % version) os.system('HBB=`pwd` rpmbuild -ba rpm-suse.spec') os.system('mv $HOME/rpmbuild/RPMS/x86_64/rustdesk-%s-0.x86_64.rpm ./rustdesk-%s-suse.rpm' % (version, version)) # yum localinstall rustdesk.rpm else: - os.system('cargo bundle --release --features inline') + os.system('cargo bundle --release --features ' + features) if osx: os.system( 'strip target/release/bundle/osx/RustDesk.app/Contents/MacOS/rustdesk') From 3fe3ba00a0ed334d9a747972fbdb675d0f68f541 Mon Sep 17 00:00:00 2001 From: 21pages Date: Fri, 22 Jul 2022 12:41:49 +0800 Subject: [PATCH 17/17] fix spell mistake Signed-off-by: 21pages --- build.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.py b/build.py index f612caa22..341f4f4e6 100755 --- a/build.py +++ b/build.py @@ -22,7 +22,7 @@ def get_version(): return '' -def prase_rc_features(feature): +def parse_rc_features(feature): available_features = { 'IddDriver': { 'zip_url': 'https://github.com/fufesou/RustDeskIddDriver/releases/download/v0.1/RustDeskIddDriver_x64.zip', @@ -95,7 +95,7 @@ def download_extract_features(features, res_dir): def get_rc_features(args): - features = prase_rc_features(args.feature) + features = parse_rc_features(args.feature) if features: print(f'Build with features {list(features.keys())}') res_dir = 'resources'