not use max fps by default

Signed-off-by: 21pages <pages21@163.com>
This commit is contained in:
21pages 2023-11-13 19:29:16 +08:00
parent 5a6a773583
commit 1b08adb178
9 changed files with 111 additions and 120 deletions

View File

@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_hbb/common/shared_state.dart'; import 'package:flutter_hbb/common/shared_state.dart';
import 'package:flutter_hbb/common/widgets/setting_widgets.dart'; import 'package:flutter_hbb/common/widgets/setting_widgets.dart';
import 'package:flutter_hbb/consts.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import '../../common.dart'; import '../../common.dart';
@ -1244,8 +1245,8 @@ void showConfirmSwitchSidesDialog(
} }
customImageQualityDialog(SessionID sessionId, String id, FFI ffi) async { customImageQualityDialog(SessionID sessionId, String id, FFI ffi) async {
double qualityInitValue = 50; double initQuality = kDefaultQuality;
double fpsInitValue = 30; double initFps = kDefaultFps;
bool qualitySet = false; bool qualitySet = false;
bool fpsSet = false; bool fpsSet = false;
@ -1261,28 +1262,25 @@ customImageQualityDialog(SessionID sessionId, String id, FFI ffi) async {
versionCmp(ffi.ffiModel.pi.version, '1.2.2') < 0; versionCmp(ffi.ffiModel.pi.version, '1.2.2') < 0;
setCustomValues({double? quality, double? fps}) async { setCustomValues({double? quality, double? fps}) async {
debugPrint("setCustomValues quality:$quality, fps:$fps");
if (quality != null) { if (quality != null) {
qualitySet = true; qualitySet = true;
await bind.sessionSetCustomImageQuality( await bind.sessionSetCustomImageQuality(
sessionId: sessionId, value: quality.toInt()); sessionId: sessionId, value: quality.toInt());
print("quality:$quality");
} }
if (fps != null) { if (fps != null) {
fpsSet = true; fpsSet = true;
await bind.sessionSetCustomFps(sessionId: sessionId, fps: fps.toInt()); await bind.sessionSetCustomFps(sessionId: sessionId, fps: fps.toInt());
print("fps:$fps");
} }
if (!qualitySet) { if (!qualitySet) {
qualitySet = true; qualitySet = true;
await bind.sessionSetCustomImageQuality( await bind.sessionSetCustomImageQuality(
sessionId: sessionId, value: qualityInitValue.toInt()); sessionId: sessionId, value: initQuality.toInt());
print("qualityInitValue:$qualityInitValue");
} }
if (!hideFps && !fpsSet) { if (!hideFps && !fpsSet) {
fpsSet = true; fpsSet = true;
await bind.sessionSetCustomFps( await bind.sessionSetCustomFps(
sessionId: sessionId, fps: fpsInitValue.toInt()); sessionId: sessionId, fps: initFps.toInt());
print("fpsInitValue:$fpsInitValue");
} }
} }
@ -1293,24 +1291,26 @@ customImageQualityDialog(SessionID sessionId, String id, FFI ffi) async {
// quality // quality
final quality = await bind.sessionGetCustomImageQuality(sessionId: sessionId); final quality = await bind.sessionGetCustomImageQuality(sessionId: sessionId);
qualityInitValue = initQuality = quality != null && quality.isNotEmpty
quality != null && quality.isNotEmpty ? quality[0].toDouble() : 50.0; ? quality[0].toDouble()
if ((hideMoreQuality && qualityInitValue > 100) || : kDefaultQuality;
qualityInitValue < 10 || if (initQuality < kMinQuality ||
qualityInitValue > 2000) { initQuality > (!hideMoreQuality ? kMaxMoreQuality : kMaxQuality)) {
qualityInitValue = 50; initQuality = kDefaultQuality;
} }
// fps // fps
final fpsOption = final fpsOption =
await bind.sessionGetOption(sessionId: sessionId, arg: 'custom-fps'); await bind.sessionGetOption(sessionId: sessionId, arg: 'custom-fps');
fpsInitValue = fpsOption == null ? 30 : double.tryParse(fpsOption) ?? 30; initFps = fpsOption == null
if (fpsInitValue < 5 || fpsInitValue > 120) { ? kDefaultFps
fpsInitValue = 30; : double.tryParse(fpsOption) ?? kDefaultFps;
if (initFps < kMinFps || initFps > kMaxFps) {
initFps = kDefaultFps;
} }
final content = customImageQualityWidget( final content = customImageQualityWidget(
initQuality: qualityInitValue, initQuality: initQuality,
initFps: fpsInitValue, initFps: initFps,
setQuality: (v) => setCustomValues(quality: v), setQuality: (v) => setCustomValues(quality: v),
setFps: (v) => setCustomValues(fps: v), setFps: (v) => setCustomValues(fps: v),
showFps: !hideFps, showFps: !hideFps,

View File

@ -2,6 +2,7 @@ import 'package:debounce_throttle/debounce_throttle.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_hbb/common.dart'; import 'package:flutter_hbb/common.dart';
import 'package:flutter_hbb/consts.dart';
import 'package:flutter_hbb/models/platform_model.dart'; import 'package:flutter_hbb/models/platform_model.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
@ -12,13 +13,17 @@ customImageQualityWidget(
required Function(double) setFps, required Function(double) setFps,
required bool showFps, required bool showFps,
required bool showMoreQuality}) { required bool showMoreQuality}) {
if (!showMoreQuality && initQuality > 100) { if (initQuality < kMinQuality ||
initQuality = 50; initQuality > (showMoreQuality ? kMaxMoreQuality : kMaxQuality)) {
initQuality = kDefaultQuality;
}
if (initFps < kMinFps || initFps > kMaxFps) {
initFps = kDefaultFps;
} }
final qualityValue = initQuality.obs; final qualityValue = initQuality.obs;
final fpsValue = initFps.obs; final fpsValue = initFps.obs;
final RxBool moreQualityChecked = RxBool(qualityValue.value > 100); final RxBool moreQualityChecked = RxBool(qualityValue.value > kMaxQuality);
final debouncerQuality = Debouncer<double>( final debouncerQuality = Debouncer<double>(
Duration(milliseconds: 1000), Duration(milliseconds: 1000),
onChanged: (double v) { onChanged: (double v) {
@ -51,9 +56,11 @@ customImageQualityWidget(
flex: 3, flex: 3,
child: Slider( child: Slider(
value: qualityValue.value, value: qualityValue.value,
min: 10.0, min: kMinQuality,
max: moreQualityChecked.value ? 2000 : 100, max: moreQualityChecked.value ? kMaxMoreQuality : kMaxQuality,
divisions: moreQualityChecked.value ? 199 : 18, divisions: moreQualityChecked.value
? ((kMaxMoreQuality - kMinQuality) / 10).round()
: ((kMaxQuality - kMinQuality) / 5).round(),
onChanged: (double value) async { onChanged: (double value) async {
qualityValue.value = value; qualityValue.value = value;
debouncerQuality.value = value; debouncerQuality.value = value;
@ -113,9 +120,9 @@ customImageQualityWidget(
flex: 3, flex: 3,
child: Slider( child: Slider(
value: fpsValue.value, value: fpsValue.value,
min: 5.0, min: kMinFps,
max: 120.0, max: kMaxFps,
divisions: 23, divisions: ((kMaxFps - kMinFps) / 5).round(),
onChanged: (double value) async { onChanged: (double value) async {
fpsValue.value = value; fpsValue.value = value;
debouncerFps.value = value; debouncerFps.value = value;
@ -145,15 +152,10 @@ customImageQualitySetting() {
final fpsKey = 'custom-fps'; final fpsKey = 'custom-fps';
var initQuality = var initQuality =
(double.tryParse(bind.mainGetUserDefaultOption(key: qualityKey)) ?? 50.0); (double.tryParse(bind.mainGetUserDefaultOption(key: qualityKey)) ??
if (initQuality < 10 || initQuality > 2000) { kDefaultQuality);
initQuality = 50; var initFps = (double.tryParse(bind.mainGetUserDefaultOption(key: fpsKey)) ??
} kDefaultFps);
var initFps =
(double.tryParse(bind.mainGetUserDefaultOption(key: fpsKey)) ?? 30.0);
if (initFps < 5 || initFps > 120) {
initFps = 30;
}
return customImageQualityWidget( return customImageQualityWidget(
initQuality: initQuality, initQuality: initQuality,

View File

@ -102,6 +102,15 @@ const int kDesktopMaxDisplaySize = 3840;
const double kDesktopFileTransferRowHeight = 30.0; const double kDesktopFileTransferRowHeight = 30.0;
const double kDesktopFileTransferHeaderHeight = 25.0; const double kDesktopFileTransferHeaderHeight = 25.0;
const double kMinFps = 5;
const double kDefaultFps = 30;
const double kMaxFps = 120;
const double kMinQuality = 10;
const double kDefaultQuality = 50;
const double kMaxQuality = 100;
const double kMaxMoreQuality = 2000;
double kNewWindowOffset = Platform.isWindows double kNewWindowOffset = Platform.isWindows
? 56.0 ? 56.0
: Platform.isLinux : Platform.isLinux

View File

@ -715,7 +715,7 @@ message Misc {
Resolution change_resolution = 24; Resolution change_resolution = 24;
PluginRequest plugin_request = 25; PluginRequest plugin_request = 25;
PluginFailure plugin_failure = 26; PluginFailure plugin_failure = 26;
uint32 full_speed_fps = 27; uint32 full_speed_fps = 27; // deprecated
uint32 auto_adjust_fps = 28; uint32 auto_adjust_fps = 28;
bool client_record_status = 29; bool client_record_status = 29;
CaptureDisplays capture_displays = 30; CaptureDisplays capture_displays = 30;

View File

@ -1113,6 +1113,7 @@ pub struct LoginConfigHandler {
switch_uuid: Option<String>, switch_uuid: Option<String>,
pub save_ab_password_to_recent: bool, // true: connected with ab password pub save_ab_password_to_recent: bool, // true: connected with ab password
pub other_server: Option<(String, String, String)>, pub other_server: Option<(String, String, String)>,
pub custom_fps: Arc<Mutex<Option<usize>>>,
} }
impl Deref for LoginConfigHandler { impl Deref for LoginConfigHandler {
@ -1483,15 +1484,26 @@ impl LoginConfigHandler {
n += 1; n += 1;
} else if q == "custom" { } else if q == "custom" {
let config = self.load_config(); let config = self.load_config();
let allow_more =
!crate::ui_interface::using_public_server() || self.direct == Some(true);
let quality = if config.custom_image_quality.is_empty() { let quality = if config.custom_image_quality.is_empty() {
50 50
} else { } else {
config.custom_image_quality[0] let mut quality = config.custom_image_quality[0];
if !allow_more && quality > 100 {
quality = 50;
}
quality
}; };
msg.custom_image_quality = quality << 8; msg.custom_image_quality = quality << 8;
#[cfg(feature = "flutter")] #[cfg(feature = "flutter")]
if let Some(custom_fps) = self.options.get("custom-fps") { if let Some(custom_fps) = self.options.get("custom-fps") {
msg.custom_fps = custom_fps.parse().unwrap_or(30); let mut custom_fps = custom_fps.parse().unwrap_or(30);
if !allow_more && custom_fps > 30 {
custom_fps = 30;
}
msg.custom_fps = custom_fps;
*self.custom_fps.lock().unwrap() = Some(custom_fps as _);
} }
n += 1; n += 1;
} }
@ -1678,7 +1690,8 @@ impl LoginConfigHandler {
/// # Arguments /// # Arguments
/// ///
/// * `fps` - The given fps. /// * `fps` - The given fps.
pub fn set_custom_fps(&mut self, fps: i32) -> Message { /// * `save_config` - Save the config.
pub fn set_custom_fps(&mut self, fps: i32, save_config: bool) -> Message {
let mut misc = Misc::new(); let mut misc = Misc::new();
misc.set_option(OptionMessage { misc.set_option(OptionMessage {
custom_fps: fps, custom_fps: fps,
@ -1686,11 +1699,14 @@ impl LoginConfigHandler {
}); });
let mut msg_out = Message::new(); let mut msg_out = Message::new();
msg_out.set_misc(misc); msg_out.set_misc(misc);
if save_config {
let mut config = self.load_config(); let mut config = self.load_config();
config config
.options .options
.insert("custom-fps".to_owned(), fps.to_string()); .insert("custom-fps".to_owned(), fps.to_string());
self.save_config(config); self.save_config(config);
}
*self.custom_fps.lock().unwrap() = Some(fps as _);
msg_out msg_out
} }

View File

@ -939,6 +939,12 @@ impl<T: InvokeUiSession> Remote<T> {
#[inline] #[inline]
fn fps_control(&mut self, direct: bool) { fn fps_control(&mut self, direct: bool) {
let custom_fps = self.handler.lc.read().unwrap().custom_fps.clone();
let custom_fps = custom_fps.lock().unwrap().clone();
let mut custom_fps = custom_fps.unwrap_or(30);
if custom_fps < 5 || custom_fps > 120 {
custom_fps = 30;
}
let decode_fps_read = self.decode_fps_map.read().unwrap(); let decode_fps_read = self.decode_fps_map.read().unwrap();
for (display, decode_fps) in decode_fps_read.iter() { for (display, decode_fps) in decode_fps_read.iter() {
let video_queue_map_read = self.video_queue_map.read().unwrap(); let video_queue_map_read = self.video_queue_map.read().unwrap();
@ -955,32 +961,15 @@ impl<T: InvokeUiSession> Remote<T> {
let len = video_queue.len(); let len = video_queue.len();
let decode_fps = *decode_fps; let decode_fps = *decode_fps;
let limited_fps = if direct { let mut limited_fps = if direct {
decode_fps * 9 / 10 // 30 got 27 decode_fps * 9 / 10 // 30 got 27
} else { } else {
decode_fps * 4 / 5 // 30 got 24 decode_fps * 4 / 5 // 30 got 24
}; };
// send full speed fps if limited_fps > custom_fps {
let version = self.handler.lc.read().unwrap().version; limited_fps = custom_fps;
let max_encode_speed = 144 * 10 / 9;
if version >= hbb_common::get_version_number("1.2.1")
&& (ctl.last_full_speed_fps.is_none() // First time
|| ((ctl.last_full_speed_fps.unwrap_or_default() - decode_fps as i32).abs() >= 5 // diff 5
&& !(decode_fps > max_encode_speed // already exceed max encoding speed
&& ctl.last_full_speed_fps.unwrap_or_default() > max_encode_speed as i32)))
{
let mut misc = Misc::new();
misc.set_full_speed_fps(decode_fps as _);
let mut msg = Message::new();
msg.set_misc(misc);
self.sender.send(Data::Message(msg)).ok();
ctl.last_full_speed_fps = Some(decode_fps as _);
} }
// decrease judgement let should_decrease = len > 1 && ctl.last_auto_fps.unwrap_or(0) > limited_fps as i32;
let debounce = if decode_fps > 10 { decode_fps / 2 } else { 5 }; // 500ms
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 // increase judgement
if len <= 1 { if len <= 1 {
@ -989,35 +978,30 @@ impl<T: InvokeUiSession> Remote<T> {
ctl.idle_counter = 0; ctl.idle_counter = 0;
} }
let mut should_increase = false; let mut should_increase = false;
if let Some(last_custom_fps) = ctl.last_custom_fps { if let Some(last_auto_fps) = ctl.last_auto_fps {
// ever set // ever set
if last_custom_fps + 5 < limited_fps as i32 && ctl.idle_counter > 3 { if last_auto_fps + 3 <= limited_fps as i32 && ctl.idle_counter > 3 {
// limited_fps is 5 larger than last set, and idle time is more than 3 seconds // limited_fps is 5 larger than last set, and idle time is more than 3 seconds
should_increase = true; should_increase = true;
} }
} }
if should_decrease || should_increase { if ctl.last_auto_fps.is_none() || should_decrease || should_increase {
// limited_fps to ensure decoding is faster than encoding // limited_fps to ensure decoding is faster than encoding
let mut custom_fps = limited_fps as i32; let mut auto_fps = limited_fps as i32;
if custom_fps < 1 { if auto_fps < 1 {
custom_fps = 1; auto_fps = 1;
} }
// send custom fps // send custom fps
let mut misc = Misc::new(); let mut misc = Misc::new();
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 { misc.set_option(OptionMessage {
custom_fps, custom_fps: auto_fps,
..Default::default() ..Default::default()
}); });
}
let mut msg = Message::new(); let mut msg = Message::new();
msg.set_misc(misc); msg.set_misc(misc);
self.sender.send(Data::Message(msg)).ok(); self.sender.send(Data::Message(msg)).ok();
ctl.last_queue_size = len; ctl.last_queue_size = len;
ctl.last_custom_fps = Some(custom_fps); ctl.last_auto_fps = Some(auto_fps);
} }
// send refresh // send refresh
if ctl.refresh_times < 10 // enough if ctl.refresh_times < 10 // enough
@ -1805,8 +1789,7 @@ struct FpsControl {
last_queue_size: usize, last_queue_size: usize,
refresh_times: usize, refresh_times: usize,
last_refresh_instant: Instant, last_refresh_instant: Instant,
last_full_speed_fps: Option<i32>, last_auto_fps: Option<i32>,
last_custom_fps: Option<i32>,
idle_counter: usize, idle_counter: usize,
} }
@ -1816,8 +1799,7 @@ impl Default for FpsControl {
last_queue_size: Default::default(), last_queue_size: Default::default(),
refresh_times: Default::default(), refresh_times: Default::default(),
last_refresh_instant: Instant::now(), last_refresh_instant: Instant::now(),
last_full_speed_fps: None, last_auto_fps: None,
last_custom_fps: None,
idle_counter: 0, idle_counter: 0,
} }
} }

View File

@ -2179,10 +2179,6 @@ impl Connection {
crate::plugin::handle_client_event(&p.id, &self.lr.my_id, &p.content); crate::plugin::handle_client_event(&p.id, &self.lr.my_id, &p.content);
self.send(msg).await; self.send(msg).await;
} }
Some(misc::Union::FullSpeedFps(fps)) => video_service::VIDEO_QOS
.lock()
.unwrap()
.user_full_speed_fps(self.inner.id(), fps),
Some(misc::Union::AutoAdjustFps(fps)) => video_service::VIDEO_QOS Some(misc::Union::AutoAdjustFps(fps)) => video_service::VIDEO_QOS
.lock() .lock()
.unwrap() .unwrap()

View File

@ -30,8 +30,7 @@ struct Delay {
#[derive(Default, Debug, Copy, Clone)] #[derive(Default, Debug, Copy, Clone)]
struct UserData { struct UserData {
full_speed_fps: Option<u32>, auto_adjust_fps: Option<u32>, // reserve for compatibility
auto_adjust_fps: Option<u32>,
custom_fps: Option<u32>, custom_fps: Option<u32>,
quality: Option<(i64, Quality)>, // (time, quality) quality: Option<(i64, Quality)>, // (time, quality)
delay: Option<Delay>, delay: Option<Delay>,
@ -126,20 +125,14 @@ impl VideoQoS {
pub fn refresh(&mut self, typ: Option<RefreshType>) { pub fn refresh(&mut self, typ: Option<RefreshType>) {
// fps // fps
let user_fps = |u: &UserData| { let user_fps = |u: &UserData| {
// full_speed_fps // custom_fps
let mut fps = u.full_speed_fps.unwrap_or_default() * 9 / 10; let mut fps = u.custom_fps.unwrap_or(FPS);
// auto adjust fps // auto adjust fps
if let Some(auto_adjust_fps) = u.auto_adjust_fps { if let Some(auto_adjust_fps) = u.auto_adjust_fps {
if fps == 0 || auto_adjust_fps < fps { if fps == 0 || auto_adjust_fps < fps {
fps = auto_adjust_fps; fps = auto_adjust_fps;
} }
} }
// custom_fps
if let Some(custom_fps) = u.custom_fps {
if fps == 0 || custom_fps < fps {
fps = custom_fps;
}
}
// delay // delay
if let Some(delay) = u.delay { if let Some(delay) = u.delay {
fps = match delay.state { fps = match delay.state {
@ -264,21 +257,6 @@ impl VideoQoS {
self.refresh(None); self.refresh(None);
} }
pub fn user_full_speed_fps(&mut self, id: i32, full_speed_fps: u32) {
if let Some(user) = self.users.get_mut(&id) {
user.full_speed_fps = Some(full_speed_fps);
} else {
self.users.insert(
id,
UserData {
full_speed_fps: Some(full_speed_fps),
..Default::default()
},
);
}
self.refresh(None);
}
pub fn user_auto_adjust_fps(&mut self, id: i32, fps: u32) { pub fn user_auto_adjust_fps(&mut self, id: i32, fps: u32) {
if let Some(user) = self.users.get_mut(&id) { if let Some(user) = self.users.get_mut(&id) {
user.auto_adjust_fps = Some(fps); user.auto_adjust_fps = Some(fps);

View File

@ -1,4 +1,7 @@
use crate::{input::{MOUSE_BUTTON_LEFT, MOUSE_TYPE_DOWN, MOUSE_TYPE_UP, MOUSE_TYPE_WHEEL}, common::{is_keyboard_mode_supported, get_supported_keyboard_modes}}; use crate::{
common::{get_supported_keyboard_modes, is_keyboard_mode_supported},
input::{MOUSE_BUTTON_LEFT, MOUSE_TYPE_DOWN, MOUSE_TYPE_UP, MOUSE_TYPE_WHEEL},
};
use async_trait::async_trait; use async_trait::async_trait;
use bytes::Bytes; use bytes::Bytes;
use rdev::{Event, EventType::*, KeyCode}; use rdev::{Event, EventType::*, KeyCode};
@ -386,14 +389,19 @@ impl<T: InvokeUiSession> Session<T> {
} }
pub fn save_image_quality(&self, value: String) { pub fn save_image_quality(&self, value: String) {
let msg = self.lc.write().unwrap().save_image_quality(value); let msg = self.lc.write().unwrap().save_image_quality(value.clone());
if let Some(msg) = msg { if let Some(msg) = msg {
self.send(Data::Message(msg)); self.send(Data::Message(msg));
} }
if value != "custom" {
// non custom quality use 30 fps
let msg = self.lc.write().unwrap().set_custom_fps(30, false);
self.send(Data::Message(msg));
}
} }
pub fn set_custom_fps(&self, custom_fps: i32) { pub fn set_custom_fps(&self, custom_fps: i32) {
let msg = self.lc.write().unwrap().set_custom_fps(custom_fps); let msg = self.lc.write().unwrap().set_custom_fps(custom_fps, true);
self.send(Data::Message(msg)); self.send(Data::Message(msg));
} }