From eaaeefd90b3be3ae51b39e6aa5d8aad016130a50 Mon Sep 17 00:00:00 2001 From: csf Date: Wed, 29 Jun 2022 23:36:45 +0800 Subject: [PATCH 1/5] sync codec format --- libs/hbb_common/protos/message.proto | 8 ++++++++ libs/scrap/src/common/codec.rs | 4 +++- libs/scrap/src/common/hwcodec.rs | 9 ++++++++- libs/scrap/src/common/vpxcodec.rs | 14 +++++++++++++- src/server/connection.rs | 1 + src/server/video_service.rs | 16 +++++++++++----- src/ui/remote.rs | 13 ++++++++++++- src/ui/remote.tis | 6 +++++- 8 files changed, 61 insertions(+), 10 deletions(-) diff --git a/libs/hbb_common/protos/message.proto b/libs/hbb_common/protos/message.proto index f6c57b1e4..40da75a5d 100644 --- a/libs/hbb_common/protos/message.proto +++ b/libs/hbb_common/protos/message.proto @@ -479,10 +479,18 @@ message OptionMessage { } message TestDelay { + enum CodecFormat { + Unknown = 0; + VP8 = 1; + VP9 = 2; + H264 = 3; + H265 = 4; + } int64 time = 1; bool from_client = 2; uint32 last_delay = 3; uint32 target_bitrate = 4; + CodecFormat codec_format = 5; } message PublicKey { diff --git a/libs/scrap/src/common/codec.rs b/libs/scrap/src/common/codec.rs index 1dad08701..6e9d1a8b9 100644 --- a/libs/scrap/src/common/codec.rs +++ b/libs/scrap/src/common/codec.rs @@ -12,7 +12,7 @@ use crate::vpxcodec::*; use hbb_common::{ anyhow::anyhow, log, - message_proto::{video_frame, Message, VP9s, VideoCodecState}, + message_proto::{video_frame, Message, VP9s, VideoCodecState, test_delay}, ResultType, }; #[cfg(feature = "hwcodec")] @@ -52,6 +52,8 @@ pub trait EncoderApi { fn use_yuv(&self) -> bool; fn set_bitrate(&mut self, bitrate: u32) -> ResultType<()>; + + fn get_codec_format(&self) -> test_delay::CodecFormat; } pub struct DecoderCfg { diff --git a/libs/scrap/src/common/hwcodec.rs b/libs/scrap/src/common/hwcodec.rs index 945de6335..70d944a33 100644 --- a/libs/scrap/src/common/hwcodec.rs +++ b/libs/scrap/src/common/hwcodec.rs @@ -6,7 +6,7 @@ use hbb_common::{ anyhow::{anyhow, Context}, config::HwCodecConfig, lazy_static, log, - message_proto::{H264s, H265s, Message, VideoFrame, H264, H265}, + message_proto::{test_delay, H264s, H265s, Message, VideoFrame, H264, H265}, ResultType, }; use hwcodec::{ @@ -143,6 +143,13 @@ impl EncoderApi for HwEncoder { self.encoder.set_bitrate((bitrate * 1000) as _).ok(); Ok(()) } + + fn get_codec_format(&self) -> test_delay::CodecFormat { + match self.format { + DataFormat::H264 => test_delay::CodecFormat::H264, + DataFormat::H265 => test_delay::CodecFormat::H265, + } + } } impl HwEncoder { diff --git a/libs/scrap/src/common/vpxcodec.rs b/libs/scrap/src/common/vpxcodec.rs index 2943419e4..a44078eba 100644 --- a/libs/scrap/src/common/vpxcodec.rs +++ b/libs/scrap/src/common/vpxcodec.rs @@ -3,7 +3,7 @@ // https://github.com/rust-av/vpx-rs/blob/master/src/decoder.rs use hbb_common::anyhow::{anyhow, Context}; -use hbb_common::message_proto::{Message, VP9s, VideoFrame, VP9}; +use hbb_common::message_proto::{Message, VP9s, VideoFrame, VP9, test_delay}; use hbb_common::ResultType; use crate::codec::EncoderApi; @@ -27,6 +27,7 @@ impl Default for VpxVideoCodecId { pub struct VpxEncoder { ctx: vpx_codec_ctx_t, + format: VpxVideoCodecId, width: usize, height: usize, } @@ -96,14 +97,17 @@ impl EncoderApi for VpxEncoder { { match cfg { crate::codec::EncoderCfg::VPX(config) => { + let format; let i; if cfg!(feature = "VP8") { i = match config.codec { VpxVideoCodecId::VP8 => call_vpx_ptr!(vpx_codec_vp8_cx()), VpxVideoCodecId::VP9 => call_vpx_ptr!(vpx_codec_vp9_cx()), }; + format = config.codec; } else { i = call_vpx_ptr!(vpx_codec_vp9_cx()); + format = VpxVideoCodecId::VP9; } let mut c = unsafe { std::mem::MaybeUninit::zeroed().assume_init() }; call_vpx!(vpx_codec_enc_config_default(i, &mut c, 0)); @@ -190,6 +194,7 @@ impl EncoderApi for VpxEncoder { Ok(Self { ctx, + format, width: config.width as _, height: config.height as _, }) @@ -228,6 +233,13 @@ impl EncoderApi for VpxEncoder { call_vpx!(vpx_codec_enc_config_set(&mut self.ctx, &new_enc_cfg)); return Ok(()); } + + fn get_codec_format(&self) -> test_delay::CodecFormat { + match self.format { + VpxVideoCodecId::VP8 => test_delay::CodecFormat::VP8, + VpxVideoCodecId::VP9 => test_delay::CodecFormat::VP9 + } + } } impl VpxEncoder { diff --git a/src/server/connection.rs b/src/server/connection.rs index 46c730092..f8bf5d16a 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -380,6 +380,7 @@ impl Connection { time, last_delay:qos.current_delay, target_bitrate:qos.target_bitrate, + codec_format:qos.codec_format.into(), ..Default::default() }); conn.inner.send(msg_out.into()); diff --git a/src/server/video_service.rs b/src/server/video_service.rs index 10ddf3223..9a42c6c31 100644 --- a/src/server/video_service.rs +++ b/src/server/video_service.rs @@ -72,11 +72,11 @@ pub struct VideoQoS { height: u32, user_image_quality: u32, current_image_quality: u32, - + enable_abr: bool, + pub codec_format: test_delay::CodecFormat, pub current_delay: u32, pub fps: u8, // abr pub target_bitrate: u32, // abr - updated: bool, state: DelayState, debounce_count: u32, @@ -110,6 +110,8 @@ impl Default for VideoQoS { fps: FPS, user_image_quality: ImageQuality::Balanced.as_percent(), current_image_quality: ImageQuality::Balanced.as_percent(), + enable_abr: false, + codec_format: Default::default(), width: 0, height: 0, current_delay: 0, @@ -145,14 +147,16 @@ impl VideoQoS { self.current_delay = delay / 2 + self.current_delay / 2; log::trace!( - "VideoQoS update_network_delay:{}, {}, state:{:?},count:{}", + "VideoQoS update_network_delay:{}, {}, state:{:?}", self.current_delay, delay, self.state, - self.debounce_count ); // ABR + if !self.enable_abr { + return; + } let current_state = DelayState::from_delay(self.current_delay); if current_state != self.state && self.debounce_count > 5 { log::debug!( @@ -544,7 +548,6 @@ fn run(sp: GenericService) -> ResultType<()> { video_qos.set_size(width as _, height as _); let mut spf = video_qos.spf(); let bitrate = video_qos.generate_bitrate()?; - drop(video_qos); log::info!("init bitrate={}", bitrate); @@ -571,6 +574,9 @@ fn run(sp: GenericService) -> ResultType<()> { Err(err) => bail!("Failed to create encoder: {}", err), } + video_qos.codec_format = encoder.get_codec_format(); + drop(video_qos); + let privacy_mode_id = *PRIVACY_MODE_CONN_ID.lock().unwrap(); #[cfg(not(windows))] let captuerer_privacy_mode_id = privacy_mode_id; diff --git a/src/ui/remote.rs b/src/ui/remote.rs index 22ae5f505..fefc42f98 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -240,6 +240,7 @@ struct QualityStatus { fps: i32, delay: i32, target_bitrate: i32, + codec_format: test_delay::CodecFormat, } impl Default for QualityStatus { @@ -249,6 +250,7 @@ impl Default for QualityStatus { fps: -1, delay: -1, target_bitrate: -1, + codec_format: test_delay::CodecFormat::Unknown, } } } @@ -269,13 +271,21 @@ impl Handler { } fn update_quality_status(&self, status: QualityStatus) { + let codec_format = match status.codec_format { + test_delay::CodecFormat::Unknown => "Unknown", + test_delay::CodecFormat::VP8 => "VP8", + test_delay::CodecFormat::VP9 => "VP9", + test_delay::CodecFormat::H264 => "H264", + test_delay::CodecFormat::H265 => "H265", + }; self.call2( "updateQualityStatus", &make_args!( status.speed, status.fps, status.delay, - status.target_bitrate + status.target_bitrate, + codec_format ), ); } @@ -2604,6 +2614,7 @@ impl Interface for Handler { self.update_quality_status(QualityStatus { delay: t.last_delay as _, target_bitrate: t.target_bitrate as _, + codec_format: t.codec_format.enum_value_or_default(), ..Default::default() }); let mut msg_out = Message::new(); diff --git a/src/ui/remote.tis b/src/ui/remote.tis index cc5727755..dc2470ac1 100644 --- a/src/ui/remote.tis +++ b/src/ui/remote.tis @@ -482,16 +482,20 @@ class QualityMonitor: Reactor.Component
Target Bitrate: {qualityMonitorData[3]}kb
+
+ Codec: {qualityMonitorData[4]} +
; } } $(#quality-monitor).content(); -handler.updateQualityStatus = function(speed, fps, delay, bitrate) { +handler.updateQualityStatus = function(speed, fps, delay, bitrate, codec_format) { speed ? qualityMonitorData[0] = speed:null; fps > -1 ? qualityMonitorData[1] = fps:null; delay > -1 ? qualityMonitorData[2] = delay:null; bitrate > -1 ? qualityMonitorData[3] = bitrate:null; + codec_format != "Unknown" ? qualityMonitorData[4] = codec_format:null; qualityMonitor.update(); } From 09937049a6edb10d6a54ac10de998712cfa9a693 Mon Sep 17 00:00:00 2001 From: csf Date: Thu, 30 Jun 2022 16:19:36 +0800 Subject: [PATCH 2/5] enable hwcodec --- libs/scrap/src/common/codec.rs | 25 +++++++++++++++++++--- src/ui.rs | 10 ++++++++- src/ui/index.tis | 39 ++++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 4 deletions(-) diff --git a/libs/scrap/src/common/codec.rs b/libs/scrap/src/common/codec.rs index 6e9d1a8b9..bfcae031e 100644 --- a/libs/scrap/src/common/codec.rs +++ b/libs/scrap/src/common/codec.rs @@ -11,8 +11,9 @@ use crate::vpxcodec::*; use hbb_common::{ anyhow::anyhow, + config::Config2, log, - message_proto::{video_frame, Message, VP9s, VideoCodecState, test_delay}, + message_proto::{test_delay, video_frame, Message, VP9s, VideoCodecState}, ResultType, }; #[cfg(feature = "hwcodec")] @@ -187,7 +188,11 @@ impl Encoder { #[inline] pub fn current_hw_encoder_name() -> Option { #[cfg(feature = "hwcodec")] - return HwEncoder::current_name().lock().unwrap().clone(); + if check_hwcodec_config() { + return HwEncoder::current_name().lock().unwrap().clone(); + } else { + return None; + } #[cfg(not(feature = "hwcodec"))] return None; } @@ -208,7 +213,14 @@ impl Decoder { // video_codec_state is mainted by creation and destruction of Decoder. // It has been ensured to use after Decoder's creation. #[cfg(feature = "hwcodec")] - return MY_DECODER_STATE.lock().unwrap().clone(); + if check_hwcodec_config() { + return MY_DECODER_STATE.lock().unwrap().clone(); + } else { + return VideoCodecState { + ScoreVpx: SCORE_VPX, + ..Default::default() + }; + } #[cfg(not(feature = "hwcodec"))] VideoCodecState { ScoreVpx: SCORE_VPX, @@ -330,3 +342,10 @@ impl Decoder { return Ok(ret); } } + +fn check_hwcodec_config() -> bool { + if let Some(v) = Config2::get().options.get("enable-hwcodec") { + return v != "N"; + } + return true; // default is true +} diff --git a/src/ui.rs b/src/ui.rs index b93c11d44..4671ff19b 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -702,7 +702,7 @@ impl UI { let p = "explorer"; #[cfg(target_os = "macos")] let p = "open"; - #[cfg(target_os = "linux")] + #[cfg(target_os = "linux")] let p = if std::path::Path::new("/usr/bin/firefox").exists() { "firefox" } else { @@ -753,6 +753,13 @@ impl UI { self.get_option_("custom-rendezvous-server"), ) } + + fn has_hwcodec(&self) -> bool { + #[cfg(not(feature = "hwcodec"))] + return false; + #[cfg(feature = "hwcodec")] + return true; + } } impl sciter::EventHandler for UI { @@ -829,6 +836,7 @@ impl sciter::EventHandler for UI { fn discover(); fn get_lan_peers(); fn get_uuid(); + fn has_hwcodec(); } } diff --git a/src/ui/index.tis b/src/ui/index.tis index 70cc8f870..4a998220d 100644 --- a/src/ui/index.tis +++ b/src/ui/index.tis @@ -165,6 +165,44 @@ class AudioInputs: Reactor.Component { } } +var enhancementsMenu; +class Enhancements: Reactor.Component { + function this() { + enhancementsMenu = this; + } + + function render() { + var has_hwcodec = handler.has_hwcodec(); + var me = this; + self.timer(1ms, function() { me.toggleMenuState() }); + return
  • {translate('Enhancements')} + + {has_hwcodec ?
  • {svg_checkmark}{translate("Hardware Codec")}
  • : ""} +
  • {svg_checkmark}{translate("ABR")}
  • +
    +
  • ; + } + + function toggleMenuState() { + for (var el in $$(menu#enhancements-menu>li)) { + if (el.id && el.id.indexOf("enable-") == 0) { + var enabled = handler.get_option(el.id) != "N"; + el.attributes.toggleClass("selected", enabled); + } + } + + } + + event click $(menu#enhancements-menu>li) (_, me) { + var v = me.id; + if (v.indexOf("enable-") == 0) { + handler.set_option(v, handler.get_option(v) != 'N' ? 'N' : ''); + } + this.toggleMenuState(); + } +} + + function getUserName() { try { return JSON.parse(handler.get_local_option("user_info")).name; @@ -204,6 +242,7 @@ class MyIdMenu: Reactor.Component {
  • {svg_checkmark}{translate('Enable File Transfer')}
  • {svg_checkmark}{translate('Enable TCP Tunneling')}
  • +
  • {svg_checkmark}{translate('Enable remote configuration modification')}
  • {translate('ID/Relay Server')}
  • From a5ab0db5b9be612d802a237e5cab20b96f1851e4 Mon Sep 17 00:00:00 2001 From: csf Date: Thu, 30 Jun 2022 18:24:36 +0800 Subject: [PATCH 3/5] switch enable abr --- libs/scrap/src/common/codec.rs | 1 + src/server/video_service.rs | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/libs/scrap/src/common/codec.rs b/libs/scrap/src/common/codec.rs index bfcae031e..1dc39090e 100644 --- a/libs/scrap/src/common/codec.rs +++ b/libs/scrap/src/common/codec.rs @@ -343,6 +343,7 @@ impl Decoder { } } +#[cfg(feature = "hwcodec")] fn check_hwcodec_config() -> bool { if let Some(v) = Config2::get().options.get("enable-hwcodec") { return v != "N"; diff --git a/src/server/video_service.rs b/src/server/video_service.rs index 9a42c6c31..cca8b4c83 100644 --- a/src/server/video_service.rs +++ b/src/server/video_service.rs @@ -243,6 +243,15 @@ impl VideoQoS { *self = Default::default(); } + fn check_abr_config(&mut self) -> bool { + self.enable_abr = if let Some(v) = Config2::get().options.get("enable-abr") { + v != "N" + } else { + true // default is true + }; + self.enable_abr + } + pub fn convert_quality(q: i32) -> i32 { if q == ImageQuality::Balanced.value() { 100 * 2 / 3 @@ -548,8 +557,9 @@ fn run(sp: GenericService) -> ResultType<()> { video_qos.set_size(width as _, height as _); let mut spf = video_qos.spf(); let bitrate = video_qos.generate_bitrate()?; + let abr = video_qos.check_abr_config(); - log::info!("init bitrate={}", bitrate); + log::info!("init bitrate={}, abr enabled:{}", bitrate, abr); let encoder_cfg = match Encoder::current_hw_encoder_name() { Some(codec_name) => EncoderCfg::HW(HwEncoderConfig { From 5a7dca72c8fd3c4ffea6d9485d1c9711c061d5d5 Mon Sep 17 00:00:00 2001 From: csf Date: Thu, 30 Jun 2022 20:48:29 +0800 Subject: [PATCH 4/5] fix custom_image_qulity and android --- libs/scrap/src/common/codec.rs | 2 +- libs/scrap/src/common/vpxcodec.rs | 4 ++-- src/client.rs | 10 +++++++++- src/server/video_service.rs | 14 ++++++++++---- src/ui/remote.rs | 6 ++---- 5 files changed, 24 insertions(+), 12 deletions(-) diff --git a/libs/scrap/src/common/codec.rs b/libs/scrap/src/common/codec.rs index 1dc39090e..2a05c7326 100644 --- a/libs/scrap/src/common/codec.rs +++ b/libs/scrap/src/common/codec.rs @@ -11,13 +11,13 @@ use crate::vpxcodec::*; use hbb_common::{ anyhow::anyhow, - config::Config2, log, message_proto::{test_delay, video_frame, Message, VP9s, VideoCodecState}, ResultType, }; #[cfg(feature = "hwcodec")] use hbb_common::{ + config::Config2, lazy_static, message_proto::{H264s, H265s}, }; diff --git a/libs/scrap/src/common/vpxcodec.rs b/libs/scrap/src/common/vpxcodec.rs index a44078eba..b9b95b93e 100644 --- a/libs/scrap/src/common/vpxcodec.rs +++ b/libs/scrap/src/common/vpxcodec.rs @@ -3,7 +3,7 @@ // https://github.com/rust-av/vpx-rs/blob/master/src/decoder.rs use hbb_common::anyhow::{anyhow, Context}; -use hbb_common::message_proto::{Message, VP9s, VideoFrame, VP9, test_delay}; +use hbb_common::message_proto::{test_delay, Message, VP9s, VideoFrame, VP9}; use hbb_common::ResultType; use crate::codec::EncoderApi; @@ -237,7 +237,7 @@ impl EncoderApi for VpxEncoder { fn get_codec_format(&self) -> test_delay::CodecFormat { match self.format { VpxVideoCodecId::VP8 => test_delay::CodecFormat::VP8, - VpxVideoCodecId::VP9 => test_delay::CodecFormat::VP9 + VpxVideoCodecId::VP9 => test_delay::CodecFormat::VP9, } } } diff --git a/src/client.rs b/src/client.rs index d4cd44351..48495d184 100644 --- a/src/client.rs +++ b/src/client.rs @@ -914,7 +914,7 @@ impl LoginConfigHandler { n += 1; } else if q == "custom" { let config = PeerConfig::load(&self.id); - msg.custom_image_quality = config.custom_image_quality[0] as _; + msg.custom_image_quality = config.custom_image_quality[0] << 8; n += 1; } if self.get_toggle_option("show-remote-cursor") { @@ -1212,6 +1212,14 @@ where return (video_sender, audio_sender); } +pub async fn handle_test_delay(t: TestDelay, peer: &mut Stream) { + if !t.from_client { + let mut msg_out = Message::new(); + msg_out.set_test_delay(t); + allow_err!(peer.send(&msg_out).await); + } +} + // mask = buttons << 3 | type // type, 1: down, 2: up, 3: wheel // buttons, 1: left, 2: right, 4: middle diff --git a/src/server/video_service.rs b/src/server/video_service.rs index cca8b4c83..355a43305 100644 --- a/src/server/video_service.rs +++ b/src/server/video_service.rs @@ -139,6 +139,8 @@ impl VideoQoS { time::Duration::from_secs_f32(1. / (self.fps as f32)) } + // update_network_delay periodically + // decrease the bitrate when the delay gets bigger pub fn update_network_delay(&mut self, delay: u32) { if self.current_delay.eq(&0) { self.current_delay = delay; @@ -195,9 +197,10 @@ impl VideoQoS { self.updated = true; } + // handle image_quality change from peer pub fn update_image_quality(&mut self, image_quality: i32) { let image_quality = Self::convert_quality(image_quality) as _; - log::debug!("VideoQoS update_image_quality{}", image_quality); + log::debug!("VideoQoS update_image_quality: {}", image_quality); if self.current_image_quality != image_quality { self.current_image_quality = image_quality; let _ = self.generate_bitrate().ok(); @@ -224,11 +227,14 @@ impl VideoQoS { let fix = Display::fix_quality() as u32; log::debug!("Android screen, fix quality:{}", fix); let base_bitrate = base_bitrate * fix; - self.target_bitrate = base_bitrate * self.image_quality / 100; + self.target_bitrate = base_bitrate * self.current_image_quality / 100; + Ok(self.target_bitrate) + } + #[cfg(not(target_os = "android"))] + { + self.target_bitrate = base_bitrate * self.current_image_quality / 100; Ok(self.target_bitrate) } - self.target_bitrate = base_bitrate * self.current_image_quality / 100; - Ok(self.target_bitrate) } pub fn check_if_updated(&mut self) -> bool { diff --git a/src/ui/remote.rs b/src/ui/remote.rs index fefc42f98..1dd685f15 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -277,7 +277,7 @@ impl Handler { test_delay::CodecFormat::VP9 => "VP9", test_delay::CodecFormat::H264 => "H264", test_delay::CodecFormat::H265 => "H265", - }; + }; self.call2( "updateQualityStatus", &make_args!( @@ -2617,9 +2617,7 @@ impl Interface for Handler { codec_format: t.codec_format.enum_value_or_default(), ..Default::default() }); - let mut msg_out = Message::new(); - msg_out.set_test_delay(t); - allow_err!(peer.send(&msg_out).await); + handle_test_delay(t, peer).await; } } } From b34a87a220da92af085c20caa35519c23827e941 Mon Sep 17 00:00:00 2001 From: csf Date: Thu, 30 Jun 2022 21:01:04 +0800 Subject: [PATCH 5/5] update lang --- src/lang/cn.rs | 4 ++++ src/lang/cs.rs | 4 ++++ src/lang/da.rs | 4 ++++ src/lang/de.rs | 4 ++++ src/lang/eo.rs | 4 ++++ src/lang/es.rs | 4 ++++ src/lang/fr.rs | 4 ++++ src/lang/id.rs | 5 ++++- src/lang/it.rs | 4 ++++ src/lang/ptbr.rs | 4 ++++ src/lang/ru.rs | 6 +++++- src/lang/sk.rs | 4 ++++ src/lang/template.rs | 6 +++++- src/lang/tr.rs | 4 ++++ src/lang/tw.rs | 9 ++++++--- src/ui/index.tis | 4 ++-- 16 files changed, 66 insertions(+), 8 deletions(-) diff --git a/src/lang/cn.rs b/src/lang/cn.rs index a09ab8d39..5aa7dcbdd 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -35,6 +35,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "关于"), ("Mute", "静音"), ("Audio Input", "音频输入"), + ("Enhancements", "增强功能"), + ("Hardware Codec", "硬件编解码"), + ("Adaptive Bitrate", "自适应码率"), ("ID Server", "ID服务器"), ("Relay Server", "中继服务器"), ("API Server", "API服务器"), @@ -105,6 +108,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Optimize reaction time", "优化反应时间"), ("Custom", "自定义画质"), ("Show remote cursor", "显示远程光标"), + ("Show quality monitor", "显示质量监测"), ("Disable clipboard", "禁止剪贴板"), ("Lock after session end", "断开后锁定远程电脑"), ("Insert", "插入"), diff --git a/src/lang/cs.rs b/src/lang/cs.rs index 80e1568eb..75ad8afde 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -35,6 +35,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "O aplikaci"), ("Mute", "Ztlumit"), ("Audio Input", "Vstup zvuku"), + ("Enhancements", ""), + ("Hardware Codec", ""), + ("Adaptive Bitrate", ""), ("ID Server", "Server pro identif."), ("Relay Server", "Předávací (relay) server"), ("API Server", "Server s API rozhraním"), @@ -105,6 +108,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Optimize reaction time", "Optimalizovat pro co nejnižší prodlevu odezvy"), ("Custom", "Uživatelsky určené"), ("Show remote cursor", "Zobrazovat ukazatel myši z protějšku"), + ("Show quality monitor", ""), ("Disable clipboard", "Vypnout schránku"), ("Lock after session end", "Po ukončení relace zamknout plochu"), ("Insert", "Vložit"), diff --git a/src/lang/da.rs b/src/lang/da.rs index 429b08b05..116f2067c 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -35,6 +35,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "Omkring"), ("Mute", "Sluk for mikrofonen"), ("Audio Input", "Lydindgang"), + ("Enhancements", ""), + ("Hardware Codec", ""), + ("Adaptive Bitrate", ""), ("ID Server", "identifikations Server"), ("Relay Server", "Relæ Server"), ("API Server", "API Server"), @@ -105,6 +108,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Optimize reaction time", "Optimeret responstid"), ("Custom", "Brugerdefineret"), ("Show remote cursor", "Vis fjernbetjeningskontrolleret markør"), + ("Show quality monitor", ""), ("Disable clipboard", "Deaktiver udklipsholder"), ("Lock after session end", "Lås efter afslutningen af fjernstyring"), ("Insert", "Indsæt"), diff --git a/src/lang/de.rs b/src/lang/de.rs index 8bbfbb4c4..bd1ae3de1 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -35,6 +35,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "Über"), ("Mute", "Stummschalten"), ("Audio Input", "Audio-Eingang"), + ("Enhancements", ""), + ("Hardware Codec", ""), + ("Adaptive Bitrate", ""), ("ID Server", "ID Server"), ("Relay Server", "Verbindungsserver Server"), ("API Server", "API Server"), @@ -105,6 +108,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Optimize reaction time", "Optimierte Reaktionszeit"), ("Custom", "Benutzerdefiniert"), ("Show remote cursor", "Ferngesteuerten Cursor anzeigen"), + ("Show quality monitor", ""), ("Disable clipboard", "Zwischenablage deaktivieren"), ("Lock after session end", "Sperren nach Sitzungsende"), ("Insert", "Einfügen"), diff --git a/src/lang/eo.rs b/src/lang/eo.rs index 49c9f38fa..38b7d004f 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -35,6 +35,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "Pri"), ("Mute", "Muta"), ("Audio Input", "Aŭdia enigo"), + ("Enhancements", ""), + ("Hardware Codec", ""), + ("Adaptive Bitrate", ""), ("ID Server", "Servilo de identigiloj"), ("Relay Server", "Relajsa servilo"), ("API Server", "Servilo de API"), @@ -105,6 +108,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Optimize reaction time", "Optimigi reakcia tempo"), ("Custom", "Personigi bilda kvalito"), ("Show remote cursor", "Montri foran kursoron"), + ("Show quality monitor", ""), ("Disable clipboard", "Malebligi poŝon"), ("Lock after session end", "Ŝlosi foran komputilon post malkonektado"), ("Insert", "Enmeti"), diff --git a/src/lang/es.rs b/src/lang/es.rs index ba4c671a8..575160a25 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -35,6 +35,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "Sobre"), ("Mute", "Silencio"), ("Audio Input", "Entrada de audio"), + ("Enhancements", ""), + ("Hardware Codec", ""), + ("Adaptive Bitrate", ""), ("ID Server", "ID server"), ("Relay Server", "Server relay"), ("API Server", "Server API"), @@ -105,6 +108,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Optimize reaction time", "Optimizar el tiempo de reacción"), ("Custom", "Personalizado"), ("Show remote cursor", "Mostrar cursor remoto"), + ("Show quality monitor", ""), ("Disable clipboard", "Deshabilitar portapapeles"), ("Lock after session end", "Bloquear después del final de la sesión"), ("Insert", "Insertar"), diff --git a/src/lang/fr.rs b/src/lang/fr.rs index d2d41c550..420f6a229 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -35,6 +35,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "À propos de"), ("Mute", "Muet"), ("Audio Input", "Entrée audio"), + ("Enhancements", ""), + ("Hardware Codec", ""), + ("Adaptive Bitrate", ""), ("ID Server", "Serveur ID"), ("Relay Server", "Serveur relais"), ("API Server", "Serveur API"), @@ -105,6 +108,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Optimize reaction time", "Optimiser le temps de réaction"), ("Custom", "Qualité d'image personnalisée"), ("Show remote cursor", "Afficher le curseur distant"), + ("Show quality monitor", ""), ("Disable clipboard", "Désactiver le presse-papier"), ("Lock after session end", "Verrouiller l'ordinateur distant après la déconnexion"), ("Insert", "Insérer"), diff --git a/src/lang/id.rs b/src/lang/id.rs index 2e2f2fd1c..808711cf1 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -35,6 +35,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "Tentang"), ("Mute", "Bisukan"), ("Audio Input", "Masukkan Audio"), + ("Enhancements", ""), + ("Hardware Codec", ""), + ("Adaptive Bitrate", ""), ("ID Server", "Server ID"), ("Relay Server", "Server Relay"), ("API Server", "API Server"), @@ -105,6 +108,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Optimize reaction time", "Optimalkan waktu reaksi"), ("Custom", "Custom"), ("Show remote cursor", "Tampilkan remote kursor"), + ("Show quality monitor", ""), ("Disable clipboard", "Matikan papan klip"), ("Lock after session end", "Kunci setelah sesi berakhir"), ("Insert", "Menyisipkan"), @@ -158,7 +162,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Allow using clipboard", "Izinkan menggunakan papan klip"), ("Allow hearing sound", "Izinkan mendengarkan suara"), ("Allow file copy and paste", "Izinkan penyalinan dan tempel file"), - ("File transfer", "Transfer file"), ("Connected", "Terkoneksi"), ("Direct and encrypted connection", "Koneksi langsung dan terenkripsi"), ("Relayed and encrypted connection", "Koneksi relai dan terenkripsi"), diff --git a/src/lang/it.rs b/src/lang/it.rs index 4bf692169..29556d348 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -35,6 +35,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "Informazioni"), ("Mute", "Silenzia"), ("Audio Input", "Input audio"), + ("Enhancements", ""), + ("Hardware Codec", ""), + ("Adaptive Bitrate", ""), ("ID Server", "ID server"), ("Relay Server", "Server relay"), ("API Server", "Server API"), @@ -105,6 +108,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Optimize reaction time", "Ottimizza il tempo di reazione"), ("Custom", "Personalizzato"), ("Show remote cursor", "Mostra il cursore remoto"), + ("Show quality monitor", ""), ("Disable clipboard", "Disabilita appunti"), ("Lock after session end", "Blocca al termine della sessione"), ("Insert", "Inserisci"), diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index e51d5f5f9..457496eba 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -35,6 +35,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "Sobre"), ("Mute", "Emudecer"), ("Audio Input", "Entrada de Áudio"), + ("Enhancements", ""), + ("Hardware Codec", ""), + ("Adaptive Bitrate", ""), ("ID Server", "Servidor de ID"), ("Relay Server", "Servidor de Relay"), ("API Server", "Servidor da API"), @@ -105,6 +108,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Optimize reaction time", "Otimizar tempo de reação"), ("Custom", "Personalizado"), ("Show remote cursor", "Mostrar cursor remoto"), + ("Show quality monitor", ""), ("Disable clipboard", "Desabilitar área de transferência"), ("Lock after session end", "Bloquear após o fim da sessão"), ("Insert", "Inserir"), diff --git a/src/lang/ru.rs b/src/lang/ru.rs index 88245b1d0..f2a17f485 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -35,6 +35,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "О RustDesk"), ("Mute", "Отключить звук"), ("Audio Input", "Аудиовход"), + ("Enhancements", ""), + ("Hardware Codec", ""), + ("Adaptive Bitrate", ""), ("ID Server", "ID-сервер"), ("Relay Server", "Сервер ретрансляции"), ("API Server", "API-сервер"), @@ -105,6 +108,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Optimize reaction time", "Оптимизировать время реакции"), ("Custom", "Пользовательский"), ("Show remote cursor", "Показать удаленный курсор"), + ("Show quality monitor", ""), ("Disable clipboard", "Отключить буфер обмена"), ("Lock after session end", "Выход из учётной записи после завершения сеанса"), ("Insert", "Вставить"), @@ -263,9 +267,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_version_audio_tip", "Текущая версия Android не поддерживает захват звука, обновите ее до Android 10 или выше."), ("android_start_service_tip", "Нажмите [Запуск промежуточного сервера] или ОТКРЫТЬ разрешение [Захват экрана], чтобы запустить службу демонстрации экрана."), ("Account", "Аккаунт"), - ("Quit", "Выйти"), ("Overwrite", "Перезаписать"), ("This file exists, skip or overwrite this file?", "Этот файл существует, пропустить или перезаписать этот файл?"), + ("Quit", "Выйти"), ("doc_mac_permission", "https://rustdesk.com/docs/ru/manual/mac/#включение-разрешений"), ("Help", "Помощь"), ("Failed", "Неуспешный"), diff --git a/src/lang/sk.rs b/src/lang/sk.rs index 6cea1479b..37b32c8a9 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -35,6 +35,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "O RustDesk"), ("Mute", "Stíšiť"), ("Audio Input", "Zvukový vstup"), + ("Enhancements", ""), + ("Hardware Codec", ""), + ("Adaptive Bitrate", ""), ("ID Server", "ID server"), ("Relay Server", "Prepojovací server"), ("API Server", "API server"), @@ -105,6 +108,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Optimize reaction time", "Optimalizované pre čas odozvy"), ("Custom", "Vlastné"), ("Show remote cursor", "Zobrazovať vzdialený ukazovateľ myši"), + ("Show quality monitor", ""), ("Disable clipboard", "Vypnúť schránku"), ("Lock after session end", "Po skončení uzamknúť plochu"), ("Insert", "Vložiť"), diff --git a/src/lang/template.rs b/src/lang/template.rs index 91c572e44..bf49a1178 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -35,6 +35,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", ""), ("Mute", ""), ("Audio Input", ""), + ("Enhancements", ""), + ("Hardware Codec", ""), + ("Adaptive Bitrate", ""), ("ID Server", ""), ("Relay Server", ""), ("API Server", ""), @@ -105,6 +108,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Optimize reaction time", ""), ("Custom", ""), ("Show remote cursor", ""), + ("Show quality monitor", ""), ("Disable clipboard", ""), ("Lock after session end", ""), ("Insert", ""), @@ -264,7 +268,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_start_service_tip", ""), ("Account", ""), ("Overwrite", ""), - ("This file exists, skip or overwrite this file?", "") + ("This file exists, skip or overwrite this file?", ""), ("Quit", ""), ("doc_mac_permission", ""), ("Help", ""), diff --git a/src/lang/tr.rs b/src/lang/tr.rs index d82901298..8fe5f5d9b 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -35,6 +35,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "Hakkında"), ("Mute", "Sesi Kapat"), ("Audio Input", "Ses Girişi"), + ("Enhancements", ""), + ("Hardware Codec", ""), + ("Adaptive Bitrate", ""), ("ID Server", "ID Sunucu"), ("Relay Server", "Relay Sunucu"), ("API Server", "API Sunucu"), @@ -105,6 +108,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Optimize reaction time", "Tepki süresini optimize et"), ("Custom", "Özel"), ("Show remote cursor", "Uzaktaki fare imlecini göster"), + ("Show quality monitor", ""), ("Disable clipboard", "Hafızadaki kopyalanmışları engelle"), ("Lock after session end", "Bağlantıdan sonra kilitle"), ("Insert", "Ekle"), diff --git a/src/lang/tw.rs b/src/lang/tw.rs index 2de3f4414..f4c246524 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -35,6 +35,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("About", "關於"), ("Mute", "靜音"), ("Audio Input", "音訊輸入"), + ("Enhancements", "增強功能"), + ("Hardware Codec", "硬件編解碼"), + ("Adaptive Bitrate", "自適應碼率"), ("ID Server", "ID 伺服器"), ("Relay Server", "轉送伺服器"), ("API Server", "API 伺服器"), @@ -105,6 +108,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Optimize reaction time", "回應速度最佳化"), ("Custom", "自訂"), ("Show remote cursor", "顯示遠端游標"), + ("Show quality monitor", "顯示質量監測"), ("Disable clipboard", "停用剪貼簿"), ("Lock after session end", "工作階段結束後鎖定電腦"), ("Insert", "插入"), @@ -262,13 +266,12 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_stop_service_tip", "關閉服務將自動關閉所有已建立的連接。"), ("android_version_audio_tip", "目前的 Android 版本不支持音訊錄製,請升級至 Android 10 或以上版本。"), ("android_start_service_tip", "點擊 「啟動服務」 或啟用 「畫面錄製」 權限以開啟手機畫面共享服務。"), - ("Account", "帳號"), - ("Quit", "退出"), + ("Account", "帳戶"), ("Overwrite", "覆寫"), ("This file exists, skip or overwrite this file?", "此檔案/資料夾已存在,要跳過或是覆寫此檔案嗎?"), + ("Quit", "退出"), ("doc_mac_permission", "https://rustdesk.com/docs/zh-tw/manual/mac/#啟用權限"), ("Help", "幫助"), - ("Account", "帳戶"), ("Failed", "失敗"), ("Succeeded", "成功"), ("Someone turns on privacy mode, exit", "其他用戶開啟隱私模式,退出"), diff --git a/src/ui/index.tis b/src/ui/index.tis index 4a998220d..9e1ab6379 100644 --- a/src/ui/index.tis +++ b/src/ui/index.tis @@ -177,8 +177,8 @@ class Enhancements: Reactor.Component { self.timer(1ms, function() { me.toggleMenuState() }); return
  • {translate('Enhancements')} - {has_hwcodec ?
  • {svg_checkmark}{translate("Hardware Codec")}
  • : ""} -
  • {svg_checkmark}{translate("ABR")}
  • + {has_hwcodec ?
  • {svg_checkmark}{translate("Hardware Codec")}{"(beta)"}
  • : ""} +
  • {svg_checkmark}{translate("Adaptive Bitrate")}{"(beta)"}
  • ; }