diff --git a/client/ScreenCapture.h b/client/ScreenCapture.h index ffa4da2..4ec2471 100644 --- a/client/ScreenCapture.h +++ b/client/ScreenCapture.h @@ -970,6 +970,16 @@ public: int width = m_BitmapInfor_Send->bmiHeader.biWidth, height = m_BitmapInfor_Send->bmiHeader.biHeight; ensureEncoder(width, height); if (!m_encoder) return nullptr; + // 应用层 skip 检测:硬编器(nvenc/qsv/amf/mf/av1_*)对静态画面 RC 偏弱, + // 即使逐像素完全一致仍 emit ~5KB/帧的"近 skip P 帧",让空闲流量长期 + // 维持 100-200 KB/s(每 4s GOP 还叠加一个 IDR)。整帧 memcmp BGRA + // 找出真无变化帧直接跳过 encode,仅发 cursor;x264 走这里也省 CPU 无副作用。 + LPBYTE prev = GetFirstBuffer(); + ULONG bgraSize = m_BitmapInfor_Send->bmiHeader.biSizeImage; + if (prev && memcmp(nextData, prev, bgraSize) == 0) { + *ulNextSendLength = 1 + offset; // 仅 cursor,无视频负载 + return m_RectBuffer; + } int err = m_encoder->encode(nextData, 32, 4 * width, width, height, &encoded_data, &encoded_size); // encoded_size == 0:硬编首帧延迟,本帧无码流,按失败跳过 if (err || encoded_size == 0) { @@ -977,6 +987,9 @@ public: } *ulNextSendLength = 1 + offset + encoded_size; memcpy(data + offset, encoded_data, encoded_size); + // 更新参考帧供下一帧 memcmp。必须在 encode 成功之后更新,否则编码 + // 失败时下一帧会误以为"已发"而漏发真实变化。 + memcpy(prev, nextData, bgraSize); break; } default: