From 91d4c0a52320fdd649db63a65fd56c8535cc54c7 Mon Sep 17 00:00:00 2001 From: yuanyuanxiang <962914132@qq.com> Date: Mon, 15 Jun 2026 22:14:06 +0200 Subject: [PATCH] Fix: eliminate extra screen restarts on connection init Two changes to reduce unnecessary CScreenSpy restarts when connecting: 1. Client (ScreenManager.cpp): Initialize CScreenSpy with bitrate from the locally-saved quality profile, so CMD_QUALITY_LEVEL arriving from the server (same bitrate as default) hits SetBitRate(3000)==3000 and skips the restart instead of comparing against the hard-coded 0. Also fixes QualityLevel init to use the already-computed `quality` variable (which honours the QUALITY_DISABLED override when algo!=NUL) rather than re-reading the cfg key a second time. 2. Server (ScreenSpyDlg.cpp): Only send CMD_SCREEN_SIZE strategy=2 when the session is in QUALITY_ADAPTIVE mode and a cached maxWidth exists. Fixed quality levels already carry resolution via CMD_QUALITY_PROFILES, so unconditionally sending CMD_SCREEN_SIZE caused a second restart when the screen spy was still rebuilding from the first one. Co-Authored-By: Claude Sonnet 4.6 --- client/ScreenManager.cpp | 6 +++++- server/2015Remote/ScreenSpyDlg.cpp | 11 ++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/client/ScreenManager.cpp b/client/ScreenManager.cpp index 89e2a21..55a7da2 100644 --- a/client/ScreenManager.cpp +++ b/client/ScreenManager.cpp @@ -153,7 +153,7 @@ CScreenManager::CScreenManager(IOCPClient* ClientObject, int n, void* user, BOOL m_ScreenSettings.FullScreen = cfg.GetInt("settings", "FullScreen", priv); m_ScreenSettings.RemoteCursor = cfg.GetInt("settings", "RemoteCursor", 0); m_ScreenSettings.ScrollDetectInterval = cfg.GetInt("settings", "ScrollDetectInterval", 2); // 默认每2帧 - m_ScreenSettings.QualityLevel = cfg.GetInt("settings", "QualityLevel", quality); + m_ScreenSettings.QualityLevel = quality; m_ScreenSettings.CpuSpeedup = cfg.GetInt("settings", "CpuSpeedup", 0); m_ScreenSettings.AudioEnabled = cfg.GetInt("settings", "AudioEnabled", 0); // 默认禁用音频 m_ScreenSettings.EncodeLevel = cfg.GetInt("settings", "EncodeLevel", LEVEL_H264_SOFT); @@ -556,6 +556,10 @@ void CScreenManager::InitScreenSpy() m_isGDI = TRUE; m_ScreenSpyObject = new CScreenSpy(32, algo, DXGI == USING_VIRTUAL, DEFAULT_GOP, all, m_ScreenSettings.EncodeLevel, rect, switchScreen, m_hTargetWnd, m_bDynamicForeground); } + // 用已保存的质量配置初始化码率,避免 CMD_QUALITY_LEVEL 到达时 0→3000 触发不必要重启 + if (m_ScreenSpyObject && level >= 0 && level < QUALITY_COUNT) { + m_ScreenSpyObject->SetBitRate(m_QualityProfiles[level].bitRate); + } } BOOL IsRunningAsSystem() diff --git a/server/2015Remote/ScreenSpyDlg.cpp b/server/2015Remote/ScreenSpyDlg.cpp index b143be5..96dbcbd 100644 --- a/server/2015Remote/ScreenSpyDlg.cpp +++ b/server/2015Remote/ScreenSpyDlg.cpp @@ -856,11 +856,12 @@ BOOL CScreenSpyDlg::OnInitDialog() BYTE cmd[4] = { CMD_QUALITY_LEVEL, (BYTE)m_AdaptiveQuality.currentLevel, 0 }; m_ContextObject->Send2Client(cmd, sizeof(cmd)); - // 始终发送 CMD_SCREEN_SIZE,让客户端同步分辨率策略 - // maxWidth=0 表示使用默认分辨率(1080p 限制) - BYTE sizeCmd[16] = { CMD_SCREEN_SIZE, 2 }; // strategy=2 表示自适应质量 - memcpy(sizeCmd + 2, &m_AdaptiveQuality.currentMaxWidth, sizeof(int)); - m_ContextObject->Send2Client(sizeCmd, 10); + // 仅在自适应模式且有缓存宽度时同步分辨率,固定等级分辨率由 profile 决定无需重发 + if (m_Settings.QualityLevel == QUALITY_ADAPTIVE && m_AdaptiveQuality.currentMaxWidth > 0) { + BYTE sizeCmd[16] = { CMD_SCREEN_SIZE, 2 }; // strategy=2 = 自适应质量 + memcpy(sizeCmd + 2, &m_AdaptiveQuality.currentMaxWidth, sizeof(int)); + m_ContextObject->Send2Client(sizeCmd, 10); + } } SendNext();