diff --git a/libs/hbb_common/protos/message.proto b/libs/hbb_common/protos/message.proto index ca12eb908..dac137e1c 100644 --- a/libs/hbb_common/protos/message.proto +++ b/libs/hbb_common/protos/message.proto @@ -663,6 +663,7 @@ message Misc { PluginRequest plugin_request = 25; PluginFailure plugin_failure = 26; uint32 full_speed_fps = 27; + uint32 auto_adjust_fps = 28; } } diff --git a/libs/scrap/src/common/codec.rs b/libs/scrap/src/common/codec.rs index 84eb1c43e..fac5f82d7 100644 --- a/libs/scrap/src/common/codec.rs +++ b/libs/scrap/src/common/codec.rs @@ -535,11 +535,10 @@ pub fn codec_thread_num() -> usize { info = format!("cpu loadavg:{}", avg.one); res = (((max as f64) - avg.one) * 0.5).round() as usize; } - res = if res > 0 && res <= max / 2 { - res - } else { - std::cmp::max(1, max / 2) - }; + res = std::cmp::min(res, max / 2); + if res == 0 { + res = 1; + } // avoid frequent log let log = match THREAD_LOG_TIME.lock().unwrap().clone() { Some(instant) => instant.elapsed().as_secs() > 1, diff --git a/src/client/io_loop.rs b/src/client/io_loop.rs index fb0bba5a9..b4e311227 100644 --- a/src/client/io_loop.rs +++ b/src/client/io_loop.rs @@ -895,7 +895,9 @@ impl Remote { } // decrease judgement let debounce = if decode_fps > 10 { decode_fps / 2 } else { 5 }; // 500ms - let should_decrease = len >= debounce && len > ctl.last_queue_size + 5; // exceed debounce or still caching + let should_decrease = len >= debounce // exceed debounce + && len > ctl.last_queue_size + 5 // still caching + && !ctl.last_custom_fps.unwrap_or(i32::MAX) < limited_fps as i32; // NOT already set a smaller one // increase judgement if len <= 1 { @@ -919,10 +921,15 @@ impl Remote { } // send custom fps let mut misc = Misc::new(); - misc.set_option(OptionMessage { - custom_fps, - ..Default::default() - }); + if version > hbb_common::get_version_number("1.2.1") { + // avoid confusion with custom image quality fps + misc.set_auto_adjust_fps(custom_fps as _); + } else { + misc.set_option(OptionMessage { + custom_fps, + ..Default::default() + }); + } let mut msg = Message::new(); msg.set_misc(misc); self.sender.send(Data::Message(msg)).ok(); diff --git a/src/server/connection.rs b/src/server/connection.rs index 39a87547e..cb993301e 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -1940,6 +1940,10 @@ impl Connection { .lock() .unwrap() .user_full_speed_fps(self.inner.id(), fps), + Some(misc::Union::AutoAdjustFps(fps)) => video_service::VIDEO_QOS + .lock() + .unwrap() + .user_auto_adjust_fps(self.inner.id(), fps), _ => {} }, Some(message::Union::AudioFrame(frame)) => { diff --git a/src/server/video_qos.rs b/src/server/video_qos.rs index 18b5f50de..dda15fd55 100644 --- a/src/server/video_qos.rs +++ b/src/server/video_qos.rs @@ -31,6 +31,7 @@ struct Delay { #[derive(Default, Debug, Copy, Clone)] struct UserData { full_speed_fps: Option, + auto_adjust_fps: Option, custom_fps: Option, quality: Option<(i64, Quality)>, // (time, quality) delay: Option, @@ -90,11 +91,15 @@ pub enum RefreshType { impl VideoQoS { pub fn spf(&self) -> Duration { - Duration::from_secs_f32(1. / (self.fps as f32)) + Duration::from_secs_f32(1. / (self.fps() as f32)) } pub fn fps(&self) -> u32 { - self.fps + if self.fps >= MIN_FPS && self.fps <= MAX_FPS { + self.fps + } else { + FPS + } } pub fn store_bitrate(&mut self, bitrate: u32) { @@ -118,6 +123,12 @@ impl VideoQoS { let user_fps = |u: &UserData| { // full_speed_fps let mut fps = u.full_speed_fps.unwrap_or_default() * 9 / 10; + // auto adjust fps + if let Some(auto_adjust_fps) = u.auto_adjust_fps { + if fps == 0 || auto_adjust_fps < fps { + fps = auto_adjust_fps; + } + } // custom_fps if let Some(custom_fps) = u.custom_fps { if fps == 0 || custom_fps < fps { @@ -128,7 +139,7 @@ impl VideoQoS { if let Some(delay) = u.delay { fps = match delay.state { DelayState::Normal => fps, - DelayState::LowDelay => fps, + DelayState::LowDelay => fps * 3 / 4, DelayState::HighDelay => fps / 2, DelayState::Broken => fps / 4, } @@ -181,7 +192,11 @@ impl VideoQoS { if delay != DelayState::Normal { match self.quality { Quality::Best => { - quality = Quality::Balanced; + quality = if delay == DelayState::Broken { + Quality::Low + } else { + Quality::Balanced + }; } Quality::Balanced => { quality = Quality::Low; @@ -259,6 +274,21 @@ impl VideoQoS { self.refresh(None); } + pub fn user_auto_adjust_fps(&mut self, id: i32, fps: u32) { + if let Some(user) = self.users.get_mut(&id) { + user.auto_adjust_fps = Some(fps); + } else { + self.users.insert( + id, + UserData { + auto_adjust_fps: Some(fps), + ..Default::default() + }, + ); + } + self.refresh(None); + } + pub fn user_image_quality(&mut self, id: i32, image_quality: i32) { // https://github.com/rustdesk/rustdesk/blob/d716e2b40c38737f1aa3f16de0dec67394a6ac68/src/server/video_service.rs#L493 let convert_quality = |q: i32| {