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..2a05c7326 100644 --- a/libs/scrap/src/common/codec.rs +++ b/libs/scrap/src/common/codec.rs @@ -12,11 +12,12 @@ use crate::vpxcodec::*; use hbb_common::{ anyhow::anyhow, log, - message_proto::{video_frame, Message, VP9s, VideoCodecState}, + message_proto::{test_delay, video_frame, Message, VP9s, VideoCodecState}, ResultType, }; #[cfg(feature = "hwcodec")] use hbb_common::{ + config::Config2, lazy_static, message_proto::{H264s, H265s}, }; @@ -52,6 +53,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 { @@ -185,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; } @@ -206,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, @@ -328,3 +342,11 @@ impl Decoder { return Ok(ret); } } + +#[cfg(feature = "hwcodec")] +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/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..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}; +use hbb_common::message_proto::{test_delay, Message, VP9s, VideoFrame, VP9}; 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/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/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/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..355a43305 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, @@ -137,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; @@ -145,14 +149,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!( @@ -191,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(); @@ -220,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 { @@ -239,6 +249,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 @@ -544,9 +563,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()?; - drop(video_qos); + 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 { @@ -571,6 +590,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.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..9e1ab6379 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")}{"(beta)"}
  • : ""} +
  • {svg_checkmark}{translate("Adaptive Bitrate")}{"(beta)"}
  • +
    +
  • ; + } + + 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')}
  • diff --git a/src/ui/remote.rs b/src/ui/remote.rs index 22ae5f505..1dd685f15 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,11 +2614,10 @@ 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(); - msg_out.set_test_delay(t); - allow_err!(peer.send(&msg_out).await); + handle_test_delay(t, peer).await; } } } 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(); }