[feat] add live remote video settings to the toolbar

This commit is contained in:
dijunkun
2026-09-24 15:44:02 +08:00
parent 88da1081ef
commit e0cd4c0567
18 changed files with 363 additions and 217 deletions
+6 -22
View File
@@ -136,28 +136,12 @@ int GuiRuntime::CreateConnectionPeer() {
params_.turn_mode = static_cast<TurnMode>(config_center_->GetTurnMode());
params_.enable_srtp = config_center_->IsEnableSrtp();
params_.video_content_type = VideoContentType::ScreenContent;
params_.video_quality =
static_cast<VideoQuality>(config_center_->GetVideoQuality());
params_.video_frame_rate =
config_center_->GetVideoFrameRate() ==
ConfigCenter::VIDEO_FRAME_RATE::FPS_30
? 30
: 60;
switch (config_center_->GetVideoAdaptationPolicy()) {
case ConfigCenter::VIDEO_ADAPTATION_POLICY::FRAME_RATE_PRIORITY:
params_.video_degradation_preference =
VideoDegradationPreference::MaintainFrameRate;
break;
case ConfigCenter::VIDEO_ADAPTATION_POLICY::BALANCED:
params_.video_degradation_preference =
VideoDegradationPreference::Balanced;
break;
case ConfigCenter::VIDEO_ADAPTATION_POLICY::QUALITY_PRIORITY:
default:
params_.video_degradation_preference =
VideoDegradationPreference::MaintainResolution;
break;
}
// Bootstrap outgoing media with fixed defaults. Live overrides come only
// from the authorized controller and apply to its connection on this host.
params_.video_quality = VideoQuality::QualityHigh;
params_.video_frame_rate = 60;
params_.video_degradation_preference =
VideoDegradationPreference::MaintainResolution;
params_.on_receive_video_buffer = nullptr;
params_.on_receive_audio_buffer = PeerEventHandler::OnReceiveAudioBuffer;
params_.on_receive_data_buffer = PeerEventHandler::OnReceiveDataBuffer;
@@ -146,6 +146,47 @@ void PeerEventHandler::OnReceiveDataBuffer(
}
std::string remote_id(user_id, user_id_size);
if (remote_action.type == ControlType::video_settings_status) {
if (auto props = runtime->FindRemoteSession(remote_id)) {
if (source_id != props->control_data_label_) return;
std::lock_guard lock(props->video_settings_mutex_);
if (!props->video_settings_supported_) return;
if (remote_action.vs.accepted &&
static_cast<int32_t>(remote_action.vs.request_id -
props->applied_video_settings_.request_id) >= 0) {
props->applied_video_settings_ = remote_action.vs;
}
if (remote_action.vs.request_id != props->video_settings_.request_id) return;
props->video_settings_pending_ = false;
props->video_settings_failed_ = !remote_action.vs.accepted;
if (remote_action.vs.accepted) {
props->video_settings_ = remote_action.vs;
props->applied_video_settings_ = remote_action.vs;
} else {
const auto request_id = props->video_settings_.request_id;
props->video_settings_ = props->applied_video_settings_;
props->video_settings_.request_id = request_id;
}
}
return;
}
if (remote_action.type == ControlType::video_settings) {
if (source_id != runtime->control_data_label_ ||
!runtime->IsAuthorizedController(remote_id))
return;
const auto& settings = remote_action.vs;
remote_action.vs.accepted =
UpdateVideoSettings(
runtime->peer_, remote_id.data(), remote_id.size(),
static_cast<VideoQuality>(settings.quality), settings.frame_rate,
static_cast<VideoDegradationPreference>(settings.preference)) == 0;
remote_action.type = ControlType::video_settings_status;
const auto message = remote_action.to_json();
SendReliableDataFrameToPeer(runtime->peer_, message.data(), message.size(),
runtime->control_data_label_.c_str(),
remote_id.data(), remote_id.size());
return;
}
if (remote_action.type == ControlType::privacy_status) {
if (auto props = runtime->FindRemoteSession(remote_id)) {
if (source_id != props->control_data_label_) return;
@@ -274,6 +315,25 @@ void PeerEventHandler::OnReceiveDataBuffer(
}
if (is_client_mode) {
// Negotiate live settings only on the reliable control stream. Old
// hosts omit this capability and retain their existing video behavior.
if (props && source_id == props->control_data_label_) {
std::lock_guard lock(props->video_settings_mutex_);
const bool first_advertisement = !props->video_settings_supported_;
props->video_settings_supported_ =
remote_action.i.supports_video_settings;
if (first_advertisement && props->video_settings_supported_) {
RemoteAction settings{};
settings.type = ControlType::video_settings;
++props->video_settings_.request_id;
props->video_settings_pending_ = true;
props->video_settings_request_tick_ = SDL_GetTicks();
settings.vs = props->video_settings_;
const auto message = settings.to_json();
SendReliableDataFrame(props->peer_, message.data(), message.size(),
props->control_data_label_.c_str());
}
}
// client mode
if (props && props->remote_host_name_.empty()) {
props->remote_host_name_ = std::string(remote_action.i.host_name,
@@ -267,6 +267,7 @@ void PeerEventHandler::OnConnectionStatus(ConnectionStatus status,
RemoteAction remote_action = MakeHostInformation(
GetHostName(), runtime->devices_.host_display_list(),
/*supports_privacy_screen=*/true);
remote_action.i.supports_video_settings = true;
for (std::size_t i = 0; i < remote_action.i.display_num; i++) {
LOG_INFO("Local display [{}:{}]", i + 1,
remote_action.i.display_list[i]);
@@ -297,6 +298,12 @@ void PeerEventHandler::OnConnectionStatus(ConnectionStatus status,
props->connection_established_ = false;
props->enable_mouse_control_ = false;
runtime->ResetRemoteServiceStatus(*props);
{
std::lock_guard lock(props->video_settings_mutex_);
props->video_settings_supported_ = false;
props->video_settings_pending_ = false;
props->video_settings_failed_ = false;
}
{
std::lock_guard lock(props->remote_cursor_state_mutex_);
props->remote_cursor_state_ = {};
@@ -382,6 +389,7 @@ void PeerEventHandler::OnConnectionStatus(ConnectionStatus status,
RemoteAction remote_action = MakeHostInformation(
GetHostName(), runtime->devices_.host_display_list(),
/*supports_privacy_screen=*/true);
remote_action.i.supports_video_settings = true;
for (std::size_t i = 0; i < remote_action.i.display_num; i++) {
LOG_INFO("Local display [{}:{}]", i + 1,
remote_action.i.display_list[i]);
@@ -119,6 +119,14 @@ struct RemoteSession {
bool tab_opened_ = true;
std::string remote_host_name_;
bool remote_service_status_received_ = false;
std::mutex video_settings_mutex_;
// Requested and confirmed settings for this remote session only.
VideoSettings video_settings_{2, 60, 1};
bool video_settings_supported_ = false;
VideoSettings applied_video_settings_{2, 60, 1, 0, false};
bool video_settings_pending_ = false;
bool video_settings_failed_ = false;
uint64_t video_settings_request_tick_ = 0;
std::mutex privacy_status_mutex_;
PrivacyStatus privacy_status_{};
bool privacy_status_received_ = false;
@@ -128,9 +128,6 @@ struct UserSettingsState {
char self_hosted_user_id_[17] = "";
char connection_login_identity_[17] = "";
int language_button_value_ = 0;
int video_quality_button_value_ = 2;
int video_frame_rate_button_value_ = 1;
int video_adaptation_policy_button_value_ = 1;
int video_encode_format_button_value_ = 0;
bool enable_hardware_video_codec_ = true;
bool enable_turn_ = true;
@@ -138,9 +135,6 @@ struct UserSettingsState {
char signal_server_port_[6] = "9099";
bool enable_self_hosted_ = false;
int language_button_value_last_ = 0;
int video_quality_button_value_last_ = 0;
int video_frame_rate_button_value_last_ = 0;
int video_adaptation_policy_button_value_last_ = 1;
int video_encode_format_button_value_last_ = 0;
bool enable_hardware_video_codec_last_ = false;
bool enable_turn_last_ = true;