mirror of
https://github.com/yuanyuanxiang/SimpleRemoter.git
synced 2026-02-16 03:13:30 +08:00
Improve: Adjust quality level definitions and add disable option
This commit is contained in:
@@ -156,6 +156,7 @@ public:
|
||||
bool m_bLastFrameWasScroll; // 上一帧是否是滚动帧(用于强制同步)
|
||||
int m_nScrollDetectInterval; // 滚动检测间隔(0=禁用, 1=每帧, 2=每2帧, ...)
|
||||
int m_nInstructionSet = 0;
|
||||
int m_nBitRate = 0; // H264 编码码率 (kbps), 0=自动
|
||||
|
||||
protected:
|
||||
int m_nVScreenLeft = GetSystemMetrics(SM_XVIRTUALSCREEN);
|
||||
@@ -212,12 +213,6 @@ public:
|
||||
Mprintf("=> 桌面缩放比例: %.2f, %.2f\t分辨率:%d x %d\n", m_wZoom, m_hZoom, m_ulFullWidth, m_ulFullHeight);
|
||||
m_wZoom = 1.0 / m_wZoom, m_hZoom = 1.0 / m_hZoom;
|
||||
}
|
||||
if (ALGORITHM_H264 == m_bAlgorithm) {
|
||||
m_encoder = new CX264Encoder();
|
||||
if (!m_encoder->open(m_ulFullWidth, m_ulFullHeight, 20, m_ulFullWidth * m_ulFullHeight / 1266)) {
|
||||
Mprintf("Open x264encoder failed!!!\n");
|
||||
}
|
||||
}
|
||||
|
||||
m_BlockBuffers = new LPBYTE[m_BlockNum];
|
||||
m_BlockSizes = new ULONG[m_BlockNum];
|
||||
@@ -911,8 +906,13 @@ public:
|
||||
case ALGORITHM_H264: {
|
||||
uint8_t* encoded_data = nullptr;
|
||||
uint32_t encoded_size = 0;
|
||||
int err = m_encoder->encode(nextData, 32, 4* m_BitmapInfor_Send->bmiHeader.biWidth,
|
||||
m_BitmapInfor_Send->bmiHeader.biWidth, m_BitmapInfor_Send->bmiHeader.biHeight, &encoded_data, &encoded_size);
|
||||
int width = m_BitmapInfor_Send->bmiHeader.biWidth, height = m_BitmapInfor_Send->bmiHeader.biHeight;
|
||||
if (m_encoder == nullptr) {
|
||||
m_encoder = new CX264Encoder();
|
||||
int bitrate = (m_nBitRate > 0) ? m_nBitRate : (width * height / 1266);
|
||||
m_encoder->open(width, height, 20, bitrate);
|
||||
}
|
||||
int err = m_encoder->encode(nextData, 32, 4 * width, width, height, &encoded_data, &encoded_size);
|
||||
if (err) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -936,8 +936,13 @@ public:
|
||||
case ALGORITHM_H264: {
|
||||
uint8_t* encoded_data = nullptr;
|
||||
uint32_t encoded_size = 0;
|
||||
int err = m_encoder->encode(nextData, 32, 4 * m_BitmapInfor_Send->bmiHeader.biWidth,
|
||||
m_BitmapInfor_Send->bmiHeader.biWidth, m_BitmapInfor_Send->bmiHeader.biHeight, &encoded_data, &encoded_size);
|
||||
int width = m_BitmapInfor_Send->bmiHeader.biWidth, height = m_BitmapInfor_Send->bmiHeader.biHeight;
|
||||
if (m_encoder == nullptr) {
|
||||
m_encoder = new CX264Encoder();
|
||||
int bitrate = (m_nBitRate > 0) ? m_nBitRate : (width * height / 1266);
|
||||
m_encoder->open(width, height, 20, bitrate);
|
||||
}
|
||||
int err = m_encoder->encode(nextData, 32, 4 * width, width, height, &encoded_data, &encoded_size);
|
||||
if (err) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -967,6 +972,21 @@ public:
|
||||
return oldAlgo;
|
||||
}
|
||||
|
||||
// 设置 H264 编码码率 (kbps), 0=自动计算
|
||||
// 返回码率是否变化,调用者需要在变化时 RestartScreen
|
||||
virtual bool SetBitRate(int bitrate)
|
||||
{
|
||||
if (m_nBitRate == bitrate)
|
||||
return false;
|
||||
m_nBitRate = bitrate;
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual int GetBitRate() const
|
||||
{
|
||||
return m_nBitRate;
|
||||
}
|
||||
|
||||
// 鼠标位置转换
|
||||
virtual void PointConversion(POINT& pt) const
|
||||
{
|
||||
|
||||
@@ -115,9 +115,7 @@ public:
|
||||
m_BitmapInfor_Send = new BITMAPINFO(*m_BitmapInfor_Full);
|
||||
m_nInstructionSet = cfg.GetInt("settings", "CpuSpeedup", 0);
|
||||
|
||||
bool canScale = (m_bAlgorithm != ALGORITHM_H264);
|
||||
|
||||
if (strategy == 1 || !canScale) {
|
||||
if (strategy == 1) {
|
||||
// strategy=1 或不支持缩放: 原始分辨率
|
||||
} else if (maxWidth > 0 && maxWidth < m_BitmapInfor_Send->bmiHeader.biWidth) {
|
||||
// maxWidth>0: 自定义 maxWidth,等比缩放(自适应质量使用)
|
||||
|
||||
@@ -105,6 +105,8 @@ CScreenManager::CScreenManager(IOCPClient* ClientObject, int n, void* user):CMan
|
||||
m_ScreenSettings.QualityLevel = cfg.GetInt("settings", "QualityLevel", QUALITY_ADAPTIVE); // 默认自适应
|
||||
m_ScreenSettings.CpuSpeedup = cfg.GetInt("settings", "CpuSpeedup", 0);
|
||||
|
||||
LoadQualityProfiles(); // 加载质量配置
|
||||
|
||||
m_hWorkThread = __CreateThread(NULL,0, WorkThreadProc,this,0,NULL);
|
||||
}
|
||||
|
||||
@@ -263,7 +265,7 @@ void CScreenManager::InitScreenSpy()
|
||||
// 如果已设置质量等级,使用对应的算法(优先于启动参数)
|
||||
int level = m_ScreenSettings.QualityLevel;
|
||||
if (level >= 0 && level < QUALITY_COUNT) {
|
||||
algo = GetQualityProfile(level).algorithm;
|
||||
algo = m_QualityProfiles[level].algorithm;
|
||||
}
|
||||
Mprintf("CScreenManager: Type %d Algorithm: %d (QualityLevel=%d)\n", DXGI, int(algo), level);
|
||||
if (DXGI == USING_VIRTUAL) {
|
||||
@@ -575,7 +577,7 @@ VOID CScreenManager::OnReceive(PBYTE szBuffer, ULONG ulLength)
|
||||
|
||||
iniFile cfg(CLIENT_PATH);
|
||||
|
||||
// strategy=2 是自适应质量使用的临时策略,不应覆盖用户的原始策略
|
||||
// strategy=2 是自适应质量使用的临时策略,不覆盖用户的原始 ScreenStrategy
|
||||
if (strategy == 2) {
|
||||
if (maxWidth == 0) {
|
||||
// maxWidth=0 表示"使用默认策略",读取用户原来的设置
|
||||
@@ -587,7 +589,7 @@ VOID CScreenManager::OnReceive(PBYTE szBuffer, ULONG ulLength)
|
||||
}
|
||||
Mprintf("maxWidth=0, 回退到默认策略: strategy=%d\n", strategy);
|
||||
}
|
||||
// strategy=2 只写入 ScreenWidth,不覆盖用户的 ScreenStrategy
|
||||
// 保存自适应的 ScreenWidth,下次启动时作为初始值
|
||||
cfg.SetInt("settings", "ScreenWidth", maxWidth);
|
||||
Mprintf("写入配置: ScreenWidth=%d (保留原 ScreenStrategy)\n", maxWidth);
|
||||
} else {
|
||||
@@ -616,11 +618,9 @@ VOID CScreenManager::OnReceive(PBYTE szBuffer, ULONG ulLength)
|
||||
needRestart = !m_ScreenSpyObject->IsOriginalSize();
|
||||
Mprintf("strategy=1 (原始), needRestart=%d\n", needRestart);
|
||||
break;
|
||||
case 2: // 自定义 maxWidth (maxWidth > 0)
|
||||
if (maxWidth > 0 && maxWidth != currentWidth) {
|
||||
needRestart = true;
|
||||
}
|
||||
Mprintf("strategy=2 (自定义), maxWidth=%d, currentWidth=%d, needRestart=%d\n",
|
||||
case 2: // 自适应质量调整 (maxWidth > 0,maxWidth=0 时已回退到 case 0/1)
|
||||
needRestart = (maxWidth != currentWidth);
|
||||
Mprintf("strategy=2 (自适应), maxWidth=%d, currentWidth=%d, needRestart=%d\n",
|
||||
maxWidth, currentWidth, needRestart);
|
||||
break;
|
||||
}
|
||||
@@ -663,8 +663,8 @@ VOID CScreenManager::OnReceive(PBYTE szBuffer, ULONG ulLength)
|
||||
break;
|
||||
}
|
||||
case CMD_QUALITY_LEVEL: {
|
||||
// 质量等级调整 (level: -1=自适应, 0-4=具体等级)
|
||||
int8_t level = (int8_t)szBuffer[1]; // 有符号,支持 -1
|
||||
// 质量等级调整 (level: -2=关闭, -1=自适应, 0-5=具体等级)
|
||||
int8_t level = (int8_t)szBuffer[1]; // 有符号,支持负值
|
||||
int persist = ulLength >= 3 ? szBuffer[2] : 0; // 是否保存到配置
|
||||
m_ScreenSettings.QualityLevel = level;
|
||||
// 保存到配置
|
||||
@@ -672,15 +672,32 @@ VOID CScreenManager::OnReceive(PBYTE szBuffer, ULONG ulLength)
|
||||
iniFile cfg(CLIENT_PATH);
|
||||
cfg.SetInt("settings", "QualityLevel", level);
|
||||
}
|
||||
// 应用具体等级的配置 (自适应模式由服务端动态调整)
|
||||
if (level >= 0 && level < QUALITY_COUNT) {
|
||||
const QualityProfile& profile = GetQualityProfile(level);
|
||||
// 应用具体等级的配置
|
||||
if (level == QUALITY_DISABLED) {
|
||||
// 关闭模式:不修改任何设置,使用原有的算法和帧率配置
|
||||
Mprintf("质量等级: 关闭 (使用原有设置)\n");
|
||||
} else if (level >= 0 && level < QUALITY_COUNT) {
|
||||
// 具体等级:应用本地配置
|
||||
const QualityProfile& profile = m_QualityProfiles[level];
|
||||
m_ScreenSettings.MaxFPS = profile.maxFPS;
|
||||
bool needRestart = false;
|
||||
if (m_ScreenSpyObject) {
|
||||
// 如果当前是 H264 且码率变化,需要重启以重新创建编码器
|
||||
bool isH264 = (m_ScreenSpyObject->GetAlgorithm() == ALGORITHM_H264);
|
||||
bool bitRateChanged = m_ScreenSpyObject->SetBitRate(profile.bitRate);
|
||||
if (isH264 && bitRateChanged) {
|
||||
needRestart = true;
|
||||
}
|
||||
m_ScreenSpyObject->SetAlgorithm(profile.algorithm);
|
||||
}
|
||||
Mprintf("质量等级: Level=%d, FPS=%d, Algo=%d\n", level, profile.maxFPS, profile.algorithm);
|
||||
Mprintf("质量等级: Level=%d, FPS=%d, Algo=%d, BitRate=%d\n", level,
|
||||
profile.maxFPS, profile.algorithm, profile.bitRate);
|
||||
if (needRestart) {
|
||||
Mprintf("H264 码率变化,重启截屏...\n");
|
||||
RestartScreen();
|
||||
}
|
||||
} else {
|
||||
// 自适应模式:由服务端动态调整
|
||||
Mprintf("质量等级: 自适应模式\n");
|
||||
}
|
||||
break;
|
||||
@@ -695,6 +712,15 @@ VOID CScreenManager::OnReceive(PBYTE szBuffer, ULONG ulLength)
|
||||
Mprintf("使用的CPU加速指令集: %d\n", set);
|
||||
break;
|
||||
}
|
||||
case CMD_QUALITY_PROFILES: {
|
||||
// 接收服务端下发的质量配置
|
||||
if (ulLength >= 1 + sizeof(QualityProfile) * QUALITY_COUNT) {
|
||||
memcpy(m_QualityProfiles, szBuffer + 1, sizeof(QualityProfile) * QUALITY_COUNT);
|
||||
SaveQualityProfiles();
|
||||
Mprintf("收到质量配置更新\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case COMMAND_NEXT: {
|
||||
m_DlgID = ulLength >= 9 ? *((uint64_t*)(szBuffer + 1)) : 0;
|
||||
// 解析服务端能力标志(如果有)
|
||||
@@ -1294,3 +1320,38 @@ VOID CScreenManager::ProcessCommand(LPBYTE szBuffer, ULONG ulLength)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CScreenManager::LoadQualityProfiles()
|
||||
{
|
||||
iniFile cfg(CLIENT_PATH);
|
||||
for (int i = 0; i < QUALITY_COUNT; i++) {
|
||||
char section[32];
|
||||
sprintf(section, "profile%d", i);
|
||||
// 读取配置,没有则用默认值
|
||||
const QualityProfile& def = GetQualityProfile(i);
|
||||
m_QualityProfiles[i].maxFPS = cfg.GetInt(section, "maxFPS", def.maxFPS);
|
||||
m_QualityProfiles[i].maxWidth = cfg.GetInt(section, "maxWidth", def.maxWidth);
|
||||
m_QualityProfiles[i].algorithm = cfg.GetInt(section, "algorithm", def.algorithm);
|
||||
m_QualityProfiles[i].bitRate = cfg.GetInt(section, "bitRate", def.bitRate);
|
||||
}
|
||||
}
|
||||
|
||||
void CScreenManager::SaveQualityProfiles()
|
||||
{
|
||||
iniFile cfg(CLIENT_PATH);
|
||||
for (int i = 0; i < QUALITY_COUNT; i++) {
|
||||
const QualityProfile& def = GetQualityProfile(i);
|
||||
const QualityProfile& cur = m_QualityProfiles[i];
|
||||
// 只有与默认值不同时才保存
|
||||
if (cur.maxFPS == def.maxFPS && cur.maxWidth == def.maxWidth &&
|
||||
cur.algorithm == def.algorithm && cur.bitRate == def.bitRate) {
|
||||
continue;
|
||||
}
|
||||
char section[32];
|
||||
sprintf(section, "profile%d", i);
|
||||
cfg.SetInt(section, "maxFPS", cur.maxFPS);
|
||||
cfg.SetInt(section, "maxWidth", cur.maxWidth);
|
||||
cfg.SetInt(section, "algorithm", cur.algorithm);
|
||||
cfg.SetInt(section, "bitRate", cur.bitRate);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,8 +30,11 @@ public:
|
||||
virtual ~CScreenManager();
|
||||
HANDLE m_hWorkThread;
|
||||
ScreenSettings m_ScreenSettings = { 20 };
|
||||
QualityProfile m_QualityProfiles[QUALITY_COUNT]; // 本地质量配置(可被服务端覆盖)
|
||||
|
||||
void InitScreenSpy();
|
||||
void LoadQualityProfiles(); // 从配置文件加载质量配置
|
||||
void SaveQualityProfiles(); // 保存质量配置到配置文件
|
||||
static DWORD WINAPI WorkThreadProc(LPVOID lParam);
|
||||
VOID SendBitMapInfo();
|
||||
VOID OnReceive(PBYTE szBuffer, ULONG ulLength);
|
||||
|
||||
@@ -25,12 +25,11 @@ CScreenSpy::CScreenSpy(ULONG ulbiBitCount, BYTE algo, BOOL vDesk, int gop, BOOL
|
||||
m_BitmapInfor_Send = new BITMAPINFO(*m_BitmapInfor_Full);
|
||||
m_nInstructionSet = cfg.GetInt("settings", "CpuSpeedup", 0);
|
||||
|
||||
bool canScale = (m_bAlgorithm != ALGORITHM_H264);
|
||||
Mprintf("CScreenSpy: strategy=%d, maxWidth=%d, fullWidth=%d\n",
|
||||
strategy, maxWidth, m_BitmapInfor_Send->bmiHeader.biWidth);
|
||||
Mprintf("CScreenSpy: strategy=%d, maxWidth=%d, fullWidth=%d, algo=%d\n",
|
||||
strategy, maxWidth, m_BitmapInfor_Send->bmiHeader.biWidth, m_bAlgorithm);
|
||||
|
||||
if (strategy == 1 || !canScale) {
|
||||
// strategy=1 或不支持缩放: 原始分辨率
|
||||
if (strategy == 1) {
|
||||
// strategy=1: 用户明确选择原始分辨率
|
||||
Mprintf("CScreenSpy: 使用原始分辨率\n");
|
||||
} else if (maxWidth > 0 && maxWidth < m_BitmapInfor_Send->bmiHeader.biWidth) {
|
||||
// maxWidth>0: 自定义 maxWidth,等比缩放(自适应质量使用)
|
||||
|
||||
@@ -213,6 +213,7 @@ enum {
|
||||
CMD_SCROLL_INTERVAL = 77, // 滚动检测间隔
|
||||
CMD_QUALITY_LEVEL = 78, // 质量等级 (-1=自适应, 0-4=具体等级)
|
||||
CMD_INSTRUCTION_SET = 79,
|
||||
CMD_QUALITY_PROFILES = 80, // 下发质量配置表 (1 + QUALITY_COUNT * sizeof(QualityProfile))
|
||||
|
||||
TOKEN_SCROLL_FRAME = 99, // 滚动优化帧
|
||||
// 服务端发出的标识
|
||||
@@ -942,42 +943,57 @@ typedef struct MasterSettings {
|
||||
|
||||
// 自适应质量等级
|
||||
enum QualityLevel {
|
||||
QUALITY_DISABLED = -2, // 关闭质量控制(使用原有算法设置)
|
||||
QUALITY_ADAPTIVE = -1, // 自适应模式
|
||||
QUALITY_ULTRA = 0, // 极佳 (局域网)
|
||||
QUALITY_HIGH = 1, // 良好
|
||||
QUALITY_MEDIUM = 2, // 一般
|
||||
QUALITY_LOW = 3, // 较差
|
||||
QUALITY_MINIMAL = 4, // 最低
|
||||
QUALITY_COUNT = 5,
|
||||
QUALITY_ULTRA = 0, // 极佳 (局域网, DIFF)
|
||||
QUALITY_HIGH = 1, // 优秀 (RGB565)
|
||||
QUALITY_GOOD = 2, // 良好 (H264, 1080P)
|
||||
QUALITY_MEDIUM = 3, // 一般 (H264, 900P)
|
||||
QUALITY_LOW = 4, // 较差 (H264, 720P)
|
||||
QUALITY_MINIMAL = 5, // 最低 (H264, 540P)
|
||||
QUALITY_COUNT = 6,
|
||||
};
|
||||
|
||||
// 质量配置 (与 QualityLevel 对应)
|
||||
/* 质量配置(与 QualityLevel 对应)
|
||||
- strategy = 0:1080p 限制
|
||||
- strategy = 1:原始分辨率
|
||||
- strategy = 2 + maxWidth > 0:自定义宽度
|
||||
- strategy = 2 + maxWidth = 0:回退到用户保存的 strategy(0 或 1)
|
||||
*/
|
||||
struct QualityProfile {
|
||||
int maxFPS; // 最大帧率
|
||||
int maxWidth; // 最大宽度 (0=不限)
|
||||
int algorithm; // 压缩算法: 0=GRAY, 1=DIFF, 3=RGB565
|
||||
int algorithm; // 压缩算法: 0=GRAY, 1=DIFF, 2=H264, 3=RGB565
|
||||
int bitRate; // kbps - H264
|
||||
};
|
||||
|
||||
// 控制端使用,客户端优先从配置中读取
|
||||
inline const QualityProfile& GetQualityProfile(int level) {
|
||||
// 预定义质量配置: algorithm: 0=GRAY, 1=DIFF, 3=RGB565
|
||||
// 预定义质量配置: algorithm: 0=GRAY, 1=DIFF, 2=H264, 3=RGB565
|
||||
// 注意: level 必须在 [0, QUALITY_COUNT) 范围内
|
||||
static const QualityProfile g_QualityProfiles[QUALITY_COUNT] = {
|
||||
{30, 0, 1}, // Ultra: 30FPS, 原始, DIFF
|
||||
{20, 0, 3}, // High: 20FPS, 原始, RGB565
|
||||
{15, 1920, 3}, // Medium: 15FPS, 1080P,RGB565
|
||||
{10, 1920, 0}, // Low: 10FPS, 1080P,GRAY
|
||||
{5, 1280, 0}, // Minimal: 5FPS, 720P, GRAY
|
||||
{25, 0, 1, 0 }, // Ultra: 25FPS, 原始, DIFF (局域网办公)
|
||||
{20, 0, 3, 0 }, // High: 20FPS, 原始, RGB565 (一般办公)
|
||||
{20, 1920, 2, 3000}, // Good: 20FPS, 1080P, H264 (跨网/偶尔视频)
|
||||
{15, 1600, 2, 2000}, // Medium: 15FPS, 900P, H264
|
||||
{12, 1280, 2, 1200}, // Low: 12FPS, 720P, H264
|
||||
{8, 1024, 2, 800 }, // Minimal: 8FPS, 540P, H264 (极差网络)
|
||||
};
|
||||
if (level < 0 || level >= QUALITY_COUNT) {
|
||||
static const QualityProfile disabled = {0, 0, -1, 0}; // 关闭模式返回空配置
|
||||
return disabled;
|
||||
}
|
||||
return g_QualityProfiles[level];
|
||||
}
|
||||
|
||||
// 根据RTT获取目标质量等级
|
||||
// 根据RTT获取目标质量等级 (控制端使用)
|
||||
inline int GetTargetQualityLevel(int rtt, int usingFRP) {
|
||||
// 根据模式应用不同 RTT阈值 (毫秒)
|
||||
static const int g_RttThresholds[2][QUALITY_COUNT] = {
|
||||
// 直连: ULTRA, HIGH, MEDIUM, LOW, MINIMAL
|
||||
/* DIRECT */ { 30, 100, 200, 400, INT_MAX },
|
||||
// 直连: ULTRA, HIGH, GOOD, MEDIUM, LOW, MINIMAL
|
||||
/* DIRECT */ { 30, 80, 150, 250, 400, INT_MAX },
|
||||
// FRP:
|
||||
/* PROXY */ { 60, 200, 400, 800, INT_MAX },
|
||||
/* PROXY */ { 60, 160, 300, 500, 800, INT_MAX },
|
||||
};
|
||||
for (int i = 0; i < QUALITY_COUNT; i++) {
|
||||
if (rtt < g_RttThresholds[usingFRP][i])
|
||||
|
||||
@@ -43,9 +43,11 @@ enum {
|
||||
IDM_SCROLL_DETECT_2, // 滚动检测:跨网推荐
|
||||
IDM_SCROLL_DETECT_4, // 滚动检测:标准模式
|
||||
IDM_SCROLL_DETECT_8, // 滚动检测:省CPU模式
|
||||
IDM_QUALITY_OFF, // 关闭质量控制(使用原有算法)
|
||||
IDM_ADAPTIVE_QUALITY, // 自适应质量
|
||||
IDM_QUALITY_ULTRA, // 手动质量:Ultra
|
||||
IDM_QUALITY_HIGH, // 手动质量:High
|
||||
IDM_QUALITY_GOOD, // 手动质量:Good
|
||||
IDM_QUALITY_MEDIUM, // 手动质量:Medium
|
||||
IDM_QUALITY_LOW, // 手动质量:Low
|
||||
IDM_QUALITY_MINIMAL, // 手动质量:Minimal
|
||||
@@ -154,16 +156,23 @@ CScreenSpyDlg::CScreenSpyDlg(CMy2015RemoteDlg* Parent, Server* IOCPServer, CONTE
|
||||
m_ContextObject->InDeCompressedBuffer.CopyBuffer(m_BitmapInfor_Full, ulBitmapInforLength, 1);
|
||||
m_ContextObject->InDeCompressedBuffer.CopyBuffer(&m_Settings, sizeof(ScreenSettings), 57);
|
||||
|
||||
// 从客户端配置初始化自适应质量状态 (QualityLevel: -1=自适应, 0-4=具体等级)
|
||||
if (m_Settings.QualityLevel == QUALITY_ADAPTIVE) {
|
||||
// 从客户端配置初始化自适应质量状态 (QualityLevel: -2=关闭, -1=自适应, 0-5=具体等级)
|
||||
if (m_Settings.QualityLevel == QUALITY_DISABLED) {
|
||||
m_AdaptiveQuality.enabled = false;
|
||||
m_AdaptiveQuality.currentLevel = QUALITY_HIGH; // 关闭模式时不使用等级
|
||||
} else if (m_Settings.QualityLevel == QUALITY_ADAPTIVE) {
|
||||
m_AdaptiveQuality.enabled = true;
|
||||
m_AdaptiveQuality.currentLevel = QUALITY_HIGH; // 自适应默认从 High 开始
|
||||
} else if (m_Settings.QualityLevel >= 0 && m_Settings.QualityLevel < QUALITY_COUNT) {
|
||||
m_AdaptiveQuality.enabled = false;
|
||||
m_AdaptiveQuality.currentLevel = m_Settings.QualityLevel;
|
||||
}
|
||||
// 初始化当前分辨率限制
|
||||
m_AdaptiveQuality.currentMaxWidth = GetQualityProfile(m_AdaptiveQuality.currentLevel).maxWidth;
|
||||
// 初始化当前分辨率限制(关闭模式时为0,不限制)
|
||||
if (m_Settings.QualityLevel != QUALITY_DISABLED) {
|
||||
m_AdaptiveQuality.currentMaxWidth = GetQualityProfile(m_AdaptiveQuality.currentLevel).maxWidth;
|
||||
} else {
|
||||
m_AdaptiveQuality.currentMaxWidth = 0;
|
||||
}
|
||||
|
||||
m_bIsCtrl = FALSE;
|
||||
m_bIsTraceCursor = FALSE;
|
||||
@@ -348,13 +357,15 @@ BOOL CScreenSpyDlg::OnInitDialog()
|
||||
// 屏幕质量子菜单
|
||||
CMenu qualityMenu;
|
||||
if (qualityMenu.CreatePopupMenu()) {
|
||||
qualityMenu.AppendMenuL(MF_STRING, IDM_QUALITY_OFF, "关闭(&O)");
|
||||
qualityMenu.AppendMenuL(MF_STRING, IDM_ADAPTIVE_QUALITY, "自适应(&A)");
|
||||
qualityMenu.AppendMenuSeparator(MF_SEPARATOR);
|
||||
qualityMenu.AppendMenuL(MF_STRING, IDM_QUALITY_ULTRA, "Ultra (30FPS, DIFF)");
|
||||
qualityMenu.AppendMenuL(MF_STRING, IDM_QUALITY_ULTRA, "Ultra (25FPS, DIFF)");
|
||||
qualityMenu.AppendMenuL(MF_STRING, IDM_QUALITY_HIGH, "High (20FPS, RGB565)");
|
||||
qualityMenu.AppendMenuL(MF_STRING, IDM_QUALITY_MEDIUM, "Medium (15FPS, RGB565)");
|
||||
qualityMenu.AppendMenuL(MF_STRING, IDM_QUALITY_LOW, "Low (10FPS, RGB565)");
|
||||
qualityMenu.AppendMenuL(MF_STRING, IDM_QUALITY_MINIMAL, "Minimal (5FPS, GRAY)");
|
||||
qualityMenu.AppendMenuL(MF_STRING, IDM_QUALITY_GOOD, "Good (20FPS, H264)");
|
||||
qualityMenu.AppendMenuL(MF_STRING, IDM_QUALITY_MEDIUM, "Medium (15FPS, H264)");
|
||||
qualityMenu.AppendMenuL(MF_STRING, IDM_QUALITY_LOW, "Low (12FPS, H264)");
|
||||
qualityMenu.AppendMenuL(MF_STRING, IDM_QUALITY_MINIMAL, "Minimal (8FPS, H264)");
|
||||
SysMenu->AppendMenuL(MF_STRING | MF_POPUP, (UINT_PTR)qualityMenu.Detach(), _T("屏幕质量(&Q)"));
|
||||
}
|
||||
// 初始化勾选状态
|
||||
@@ -427,17 +438,30 @@ BOOL CScreenSpyDlg::OnInitDialog()
|
||||
// 启动传输速率更新定时器 (1秒)
|
||||
SetTimer(4, 1000, NULL);
|
||||
|
||||
// 如果非自适应模式,发送保存的质量等级给客户端应用
|
||||
if (!m_AdaptiveQuality.enabled) {
|
||||
// 下发质量配置表(让客户端可以持久化保存)
|
||||
{
|
||||
BYTE profileCmd[1 + sizeof(QualityProfile) * QUALITY_COUNT];
|
||||
profileCmd[0] = CMD_QUALITY_PROFILES;
|
||||
for (int i = 0; i < QUALITY_COUNT; i++) {
|
||||
memcpy(profileCmd + 1 + i * sizeof(QualityProfile),
|
||||
&GetQualityProfile(i), sizeof(QualityProfile));
|
||||
}
|
||||
m_ContextObject->Send2Client(profileCmd, sizeof(profileCmd));
|
||||
}
|
||||
|
||||
// 发送初始质量配置给客户端
|
||||
if (m_Settings.QualityLevel == QUALITY_DISABLED) {
|
||||
// 关闭模式:不发送任何质量命令,保持客户端原有设置
|
||||
} else {
|
||||
// 自适应或固定等级模式:发送质量等级和分辨率
|
||||
BYTE cmd[4] = { CMD_QUALITY_LEVEL, (BYTE)m_AdaptiveQuality.currentLevel, 0 };
|
||||
m_ContextObject->Send2Client(cmd, sizeof(cmd));
|
||||
|
||||
// 如果有分辨率限制,也发送
|
||||
if (m_AdaptiveQuality.currentMaxWidth > 0) {
|
||||
BYTE sizeCmd[16] = { CMD_SCREEN_SIZE, 2 }; // strategy=2 表示自定义maxWidth
|
||||
memcpy(sizeCmd + 2, &m_AdaptiveQuality.currentMaxWidth, sizeof(int));
|
||||
m_ContextObject->Send2Client(sizeCmd, 10);
|
||||
}
|
||||
// 始终发送 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);
|
||||
}
|
||||
|
||||
SendNext();
|
||||
@@ -1102,23 +1126,34 @@ void CScreenSpyDlg::OnSysCommand(UINT nID, LPARAM lParam)
|
||||
break;
|
||||
}
|
||||
|
||||
case IDM_QUALITY_OFF: { // 关闭质量控制
|
||||
m_AdaptiveQuality.enabled = false;
|
||||
m_Settings.QualityLevel = QUALITY_DISABLED;
|
||||
UpdateQualityMenuCheck(SysMenu);
|
||||
// 发送给客户端保存 (QualityLevel=-2 表示关闭)
|
||||
BYTE cmd[4] = { CMD_QUALITY_LEVEL, (BYTE)QUALITY_DISABLED, 1 }; // persist=1
|
||||
m_ContextObject->Send2Client(cmd, sizeof(cmd));
|
||||
UpdateWindowTitle();
|
||||
Mprintf("关闭质量控制,使用原有算法设置\n");
|
||||
break;
|
||||
}
|
||||
|
||||
case IDM_ADAPTIVE_QUALITY: { // 自适应质量开关
|
||||
m_AdaptiveQuality.enabled = !m_AdaptiveQuality.enabled;
|
||||
m_AdaptiveQuality.enabled = true;
|
||||
m_Settings.QualityLevel = QUALITY_ADAPTIVE;
|
||||
UpdateQualityMenuCheck(SysMenu);
|
||||
// 发送给客户端保存 (QualityLevel=-1 表示自适应)
|
||||
int8_t level = m_AdaptiveQuality.enabled ? QUALITY_ADAPTIVE : m_AdaptiveQuality.currentLevel;
|
||||
BYTE cmd[4] = { CMD_QUALITY_LEVEL, (BYTE)level, 1 }; // persist=1
|
||||
BYTE cmd[4] = { CMD_QUALITY_LEVEL, (BYTE)QUALITY_ADAPTIVE, 1 }; // persist=1
|
||||
m_ContextObject->Send2Client(cmd, sizeof(cmd));
|
||||
if (m_AdaptiveQuality.enabled) {
|
||||
// 启用时立即评估一次
|
||||
EvaluateQuality();
|
||||
}
|
||||
// 启用时立即评估一次
|
||||
EvaluateQuality();
|
||||
UpdateWindowTitle();
|
||||
break;
|
||||
}
|
||||
|
||||
case IDM_QUALITY_ULTRA:
|
||||
case IDM_QUALITY_HIGH:
|
||||
case IDM_QUALITY_GOOD:
|
||||
case IDM_QUALITY_MEDIUM:
|
||||
case IDM_QUALITY_LOW:
|
||||
case IDM_QUALITY_MINIMAL: {
|
||||
@@ -1126,6 +1161,7 @@ void CScreenSpyDlg::OnSysCommand(UINT nID, LPARAM lParam)
|
||||
int level = nID - IDM_QUALITY_ULTRA;
|
||||
// 关闭自适应模式
|
||||
m_AdaptiveQuality.enabled = false;
|
||||
m_Settings.QualityLevel = level;
|
||||
// 应用选择的等级 (persist=true 保存到客户端)
|
||||
ApplyQualityLevel(level, true);
|
||||
UpdateQualityMenuCheck(SysMenu);
|
||||
@@ -1228,16 +1264,19 @@ void CScreenSpyDlg::UpdateWindowTitle()
|
||||
|
||||
int width = m_BitmapInfor_Full->bmiHeader.biWidth;
|
||||
int height = m_BitmapInfor_Full->bmiHeader.biHeight;
|
||||
const char* qualityName = GetQualityName(m_AdaptiveQuality.currentLevel);
|
||||
|
||||
// 构建质量名称:关闭显示 "Off",自适应和手动都会显示 "当前等级"
|
||||
CString qualityName = m_Settings.QualityLevel == QUALITY_DISABLED ? "" :
|
||||
CString(" | ") + GetQualityName(m_AdaptiveQuality.currentLevel);
|
||||
|
||||
CString strTitle;
|
||||
UINT fps = (UINT)(m_dFrameRate + 0.5); // 四舍五入显示
|
||||
if (m_dTransferRate >= 1024) {
|
||||
strTitle.FormatL("%s - 远程桌面控制 %d×%d | %u FPS | %.1f MB/s | %s",
|
||||
m_IPAddress, width, height, fps, m_dTransferRate / 1024, qualityName);
|
||||
strTitle.FormatL("%s - 远程桌面控制 %d×%d | %u FPS | %.1f MB/s%s",
|
||||
m_IPAddress, width, height, fps, m_dTransferRate / 1024, qualityName.GetString());
|
||||
} else {
|
||||
strTitle.FormatL("%s - 远程桌面控制 %d×%d | %u FPS | %.0f KB/s | %s",
|
||||
m_IPAddress, width, height, fps, m_dTransferRate, qualityName);
|
||||
strTitle.FormatL("%s - 远程桌面控制 %d×%d | %u FPS | %.0f KB/s%s",
|
||||
m_IPAddress, width, height, fps, m_dTransferRate, qualityName.GetString());
|
||||
}
|
||||
SetWindowText(strTitle);
|
||||
}
|
||||
@@ -1245,8 +1284,12 @@ void CScreenSpyDlg::UpdateWindowTitle()
|
||||
const char* CScreenSpyDlg::GetQualityName(int level)
|
||||
{
|
||||
static const char* names[] = {
|
||||
"Ultra", "High", "Medium", "Low", "Minimal"
|
||||
"Ultra", "High", "Good", "Medium", "Low", "Minimal"
|
||||
};
|
||||
if (level == QUALITY_DISABLED)
|
||||
return "Off";
|
||||
if (level == QUALITY_ADAPTIVE)
|
||||
return "Auto";
|
||||
if (level >= 0 && level < QUALITY_COUNT)
|
||||
return names[level];
|
||||
return "Unknown";
|
||||
@@ -1256,16 +1299,20 @@ void CScreenSpyDlg::UpdateQualityMenuCheck(CMenu* SysMenu)
|
||||
{
|
||||
if (!SysMenu) SysMenu = GetSystemMenu(FALSE);
|
||||
// 先全部取消勾选
|
||||
SysMenu->CheckMenuItem(IDM_QUALITY_OFF, MF_UNCHECKED);
|
||||
SysMenu->CheckMenuItem(IDM_ADAPTIVE_QUALITY, MF_UNCHECKED);
|
||||
SysMenu->CheckMenuItem(IDM_QUALITY_ULTRA, MF_UNCHECKED);
|
||||
SysMenu->CheckMenuItem(IDM_QUALITY_HIGH, MF_UNCHECKED);
|
||||
SysMenu->CheckMenuItem(IDM_QUALITY_GOOD, MF_UNCHECKED);
|
||||
SysMenu->CheckMenuItem(IDM_QUALITY_MEDIUM, MF_UNCHECKED);
|
||||
SysMenu->CheckMenuItem(IDM_QUALITY_LOW, MF_UNCHECKED);
|
||||
SysMenu->CheckMenuItem(IDM_QUALITY_MINIMAL, MF_UNCHECKED);
|
||||
// 勾选当前项
|
||||
if (m_AdaptiveQuality.enabled) {
|
||||
if (m_Settings.QualityLevel == QUALITY_DISABLED) {
|
||||
SysMenu->CheckMenuItem(IDM_QUALITY_OFF, MF_CHECKED);
|
||||
} else if (m_AdaptiveQuality.enabled) {
|
||||
SysMenu->CheckMenuItem(IDM_ADAPTIVE_QUALITY, MF_CHECKED);
|
||||
} else {
|
||||
} else if (m_AdaptiveQuality.currentLevel >= 0 && m_AdaptiveQuality.currentLevel < QUALITY_COUNT) {
|
||||
SysMenu->CheckMenuItem(IDM_QUALITY_ULTRA + m_AdaptiveQuality.currentLevel, MF_CHECKED);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -915,8 +915,8 @@ NtCreateThreadEx(shellcodeע
|
||||
%s - <20><><EFBFBD>̼<EFBFBD>¼=%s - Keylogger
|
||||
%s - ע<><D7A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>=%s - Registry Manager
|
||||
%s - Զ<><D4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> %d<><64>%d=%s - Remote Desktop %d<><64>%d
|
||||
%s - Զ<><D4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> %d<><64>%d | %u FPS | %.1f MB/s | %s=%s - Remote Desktop %d<><64>%d | %u FPS | %.1f MB/s | %s
|
||||
%s - Զ<><D4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> %d<><64>%d | %u FPS | %.0f KB/s | %s=%s - Remote Desktop %d<><64>%d | %u FPS | %.1f KB/s | %s
|
||||
%s - Զ<><D4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> %d<><64>%d | %u FPS | %.1f MB/s%s=%s - Remote Desktop %d<><64>%d | %u FPS | %.1f MB/s%s
|
||||
%s - Զ<><D4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> %d<><64>%d | %u FPS | %.0f KB/s%s=%s - Remote Desktop %d<><64>%d | %u FPS | %.0f KB/s%s
|
||||
%s - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>=%s - Proxy Service
|
||||
%s - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>=%s - Service Manager
|
||||
%s - Զ<><D4B6><EFBFBD>ն<EFBFBD>=%s - Terminal
|
||||
@@ -1212,3 +1212,5 @@ PE
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѶϿ<EFBFBD>=Connection lost
|
||||
- Զ<><D4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѶϿ<D1B6>= - Remote desktop disconnected
|
||||
λͼ<EFBFBD>ļ<EFBFBD>(*.bmp)|*.bmp|=Bitmap Files(*.bmp)|*.bmp|
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>SSE2ָ<EFBFBD>(&5)=Enable Client SSE2(&5)
|
||||
<EFBFBD>ر<EFBFBD>(&O)=Disbale(&O)
|
||||
|
||||
@@ -912,8 +912,8 @@ NtCreateThreadEx(shellcodeע
|
||||
%s - <20><><EFBFBD>̼<EFBFBD>¼=%s - <20>I<EFBFBD>Pӛ<50><D39B>
|
||||
%s - ע<><D7A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>=%s - <20><>䛾<EFBFBD><EFBFBD><DD8B>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD>
|
||||
%s - Զ<><D4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> %d<><64>%d=%s - <20>h<EFBFBD><68><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> %d<><64>%d
|
||||
%s - Զ<><D4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> %d<><64>%d | %u FPS | %.1f MB/s | %s=%s - <20>h<EFBFBD><68><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> %d<><64>%d | %u FPS | %.1f MB/s | %s
|
||||
%s - Զ<><D4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> %d<><64>%d | %u FPS | %.0f KB/s | %s=%s - <20>h<EFBFBD><68><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> %d<><64>%d | %u FPS | %.1f KB/s | %s
|
||||
%s - Զ<><D4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> %d<><64>%d | %u FPS | %.1f MB/s%s=%s - <20>h<EFBFBD><68><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> %d<><64>%d | %u FPS | %.1f MB/s%s
|
||||
%s - Զ<><D4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> %d<><64>%d | %u FPS | %.0f KB/s%s=%s - <20>h<EFBFBD><68><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> %d<><64>%d | %u FPS | %.0f KB/s%s
|
||||
%s - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>=%s - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
%s - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>=%s - <20><><EFBFBD>չ<EFBFBD><D5B9><EFBFBD>
|
||||
%s - Զ<><D4B6><EFBFBD>ն<EFBFBD>=%s - <20>h<EFBFBD>˽K<CBBD>˙C
|
||||
@@ -1209,3 +1209,5 @@ PE
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѶϿ<EFBFBD>=<EFBFBD>B<EFBFBD><EFBFBD><EFBFBD>є<EFBFBD><EFBFBD>_
|
||||
- Զ<><D4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѶϿ<D1B6>= - <20>h<EFBFBD><68><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>B<EFBFBD><42><EFBFBD>є<EFBFBD><D194>_
|
||||
λͼ<EFBFBD>ļ<EFBFBD>(*.bmp)|*.bmp|=<EFBFBD>cꇈD<EFBFBD>n(*.bmp)|*.bmp|
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>SSE2ָ<EFBFBD>(&5)=<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ñ<EFBFBD><EFBFBD><EFBFBD> SSE2(&5)
|
||||
<EFBFBD>ر<EFBFBD>(&O)=<EFBFBD>P<EFBFBD>](&O)
|
||||
|
||||
Reference in New Issue
Block a user