郑博文
|
78ac9d9972
|
feat(agent): 相对鼠标注入(读光标+增量+clamp 绝对注入)+ 显式 DPI 感知
注入实现刻意**不用** SendInput(MOUSEEVENTF_MOVE):实测该路径的 dx 不是
像素而是 mickey,会被「指针加速」与「DPI 缩放」双重放大——本机 dx=1 走 0px、
dx=20 走 41px、dx=100 走 309px,且倍率随用户系统设置与机器变化,无法标定。
改为「GetCursorPos + 增量 + clamp + 绝对注入」,实测 1:1 精确(±1/2/3/5/17/100
四次重复全部等于请求值),撞边后回滑立即响应、不积步数债。
同时显式设 PER_MONITOR_AWARE_V2:实测本机 agent.exe 虽是 per-monitor,
但那是注册表 AppCompatFlags\\Layers 里一条**路径绑定**的 HIGHDPIAWARE 覆盖
造成的(同一 exe 复制到 %TEMP% 启动即变 UNAWARE),换机器/换构建路径即失效。
UNAWARE 时 GetCursorPos 返回逻辑坐标(1536x864)而采集是物理像素(1920x1080),
clamp 上界与增量尺度都会错。设置失败时区分「已被外部设定」与「真正降级」并分别报日志。
|
2026-10-31 17:34:54 +08:00 |
|
郑博文
|
44767ed370
|
feat(android-ffi): viewer-core 的 JNI 薄层,arm64 交叉编译通过(QUIC 栈上手机的第一道关)
方案变更说明(A2 落地修正):原裁决选 UniFFI,但实查 Maven Central 与
maven.mozilla.org 均无 uniffi Kotlin 运行时构件(404),自编译发布成本超过收益。
改为裸 JNI:阶段 0(真机)已验证该链路,接口刻意保持窄(连接/取帧/发输入/销毁),
将来若引入 UniFFI 只替换本层。
线程与锁纪律(决定接口形态):
- nativeNextFrame 等帧期间不持会话锁(clone Arc<Session> 后即释放),
桌面静止 500ms 帧间隔不会卡住 UI 线程的输入调用
- destroy 前必须先停解码线程,Kotlin 侧顺序纪律保证(已登记风险清单)
- 句柄 = Box 裸指针(永不为 0),destroy 后置 0
帧返回约定:byte[] = [keyframe 标志 1][seq 8][ts 8][w 4][h 4][Annex-B payload],
定长 25 字节头,Kotlin 切片零 JNI 往返。
viewer-core 适配:Session.frames 改 Arc<tokio Mutex>,next_frame 取 &self,
使解码线程与输入线程可并发借用同一 Session。
验证:
- 桌面 cargo build -p android-ffi 零警告
- cargo ndk -t arm64-v8a --release:quinn/ring/rustls 交叉编译全部通过
(消除阶段 1 最大未知:QUIC 栈能否编到 Android)
- libandroidffi.so 4.2MB,10 个 Java_com_verify_remote_RustBridge_* 符号导出正确
|
2026-10-29 18:27:34 +08:00 |
|
郑博文
|
34df7b070b
|
feat(viewer-core): 新增安卓主控的连接/协议/收帧层(阶段 1 桌面验证通过)
定位(2026-10-29 方案裁决 A1-A4):
纯 Rust、平台无关,只做「怎么连 + 收发什么」——QUIC 会话、协议 v2 认证、
视频帧流、输入上行、Ping/Pong、KeyFrameReq。解码/渲染/触摸全在 Kotlin 侧,
本 crate 不碰像素、不依赖 openh264(dev-dependency 仅验证工具用)。
设计要点
- PeerTarget::Direct 是唯一的连接形态;不做中继、不定义 Relay 变体
(《多平台架构设计》§6.1 裁决)。将来设备码+打洞只换 connect() 内部。
- 帧经容量 2 的 mpsc 交付,**不丢帧**:跳帧决策属于看得到解码器状态的消费方
(Kotlin),Rust 层丢帧会重演 R-3 教训(跳帧断参考链)。
- insecure_skip_verify=false 时明确报错而非静默放行——证书钉扎登记在方案
阶段 4,安全红线不允许默默降级。
- 双流结构与桌面 viewer 一致(流1 认证+视频,流2 输入+控制),入会即请求 IDR。
验证(headless,桌面→桌面 127.0.0.1)
- 单测 3 passed(帧契约、默认配置、strict-verify 显式报错)
- examples/headless_check:300 帧,seq 违例 0、keyframe 标志不符 0、
解码成功 300/300、RTT 路径工作(RTT=1ms 出现)
- 全 workspace 回归:common 20 passed,构建全绿
|
2026-10-29 18:14:27 +08:00 |
|
郑博文
|
e814cb64e7
|
fix(agent): vendor nvenc 并补 FORCEIDR 标志——修复运行期关键帧请求被静默忽略
根因(实测确认,非推测)
上游 nvenc 0.1.0 的 encode_picture 只设置 picture_type=NV_ENC_PIC_TYPE_IDR,
却从未设置 encode_pic_flags=NV_ENC_PIC_FLAG_FORCEIDR。NVENC 会据此忽略请求、
继续输出 P 帧。首帧之所以「看起来正常」,是因为 frame_idx==0 本来就强制 IDR,
与该字段无关——这也是该缺陷长期未被发现的原因。
证据(同一 frame_count=4,修复前后)
- 修复前:输出 NAL 首字节 0x61 → 0x61 & 0x1F = 1 = 普通 P 片
- 修复后:输出 NAL 首字节 0x65 → 0x65 & 0x1F = 5 = IDR 片
影响
这解释了构建运行手册 §6.1 记录的「静止桌面黑屏」:NVENC 路径的重编 IDR 从未
真正生效,KeyFrameReq 拿不到 IDR 就无法从解码错误中恢复。
改动
- 新增 vendor/nvenc(上游为 MIT 许可,可自由修改分发,符合商用要求)
- vendor/nvenc/src/safe/encoder.rs:picture_type=IDR 时置 ForceIDR;
IntraRefresh 时置 ForceIntra。改动处有「本项目补丁」注释标记
- agent/Cargo.toml:nvenc 改为 path 依赖指向 vendor 版本
建议后续向上游提 PR(github.com/AlsoSylv/nvenc),以降低长期维护成本。
验证:跳帧后发 KeyFrameReq,第 3 帧即收到 IDR 并解码成功
|
2026-10-28 16:05:41 +08:00 |
|
yu
|
9c340813a8
|
feat(agent): 新增 agent-core 与 Linux 被控端(X11 + XTest,纯新增不动 agent/)
本期只在新增文件里做,**未改动 Windows agent/ 一个字节**(与 NVENC 线并行,避免争抢)。
- 新增 agent-core:平台无关会话层 —— QUIC/TLS 握手、传输调优(沿用 512KB 发送窗口
结论)、验证码认证、会话/select 循环、latest-wins 单槽、输入分发,以及软件编码
视频管线(openh264)。同步跟进协议新增的 Pong{lost,sent} 下行丢包统计字段
- 新增 linux-agent:X11 GetImage 采集 + 整帧变更检测;XTest 注入 + 扫描码→X11
keycode 映射(主键区 = scancode+8,E0 扩展键必须查表,含单元测试)
- 协议零改动:复用 Set-1 扫描码与虚拟桌面归一化坐标,viewer 无需任何修改
- 新增端到端冒烟测试 tests/smoke.rs 与 scripts/linux-smoke.sh(自建 Xvfb,无需
图形桌面):采集→编码→QUIC 解帧、认证(含错误码拒绝)、Ping/Pong(含丢包字段)、
静止桌面关键帧恢复、输入注入实证(注入后从另一条 X11 连接读回指针真实坐标)
- 该关键帧用例做过变异测试:把修复退回会失败、恢复后通过,确认断言有效
- .gitattributes:shell 脚本强制 LF(Windows checkout 成 CRLF 会导致容器内无法执行)
- 手册:修正已失效的工具链路径;补充 cargo 镜像;新增第 8 节(Linux)与 6.1 节
(三条待修问题,含两条 Windows 侧仍存在的关键帧缺陷)
验证:
- Linux(容器, USTC 源 + Xvfb): cargo test -p linux-agent 通过,2 passed
- Windows: 本期未改 agent/,default-members 未变,`cargo build --release` 行为不变
|
2026-10-23 13:31:08 +08:00 |
|
dev-team
|
ddbb53d41a
|
feat(agent): NVENC 硬编接入(GPU 零拷贝 ARGB 直通,软编自动兜底)
- 编码器自动选择:NVENC(H264 High/CBR 5Mbps/UltraLowLatency/无B帧/按需IDR)→ openh264 兜底
- Duplication 增加 GPU 中间纹理(B8G8R8A8 DEFAULT),NVENC register_resource_dx11 直读,颜色转换完全省略
- KeyFrameReq → encode_picture(picture_type=IDR),静止 500ms 重编码 P 帧
- windows 0.58→0.62(nvenc crate 依赖 0.62,运行时 dlopen nvEncodeAPI64.dll 零 SDK 依赖)
- 实测(GTX 1650 Ti 回环):encode 41ms→4ms/帧(10x),convert 0ms,viewer 解码正常
|
2026-10-23 10:18:29 +08:00 |
|
dev-team
|
61e8a75cdd
|
init: MVP remote desktop (agent/viewer/common) with H.264 pipeline
|
2026-10-23 09:17:55 +08:00 |
|