功能:完善2K串流、显示恢复与输入优化

This commit is contained in:
宋一鸣 2026-11-03 13:43:50 +08:00
parent e47b01beec
commit 938ec97cce
95 changed files with 5788 additions and 72 deletions

2
.gitattributes vendored Normal file
View File

@ -0,0 +1,2 @@
# Patches are applied to LF sources on the Linux terminal.
terminal/moonlight/patches/*.patch text eol=lf

View File

@ -2,7 +2,42 @@
完整对话总结在:`D:\DAIMA\vdi-cloud\PROJECT_CONTEXT.md` 完整对话总结在:`D:\DAIMA\vdi-cloud\PROJECT_CONTEXT.md`
## 2026-11-03 显示器关开修复(优先于下文旧状态)
- 关屏再开后画面变矮:盒子回退1920x1440@75(4:3),Moonlight 16:9视频上下黑边;
MATE monitors.xml仍存旧4:3布局,原启动脚本只设置一次2K。
- 已部署vdi-display-guard用户服务(active/enabled)和幂等启动恢复,保留297MHz定制2K时序;
2秒检查、异常稳定2秒后恢复;断开不强设、失败退避、命令超时、单实例锁,正常不反复切换。
修正当前GWR/0x2708显示器旧保存布局。仅部署tools/deploy_display_guard.sh,不重启串流。
- 9个场景测试通过,CTest 3/3;两次主动回退均约14秒恢复,Moonlight PID66385和boot ID不变。
用户真实关屏再开确认自动全屏;10:03:19断开、10:03:31正确2K模式,10:04现场2560x1440。
- 备份~/vdi-terminal/backups/display-guard-20261103-095920/;详情/回退见
docs/display-resume-fix-20261103.md。此修复仅限当前Xorg单HDMI 2K POC,未做隔夜老化。
## 2026-11-03 鼠标/点击跳转优化(优先于下文旧状态)
- Moonlight私有客户端新增两个补丁:鼠标合并不跨点击/键盘/窗口边界,绝对鼠标按钮封住前一位置批次;
低延迟非pacing队列可丢弃等待帧保留最新帧,wrapper默认VDI_LATEST_FRAME=1。保持单白色Windows光标。
- 现场32次交替点击:旧客户端30/32正确(第1、13错位),补丁32/32正确;native输入测试1000轮和ASAN通过。
配对串流补丁队列2.14ms/呈现6.12ms,原3.39ms/6.84ms;帧率约28.4/28.1,受网络/软件编码波动,不能称零延迟。
- Windows保留DragFullWindows=1、MouseTrails=0;已在test交互会话将MinAnimate从1改0、菜单400改100ms,读回通过,
原值备份在test的LocalAppData/VDI;临时执行/测试任务已清理。
- 用户确认蓝框在盒子登录/选择页:QFrame:hover错误匹配QLabel。移除蓝色悬停框和登录焦点蓝框,限定卡片对象样式,
局部编译CTest3/3,部署新版kiosk;悬停截图亮蓝像素8302→0。UI/wrapper备份input-rendering-20261103-114542。
详情见docs/input-rendering-optimization-20261103.md和terminal/moonlight/README.md。
## 2026-11-02 最新实测(优先于下文旧状态) ## 2026-11-02 最新实测(优先于下文旧状态)
- 2026-11-02晚:已在用户目录完成MPP+FFmpeg-Rockchip+Moonlight6.2.0私有构建,
实际2K串流选中h264_rkmpp/drm_prime与EGL/GLES呈现,非仅FFmpeg样本测试。
2K20 smooth会话平均呈现18.97FPS、解码10.53ms、呈现2.54ms;2K30 low-latency
呈现23.46FPS、解码9.11ms、队列2.39ms、呈现5.41ms。服务端仍Code43/libx264。
2K30 smooth队列31.95ms,VSync开/帧步调关也有28.93ms,故该盒子选低延迟档。
原始日志和限制见 `docs/rendering-execution-20261102.md`。
通过 `~/.config/vdi-terminal/render.conf` 显式选择私有wrapper+hardware,系统客户端不覆盖;
Windows桌面票据改30FPS,原20FPS文件备份为desktops.before-rkmpp-20261102.json。
构建脚本 `tools/build-rkmpp-client.sh` 修Qt5 optional、EGL探测缓存与旧对象不重编;
kiosk就绪判断兼容RKMPP独立测试解码器日志,CTest 2/2通过。
鼠标MouseTrails=0、DragFullWindows=1;现场仍有VDIApplyTransparentCursor刷新参数任务,
先前“任务已删除”的记录不准确,本轮未改变光标配置;截图单白光标正常。
不能把23FPS、硬解接通解释为GPU已恢复、2K60或端到端零延迟。
- 已部署真实2K:盒子HDMI 2560x1440约60Hz、Windows VDD 2560x1440@30、Moonlight 2560x1440@20/30Mbps。 - 已部署真实2K:盒子HDMI 2560x1440约60Hz、Windows VDD 2560x1440@30、Moonlight 2560x1440@20/30Mbps。
- RK3528旧PHY拒绝EDID的241.70MHz,实测用297MHz固定时钟和扩展消隐成功: - RK3528旧PHY拒绝EDID的241.70MHz,实测用297MHz固定时钟和扩展消隐成功:
`297.00 2560 2608 2640 2720 1440 1443 1448 1820 +HSync -VSync`;盒子重启已验证,link Good。 `297.00 2560 2608 2640 2720 1440 1443 1448 1820 +HSync -VSync`;盒子重启已验证,link Good。

View File

@ -258,11 +258,8 @@ Qt QImage/QLabel 显示
重要:当前 POC 已成功显示 Windows 10 的真实远程桌面画面,颜色正确,进程保持运行。这是目前最重要的实测成果。 重要:当前 POC 已成功显示 Windows 10 的真实远程桌面画面,颜色正确,进程保持运行。这是目前最重要的实测成果。
详细说明在: 这部分属于早期 FreeRDP POC 历史记录;对应的临时笔记文件已从仓库移除。
当前终端会话实现和维护说明以 `terminal/kiosk-shell/` 及其 README 为准。
```text
D:\DAIMA\vdi-cloud\docs\freerdp3-embedding-notes.md
```
### 6.5 显示问题 ### 6.5 显示问题
@ -276,12 +273,15 @@ D:\DAIMA\vdi-cloud\docs\freerdp3-embedding-notes.md
注意:此前对“X11 无 glamor 硬件合成”的判断不准确,Xorg 日志实际显示 `glamor X acceleration enabled on Mali450`;后续不要继续引用这个错误结论。正确表述是:当前路径仍未达到目标流畅度,具体瓶颈需要后续基准测试确认。 注意:此前对“X11 无 glamor 硬件合成”的判断不准确,Xorg 日志实际显示 `glamor X acceleration enabled on Mali450`;后续不要继续引用这个错误结论。正确表述是:当前路径仍未达到目标流畅度,具体瓶颈需要后续基准测试确认。
### 6.6 Moonlight 云桌面开机直达(2026-10-28) ### 6.6 Moonlight 云桌面开机直达(2026-10-28,历史记录)
本节保留当时的联调过程和取舍。2026-11-03 的实际部署状态、显示恢复、输入补丁及
渲染参数以后续 `MEMORY.md` 和对应日期的 `docs/` 记录为准。
RDP/Moonlight 实测对比见 `docs/rdp-vs-moonlight-comparison-20261028.md`, RDP/Moonlight 实测对比见 `docs/rdp-vs-moonlight-comparison-20261028.md`,
落地记录见 `docs/moonlight-kiosk-20261028.md`。 落地记录见 `docs/moonlight-kiosk-20261028.md`。
盒子当前开机默认走 Moonlight 直连云桌面,链路: 当时盒子开机默认走 Moonlight 直连云桌面,链路如下:
```text ```text
~/.config/autostart/vdi-moonlight.desktop ~/.config/autostart/vdi-moonlight.desktop

View File

@ -44,7 +44,7 @@ vdi-cloud/
├─ platform/ # Go 云端服务 ├─ platform/ # Go 云端服务
├─ console/ # Vue 3 + TypeScript Web 管理控制台 ├─ console/ # Vue 3 + TypeScript Web 管理控制台
├─ deploy/ # Docker Compose、Helm、离线部署包 ├─ deploy/ # Docker Compose、Helm、离线部署包
├─ docs/ # OpenAPI、MQTT、数据库等正式协议文档 ├─ docs/ # 方案文档、实施记录、测试证据和运维资料
└─ tools/ # 烧录、构建、压测和 CI 工具 └─ tools/ # 烧录、构建、压测和 CI 工具
``` ```

View File

@ -1 +0,0 @@
# Keep the monorepo directory structure in Git.

View File

@ -0,0 +1,70 @@
# 2026-11-03 显示器关屏再开后云桌面变矮:修复与验收
已在 `armbian@192.168.1.188` 部署。用户现场关闭显示器、等待后重新打开,确认“已自动恢复全屏”。修复过程没有重启盒子,也没有重启或重连 Moonlight。
## 原因与证据
- 异常时盒子 HDMI 输出为 **1920×1440@75Hz(4:3)**,Windows/Moonlight 视频为 **2560×1440(16:9)**。
- Moonlight 全屏窗口跟随盒子变为 1920×1440,视频保持宽高比,因此视频内容为 1920×1080,上下各有约 180 像素黑边,表现为“宽度一样,高度矮了一点”。异常截图见 `evidence/display-resume-20261103/before.png`。
- MATE 的 `~/.config/monitors.xml` 还保存着 HDMI-1 的 1920×1440@75Hz 配置;原启动脚本只在启动时设置一次 2K,没有处理后续热插拔和模式回退。
- 显示器 EDID 的 241.70MHz 时序仍不适用于此 RK3528 vendor PHY;沿用此前已验证的 297MHz 定制 2K 时序,不切回该原厂时序。
## 修改
1. 新增 `terminal/kiosk-shell/scripts/vdi-display-guard`:每 2 秒检查 XRandR 状态,模式异常持续至少 2 秒后恢复 `2560x1440_60_fixed297`。模式已存在时不重复创建,热插拔后丢失关联时重新关联。
2. 健康状态只查询,不反复设置分辨率;显示器断开或 X11 尚不可用时等待,不强设;设置失败按 2/4/8/16/32/60 秒退避,并在设置后重新读取验证。XRandR 每条命令有 10 秒超时。
3. 新增用户级 `vdi-display-guard.service`,已启用 `default.target` 自启、异常退出重启;使用文件锁防止启动恢复与常驻守护竞争。服务独立受 systemd 管理,不挂无主后台循环。
4. `vdi-kiosk-start` 使用相同恢复程序做启动检查,再确保服务运行;保留此前渲染配置解析及单一 kiosk 启动链。
5. 将本机已知显示器(HDMI-1,GWR/0x2708)的旧保存布局改为 2560×1440@60,其余布局不改。部署前保存原文件。
6. 新增只部署显示修复的 `tools/deploy_display_guard.sh`;完整 `deploy_kiosk.sh` 也接入该步骤,避免下次部署覆盖修复。此次只执行前者,未执行会停止串流的完整部署。
时序仍为:
```text
297.00 2560 2608 2640 2720 1440 1443 1448 1820 +HSync -VSync
```
本次仅调整盒子本地显示,不修改 Windows、Sunshine、GPU、远程光标或已有硬解参数。
## 验收
| 项目 | 结果 |
| --- | --- |
| 自动化显示恢复场景 | 9/9 通过:正常不写、断开/重连、首次创建、重新关联、晚到覆盖、失败退避、设置结果校验、X11 暂不可用等 |
| 盒子 CTest | 3/3 通过:display-guard、moonlight-session、desktop-list-page |
| 连续两次主动回退 1920×1440@75 | 均自动恢复 2560×1440,全屏窗口恢复 2560×1440,单次从发起切换到观测恢复约 14 秒(含两次驱动切换耗时) |
| 真实显示器电源循环 | 用户确认自动恢复全屏;日志在 10:03:19 检测断开,10:03:31 检测到正确 2K 模式,无需额外模式设置 |
| 会话连续性 | Moonlight PID 始终为 66385,窗口始终为 44040203;模拟测试前后 boot ID 不变;服务未发生异常重启 |
| 最终现场 | 2026-11-03 10:04,HDMI 2560×1440 约 60Hz,Moonlight 窗口 2560×1440,守护 active/enabled |
原始测试输出:`evidence/display-resume-20261103/recovery-test.txt`。最终模式、进程及包含真实关屏过程的日志:`evidence/display-resume-20261103/final-state.txt`。真实开屏后的截图:`evidence/display-resume-20261103/after-power-cycle.png`。
这是当前这一台盒子与显示器的现场验收,未执行隔夜或多型号显示器测试。守护固定针对当前单 HDMI、2K、Xorg POC;以后换不同显示器或迁移到 Weston/Wayland 时需改为对应的输出配置机制。当前修复不代表服务端 Code43、帧率或鼠标动态残影问题已解决。
## 运维
Windows 开发机在 Git Bash 中只部署此修复:
```bash
bash tools/deploy_display_guard.sh
```
盒子上查看状态与日志(当前环境 `journalctl --user` 看不到用户服务日志,因此使用系统日志的用户单元过滤):
```bash
systemctl --user status vdi-display-guard.service
sudo -n journalctl _SYSTEMD_USER_UNIT=vdi-display-guard.service -n 50 --no-pager
DISPLAY=:0 XAUTHORITY=/home/armbian/.Xauthority xrandr --query
```
本次部署备份目录为 `/home/armbian/vdi-terminal/backups/display-guard-20261103-095920/`,包含原 `vdi-kiosk-start` 和原 `monitors.xml`。必要时可回退到原行为;这也会恢复旧的 4:3 保存布局和“仅启动时修复”的限制:
```bash
systemctl --user disable --now vdi-display-guard.service
cp -p ~/vdi-terminal/backups/display-guard-20261103-095920/vdi-kiosk-start ~/vdi-terminal/bin/vdi-kiosk-start
cp -p ~/vdi-terminal/backups/display-guard-20261103-095920/monitors.xml ~/.config/monitors.xml
rm -- ~/.config/systemd/user/vdi-display-guard.service
systemctl --user daemon-reload
```
日常操作:盒子保持开机,显示器可正常关开。若 HDMI 模式确实回退,给驱动和恢复程序约 15 秒完成切换,无需为此重启盒子。

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

View File

@ -0,0 +1,43 @@
2026-11-03T10:04:16+08:00
Screen 0: minimum 320 x 200, current 2560 x 1440, maximum 16384 x 16384
HDMI-1 connected primary 2560x1440+0+0 (normal left inverted right x axis y axis) 597mm x 336mm
1920x1440 75.00
2048x1152 60.00
1920x1080 100.00 60.00 60.00 50.00 59.94
1920x1080i 60.00 50.00 59.94
1600x1200 60.00
1680x1050 59.88
1600x900 60.00
1280x1024 60.02
1440x900 59.90
1280x960 85.00 60.00
1280x800 59.91
1152x864 75.00
1280x720 100.00 60.00 50.00 59.94
1024x768 60.00
800x600 60.32
720x576 50.00
720x480 59.94
2560x1440_60_fixed297 60.00*
WINDOW=44040203
X=0
Y=0
WIDTH=2560
HEIGHT=1440
SCREEN=0
66385 /home/armbian/vdi-build/rkmpp-experiment/build/moonlight/app/moonlight stream 192.168.1.70 Desktop --resolution 2560x1440 --fps 30 --bitrate 30000 --display-mode fullscreen --video-codec H.264 --video-decoder hardware --absolute-mouse --keep-awake --no-vsync --no-frame-pacing --audio-on-host
MainPID=76385
NRestarts=0
CPUUsageNSec=2960579000
ActiveState=active
UnitFileState=enabled
11月 03 09:59:22 rk3528pro-ddr4 vdi-display-guard[76385]: 2026-11-03 09:59:22 mode drift: 1920x1440 1920x1440+0+0
11月 03 09:59:30 rk3528pro-ddr4 vdi-display-guard[76385]: 2026-11-03 09:59:30 restored: 2560x1440_60_fixed297 (stream process untouched)
11月 03 09:59:33 rk3528pro-ddr4 vdi-display-guard[76385]: 2026-11-03 09:59:33 healthy: 2560x1440_60_fixed297
11月 03 10:00:26 rk3528pro-ddr4 vdi-display-guard[76385]: 2026-11-03 10:00:26 mode drift: 1920x1440 1920x1440+0+0
11月 03 10:00:34 rk3528pro-ddr4 vdi-display-guard[76385]: 2026-11-03 10:00:34 restored: 2560x1440_60_fixed297 (stream process untouched)
11月 03 10:00:41 rk3528pro-ddr4 vdi-display-guard[76385]: 2026-11-03 10:00:41 mode drift: 1920x1440 1920x1440+0+0
11月 03 10:00:49 rk3528pro-ddr4 vdi-display-guard[76385]: 2026-11-03 10:00:49 restored: 2560x1440_60_fixed297 (stream process untouched)
11月 03 10:00:51 rk3528pro-ddr4 vdi-display-guard[76385]: 2026-11-03 10:00:51 healthy: 2560x1440_60_fixed297
11月 03 10:03:19 rk3528pro-ddr4 vdi-display-guard[76385]: 2026-11-03 10:03:19 HDMI-1 disconnected; no mode changes
11月 03 10:03:31 rk3528pro-ddr4 vdi-display-guard[76385]: 2026-11-03 10:03:31 healthy: 2560x1440_60_fixed297

View File

@ -0,0 +1,10 @@
--query seconds= 0.109
--current seconds= 0.015
11月 03 09:59:22 rk3528pro-ddr4 vdi-display-guard[76385]: 2026-11-03 09:59:22 mode drift: 1920x1440 1920x1440+0+0
11月 03 09:59:30 rk3528pro-ddr4 vdi-display-guard[76385]: 2026-11-03 09:59:30 restored: 2560x1440_60_fixed297 (stream process untouched)
11月 03 09:59:33 rk3528pro-ddr4 vdi-display-guard[76385]: 2026-11-03 09:59:33 healthy: 2560x1440_60_fixed297
11月 03 10:00:26 rk3528pro-ddr4 vdi-display-guard[76385]: 2026-11-03 10:00:26 mode drift: 1920x1440 1920x1440+0+0
11月 03 10:00:34 rk3528pro-ddr4 vdi-display-guard[76385]: 2026-11-03 10:00:34 restored: 2560x1440_60_fixed297 (stream process untouched)
11月 03 10:00:41 rk3528pro-ddr4 vdi-display-guard[76385]: 2026-11-03 10:00:41 mode drift: 1920x1440 1920x1440+0+0
11月 03 10:00:49 rk3528pro-ddr4 vdi-display-guard[76385]: 2026-11-03 10:00:49 restored: 2560x1440_60_fixed297 (stream process untouched)
11月 03 10:00:51 rk3528pro-ddr4 vdi-display-guard[76385]: 2026-11-03 10:00:51 healthy: 2560x1440_60_fixed297

View File

@ -0,0 +1,25 @@
before_stream_pid=66385 boot_id=89a44e11-5cfd-46bb-ae72-3232edc4ea62
enabled
active
2026-11-03 10:00:20 display guard already running
cycle=1 drift_at=2026-11-03T10:00:20+08:00
cycle=1 recovered_at=2026-11-03T10:00:34+08:00
WINDOW=44040203
X=0
Y=0
WIDTH=2560
HEIGHT=1440
SCREEN=0
cycle=2 drift_at=2026-11-03T10:00:35+08:00
cycle=2 recovered_at=2026-11-03T10:00:49+08:00
WINDOW=44040203
X=0
Y=0
WIDTH=2560
HEIGHT=1440
SCREEN=0
PASS: both recoveries kept stream PID and boot ID
MainPID=76385
NRestarts=0
CPUUsageNSec=1092599000
-- No entries --

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 MiB

View File

@ -0,0 +1,71 @@
width=2560 height=1440 paints=19411 elapsed_ms=536551 clicks=32
ms,x,y,target
536057,1920,600,R
536060,1920,600,R
536063,639,600,L
536070,1920,600,R
536071,639,600,L
536072,1920,600,R
536077,639,600,L
536078,1920,600,R
536086,639,600,L
536148,1920,600,R
536151,639,600,L
536152,1920,600,R
536153,1920,600,R
536154,1920,600,R
536155,639,600,L
536156,1920,600,R
536157,639,600,L
536158,1920,600,R
536159,639,600,L
536160,1920,600,R
536161,639,600,L
536162,1920,600,R
536163,639,600,L
536164,1920,600,R
536165,639,600,L
536166,1920,600,R
536167,639,600,L
536168,1920,600,R
536169,639,600,L
536170,1920,600,R
536171,639,600,L
536172,1920,600,R
{"LastTaskResult":267009}

View File

@ -0,0 +1,37 @@
ELAPSED COMMAND
93 /home/armbian/vdi-build/rkmpp-experiment/build/moonlight/app/moonlight stream 192.168.1.70 Desktop --resolution 2560x1440 --fps 30 --bitrate 30000 --display-mode fullscreen --video-codec H.264 --video-decoder hardware --absolute-mouse --keep-awake --no-vsync --no-frame-pacing --audio-on-host --performance-overlay
------------------
Incoming frame rate from network: 27.45 FPS
Decoding frame rate: 27.45 FPS
Rendering frame rate: 27.14 FPS
Host processing latency min/max/average: 27.3/87.5/48.5 ms
Frames dropped by your network connection: 0.00%
Frames dropped due to network jitter: 0.52%
Average network latency: 6 ms (variance: 5 ms)
Average decoding time: 9.84 ms
Average frame queue delay: 4.50 ms
Average rendering time (including monitor V-sync latency): 6.89 ms
00:01:34 - SDL Info (0): Stopping input stream...
00:01:34 - SDL Info (0): done
00:01:34 - SDL Info (0): Stopping audio stream...
00:01:34 - SDL Info (0): No audio traffic was ever received from the host!
00:01:34 - SDL Info (0): ENet wait interrupted
00:01:34 - SDL Info (0): Control stream connection failed: 4
00:01:34 - SDL Info (0): done
00:01:34 - SDL Info (0): Stopping video stream...
00:01:34 - SDL Info (0): done
00:01:34 - SDL Info (0): Stopping control stream...
00:01:34 - SDL Info (0): ENet peer acknowledged disconnection
00:01:34 - SDL Info (0): done
00:01:34 - SDL Info (0): Cleaning up input stream...
00:01:34 - SDL Info (0): done
00:01:34 - SDL Info (0): Cleaning up video stream...
00:01:34 - SDL Info (0): done
00:01:34 - SDL Info (0): Cleaning up control stream...
00:01:34 - SDL Info (0): done
00:01:34 - SDL Info (0): Cleaning up audio stream...
00:01:34 - SDL Info (0): done
00:01:34 - SDL Info (0): Cleaning up platform...
00:01:34 - SDL Info (0): done
00:01:34 - Qt Info: Found "gamecontrollerdb.txt" at "/home/armbian/.cache/Moonlight Game Streaming Project/Moonlight/gamecontrollerdb.txt"
00:01:34 - SDL Info (0): Loaded 436 new gamepad mappings

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

View File

@ -0,0 +1,17 @@
{
"baseline": {
"received": 32,
"expected": 32,
"wrong_positions": [
1,
13
],
"correct": 30
},
"patched": {
"received": 32,
"expected": 32,
"wrong_positions": [],
"correct": 32
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

View File

@ -0,0 +1,15 @@
101612 /home/armbian/vdi-build/rkmpp-experiment/build/moonlight/app/moonlight stream 192.168.1.70 Desktop --resolution 2560x1440 --fps 30 --bitrate 30000 --display-mode fullscreen --video-codec H.264 --video-decoder hardware --absolute-mouse --keep-awake --no-vsync --no-frame-pacing --audio-on-host
Renderer 'SDL' with 'DRM' backend chosen
00:00:09 - SDL Info (0): VDI latest-frame queue: enabled
00:00:09 - SDL Info (0): Renderer 'EGL/GLES' with 'DRM' backend chosen
vdi_connection attempt=1 desktop=desk-win10-01 phase=ticket result=ready phase_ms=20 total_ms=20 error=
vdi_connection attempt=1 desktop=desk-win10-01 phase=process_start result=started phase_ms=0 total_ms=21 error=
vdi_connection attempt=1 desktop=desk-win10-01 phase=process_start result=ready phase_ms=103 total_ms=125 error=
vdi_connection attempt=1 desktop=desk-win10-01 phase=stream_ready result=ready phase_ms=10440 total_ms=10566 error=
active
WINDOW=44040203
X=0
Y=0
WIDTH=2560
HEIGHT=1440
SCREEN=0

View File

@ -0,0 +1,3 @@
Screen 0: minimum 320 x 200, current 2560 x 1440, maximum 16384 x 16384
2560x1440_60_fixed297 60.00*
active

View File

@ -0,0 +1,30 @@
baseline2 ready_at=2026-11-03T10:52:11+08:00 pid=95753
Global video stats
------------------
Incoming frame rate from network: 28.93 FPS
Decoding frame rate: 28.93 FPS
Rendering frame rate: 28.48 FPS
Host processing latency min/max/average: 27.9/78.7/42.6 ms
Frames dropped by your network connection: 0.00%
Frames dropped due to network jitter: 0.54%
Average network latency: 9 ms (variance: 4 ms)
Average decoding time: 10.49 ms
Average frame queue delay: 3.39 ms
Average rendering time (including monitor V-sync latency): 6.84 ms
00:00:54 - SDL Info (0): Stopping input stream...
baseline2 complete_at=2026-11-03T10:52:58+08:00
patched2 ready_at=2026-11-03T10:53:07+08:00 pid=95869
Global video stats
------------------
Incoming frame rate from network: 28.40 FPS
Decoding frame rate: 28.40 FPS
Rendering frame rate: 28.09 FPS
Host processing latency min/max/average: 31.2/96.2/42.3 ms
Frames dropped by your network connection: 0.00%
Frames dropped due to network jitter: 1.10%
Average network latency: 4 ms (variance: 4 ms)
Average decoding time: 7.96 ms
Average frame queue delay: 2.14 ms
Average rendering time (including monitor V-sync latency): 6.12 ms
00:00:54 - SDL Info (0): Stopping input stream...
patched2 complete_at=2026-11-03T10:53:53+08:00

View File

@ -0,0 +1,71 @@
width=2560 height=1440 paints=1532 elapsed_ms=45518 clicks=32
ms,x,y,target
44625,639,600,L
44625,1920,600,R
44627,639,600,L
44628,1920,600,R
44629,639,600,L
44630,1920,600,R
44651,639,600,L
44692,1920,600,R
44693,639,600,L
44694,1920,600,R
44695,639,600,L
44696,1920,600,R
44697,639,600,L
44697,1920,600,R
44698,639,600,L
44699,1920,600,R
44703,639,600,L
44713,1920,600,R
44716,639,600,L
44717,1920,600,R
44718,639,600,L
44718,1920,600,R
44719,639,600,L
44720,1920,600,R
44721,639,600,L
44722,1920,600,R
44722,639,600,L
44723,1920,600,R
44746,639,600,L
44747,1920,600,R
44748,639,600,L
44749,1920,600,R
{"LastTaskResult":267009}

View File

@ -0,0 +1,37 @@
ELAPSED COMMAND
147 /home/armbian/vdi-build/rkmpp-experiment/build/moonlight/app/moonlight stream 192.168.1.70 Desktop --resolution 2560x1440 --fps 30 --bitrate 30000 --display-mode fullscreen --video-codec H.264 --video-decoder hardware --absolute-mouse --keep-awake --no-vsync --no-frame-pacing --audio-on-host --performance-overlay
Frames dropped by your network connection: 0.00%
Frames dropped due to network jitter: 0.81%
Average network latency: 15 ms (variance: 14 ms)
Average decoding time: 8.30 ms
Average frame queue delay: 2.72 ms
Average rendering time (including monitor V-sync latency): 6.62 ms
00:02:05 - SDL Info (0): Stopping input stream...
00:02:05 - Qt Critical: 会话已终止
错误代码: -1
00:02:05 - SDL Info (0): done
00:02:05 - Qt Warning: stream 1 finished with error: "Connection closed"
00:02:05 - SDL Info (0): Stopping audio stream...
00:02:05 - SDL Info (0): No audio traffic was ever received from the host!
00:02:05 - SDL Info (0): done
00:02:05 - SDL Info (0): Stopping video stream...
00:02:05 - SDL Info (0): done
00:02:05 - SDL Info (0): Stopping control stream...
00:02:05 - SDL Info (0): ENet peer is already disconnected
00:02:05 - SDL Info (0): done
00:02:05 - SDL Info (0): Cleaning up input stream...
00:02:05 - SDL Info (0): done
00:02:05 - SDL Info (0): Cleaning up video stream...
00:02:05 - SDL Info (0): done
00:02:05 - SDL Info (0): Cleaning up control stream...
00:02:05 - SDL Info (0): done
00:02:05 - SDL Info (0): Cleaning up audio stream...
00:02:05 - SDL Info (0): done
00:02:05 - SDL Info (0): Cleaning up platform...
00:02:05 - SDL Info (0): done
00:02:05 - Qt Info: Found "gamecontrollerdb.txt" at "/home/armbian/.cache/Moonlight Game Streaming Project/Moonlight/gamecontrollerdb.txt"
00:02:05 - SDL Info (0): Loaded 436 new gamepad mappings
00:02:05 - Qt Warning: Failed to download latest compatibility data: QNetworkReply::RemoteHostClosedError
00:02:13 - Qt Info: "DESKTOP-Q072ICM" is now offline
00:02:22 - Qt Info: "DESKTOP-Q072ICM" is now online at "192.168.1.70:47989"

View File

@ -0,0 +1,7 @@
width=2560 height=1440 paints=19799 elapsed_ms=599310 clicks=0
ms,x,y,target
{"LastTaskResult":267014}

View File

@ -0,0 +1,28 @@
11月 03 10:48:18 rk3528pro-ddr4 NetworkManager[883]: <info> [1793674098.6211] device (wlan0): supplicant interface state: completed -> disconnected
11月 03 10:48:18 rk3528pro-ddr4 NetworkManager[883]: <info> [1793674098.6213] device (p2p-dev-wlan0): supplicant management interface state: completed -> disconnected
11月 03 10:48:18 rk3528pro-ddr4 NetworkManager[883]: <info> [1793674098.7019] device (wlan0): supplicant interface state: disconnected -> scanning
11月 03 10:48:18 rk3528pro-ddr4 NetworkManager[883]: <info> [1793674098.7030] device (p2p-dev-wlan0): supplicant management interface state: disconnected -> scanning
11月 03 10:48:18 rk3528pro-ddr4 NetworkManager[883]: <info> [1793674098.7412] device (wlan0): supplicant interface state: scanning -> associating
11月 03 10:48:18 rk3528pro-ddr4 NetworkManager[883]: <info> [1793674098.7415] device (p2p-dev-wlan0): supplicant management interface state: scanning -> associating
11月 03 10:48:18 rk3528pro-ddr4 NetworkManager[883]: <info> [1793674098.9321] device (wlan0): supplicant interface state: associating -> disconnected
11月 03 10:48:18 rk3528pro-ddr4 NetworkManager[883]: <info> [1793674098.9324] device (p2p-dev-wlan0): supplicant management interface state: associating -> disconnected
11月 03 10:48:19 rk3528pro-ddr4 NetworkManager[883]: <info> [1793674099.4318] device (wlan0): supplicant interface state: disconnected -> scanning
11月 03 10:48:19 rk3528pro-ddr4 NetworkManager[883]: <info> [1793674099.4320] device (p2p-dev-wlan0): supplicant management interface state: disconnected -> scanning
11月 03 10:48:20 rk3528pro-ddr4 NetworkManager[883]: <info> [1793674100.8003] device (wlan0): supplicant interface state: scanning -> associating
11月 03 10:48:20 rk3528pro-ddr4 NetworkManager[883]: <info> [1793674100.8005] device (p2p-dev-wlan0): supplicant management interface state: scanning -> associating
11月 03 10:48:20 rk3528pro-ddr4 NetworkManager[883]: <info> [1793674100.9901] device (wlan0): supplicant interface state: associating -> disconnected
11月 03 10:48:20 rk3528pro-ddr4 NetworkManager[883]: <info> [1793674100.9903] device (p2p-dev-wlan0): supplicant management interface state: associating -> disconnected
11月 03 10:48:21 rk3528pro-ddr4 NetworkManager[883]: <info> [1793674101.9908] device (wlan0): supplicant interface state: disconnected -> scanning
11月 03 10:48:21 rk3528pro-ddr4 NetworkManager[883]: <info> [1793674101.9910] device (p2p-dev-wlan0): supplicant management interface state: disconnected -> scanning
11月 03 10:48:22 rk3528pro-ddr4 NetworkManager[883]: <info> [1793674102.0281] device (wlan0): supplicant interface state: scanning -> associating
11月 03 10:48:22 rk3528pro-ddr4 NetworkManager[883]: <info> [1793674102.0283] device (p2p-dev-wlan0): supplicant management interface state: scanning -> associating
11月 03 10:48:22 rk3528pro-ddr4 NetworkManager[883]: <info> [1793674102.2189] device (wlan0): supplicant interface state: associating -> disconnected
11月 03 10:48:22 rk3528pro-ddr4 NetworkManager[883]: <info> [1793674102.2192] device (p2p-dev-wlan0): supplicant management interface state: associating -> disconnected
11月 03 10:48:27 rk3528pro-ddr4 NetworkManager[883]: <info> [1793674107.2236] device (wlan0): supplicant interface state: disconnected -> scanning
11月 03 10:48:27 rk3528pro-ddr4 NetworkManager[883]: <info> [1793674107.2239] device (p2p-dev-wlan0): supplicant management interface state: disconnected -> scanning
11月 03 10:48:31 rk3528pro-ddr4 NetworkManager[883]: <info> [1793674111.5980] device (wlan0): supplicant interface state: scanning -> associating
11月 03 10:48:31 rk3528pro-ddr4 NetworkManager[883]: <info> [1793674111.5983] device (p2p-dev-wlan0): supplicant management interface state: scanning -> associating
11月 03 10:48:31 rk3528pro-ddr4 NetworkManager[883]: <info> [1793674111.8979] device (wlan0): supplicant interface state: associating -> associated
11月 03 10:48:31 rk3528pro-ddr4 NetworkManager[883]: <info> [1793674111.8981] device (p2p-dev-wlan0): supplicant management interface state: associating -> associated
11月 03 10:48:31 rk3528pro-ddr4 NetworkManager[883]: <info> [1793674111.9156] device (wlan0): supplicant interface state: associated -> completed
11月 03 10:48:31 rk3528pro-ddr4 NetworkManager[883]: <info> [1793674111.9161] device (p2p-dev-wlan0): supplicant management interface state: associated -> completed

View File

@ -0,0 +1,30 @@
{"LastTaskResult":0}
{
"backup": "C:\\Users\\test\\AppData\\Local\\VDI\\desktop-responsiveness-before-20261103.json",
"before": {
"animation": 1,
"menuDelay": 400
},
"restored": false,
"after": {
"animation": 0,
"menuDelay": 100
}
}

View File

@ -0,0 +1,41 @@
[h264 @ 0xaaab09e425e0] Reinit context to 2560x1440, pix_fmt: yuv420p
Input #0, h264, from '/home/armbian/vdi-build/rkmpp-experiment/test/1440p.h264':
Duration: N/A, bitrate: N/A
Stream #0:0: Video: h264 (Constrained Baseline), 1 reference frame, yuv420p(progressive, left), 2560x1440, 25 fps, 60 tbr, 1200k tbn
[out#0/null @ 0xaaab09e42f00] No explicit maps, mapping streams automatically...
[vost#0:0/wrapped_avframe @ 0xaaab09e77260] Created video stream from input stream 0:0
[h264_mp4toannexb @ 0xaaab09e6e100] The input looks like it is Annex B already
mpp[30233]: mpp_info: mpp version: 7916c3c author: Xiaoxu Chen 2026-10-28 fix[utils]: Fix AVC cu_map allocation stride
[h264_rkmpp @ 0xaaab09f55980] Picked up an existing RKMPP hardware device
Stream mapping:
Stream #0:0 -> #0:0 (h264 (h264_rkmpp) -> wrapped_avframe (native))
Press [q] to stop, [?] for help
[h264_rkmpp @ 0xaaab09f55980] Noticed an info change
[h264_rkmpp @ 0xaaab09f55980] Decoder options: deint=true afbc=0 fast_parse=true buf_mode=0
[h264_rkmpp @ 0xaaab09f55980] Configured with size: 2560x1440 | pix_fmt: drm_prime | sw_pix_fmt: nv12
[graph 0 input from stream 0:0 @ 0xaaab09f264a0] w:2560 h:1440 pixfmt:drm_prime tb:1/1200000 fr:30/1 sar:0/1
Output #0, null, to 'pipe:':
Metadata:
encoder : Lavf60.16.101
Stream #0:0: Video: wrapped_avframe, 1 reference frame, drm_prime(tv, progressive, left), 2560x1440 (0x0), q=2-31, 200 kb/s, 30 fps, 30 tbn
Metadata:
encoder : Lavc60.31.102 wrapped_avframe
frame= 0 fps=0.0 q=-0.0 size= 0kB time=00:00:00.03 bitrate= 0.0kbits/s speed=29.3x [in#0/h264 @ 0xaaab09e3b470] EOF while reading input
[in#0/h264 @ 0xaaab09e3b470] Terminating demuxer thread
[vist#0:0/h264 @ 0xaaab09e42c30] Decoder thread received EOF packet
[vist#0:0/h264 @ 0xaaab09e42c30] Decoder returned EOF, finishing
[vist#0:0/h264 @ 0xaaab09e42c30] Terminating decoder thread
No more output streams to write to, finishing.
[out#0/null @ 0xaaab09e42f00] All streams finished
[out#0/null @ 0xaaab09e42f00] Terminating muxer thread
[out#0/null @ 0xaaab09e42f00] Output file #0 (pipe:):
[out#0/null @ 0xaaab09e42f00] Output stream #0:0 (video): 60 frames encoded; 60 packets muxed (28800 bytes);
[out#0/null @ 0xaaab09e42f00] Total: 60 packets (28800 bytes) muxed
[out#0/null @ 0xaaab09e42f00] video:28kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown
frame= 60 fps=0.0 q=-0.0 Lsize=N/A time=00:00:02.00 bitrate=N/A speed=6.91x
bench: utime=0.058s stime=0.062s rtime=0.290s
bench: maxrss=24448kB
[in#0/h264 @ 0xaaab09e3b470] Input file #0 (/home/armbian/vdi-build/rkmpp-experiment/test/1440p.h264):
[in#0/h264 @ 0xaaab09e3b470] Input stream #0:0 (video): 60 packets read (57854 bytes); 60 frames decoded; 0 decode errors;
[in#0/h264 @ 0xaaab09e3b470] Total: 60 packets (57854 bytes) demuxed
[AVIOContext @ 0xaaab09e3bb10] Statistics: 57854 bytes read, 0 seeks

View File

@ -0,0 +1,42 @@
9eba20198e9416da0be63cf8da2c34d943e6702b825528d1678eccfc7ab5b3ce /home/armbian/vdi-build/rkmpp-experiment/debs/libbrotli-dev_1.1.0-2ubuntu0.1_arm64.deb
892633787d2810eb326e3b3dc5ef43cc61fa5b58efdd8474cef71a7c706d8220 /home/armbian/vdi-build/rkmpp-experiment/debs/libdrm-dev_2.4.125-1ubuntu0.1~24.04.2_arm64.deb
99e364f5b5d5847feeb57bf4bd866331da93f16ba767c25286dd7f65e4b828ec /home/armbian/vdi-build/rkmpp-experiment/debs/libegl-dev_1.7.0-1build1_arm64.deb
887755d6aa91c12ee0eb3404b61f6dc138c4c59234aa2add0264baf270337708 /home/armbian/vdi-build/rkmpp-experiment/debs/libffi-dev_3.4.6-1build1_arm64.deb
bf051daf32337f64c23010f59bfca6e54810918531ba7757aa6797fa413ba1cb /home/armbian/vdi-build/rkmpp-experiment/debs/libfreetype-dev_2.13.2+dfsg-1ubuntu0.2_arm64.deb
f0faf030f4dc8b78420dbdefd3aa764b855aa6ff7fbe1b0851ba851c43c2fa08 /home/armbian/vdi-build/rkmpp-experiment/debs/libgbm-dev_25.2.8-0ubuntu0.24.04.4_arm64.deb
a7c9cd011c8e05fb573445560cab86d61583cda0f79c248fd73680e2d0618b54 /home/armbian/vdi-build/rkmpp-experiment/debs/libgles1_1.7.0-1build1_arm64.deb
df742afc0b66f24d80920b419723e072ab59d70726519d5994f50cf09e1f3961 /home/armbian/vdi-build/rkmpp-experiment/debs/libgles-dev_1.7.0-1build1_arm64.deb
7cf6c28c1895d6843e901f68dd2d90be5a9280bfef70e1e8dfaa2096e14c13ad /home/armbian/vdi-build/rkmpp-experiment/debs/libglib2.0-dev_2.80.0-6ubuntu3.10_arm64.deb
f6af2526f1a4b2264bbc7db25161f1d4f14ade79f731cd21a4c388d7e03debce /home/armbian/vdi-build/rkmpp-experiment/debs/libgraphite2-dev_1.3.14-2ubuntu0.24.04.1_arm64.deb
2897a334893c407502f3787fb1ca10ddfd2e35c05a19637396afcfd55873db8d /home/armbian/vdi-build/rkmpp-experiment/debs/libharfbuzz-dev_8.3.0-2build2_arm64.deb
4ef5f13cb3a4cbac89e50f48c70355a658911d8db2ff94f263daf5092074e010 /home/armbian/vdi-build/rkmpp-experiment/debs/libopus-dev_1.4-1build1_arm64.deb
d73f6246d98ad03283f6b9a30fd86da52ea360afbf5ed48c2e4eb995d04b87aa /home/armbian/vdi-build/rkmpp-experiment/debs/libpng-dev_1.6.43-5ubuntu0.7_arm64.deb
85957d625c083a85b7cade0c3696b99095eea9c03242a3452cb6d4b0cb882c3d /home/armbian/vdi-build/rkmpp-experiment/debs/libqt5qmlworkerscript5_5.15.13+dfsg-1ubuntu0.1_arm64.deb
e10c14d16d3167b29ff1c69d955d3cde68ccb65dbc2f1362c0140fe88e55274f /home/armbian/vdi-build/rkmpp-experiment/debs/libqt5quickcontrols2-5_5.15.13+dfsg-1_arm64.deb
97499cbc6dfed8ac3fc1e126861f4e4f66f5196d64eceb90810cd814a7a59069 /home/armbian/vdi-build/rkmpp-experiment/debs/libqt5quickparticles5_5.15.13+dfsg-1ubuntu0.1_arm64.deb
66d440824d1ab8845e3422a63e248e650f0efc80a07f961b5842ccdb58c199c3 /home/armbian/vdi-build/rkmpp-experiment/debs/libqt5quickshapes5_5.15.13+dfsg-1ubuntu0.1_arm64.deb
e5fc6fa488bef184069aa80e046991d8c75ec76d6f0b8e6580b27344b0543577 /home/armbian/vdi-build/rkmpp-experiment/debs/libqt5quicktemplates2-5_5.15.13+dfsg-1_arm64.deb
73f7aa7231c06cc6e4e7d215421d60cca4835c4f94d1b69587b73cb41866d45a /home/armbian/vdi-build/rkmpp-experiment/debs/libqt5quicktest5_5.15.13+dfsg-1ubuntu0.1_arm64.deb
813202055ca9743206d33e955cac3152a3bac7abbbc8254e01c18feda6e39d0d /home/armbian/vdi-build/rkmpp-experiment/debs/libqt5svg5_5.15.13-1_arm64.deb
690245647bb8fd8ce21feaf8bece72c4cf64c85747fe6baa96dc20dd4eb95c1d /home/armbian/vdi-build/rkmpp-experiment/debs/libqt5svg5-dev_5.15.13-1_arm64.deb
3406a7a3cf98a633c9a1289eb20a31e03a04477afb95c8558f2de7f70abdd0bb /home/armbian/vdi-build/rkmpp-experiment/debs/libsdl2-2.0-0_2.30.0+dfsg-1ubuntu3.1_arm64.deb
edcb8ab3594488050f0a1c3fe983cf57d00ed6680ae173a8b919ef6fd99c3c3a /home/armbian/vdi-build/rkmpp-experiment/debs/libsdl2-dev_2.30.0+dfsg-1ubuntu3.1_arm64.deb
7a23ed32398355c4e771a8a1eae344f3cbbaca6deffe4172f8ce900dd4154687 /home/armbian/vdi-build/rkmpp-experiment/debs/libsdl2-ttf-2.0-0_2.22.0+dfsg-1_arm64.deb
e6a9ddf95bbb39bd55f9587fc874291d00cc8a5723b6d5a721bc50d646565926 /home/armbian/vdi-build/rkmpp-experiment/debs/libsdl2-ttf-dev_2.22.0+dfsg-1_arm64.deb
4b287709aaddb404233155f78c4f08bb943515065d99b8a205b7a147b76b4d5d /home/armbian/vdi-build/rkmpp-experiment/debs/libudev-dev_255.4-1ubuntu8.18_arm64.deb
a2cc274d08d3b966008d0a1f43545bc569c7934d383355829706fb25220b842e /home/armbian/vdi-build/rkmpp-experiment/debs/libwayland-bin_1.22.0-2.1build1_arm64.deb
6d94b723710aae35d0ff765978818601f4320c1dc4e0eec57e73b000943a1758 /home/armbian/vdi-build/rkmpp-experiment/debs/libwayland-dev_1.22.0-2.1build1_arm64.deb
213534d13ff7afd55155ae022d972faa6d2c343fcebb1e4517f37d7193b1b6d0 /home/armbian/vdi-build/rkmpp-experiment/debs/libx264-dev_2%3a0.164.3108+git31e19f9-1_arm64.deb
de01e5d50d114ddc5419d61cde552d8a956a2dc9e6c004ce50b7f37a02a47c1d /home/armbian/vdi-build/rkmpp-experiment/debs/libxkbcommon-dev_1.6.0-1build1_arm64.deb
80edfdbc1cd71202ec56d0643e24f75745f1f60bee0cfaef7afa8a40b290ddf2 /home/armbian/vdi-build/rkmpp-experiment/debs/qml-module-qtqml-models2_5.15.13+dfsg-1ubuntu0.1_arm64.deb
5315cda68ae300ba6938ac83dbb398644419214a8febf2ed988500d8bc4b3d20 /home/armbian/vdi-build/rkmpp-experiment/debs/qml-module-qtquick2_5.15.13+dfsg-1ubuntu0.1_arm64.deb
a5c57eefe7ec2dafc5f0d9410fef4a09320349eece173e406be6b73eb4eab985 /home/armbian/vdi-build/rkmpp-experiment/debs/qml-module-qtquick-controls2_5.15.13+dfsg-1_arm64.deb
cecf088b56cbe3df083bf3b18d7da264d6ac270bb93796e749b3bd5497253340 /home/armbian/vdi-build/rkmpp-experiment/debs/qml-module-qtquick-layouts_5.15.13+dfsg-1ubuntu0.1_arm64.deb
775d0c95e6ab30a6002d6c0a0613b4c4b9d9d91616804701f7c707706c51bb0b /home/armbian/vdi-build/rkmpp-experiment/debs/qml-module-qtquick-templates2_5.15.13+dfsg-1_arm64.deb
af63b41209ee631ba5a5c7eee3976b4342373fd6cd6e47a51467834ac8aac05b /home/armbian/vdi-build/rkmpp-experiment/debs/qml-module-qtquick-window2_5.15.13+dfsg-1ubuntu0.1_arm64.deb
02313d79aa812e29f6b0494bcbad04e89df8734368e5d68485ac29c31e48b1a7 /home/armbian/vdi-build/rkmpp-experiment/debs/qt5-qmltooling-plugins_5.15.13+dfsg-1ubuntu0.1_arm64.deb
a7972aee9593b17742461d0b81e1eec1aae0d50ff76257b2bec01844c523be2f /home/armbian/vdi-build/rkmpp-experiment/debs/qtdeclarative5-dev_5.15.13+dfsg-1ubuntu0.1_arm64.deb
f4235926cc915848adc215ff279b108a19222d5a0e8f4d28210db0e8ffee5848 /home/armbian/vdi-build/rkmpp-experiment/debs/qtdeclarative5-dev-tools_5.15.13+dfsg-1ubuntu0.1_arm64.deb
852dba1e49327be8e609b9235ac5a7374fd4538d4196752075989f6bb357e590 /home/armbian/vdi-build/rkmpp-experiment/debs/qtquickcontrols2-5-dev_5.15.13+dfsg-1_arm64.deb
e4fa5eb09a9f3eee12a863718badfc51a986cda32e53e37e841b76756e5caebc /home/armbian/vdi-build/rkmpp-experiment/debs/wayland-protocols_1.45-1~ubuntu0.24.04.2_all.deb
5ad30e35e9bb0a66a1af4d1bac3d9f2035658040affec533e058001259e2796f /home/armbian/vdi-build/rkmpp-experiment/debs/zlib1g-dev_1%3a1.3.dfsg-3.1ubuntu2.3_arm64.deb

View File

@ -0,0 +1,10 @@
[libx264 @ 0xaaaaf7134470] using cpu capabilities: ARMv8 NEON
[libx264 @ 0xaaaaf7134470] profile Constrained Baseline, level 5.0, 4:2:0, 8-bit
[libx264 @ 0xaaaaf7134470] frame I:1 Avg QP:20.00 size: 15901
[libx264 @ 0xaaaaf7134470] frame P:59 Avg QP:16.00 size: 711
[libx264 @ 0xaaaaf7134470] mb I I16..4: 100.0% 0.0% 0.0%
[libx264 @ 0xaaaaf7134470] mb P I16..4: 1.3% 0.0% 0.0% P16..4: 2.8% 0.0% 0.0% 0.0% 0.0% skip:95.9%
[libx264 @ 0xaaaaf7134470] coded y,uvDC,uvAC intra: 0.4% 0.0% 0.0% inter: 0.0% 0.0% 0.0%
[libx264 @ 0xaaaaf7134470] i16 v,h,dc,p: 0% 99% 0% 0%
[libx264 @ 0xaaaaf7134470] i8c dc,h,v,p: 100% 0% 0% 0%
[libx264 @ 0xaaaaf7134470] kb/s:231.42

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

View File

@ -0,0 +1,13 @@
[monitor 2026-11-02 20:10:05] 看门狗启动,监控: /home/armbian/vdi-terminal/bin/kiosk-shell
[monitor 2026-11-02 20:10:05] 主进程已启动, pid=63682
vdi_connection attempt=1 desktop=desk-win10-01 phase=ticket result=started phase_ms=0 total_ms=0 error=
vdi_connection attempt=1 desktop=desk-win10-01 phase=ticket result=ready phase_ms=19 total_ms=19 error=
vdi_connection attempt=1 desktop=desk-win10-01 phase=process_start result=started phase_ms=0 total_ms=19 error=
vdi_connection attempt=1 desktop=desk-win10-01 phase=process_start result=ready phase_ms=110 total_ms=130 error=
vdi_connection attempt=1 desktop=desk-win10-01 phase=stream_ready result=ready phase_ms=9940 total_ms=10071 error=
vdi_connection attempt=1 desktop=desk-win10-01 phase=session result=finished phase_ms=170912 total_ms=171043 error=
vdi_connection attempt=3 desktop=desk-win10-01 phase=ticket result=started phase_ms=0 total_ms=0 error=
vdi_connection attempt=3 desktop=desk-win10-01 phase=ticket result=ready phase_ms=1 total_ms=1 error=
vdi_connection attempt=3 desktop=desk-win10-01 phase=process_start result=started phase_ms=0 total_ms=2 error=
vdi_connection attempt=3 desktop=desk-win10-01 phase=process_start result=ready phase_ms=62 total_ms=64 error=
vdi_connection attempt=3 desktop=desk-win10-01 phase=stream_ready result=ready phase_ms=9638 total_ms=9702 error=

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

View File

@ -0,0 +1,452 @@
[VDI launch]
profile=low-latency
program=/home/armbian/vdi-terminal/bin/vdi-moonlight-rkmpp
decoder=hardware
codec=H.264
vsync=0
frame-pacing=0
renderer=opengles2
video-driver=
args=stream 192.168.1.70 Desktop --resolution 2560x1440 --fps 30 --bitrate 30000 --display-mode fullscreen --video-codec H.264 --video-decoder hardware --absolute-mouse --keep-awake --no-vsync --no-frame-pacing --audio-on-host
00:00:00 - SDL Info (0): Compiled with SDL 2.30.0
00:00:00 - SDL Info (0): Running with SDL 2.30.0
00:00:00 - Qt Info: Successfully loaded translation for "zh_CN"
00:00:00 - Qt Info: Loaded unique ID from settings: "95da1945b8736669"
00:00:00 - Qt Warning: qrc:/gui/main.qml:13:1: QML ApplicationWindow: ToolTip must be attached to an Item
00:00:01 - Qt Info: Found "gamecontrollerdb.txt" at "/home/armbian/.cache/Moonlight Game Streaming Project/Moonlight/gamecontrollerdb.txt"
00:00:01 - SDL Info (0): Loaded 436 new gamepad mappings
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:9
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:47009
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:47998
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:47999
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:48000
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:48002
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:48010
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:9
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:47009
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:47998
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:47999
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:48000
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:48002
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:48010
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:9
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:47009
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:47998
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:47999
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:48000
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:48002
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:48010
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:9
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:47009
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:47998
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:47999
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:48000
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:48002
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:48010
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:9
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:47009
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:47998
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:47999
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:48000
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:48002
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:48010
00:00:01 - Qt Debug: Current Moonlight version: "6.2.0"
00:00:01 - Qt Info: Discovered mDNS host: "DESKTOP-Q072ICM.local."
00:00:01 - Qt Info: "DESKTOP-Q072ICM" is now online at "192.168.1.70:47989"
00:00:01 - Qt Info: Found "ModeSeven.ttf" at ":/data/ModeSeven.ttf"
00:00:02 - SDL Info (0): Qt UI screen is at (0,0)
00:00:02 - SDL Info (0): SDL found matching display 0
00:00:02 - Qt Info: Server GPU: ""
00:00:02 - Qt Info: Server GFE version: "3.23.0.74"
00:00:02 - SDL Info (0): Video bitrate: 30000 kbps
00:00:02 - SDL Info (0): Audio channel count: 2
00:00:02 - SDL Info (0): Audio channel mask: 3
00:00:02 - SDL Info (0): Desired audio buffer: 720 samples (5760 bytes)
00:00:02 - SDL Info (0): Obtained audio buffer: 720 samples (5760 bytes)
00:00:02 - SDL Info (0): SDL audio driver: pulseaudio
00:00:02 - Qt Info: Found "gamecontrollerdb.txt" at "/home/armbian/.cache/Moonlight Game Streaming Project/Moonlight/gamecontrollerdb.txt"
00:00:02 - SDL Info (0): Loaded 436 new gamepad mappings
00:00:02 - SDL Info (0): V-sync disabled
00:00:02 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:02 - SDL Info (0): GPU driver: rockchip
00:00:02 - SDL Info (0): Direct rendering via DRM is disabled
00:00:02 - SDL Info (0): DRM backend supports exporting EGLImage
00:00:02 - SDL Info (0): Color buffer is: R8G8B8A0
00:00:02 - SDL Info (0): Using DRM renderer
00:00:02 - FFmpeg: [h264_mp4toannexb @ 0xaaaaf977dda0] The input looks like it is Annex B already
mpp[64569]: mpp_info: mpp version: 7916c3c author: Xiaoxu Chen 2026-10-28 fix[utils]: Fix AVC cu_map allocation stride
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaf94e7ed0] Picked up an existing RKMPP hardware device
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaf94e7ed0] Wrote 390 bytes to decoder
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaf94e7ed0] Wrote 390 bytes to decoder
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaf94e7ed0] Noticed an info change
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaf94e7ed0] Decoder options: deint=true afbc=0 fast_parse=true buf_mode=0
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaf94e7ed0] Configured with size: 1280x720 | pix_fmt: drm_prime | sw_pix_fmt: nv12
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaf94e7ed0] Wrote 390 bytes to decoder
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaf94e7ed0] Received a frame
00:00:02 - SDL Warn (0): Using custom H.264 decoder (H264_DECODER_HINT): h264_rkmpp
00:00:02 - SDL Info (0): FFmpeg-based video decoder chosen
00:00:02 - SDL Info (0): V-sync disabled
00:00:02 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:02 - SDL Info (0): GPU driver: rockchip
00:00:02 - SDL Info (0): Direct rendering via DRM is disabled
00:00:02 - SDL Info (0): DRM backend supports exporting EGLImage
00:00:02 - SDL Info (0): Color buffer is: R8G8B8A0
00:00:02 - SDL Info (0): Using DRM renderer
00:00:02 - FFmpeg: [h264_mp4toannexb @ 0xaaaaf9478020] The input looks like it is Annex B already
mpp[64569]: mpp_info: mpp version: 7916c3c author: Xiaoxu Chen 2026-10-28 fix[utils]: Fix AVC cu_map allocation stride
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaf94e7ed0] Picked up an existing RKMPP hardware device
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaf94e7ed0] Wrote 390 bytes to decoder
00:00:03 - FFmpeg: [h264_rkmpp @ 0xaaaaf94e7ed0] Wrote 390 bytes to decoder
00:00:03 - FFmpeg: [h264_rkmpp @ 0xaaaaf94e7ed0] Noticed an info change
00:00:03 - FFmpeg: [h264_rkmpp @ 0xaaaaf94e7ed0] Decoder options: deint=true afbc=0 fast_parse=true buf_mode=0
00:00:03 - FFmpeg: [h264_rkmpp @ 0xaaaaf94e7ed0] Configured with size: 1280x720 | pix_fmt: drm_prime | sw_pix_fmt: nv12
00:00:03 - FFmpeg: [h264_rkmpp @ 0xaaaaf94e7ed0] Wrote 390 bytes to decoder
00:00:03 - FFmpeg: [h264_rkmpp @ 0xaaaaf94e7ed0] Received a frame
00:00:03 - SDL Warn (0): Using custom H.264 decoder (H264_DECODER_HINT): h264_rkmpp
00:00:03 - SDL Info (0): FFmpeg-based video decoder chosen
00:00:03 - Qt Warning: 启用远程桌面鼠标模式可能会导致游戏出现问题。
00:00:06 - Qt Info: Found "gamecontrollerdb.txt" at "/home/armbian/.cache/Moonlight Game Streaming Project/Moonlight/gamecontrollerdb.txt"
00:00:06 - SDL Info (0): Loaded 436 new gamepad mappings
00:00:06 - Qt Info: Executing request: "https://192.168.1.70:47984/resume?uniqueid=95da1945b8736669&uuid=1f4223efe39e4eecad4ee7e90ad131e8&appid=881448767&mode=2560x1440x30&additionalStates=1&sops=1&rikey=REDACTED&rikeyid=REDACTED&localAudioPlayMode=1&surroundAudioInfo=196610&remoteControllersBitmap=0&gcmap=0&gcpersist=0&corever=1"
00:00:07 - Qt Info: Launch response: "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root status_code=\"200\"><sessionUrl0>rtspenc://192.168.1.70:48010</sessionUrl0><resume>1</resume></root>"
00:00:07 - Qt Info: Found matching interface: "wlan0" "88:00:33:77:30:B6" QFlags<QNetworkInterface::InterfaceFlag>(IsUp|IsRunning|CanBroadcast|CanMulticast)
00:00:07 - Qt Info: Interface Type: QNetworkInterface::Wifi
00:00:07 - Qt Info: Interface MTU: 1500
00:00:07 - SDL Info (0): RTSP port: 48010
00:00:07 - SDL Info (0): Initializing platform...
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Resolving host name...
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Initializing audio stream...
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Starting RTSP handshake...
00:00:07 - SDL Info (0): Reference frame invalidation is not supported by this host
00:00:07 - SDL Info (0): Audio port: 48000
00:00:07 - SDL Info (0): Video port: 47998
00:00:07 - SDL Info (0): Control port: 47999
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Initializing control stream...
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Initializing video stream...
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Initializing input stream...
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Starting control stream...
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Starting video stream...
00:00:07 - SDL Info (0): Video stream is 2560x1440x30 (format 0x1)
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Starting audio stream...
00:00:07 - SDL Info (0): Received first video packet after 0 ms
00:00:07 - SDL Info (0): Desired audio buffer: 720 samples (5760 bytes)
00:00:07 - SDL Info (0): Obtained audio buffer: 720 samples (5760 bytes)
00:00:07 - SDL Info (0): SDL audio driver: pulseaudio
00:00:07 - SDL Info (0): Audio stream has 2 channels
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Starting input stream...
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Qt UI screen is at (0,0)
00:00:07 - SDL Info (0): SDL found matching display 0
00:00:07 - SDL Info (0): Found display mode with desktop resolution: 2560x1440x60
00:00:07 - SDL Info (0): Recreating renderer for window event: 1 (0 0)
00:00:07 - SDL Info (0): V-sync disabled
00:00:07 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:07 - SDL Info (0): GPU driver: rockchip
00:00:07 - SDL Info (0): Direct rendering via DRM is disabled
00:00:07 - SDL Info (0): DRM backend supports exporting EGLImage
00:00:08 - SDL Info (0): Video decode unit queue overflow
00:00:08 - SDL Info (0): IDR frame request sent
00:00:08 - SDL Info (0): Waiting for IDR frame
00:00:08 - SDL Info (0): Color buffer is: R8G8B8A0
00:00:08 - SDL Info (0): Using DRM renderer
00:00:08 - FFmpeg: [h264_mp4toannexb @ 0xaaaaf96822d0] The input looks like it is Annex B already
mpp[64569]: mpp_info: mpp version: 7916c3c author: Xiaoxu Chen 2026-10-28 fix[utils]: Fix AVC cu_map allocation stride
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaaf9493c60] Picked up an existing RKMPP hardware device
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaaf9493c60] Wrote 390 bytes to decoder
00:00:08 - SDL Info (0): Video decode unit queue overflow
00:00:08 - SDL Info (0): IDR frame request sent
00:00:08 - SDL Info (0): Waiting for IDR frame
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaaf9493c60] Wrote 390 bytes to decoder
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaaf9493c60] Noticed an info change
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaaf9493c60] Decoder options: deint=true afbc=0 fast_parse=true buf_mode=0
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaaf9493c60] Configured with size: 1280x720 | pix_fmt: drm_prime | sw_pix_fmt: nv12
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaaf9493c60] Wrote 390 bytes to decoder
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaaf9493c60] Received a frame
00:00:08 - SDL Info (0): Not reusing test decoder for h264_rkmpp
00:00:08 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:08 - SDL Info (0): GPU driver: rockchip
00:00:08 - SDL Info (0): Direct rendering via DRM is disabled
00:00:08 - SDL Info (0): DRM backend supports exporting EGLImage
00:00:08 - SDL Info (0): Color buffer is: R8G8B8A0
00:00:08 - SDL Info (0): Frame pacing disabled: target 60 Hz with 30 FPS stream
00:00:08 - SDL Info (0): Using DRM renderer
00:00:08 - FFmpeg: [h264_mp4toannexb @ 0xaaaaf9fc4600] The input looks like it is Annex B already
mpp[64569]: mpp_info: mpp version: 7916c3c author: Xiaoxu Chen 2026-10-28 fix[utils]: Fix AVC cu_map allocation stride
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaaf9493c60] Picked up an existing RKMPP hardware device
00:00:08 - SDL Warn (0): Unable to set render thread to high priority: setpriority() failed
00:00:08 - SDL Info (0): Using H.264 SPS fixup
00:00:08 - SDL Info (0): Renderer 'EGL/GLES' with 'DRM' backend chosen
00:00:08 - SDL Warn (0): Using custom H.264 decoder (H264_DECODER_HINT): h264_rkmpp
00:00:08 - SDL Info (0): FFmpeg-based video decoder chosen
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaaf9493c60] Wrote 48152 bytes to decoder
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaaf9493c60] Wrote 15128 bytes to decoder
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaaf9493c60] Wrote 17880 bytes to decoder
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaaf9493c60] Wrote 16504 bytes to decoder
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaaf9493c60] Noticed an info change
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaaf9493c60] Decoder options: deint=true afbc=0 fast_parse=true buf_mode=0
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaaf9493c60] Configured with size: 2560x1440 | pix_fmt: drm_prime | sw_pix_fmt: nv12
00:00:08 - SDL Info (0): Dropping window event during flush: 6 (2560 1440)
00:00:08 - SDL Info (0): IDR frame request sent
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaaf9493c60] Received a frame
00:00:08 - SDL Info (0): EGLRenderer: EGLImage pixel format: 179
00:00:08 - Qt Info: Found "egl.vert" at ":/data/egl.vert"
00:00:08 - Qt Info: Found "egl_opaque.frag" at ":/data/egl_opaque.frag"
00:00:08 - Qt Info: Found "egl.vert" at ":/data/egl.vert"
00:00:08 - Qt Info: Found "egl_overlay.frag" at ":/data/egl_overlay.frag"
00:02:50 - SDL Info (0): Detected quit key combo
00:02:50 - SDL Info (0): Quit event received
00:02:50 - SDL Info (0): Raising 3 keys
00:02:50 - SDL Info (0):
Global video stats
------------------
Incoming frame rate from network: 25.52 FPS
Decoding frame rate: 25.52 FPS
Rendering frame rate: 25.45 FPS
Host processing latency min/max/average: 34.0/127.9/45.4 ms
Frames dropped by your network connection: 0.00%
Frames dropped due to network jitter: 0.10%
Average network latency: 8 ms (variance: 4 ms)
Average decoding time: 7.06 ms
Average frame queue delay: 0.33 ms
Average rendering time (including monitor V-sync latency): 1.91 ms
00:02:50 - SDL Info (0): Stopping input stream...
00:02:50 - SDL Info (0): done
00:02:50 - SDL Info (0): Stopping audio stream...
00:02:50 - SDL Info (0): No audio traffic was ever received from the host!
00:02:50 - SDL Info (0): ENet wait interrupted
00:02:50 - SDL Info (0): Control stream connection failed: 4
00:02:50 - SDL Info (0): done
00:02:50 - SDL Info (0): Stopping video stream...
00:02:50 - Qt Info: Found "gamecontrollerdb.txt" at "/home/armbian/.cache/Moonlight Game Streaming Project/Moonlight/gamecontrollerdb.txt"
00:02:50 - SDL Info (0): done
00:02:50 - SDL Info (0): Stopping control stream...
00:02:50 - SDL Info (0): Loaded 436 new gamepad mappings
00:02:50 - SDL Info (0): ENet peer acknowledged disconnection
00:02:50 - SDL Info (0): done
00:02:50 - SDL Info (0): Cleaning up input stream...
00:02:50 - SDL Info (0): done
00:02:50 - SDL Info (0): Cleaning up video stream...
00:02:50 - SDL Info (0): done
00:02:50 - SDL Info (0): Cleaning up control stream...
00:02:50 - SDL Info (0): done
00:02:50 - SDL Info (0): Cleaning up audio stream...
00:02:50 - SDL Info (0): done
00:02:50 - SDL Info (0): Cleaning up platform...
00:02:50 - SDL Info (0): done
[VDI launch]
profile=low-latency
program=/home/armbian/vdi-terminal/bin/vdi-moonlight-rkmpp
decoder=hardware
codec=H.264
vsync=0
frame-pacing=0
renderer=opengles2
video-driver=
args=stream 192.168.1.70 Desktop --resolution 2560x1440 --fps 30 --bitrate 30000 --display-mode fullscreen --video-codec H.264 --video-decoder hardware --absolute-mouse --keep-awake --no-vsync --no-frame-pacing --audio-on-host
00:00:00 - SDL Info (0): Compiled with SDL 2.30.0
00:00:00 - SDL Info (0): Running with SDL 2.30.0
00:00:00 - Qt Info: Successfully loaded translation for "zh_CN"
00:00:00 - Qt Info: Loaded unique ID from settings: "95da1945b8736669"
00:00:00 - Qt Warning: qrc:/gui/main.qml:13:1: QML ApplicationWindow: ToolTip must be attached to an Item
00:00:01 - Qt Info: Found "gamecontrollerdb.txt" at "/home/armbian/.cache/Moonlight Game Streaming Project/Moonlight/gamecontrollerdb.txt"
00:00:01 - SDL Info (0): Loaded 436 new gamepad mappings
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:9
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:47009
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:47998
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:47999
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:48000
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:48002
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:48010
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:9
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:47009
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:47998
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:47999
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:48000
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:48002
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:48010
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:9
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:47009
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:47998
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:47999
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:48000
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:48002
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:48010
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:9
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:47009
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:47998
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:47999
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:48000
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:48002
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:48010
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:9
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:47009
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:47998
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:47999
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:48000
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:48002
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:48010
00:00:01 - Qt Debug: Current Moonlight version: "6.2.0"
00:00:01 - Qt Info: Discovered mDNS host: "DESKTOP-Q072ICM.local."
00:00:01 - Qt Info: "DESKTOP-Q072ICM" is now online at "192.168.1.70:47989"
00:00:01 - Qt Info: Found "ModeSeven.ttf" at ":/data/ModeSeven.ttf"
00:00:01 - SDL Info (0): Qt UI screen is at (0,0)
00:00:01 - SDL Info (0): SDL found matching display 0
00:00:01 - Qt Info: Server GPU: ""
00:00:01 - Qt Info: Server GFE version: "3.23.0.74"
00:00:02 - SDL Info (0): Video bitrate: 30000 kbps
00:00:02 - SDL Info (0): Audio channel count: 2
00:00:02 - SDL Info (0): Audio channel mask: 3
00:00:02 - SDL Info (0): Desired audio buffer: 720 samples (5760 bytes)
00:00:02 - SDL Info (0): Obtained audio buffer: 720 samples (5760 bytes)
00:00:02 - SDL Info (0): SDL audio driver: pulseaudio
00:00:02 - Qt Info: Found "gamecontrollerdb.txt" at "/home/armbian/.cache/Moonlight Game Streaming Project/Moonlight/gamecontrollerdb.txt"
00:00:02 - SDL Info (0): Loaded 436 new gamepad mappings
00:00:02 - SDL Info (0): V-sync disabled
00:00:02 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:02 - SDL Info (0): GPU driver: rockchip
00:00:02 - SDL Info (0): Direct rendering via DRM is disabled
00:00:02 - SDL Info (0): DRM backend supports exporting EGLImage
00:00:02 - SDL Info (0): Color buffer is: R8G8B8A0
00:00:02 - SDL Info (0): Using DRM renderer
00:00:02 - FFmpeg: [h264_mp4toannexb @ 0xaaaae8148f80] The input looks like it is Annex B already
mpp[66385]: mpp_info: mpp version: 7916c3c author: Xiaoxu Chen 2026-10-28 fix[utils]: Fix AVC cu_map allocation stride
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaae7adb140] Picked up an existing RKMPP hardware device
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaae7adb140] Wrote 390 bytes to decoder
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaae7adb140] Wrote 390 bytes to decoder
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaae7adb140] Noticed an info change
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaae7adb140] Decoder options: deint=true afbc=0 fast_parse=true buf_mode=0
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaae7adb140] Configured with size: 1280x720 | pix_fmt: drm_prime | sw_pix_fmt: nv12
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaae7adb140] Wrote 390 bytes to decoder
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaae7adb140] Received a frame
00:00:02 - SDL Warn (0): Using custom H.264 decoder (H264_DECODER_HINT): h264_rkmpp
00:00:02 - SDL Info (0): FFmpeg-based video decoder chosen
00:00:02 - SDL Info (0): V-sync disabled
00:00:02 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:02 - SDL Info (0): GPU driver: rockchip
00:00:02 - SDL Info (0): Direct rendering via DRM is disabled
00:00:02 - SDL Info (0): DRM backend supports exporting EGLImage
00:00:02 - SDL Info (0): Color buffer is: R8G8B8A0
00:00:02 - SDL Info (0): Using DRM renderer
00:00:02 - FFmpeg: [h264_mp4toannexb @ 0xaaaae859afc0] The input looks like it is Annex B already
mpp[66385]: mpp_info: mpp version: 7916c3c author: Xiaoxu Chen 2026-10-28 fix[utils]: Fix AVC cu_map allocation stride
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaae7adb140] Picked up an existing RKMPP hardware device
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaae7adb140] Wrote 390 bytes to decoder
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaae7adb140] Wrote 390 bytes to decoder
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaae7adb140] Noticed an info change
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaae7adb140] Decoder options: deint=true afbc=0 fast_parse=true buf_mode=0
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaae7adb140] Configured with size: 1280x720 | pix_fmt: drm_prime | sw_pix_fmt: nv12
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaae7adb140] Wrote 390 bytes to decoder
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaae7adb140] Received a frame
00:00:02 - SDL Warn (0): Using custom H.264 decoder (H264_DECODER_HINT): h264_rkmpp
00:00:02 - SDL Info (0): FFmpeg-based video decoder chosen
00:00:02 - Qt Warning: 启用远程桌面鼠标模式可能会导致游戏出现问题。
00:00:03 - Qt Info: Gamepad mappings are up to date
00:00:06 - Qt Info: Found "gamecontrollerdb.txt" at "/home/armbian/.cache/Moonlight Game Streaming Project/Moonlight/gamecontrollerdb.txt"
00:00:06 - SDL Info (0): Loaded 436 new gamepad mappings
00:00:06 - Qt Info: Executing request: "https://192.168.1.70:47984/resume?uniqueid=95da1945b8736669&uuid=90dfc80ae65d4b1bb02c722d2a22325f&appid=881448767&mode=2560x1440x30&additionalStates=1&sops=1&rikey=REDACTED&rikeyid=REDACTED&localAudioPlayMode=1&surroundAudioInfo=196610&remoteControllersBitmap=0&gcmap=0&gcpersist=0&corever=1"
00:00:06 - Qt Info: Launch response: "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root status_code=\"200\"><sessionUrl0>rtspenc://192.168.1.70:48010</sessionUrl0><resume>1</resume></root>"
00:00:06 - Qt Info: Found matching interface: "wlan0" "88:00:33:77:30:B6" QFlags<QNetworkInterface::InterfaceFlag>(IsUp|IsRunning|CanBroadcast|CanMulticast)
00:00:06 - Qt Info: Interface Type: QNetworkInterface::Wifi
00:00:06 - Qt Info: Interface MTU: 1500
00:00:06 - SDL Info (0): RTSP port: 48010
00:00:06 - SDL Info (0): Initializing platform...
00:00:06 - SDL Info (0): done
00:00:06 - SDL Info (0): Resolving host name...
00:00:06 - SDL Info (0): done
00:00:06 - SDL Info (0): Initializing audio stream...
00:00:06 - SDL Info (0): done
00:00:06 - SDL Info (0): Starting RTSP handshake...
00:00:06 - SDL Info (0): Reference frame invalidation is not supported by this host
00:00:06 - SDL Info (0): Audio port: 48000
00:00:06 - SDL Info (0): Video port: 47998
00:00:06 - SDL Info (0): Control port: 47999
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Initializing control stream...
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Initializing video stream...
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Initializing input stream...
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Starting control stream...
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Starting video stream...
00:00:07 - SDL Info (0): Video stream is 2560x1440x30 (format 0x1)
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Starting audio stream...
00:00:07 - SDL Info (0): Desired audio buffer: 720 samples (5760 bytes)
00:00:07 - SDL Info (0): Obtained audio buffer: 720 samples (5760 bytes)
00:00:07 - SDL Info (0): SDL audio driver: pulseaudio
00:00:07 - SDL Info (0): Audio stream has 2 channels
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Starting input stream...
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Received first video packet after 0 ms
00:00:07 - SDL Info (0): Qt UI screen is at (0,0)
00:00:07 - SDL Info (0): SDL found matching display 0
00:00:07 - SDL Info (0): Found display mode with desktop resolution: 2560x1440x60
00:00:07 - SDL Info (0): Recreating renderer for window event: 1 (0 0)
00:00:07 - SDL Info (0): V-sync disabled
00:00:07 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:07 - SDL Info (0): GPU driver: rockchip
00:00:07 - SDL Info (0): Direct rendering via DRM is disabled
00:00:07 - SDL Info (0): DRM backend supports exporting EGLImage
00:00:07 - SDL Info (0): Video decode unit queue overflow
00:00:07 - SDL Info (0): IDR frame request sent
00:00:07 - SDL Info (0): Waiting for IDR frame
00:00:08 - SDL Info (0): Color buffer is: R8G8B8A0
00:00:08 - SDL Info (0): Using DRM renderer
00:00:08 - FFmpeg: [h264_mp4toannexb @ 0xaaaae89dd090] The input looks like it is Annex B already
mpp[66385]: mpp_info: mpp version: 7916c3c author: Xiaoxu Chen 2026-10-28 fix[utils]: Fix AVC cu_map allocation stride
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaae7adb140] Picked up an existing RKMPP hardware device
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaae7adb140] Wrote 390 bytes to decoder
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaae7adb140] Wrote 390 bytes to decoder
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaae7adb140] Noticed an info change
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaae7adb140] Decoder options: deint=true afbc=0 fast_parse=true buf_mode=0
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaae7adb140] Configured with size: 1280x720 | pix_fmt: drm_prime | sw_pix_fmt: nv12
00:00:08 - SDL Info (0): Video decode unit queue overflow
00:00:08 - SDL Info (0): IDR frame request sent
00:00:08 - SDL Info (0): Waiting for IDR frame
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaae7adb140] Wrote 390 bytes to decoder
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaae7adb140] Received a frame
00:00:08 - SDL Info (0): Not reusing test decoder for h264_rkmpp
00:00:08 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:08 - SDL Info (0): GPU driver: rockchip
00:00:08 - SDL Info (0): Direct rendering via DRM is disabled
00:00:08 - SDL Info (0): DRM backend supports exporting EGLImage
00:00:08 - SDL Info (0): Color buffer is: R8G8B8A0
00:00:08 - SDL Info (0): Frame pacing disabled: target 60 Hz with 30 FPS stream
00:00:08 - SDL Info (0): Using DRM renderer
mpp[66385]: mpp_info: mpp version: 7916c3c author: Xiaoxu Chen 2026-10-28 fix[utils]: Fix AVC cu_map allocation stride
00:00:08 - FFmpeg: [h264_mp4toannexb @ 0xaaaae89d8820] The input looks like it is Annex B already
00:00:08 - SDL Warn (0): Unable to set render thread to high priority: setpriority() failed
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaae7adb140] Picked up an existing RKMPP hardware device
00:00:08 - SDL Info (0): Using H.264 SPS fixup
00:00:08 - SDL Info (0): Renderer 'EGL/GLES' with 'DRM' backend chosen
00:00:08 - SDL Warn (0): Using custom H.264 decoder (H264_DECODER_HINT): h264_rkmpp
00:00:08 - SDL Info (0): FFmpeg-based video decoder chosen
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaae7adb140] Wrote 46776 bytes to decoder
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaae7adb140] Wrote 11000 bytes to decoder
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaae7adb140] Noticed an info change
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaae7adb140] Decoder options: deint=true afbc=0 fast_parse=true buf_mode=0
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaae7adb140] Configured with size: 2560x1440 | pix_fmt: drm_prime | sw_pix_fmt: nv12
00:00:08 - SDL Info (0): Dropping window event during flush: 6 (2560 1440)
00:00:08 - SDL Info (0): IDR frame request sent
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaae7adb140] Wrote 11000 bytes to decoder
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaae7adb140] Received a frame
00:00:08 - SDL Info (0): EGLRenderer: EGLImage pixel format: 179
00:00:08 - Qt Info: Found "egl.vert" at ":/data/egl.vert"
00:00:08 - Qt Info: Found "egl_opaque.frag" at ":/data/egl_opaque.frag"
00:00:08 - Qt Info: Found "egl.vert" at ":/data/egl.vert"
00:00:08 - Qt Info: Found "egl_overlay.frag" at ":/data/egl_overlay.frag"

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

View File

@ -0,0 +1,249 @@
00:00:00 - SDL Info (0): Compiled with SDL 2.33.0
00:00:00 - SDL Info (0): Running with SDL 2.33.0
00:00:00 - Qt Info: Successfully loaded translation for "zh_CN"
00:00:00 - Qt Info: Loaded unique ID from settings: "95da1945b8736669"
00:00:00 - Qt Warning: qrc:/gui/main.qml:13:1: QML ApplicationWindow: ToolTip must be attached to an Item
00:00:01 - Qt Info: Found "gamecontrollerdb.txt" at "/home/armbian/.cache/Moonlight Game Streaming Project/Moonlight/gamecontrollerdb.txt"
00:00:01 - SDL Info (0): Loaded 435 new gamepad mappings
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:9
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:47009
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:47998
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:47999
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:48000
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:48002
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:48010
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:9
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:47009
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:47998
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:47999
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:48000
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:48002
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:48010
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:9
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:47009
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:47998
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:47999
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:48000
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:48002
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:48010
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:9
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:47009
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:47998
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:47999
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:48000
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:48002
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:48010
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:9
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:47009
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:47998
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:47999
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:48000
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:48002
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:48010
00:00:01 - Qt Debug: Current Moonlight version: "6.2.0"
00:00:01 - Qt Info: Discovered mDNS host: "DESKTOP-Q072ICM.local."
00:00:01 - Qt Info: "DESKTOP-Q072ICM" is now online at "192.168.1.70:47989"
00:00:01 - Qt Info: Found "ModeSeven.ttf" at ":/data/ModeSeven.ttf"
00:00:01 - SDL Info (0): Qt UI screen is at (0,0)
00:00:01 - SDL Info (0): SDL found matching display 0
00:00:01 - Qt Info: Server GPU: ""
00:00:01 - Qt Info: Server GFE version: "3.23.0.74"
00:00:01 - SDL Info (0): Video bitrate: 30000 kbps
00:00:01 - SDL Info (0): Audio channel count: 2
00:00:01 - SDL Info (0): Audio channel mask: 3
00:00:02 - SDL Info (0): Desired audio buffer: 720 samples (5760 bytes)
00:00:02 - SDL Info (0): Obtained audio buffer: 720 samples (5760 bytes)
00:00:02 - SDL Info (0): SDL audio driver: pulseaudio
00:00:02 - Qt Info: Found "gamecontrollerdb.txt" at "/home/armbian/.cache/Moonlight Game Streaming Project/Moonlight/gamecontrollerdb.txt"
00:00:02 - SDL Info (0): Loaded 435 new gamepad mappings
00:00:02 - SDL Info (0): V-sync disabled
00:00:02 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:02 - SDL Info (0): GPU driver: rockchip
00:00:02 - SDL Info (0): Direct rendering via DRM is disabled
00:00:02 - SDL Info (0): DRM backend supports exporting EGLImage
00:00:02 - SDL Info (0): Color buffer is: R8G8B8A0
00:00:02 - SDL Info (0): Using DRM renderer
00:00:02 - FFmpeg: [h264 @ 0xaaaaf2adf910] nal_unit_type: 7(SPS), nal_ref_idc: 3
00:00:02 - FFmpeg: [h264 @ 0xaaaaf2adf910] nal_unit_type: 8(PPS), nal_ref_idc: 3
00:00:02 - FFmpeg: [h264 @ 0xaaaaf2adf910] nal_unit_type: 5(IDR), nal_ref_idc: 3
00:00:02 - FFmpeg: [h264 @ 0xaaaaf2adf910] nal_unit_type: 5(IDR), nal_ref_idc: 3
00:00:02 - FFmpeg: [h264 @ 0xaaaaf2adf910] nal_unit_type: 5(IDR), nal_ref_idc: 3
00:00:02 - FFmpeg: [h264 @ 0xaaaaf2adf910] nal_unit_type: 5(IDR), nal_ref_idc: 3
00:00:02 - FFmpeg: [h264 @ 0xaaaaf2adf910] Decoding VUI
00:00:02 - FFmpeg: [h264 @ 0xaaaaf2adf910] Format drm_prime chosen by get_format().
00:00:02 - FFmpeg: [h264 @ 0xaaaaf2adf910] Invalid setup for format drm_prime: missing configuration.
00:00:02 - FFmpeg: [h264 @ 0xaaaaf2adf910] Format drm_prime not usable, retrying get_format() without it.
00:00:02 - FFmpeg: [h264 @ 0xaaaaf2adf910] Format yuv420p chosen by get_format().
00:00:02 - FFmpeg: [h264 @ 0xaaaaf2adf910] Reinit context to 1280x720, pix_fmt: yuv420p
00:00:02 - SDL Warn (0): EGLImage export requires hardware-backed frames
00:00:02 - SDL Warn (0): Backend failed to export EGL image for test frame
00:00:02 - SDL Warn (0): Test decode failed (testRenderFrame)
00:00:02 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:02 - SDL Info (0): GPU driver: rockchip
00:00:02 - SDL Info (0): Direct rendering via DRM is disabled
00:00:02 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:02 - SDL Info (0): GPU driver: rockchip
00:00:02 - SDL Info (0): Direct rendering via DRM is disabled
00:00:02 - SDL Info (0): Using DRM renderer
00:00:02 - FFmpeg: [h264 @ 0xaaaaf2adf910] nal_unit_type: 7(SPS), nal_ref_idc: 3
00:00:02 - FFmpeg: [h264 @ 0xaaaaf2adf910] nal_unit_type: 8(PPS), nal_ref_idc: 3
00:00:02 - FFmpeg: [h264 @ 0xaaaaf2adf910] nal_unit_type: 5(IDR), nal_ref_idc: 3
00:00:02 - FFmpeg: [h264 @ 0xaaaaf2adf910] nal_unit_type: 5(IDR), nal_ref_idc: 3
00:00:02 - FFmpeg: [h264 @ 0xaaaaf2adf910] nal_unit_type: 5(IDR), nal_ref_idc: 3
00:00:02 - FFmpeg: [h264 @ 0xaaaaf2adf910] nal_unit_type: 5(IDR), nal_ref_idc: 3
00:00:02 - FFmpeg: [h264 @ 0xaaaaf2adf910] Decoding VUI
00:00:02 - FFmpeg: [h264 @ 0xaaaaf2adf910] Format yuv420p chosen by get_format().
00:00:02 - FFmpeg: [h264 @ 0xaaaaf2adf910] Reinit context to 1280x720, pix_fmt: yuv420p
00:00:02 - SDL Info (0): FFmpeg-based video decoder chosen
00:00:02 - SDL Info (0): Encoder configured for 4 slices per frame
00:00:02 - Qt Warning: 启用远程桌面鼠标模式可能会导致游戏出现问题。
00:00:02 - Qt Warning: 你选择的用于强制软件解码的设置可能会导致流式传输性能不佳。
00:00:03 - Qt Info: Processing new PC "DESKTOP-Q072ICM.local." from mDNS with local address "192.168.1.70:47989"
00:00:03 - Qt Info: Executing request: "http://192.168.1.70:47989/serverinfo?uniqueid=0123456789ABCDEF&uuid=ebc03298cf8c48b08710bdc9e8df351a"
00:00:03 - Qt Info: Executing request: "https://192.168.1.70:47984/serverinfo?uniqueid=95da1945b8736669&uuid=81445f65f6e8426bbf57e183f3bda211"
00:00:05 - Qt Info: Found "gamecontrollerdb.txt" at "/home/armbian/.cache/Moonlight Game Streaming Project/Moonlight/gamecontrollerdb.txt"
00:00:05 - SDL Info (0): Loaded 435 new gamepad mappings
00:00:05 - Qt Info: Executing request: "https://192.168.1.70:47984/resume?uniqueid=95da1945b8736669&uuid=b788d125e836493a85f7eacede1e24eb&appid=881448767&mode=2560x1440x20&additionalStates=1&sops=1&rikey=REDACTED&rikeyid=REDACTED&localAudioPlayMode=0&surroundAudioInfo=196610&remoteControllersBitmap=0&gcmap=0&gcpersist=0&corever=1"
00:00:06 - Qt Info: Launch response: "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root status_code=\"200\"><sessionUrl0>rtspenc://192.168.1.70:48010</sessionUrl0><resume>1</resume></root>"
00:00:06 - Qt Info: Found matching interface: "wlan0" "88:00:33:77:30:B6" QFlags<QNetworkInterface::InterfaceFlag>(IsUp|IsRunning|CanBroadcast|CanMulticast)
00:00:06 - Qt Info: Interface Type: QNetworkInterface::Wifi
00:00:06 - Qt Info: Interface MTU: 1500
00:00:06 - SDL Info (0): RTSP port: 48010
00:00:06 - SDL Info (0): Initializing platform...
00:00:06 - SDL Info (0): done
00:00:06 - SDL Info (0): Resolving host name...
00:00:06 - SDL Info (0): done
00:00:06 - SDL Info (0): Initializing audio stream...
00:00:06 - SDL Info (0): done
00:00:06 - SDL Info (0): Starting RTSP handshake...
00:00:06 - SDL Info (0): Reference frame invalidation is not supported by this host
00:00:06 - SDL Info (0): Audio port: 48000
00:00:06 - SDL Info (0): Video port: 47998
00:00:06 - SDL Info (0): Control port: 47999
00:00:06 - SDL Info (0): done
00:00:06 - SDL Info (0): Initializing control stream...
00:00:06 - SDL Info (0): done
00:00:06 - SDL Info (0): Initializing video stream...
00:00:06 - SDL Info (0): done
00:00:06 - SDL Info (0): Initializing input stream...
00:00:06 - SDL Info (0): done
00:00:06 - SDL Info (0): Starting control stream...
00:00:06 - SDL Info (0): done
00:00:06 - SDL Info (0): Starting video stream...
00:00:06 - SDL Info (0): Video stream is 2560x1440x20 (format 0x1)
00:00:06 - SDL Info (0): done
00:00:06 - SDL Info (0): Starting audio stream...
00:00:06 - SDL Info (0): Desired audio buffer: 720 samples (5760 bytes)
00:00:06 - SDL Info (0): Obtained audio buffer: 720 samples (5760 bytes)
00:00:06 - SDL Info (0): SDL audio driver: pulseaudio
00:00:06 - SDL Info (0): Audio stream has 2 channels
00:00:06 - SDL Info (0): done
00:00:06 - SDL Info (0): Starting input stream...
00:00:06 - SDL Info (0): done
00:00:06 - SDL Info (0): Received first video packet after 100 ms
00:00:06 - SDL Info (0): Qt UI screen is at (0,0)
00:00:06 - SDL Info (0): SDL found matching display 0
00:00:06 - SDL Info (0): Found display mode with desktop resolution: 2560x1440x60
00:00:07 - SDL Info (0): Recreating renderer for window event: 1 (0 0)
00:00:07 - SDL Info (0): V-sync disabled
00:00:07 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:07 - SDL Info (0): GPU driver: rockchip
00:00:07 - SDL Info (0): Direct rendering via DRM is disabled
00:00:07 - SDL Info (0): DRM backend supports exporting EGLImage
00:00:07 - SDL Info (0): Video decode unit queue overflow
00:00:07 - SDL Info (0): IDR frame request sent
00:00:07 - SDL Info (0): Waiting for IDR frame
00:00:07 - SDL Info (0): Color buffer is: R8G8B8A0
00:00:07 - SDL Info (0): Frame pacing disabled: target 60 Hz with 20 FPS stream
00:00:07 - SDL Info (0): Using DRM renderer
00:00:07 - FFmpeg: [h264 @ 0xaaaaf2adf910] nal_unit_type: 7(SPS), nal_ref_idc: 3
00:00:07 - FFmpeg: [h264 @ 0xaaaaf2adf910] nal_unit_type: 8(PPS), nal_ref_idc: 3
00:00:07 - FFmpeg: [h264 @ 0xaaaaf2adf910] nal_unit_type: 5(IDR), nal_ref_idc: 3
00:00:07 - FFmpeg: [h264 @ 0xaaaaf2adf910] nal_unit_type: 5(IDR), nal_ref_idc: 3
00:00:07 - FFmpeg: [h264 @ 0xaaaaf2adf910] nal_unit_type: 5(IDR), nal_ref_idc: 3
00:00:07 - FFmpeg: [h264 @ 0xaaaaf2adf910] nal_unit_type: 5(IDR), nal_ref_idc: 3
00:00:07 - FFmpeg: [h264 @ 0xaaaaf2adf910] Decoding VUI
00:00:07 - FFmpeg: [h264 @ 0xaaaaf2adf910] Format drm_prime chosen by get_format().
00:00:07 - FFmpeg: [h264 @ 0xaaaaf2adf910] Invalid setup for format drm_prime: missing configuration.
00:00:07 - FFmpeg: [h264 @ 0xaaaaf2adf910] Format drm_prime not usable, retrying get_format() without it.
00:00:07 - FFmpeg: [h264 @ 0xaaaaf2adf910] Format yuv420p chosen by get_format().
00:00:07 - FFmpeg: [h264 @ 0xaaaaf2adf910] Reinit context to 1280x720, pix_fmt: yuv420p
00:00:07 - SDL Warn (0): Unable to set render thread to high priority: setpriority() failed
00:00:07 - SDL Warn (0): EGLImage export requires hardware-backed frames
00:00:07 - SDL Warn (0): Backend failed to export EGL image for test frame
00:00:07 - SDL Warn (0): Test decode failed (testRenderFrame)
00:00:07 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:07 - SDL Info (0): GPU driver: rockchip
00:00:07 - SDL Info (0): Direct rendering via DRM is disabled
00:00:07 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:07 - SDL Info (0): GPU driver: rockchip
00:00:07 - SDL Info (0): Direct rendering via DRM is disabled
00:00:07 - SDL Info (0): Frame pacing disabled: target 60 Hz with 20 FPS stream
00:00:07 - SDL Info (0): SDL renderer backend: opengles2
00:00:07 - SDL Info (0): SDL renderer backend requires main thread rendering
00:00:07 - SDL Info (0): Using DRM renderer
00:00:07 - FFmpeg: [h264 @ 0xaaaaf2adf910] nal_unit_type: 7(SPS), nal_ref_idc: 3
00:00:07 - FFmpeg: [h264 @ 0xaaaaf2adf910] nal_unit_type: 8(PPS), nal_ref_idc: 3
00:00:07 - FFmpeg: [h264 @ 0xaaaaf2adf910] nal_unit_type: 5(IDR), nal_ref_idc: 3
00:00:07 - FFmpeg: [h264 @ 0xaaaaf2adf910] nal_unit_type: 5(IDR), nal_ref_idc: 3
00:00:07 - FFmpeg: [h264 @ 0xaaaaf2adf910] nal_unit_type: 5(IDR), nal_ref_idc: 3
00:00:07 - FFmpeg: [h264 @ 0xaaaaf2adf910] nal_unit_type: 5(IDR), nal_ref_idc: 3
00:00:07 - FFmpeg: [h264 @ 0xaaaaf2adf910] Decoding VUI
00:00:07 - FFmpeg: [h264 @ 0xaaaaf2adf910] Format yuv420p chosen by get_format().
00:00:07 - FFmpeg: [h264 @ 0xaaaaf2adf910] Reinit context to 1280x720, pix_fmt: yuv420p
00:00:08 - SDL Info (0): Test decode successful
00:00:08 - SDL Info (0): Using H.264 SPS fixup
00:00:08 - SDL Info (0): Renderer 'SDL' with 'DRM' backend chosen
00:00:08 - SDL Info (0): FFmpeg-based video decoder chosen
00:00:08 - FFmpeg: [h264 @ 0xaaaaf2adf910] nal_unit_type: 7(SPS), nal_ref_idc: 3
00:00:08 - FFmpeg: [h264 @ 0xaaaaf2adf910] nal_unit_type: 8(PPS), nal_ref_idc: 3
00:00:08 - FFmpeg: [h264 @ 0xaaaaf2adf910] nal_unit_type: 5(IDR), nal_ref_idc: 3
00:00:08 - FFmpeg: [h264 @ 0xaaaaf2adf910] nal_unit_type: 5(IDR), nal_ref_idc: 3
00:00:08 - FFmpeg: [h264 @ 0xaaaaf2adf910] nal_unit_type: 5(IDR), nal_ref_idc: 3
00:00:08 - FFmpeg: [h264 @ 0xaaaaf2adf910] nal_unit_type: 5(IDR), nal_ref_idc: 3
00:00:08 - FFmpeg: [h264 @ 0xaaaaf2adf910] Decoding VUI
00:00:08 - FFmpeg: [h264 @ 0xaaaaf2adf910] Format yuvj420p chosen by get_format().
00:00:08 - FFmpeg: [h264 @ 0xaaaaf2adf910] Reinit context to 2560x1440, pix_fmt: yuvj420p
00:00:08 - SDL Info (0): Dropping window event during flush: 6 (2560 1440)
00:00:08 - SDL Info (0): IDR frame request sent
00:03:27 - SDL Info (0): Raising 3 keys
00:03:27 - SDL Info (0): Detected quit key combo
00:03:27 - SDL Info (0): Quit event received
00:03:27 - SDL Info (0):
Global video stats
------------------
Incoming frame rate from network: 17.07 FPS
Decoding frame rate: 17.07 FPS
Rendering frame rate: 17.01 FPS
Host processing latency min/max/average: 24.1/104.8/35.4 ms
Frames dropped by your network connection: 0.00%
Frames dropped due to network jitter: 0.29%
Average network latency: 11 ms (variance: 6 ms)
Average decoding time: 16.96 ms
Average frame queue delay: 1.14 ms
Average rendering time (including monitor V-sync latency): 10.87 ms
00:03:28 - SDL Info (0): Stopping input stream...
00:03:28 - SDL Info (0): done
00:03:28 - SDL Info (0): Stopping audio stream...
00:03:28 - SDL Info (0): No audio traffic was ever received from the host!
00:03:28 - SDL Info (0): ENet wait interrupted
00:03:28 - SDL Info (0): Control stream connection failed: 4
00:03:28 - Qt Info: Gamepad mappings are up to date
00:03:28 - SDL Info (0): done
00:03:28 - SDL Info (0): Stopping video stream...
00:03:28 - SDL Info (0): done
00:03:28 - SDL Info (0): Stopping control stream...
00:03:28 - SDL Info (0): ENet peer acknowledged disconnection
00:03:28 - SDL Info (0): done
00:03:28 - SDL Info (0): Cleaning up input stream...
00:03:28 - SDL Info (0): done
00:03:28 - SDL Info (0): Cleaning up video stream...
00:03:28 - SDL Info (0): done
00:03:28 - SDL Info (0): Cleaning up control stream...
00:03:28 - SDL Info (0): done
00:03:28 - SDL Info (0): Cleaning up audio stream...
00:03:28 - SDL Info (0): done
00:03:28 - SDL Info (0): Cleaning up platform...
00:03:28 - SDL Info (0): done
00:03:28 - Qt Info: Found "gamecontrollerdb.txt" at "/home/armbian/.cache/Moonlight Game Streaming Project/Moonlight/gamecontrollerdb.txt"
00:03:28 - SDL Info (0): Loaded 435 new gamepad mappings

View File

@ -0,0 +1,237 @@
00:00:00 - SDL Info (0): Compiled with SDL 2.30.0
00:00:00 - SDL Info (0): Running with SDL 2.30.0
00:00:00 - Qt Info: Successfully loaded translation for "zh_CN"
00:00:00 - Qt Info: Loaded unique ID from settings: "95da1945b8736669"
00:00:00 - Qt Warning: qrc:/gui/main.qml:13:1: QML ApplicationWindow: ToolTip must be attached to an Item
00:00:01 - Qt Info: Found "gamecontrollerdb.txt" at "/home/armbian/.cache/Moonlight Game Streaming Project/Moonlight/gamecontrollerdb.txt"
00:00:01 - SDL Info (0): Loaded 436 new gamepad mappings
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:9
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:47009
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:47998
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:47999
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:48000
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:48002
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:48010
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:9
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:47009
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:47998
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:47999
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:48000
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:48002
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:48010
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:9
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:47009
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:47998
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:47999
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:48000
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:48002
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:48010
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:9
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:47009
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:47998
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:47999
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:48000
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:48002
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:48010
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:9
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:47009
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:47998
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:47999
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:48000
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:48002
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:48010
00:00:01 - Qt Debug: Current Moonlight version: "6.2.0"
00:00:01 - Qt Info: Discovered mDNS host: "DESKTOP-Q072ICM.local."
00:00:01 - Qt Info: "DESKTOP-Q072ICM" is now online at "192.168.1.70:47989"
00:00:01 - Qt Info: Found "ModeSeven.ttf" at ":/data/ModeSeven.ttf"
00:00:02 - SDL Info (0): Qt UI screen is at (0,0)
00:00:02 - SDL Info (0): SDL found matching display 0
00:00:02 - Qt Info: Server GPU: ""
00:00:02 - Qt Info: Server GFE version: "3.23.0.74"
00:00:02 - SDL Info (0): Video bitrate: 30000 kbps
00:00:02 - SDL Info (0): Audio channel count: 2
00:00:02 - SDL Info (0): Audio channel mask: 3
00:00:02 - SDL Info (0): Desired audio buffer: 720 samples (5760 bytes)
00:00:02 - SDL Info (0): Obtained audio buffer: 720 samples (5760 bytes)
00:00:02 - SDL Info (0): SDL audio driver: pulseaudio
00:00:02 - Qt Info: Found "gamecontrollerdb.txt" at "/home/armbian/.cache/Moonlight Game Streaming Project/Moonlight/gamecontrollerdb.txt"
00:00:02 - SDL Info (0): Loaded 436 new gamepad mappings
00:00:02 - SDL Info (0): V-sync disabled
00:00:02 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:02 - SDL Info (0): GPU driver: rockchip
00:00:02 - SDL Info (0): Direct rendering via DRM is disabled
00:00:02 - SDL Info (0): DRM backend supports exporting EGLImage
00:00:02 - SDL Info (0): Color buffer is: R8G8B8A0
00:00:02 - SDL Info (0): Using DRM renderer
00:00:02 - FFmpeg: [h264_mp4toannexb @ 0xaaaaea8769f0] The input looks like it is Annex B already
mpp[51478]: mpp_info: mpp version: 7916c3c author: Xiaoxu Chen 2026-10-28 fix[utils]: Fix AVC cu_map allocation stride
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaea1ff9d0] Picked up an existing RKMPP hardware device
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaea1ff9d0] Wrote 390 bytes to decoder
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaea1ff9d0] Wrote 390 bytes to decoder
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaea1ff9d0] Noticed an info change
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaea1ff9d0] Decoder options: deint=true afbc=0 fast_parse=true buf_mode=0
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaea1ff9d0] Configured with size: 1280x720 | pix_fmt: drm_prime | sw_pix_fmt: nv12
00:00:03 - FFmpeg: [h264_rkmpp @ 0xaaaaea1ff9d0] Wrote 390 bytes to decoder
00:00:03 - FFmpeg: [h264_rkmpp @ 0xaaaaea1ff9d0] Received a frame
00:00:03 - SDL Warn (0): Using custom H.264 decoder (H264_DECODER_HINT): h264_rkmpp
00:00:03 - SDL Info (0): FFmpeg-based video decoder chosen
00:00:03 - SDL Info (0): V-sync disabled
00:00:03 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:03 - SDL Info (0): GPU driver: rockchip
00:00:03 - SDL Info (0): Direct rendering via DRM is disabled
00:00:03 - SDL Info (0): DRM backend supports exporting EGLImage
00:00:03 - SDL Info (0): Color buffer is: R8G8B8A0
00:00:03 - SDL Info (0): Using DRM renderer
00:00:03 - FFmpeg: [h264_mp4toannexb @ 0xaaaaea88ab90] The input looks like it is Annex B already
mpp[51478]: mpp_info: mpp version: 7916c3c author: Xiaoxu Chen 2026-10-28 fix[utils]: Fix AVC cu_map allocation stride
00:00:03 - FFmpeg: [h264_rkmpp @ 0xaaaaea1ff9d0] Picked up an existing RKMPP hardware device
00:00:03 - FFmpeg: [h264_rkmpp @ 0xaaaaea1ff9d0] Wrote 390 bytes to decoder
00:00:03 - FFmpeg: [h264_rkmpp @ 0xaaaaea1ff9d0] Wrote 390 bytes to decoder
00:00:03 - FFmpeg: [h264_rkmpp @ 0xaaaaea1ff9d0] Noticed an info change
00:00:03 - FFmpeg: [h264_rkmpp @ 0xaaaaea1ff9d0] Decoder options: deint=true afbc=0 fast_parse=true buf_mode=0
00:00:03 - FFmpeg: [h264_rkmpp @ 0xaaaaea1ff9d0] Configured with size: 1280x720 | pix_fmt: drm_prime | sw_pix_fmt: nv12
00:00:03 - FFmpeg: [h264_rkmpp @ 0xaaaaea1ff9d0] Wrote 390 bytes to decoder
00:00:03 - FFmpeg: [h264_rkmpp @ 0xaaaaea1ff9d0] Received a frame
00:00:03 - SDL Warn (0): Using custom H.264 decoder (H264_DECODER_HINT): h264_rkmpp
00:00:03 - SDL Info (0): FFmpeg-based video decoder chosen
00:00:03 - Qt Warning: 启用远程桌面鼠标模式可能会导致游戏出现问题。
00:00:03 - Qt Info: Processing new PC "DESKTOP-Q072ICM.local." from mDNS with local address "192.168.1.70:47989"
00:00:03 - Qt Info: Executing request: "http://192.168.1.70:47989/serverinfo?uniqueid=0123456789ABCDEF&uuid=2c210dd36f6e44baaef56040d444099c"
00:00:03 - Qt Info: Executing request: "https://192.168.1.70:47984/serverinfo?uniqueid=95da1945b8736669&uuid=5dc654e7557140c5ad4a28a3e0cbf0e7"
00:00:05 - Qt Info: Gamepad mappings are up to date
00:00:07 - Qt Info: Found "gamecontrollerdb.txt" at "/home/armbian/.cache/Moonlight Game Streaming Project/Moonlight/gamecontrollerdb.txt"
00:00:07 - SDL Info (0): Loaded 436 new gamepad mappings
00:00:07 - Qt Info: Executing request: "https://192.168.1.70:47984/resume?uniqueid=95da1945b8736669&uuid=d326392167b5421ab723a1fd3511fae0&appid=881448767&mode=2560x1440x20&additionalStates=1&sops=1&rikey=REDACTED&rikeyid=REDACTED&localAudioPlayMode=1&surroundAudioInfo=196610&remoteControllersBitmap=0&gcmap=0&gcpersist=0&corever=1"
00:00:07 - Qt Info: Launch response: "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root status_code=\"200\"><sessionUrl0>rtspenc://192.168.1.70:48010</sessionUrl0><resume>1</resume></root>"
00:00:07 - Qt Info: Found matching interface: "wlan0" "88:00:33:77:30:B6" QFlags<QNetworkInterface::InterfaceFlag>(IsUp|IsRunning|CanBroadcast|CanMulticast)
00:00:07 - Qt Info: Interface Type: QNetworkInterface::Wifi
00:00:07 - Qt Info: Interface MTU: 1500
00:00:07 - SDL Info (0): RTSP port: 48010
00:00:07 - SDL Info (0): Initializing platform...
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Resolving host name...
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Initializing audio stream...
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Starting RTSP handshake...
00:00:07 - SDL Info (0): Reference frame invalidation is not supported by this host
00:00:07 - SDL Info (0): Audio port: 48000
00:00:07 - SDL Info (0): Video port: 47998
00:00:07 - SDL Info (0): Control port: 47999
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Initializing control stream...
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Initializing video stream...
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Initializing input stream...
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Starting control stream...
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Starting video stream...
00:00:07 - SDL Info (0): Video stream is 2560x1440x20 (format 0x1)
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Starting audio stream...
00:00:07 - SDL Info (0): Received first video packet after 0 ms
00:00:07 - SDL Info (0): Desired audio buffer: 720 samples (5760 bytes)
00:00:07 - SDL Info (0): Obtained audio buffer: 720 samples (5760 bytes)
00:00:07 - SDL Info (0): SDL audio driver: pulseaudio
00:00:07 - SDL Info (0): Audio stream has 2 channels
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Starting input stream...
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Qt UI screen is at (0,0)
00:00:07 - SDL Info (0): SDL found matching display 0
00:00:08 - SDL Info (0): Found display mode with desktop resolution: 2560x1440x60
00:00:08 - SDL Info (0): Recreating renderer for window event: 1 (0 0)
00:00:08 - SDL Info (0): V-sync enabled
00:00:08 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:08 - SDL Info (0): GPU driver: rockchip
00:00:08 - SDL Info (0): Direct rendering via DRM is disabled
00:00:08 - SDL Info (0): DRM backend supports exporting EGLImage
00:00:08 - SDL Info (0): Video decode unit queue overflow
00:00:08 - SDL Info (0): IDR frame request sent
00:00:08 - SDL Info (0): Waiting for IDR frame
00:00:08 - SDL Info (0): Color buffer is: R8G8B8A0
00:00:08 - SDL Info (0): Using DRM renderer
00:00:08 - FFmpeg: [h264_mp4toannexb @ 0xaaaaeb135880] The input looks like it is Annex B already
mpp[51478]: mpp_info: mpp version: 7916c3c author: Xiaoxu Chen 2026-10-28 fix[utils]: Fix AVC cu_map allocation stride
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaaea1ff9d0] Picked up an existing RKMPP hardware device
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaaea1ff9d0] Wrote 390 bytes to decoder
00:00:09 - FFmpeg: [h264_rkmpp @ 0xaaaaea1ff9d0] Wrote 390 bytes to decoder
00:00:09 - FFmpeg: [h264_rkmpp @ 0xaaaaea1ff9d0] Noticed an info change
00:00:09 - FFmpeg: [h264_rkmpp @ 0xaaaaea1ff9d0] Decoder options: deint=true afbc=0 fast_parse=true buf_mode=0
00:00:09 - FFmpeg: [h264_rkmpp @ 0xaaaaea1ff9d0] Configured with size: 1280x720 | pix_fmt: drm_prime | sw_pix_fmt: nv12
00:00:09 - FFmpeg: [h264_rkmpp @ 0xaaaaea1ff9d0] Wrote 390 bytes to decoder
00:00:09 - FFmpeg: [h264_rkmpp @ 0xaaaaea1ff9d0] Received a frame
00:00:09 - SDL Info (0): Not reusing test decoder for h264_rkmpp
00:00:09 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:09 - SDL Info (0): GPU driver: rockchip
00:00:09 - SDL Info (0): Direct rendering via DRM is disabled
00:00:09 - SDL Info (0): DRM backend supports exporting EGLImage
00:00:09 - SDL Info (0): Color buffer is: R8G8B8A0
00:00:09 - SDL Info (0): Frame pacing: target 60 Hz with 20 FPS stream
00:00:09 - SDL Info (0): Using DRM renderer
00:00:09 - FFmpeg: [h264_mp4toannexb @ 0xaaaaeaef0980] The input looks like it is Annex B already
mpp[51478]: mpp_info: mpp version: 7916c3c author: Xiaoxu Chen 2026-10-28 fix[utils]: Fix AVC cu_map allocation stride
00:00:09 - SDL Warn (0): Unable to set render thread to high priority: setpriority() failed
00:00:09 - FFmpeg: [h264_rkmpp @ 0xaaaaea1ff9d0] Picked up an existing RKMPP hardware device
00:00:09 - SDL Info (0): Using H.264 SPS fixup
00:00:09 - SDL Info (0): Renderer 'EGL/GLES' with 'DRM' backend chosen
00:00:09 - SDL Warn (0): Using custom H.264 decoder (H264_DECODER_HINT): h264_rkmpp
00:00:09 - SDL Info (0): FFmpeg-based video decoder chosen
00:00:09 - FFmpeg: [h264_rkmpp @ 0xaaaaea1ff9d0] Wrote 55032 bytes to decoder
00:00:09 - FFmpeg: [h264_rkmpp @ 0xaaaaea1ff9d0] Wrote 13752 bytes to decoder
00:00:09 - FFmpeg: [h264_rkmpp @ 0xaaaaea1ff9d0] Wrote 19256 bytes to decoder
00:00:09 - FFmpeg: [h264_rkmpp @ 0xaaaaea1ff9d0] Wrote 15128 bytes to decoder
00:00:09 - FFmpeg: [h264_rkmpp @ 0xaaaaea1ff9d0] Noticed an info change
00:00:09 - FFmpeg: [h264_rkmpp @ 0xaaaaea1ff9d0] Decoder options: deint=true afbc=0 fast_parse=true buf_mode=0
00:00:09 - FFmpeg: [h264_rkmpp @ 0xaaaaea1ff9d0] Configured with size: 2560x1440 | pix_fmt: drm_prime | sw_pix_fmt: nv12
00:00:09 - SDL Info (0): Dropping window event during flush: 6 (2560 1440)
00:00:09 - SDL Info (0): IDR frame request sent
00:00:09 - FFmpeg: [h264_rkmpp @ 0xaaaaea1ff9d0] Received a frame
00:00:09 - SDL Info (0): EGLRenderer: EGLImage pixel format: 179
00:00:09 - Qt Info: Found "egl.vert" at ":/data/egl.vert"
00:00:09 - Qt Info: Found "egl_opaque.frag" at ":/data/egl_opaque.frag"
00:00:09 - Qt Info: Found "egl.vert" at ":/data/egl.vert"
00:00:09 - Qt Info: Found "egl_overlay.frag" at ":/data/egl_overlay.frag"
00:02:21 - SDL Info (0): Raising 3 keys
00:02:21 - SDL Info (0): Detected quit key combo
00:02:21 - SDL Info (0): Quit event received
00:02:21 - SDL Info (0):
Global video stats
------------------
Incoming frame rate from network: 19.14 FPS
Decoding frame rate: 19.14 FPS
Rendering frame rate: 18.97 FPS
Host processing latency min/max/average: 26.6/104.7/38.4 ms
Frames dropped by your network connection: 0.00%
Frames dropped due to network jitter: 0.20%
Average network latency: 8 ms (variance: 8 ms)
Average decoding time: 10.53 ms
Average frame queue delay: 2.78 ms
Average rendering time (including monitor V-sync latency): 2.54 ms
00:02:21 - SDL Info (0): Stopping input stream...
00:02:21 - Qt Info: Latest supported GFE server: "99.99.99.99"
00:02:21 - SDL Info (0): ENet wait interrupted
00:02:21 - SDL Info (0): Control stream connection failed: 4
00:02:21 - SDL Info (0): done
00:02:21 - SDL Info (0): Stopping audio stream...
00:02:21 - SDL Info (0): No audio traffic was ever received from the host!
00:02:21 - SDL Info (0): done
00:02:21 - SDL Info (0): Stopping video stream...
00:02:21 - SDL Info (0): done
00:02:21 - SDL Info (0): Stopping control stream...
00:02:21 - Qt Info: Found "gamecontrollerdb.txt" at "/home/armbian/.cache/Moonlight Game Streaming Project/Moonlight/gamecontrollerdb.txt"
00:02:21 - SDL Info (0): Loaded 436 new gamepad mappings
00:02:21 - SDL Info (0): ENet peer acknowledged disconnection
00:02:21 - SDL Info (0): done
00:02:21 - SDL Info (0): Cleaning up input stream...
00:02:21 - SDL Info (0): done
00:02:21 - SDL Info (0): Cleaning up video stream...
00:02:21 - SDL Info (0): done
00:02:21 - SDL Info (0): Cleaning up control stream...
00:02:21 - SDL Info (0): done
00:02:21 - SDL Info (0): Cleaning up audio stream...
00:02:21 - SDL Info (0): done
00:02:21 - SDL Info (0): Cleaning up platform...
00:02:21 - SDL Info (0): done

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

View File

@ -0,0 +1,240 @@
00:00:00 - SDL Info (0): Compiled with SDL 2.30.0
00:00:00 - SDL Info (0): Running with SDL 2.30.0
00:00:00 - Qt Info: Successfully loaded translation for "zh_CN"
00:00:00 - Qt Info: Loaded unique ID from settings: "95da1945b8736669"
00:00:00 - Qt Warning: qrc:/gui/main.qml:13:1: QML ApplicationWindow: ToolTip must be attached to an Item
00:00:01 - Qt Info: Found "gamecontrollerdb.txt" at "/home/armbian/.cache/Moonlight Game Streaming Project/Moonlight/gamecontrollerdb.txt"
00:00:01 - SDL Info (0): Loaded 436 new gamepad mappings
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:9
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:47009
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:47998
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:47999
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:48000
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:48002
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:48010
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:9
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:47009
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:47998
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:47999
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:48000
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:48002
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:48010
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:9
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:47009
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:47998
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:47999
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:48000
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:48002
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:48010
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:9
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:47009
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:47998
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:47999
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:48000
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:48002
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:48010
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:9
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:47009
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:47998
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:47999
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:48000
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:48002
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:48010
00:00:01 - Qt Debug: Current Moonlight version: "6.2.0"
00:00:01 - Qt Info: "DESKTOP-Q072ICM" is now online at "192.168.1.70:47989"
00:00:01 - Qt Info: Found "ModeSeven.ttf" at ":/data/ModeSeven.ttf"
00:00:01 - Qt Info: Discovered mDNS host: "DESKTOP-Q072ICM.local."
00:00:02 - SDL Info (0): Qt UI screen is at (0,0)
00:00:02 - SDL Info (0): SDL found matching display 0
00:00:02 - Qt Info: Server GPU: ""
00:00:02 - Qt Info: Server GFE version: "3.23.0.74"
00:00:02 - SDL Info (0): Video bitrate: 30000 kbps
00:00:02 - SDL Info (0): Audio channel count: 2
00:00:02 - SDL Info (0): Audio channel mask: 3
00:00:02 - SDL Info (0): Desired audio buffer: 720 samples (5760 bytes)
00:00:02 - SDL Info (0): Obtained audio buffer: 720 samples (5760 bytes)
00:00:02 - SDL Info (0): SDL audio driver: pulseaudio
00:00:02 - Qt Info: Found "gamecontrollerdb.txt" at "/home/armbian/.cache/Moonlight Game Streaming Project/Moonlight/gamecontrollerdb.txt"
00:00:02 - SDL Info (0): Loaded 436 new gamepad mappings
00:00:02 - SDL Info (0): V-sync disabled
00:00:02 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:02 - SDL Info (0): GPU driver: rockchip
00:00:02 - SDL Info (0): Direct rendering via DRM is disabled
00:00:02 - SDL Info (0): DRM backend supports exporting EGLImage
00:00:02 - SDL Info (0): Color buffer is: R8G8B8A0
00:00:02 - SDL Info (0): Using DRM renderer
00:00:02 - FFmpeg: [h264_mp4toannexb @ 0xaaaaf99a27a0] The input looks like it is Annex B already
mpp[54250]: mpp_info: mpp version: 7916c3c author: Xiaoxu Chen 2026-10-28 fix[utils]: Fix AVC cu_map allocation stride
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaf92e8420] Picked up an existing RKMPP hardware device
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaf92e8420] Wrote 390 bytes to decoder
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaf92e8420] Wrote 390 bytes to decoder
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaf92e8420] Noticed an info change
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaf92e8420] Decoder options: deint=true afbc=0 fast_parse=true buf_mode=0
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaf92e8420] Configured with size: 1280x720 | pix_fmt: drm_prime | sw_pix_fmt: nv12
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaf92e8420] Wrote 390 bytes to decoder
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaf92e8420] Received a frame
00:00:02 - SDL Warn (0): Using custom H.264 decoder (H264_DECODER_HINT): h264_rkmpp
00:00:02 - SDL Info (0): FFmpeg-based video decoder chosen
00:00:02 - SDL Info (0): V-sync disabled
00:00:02 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:02 - SDL Info (0): GPU driver: rockchip
00:00:02 - SDL Info (0): Direct rendering via DRM is disabled
00:00:02 - SDL Info (0): DRM backend supports exporting EGLImage
00:00:02 - SDL Info (0): Color buffer is: R8G8B8A0
00:00:02 - SDL Info (0): Using DRM renderer
00:00:02 - FFmpeg: [h264_mp4toannexb @ 0xaaaaf995fa90] The input looks like it is Annex B already
mpp[54250]: mpp_info: mpp version: 7916c3c author: Xiaoxu Chen 2026-10-28 fix[utils]: Fix AVC cu_map allocation stride
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaf92e8420] Picked up an existing RKMPP hardware device
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaf92e8420] Wrote 390 bytes to decoder
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaf92e8420] Wrote 390 bytes to decoder
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaf92e8420] Noticed an info change
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaf92e8420] Decoder options: deint=true afbc=0 fast_parse=true buf_mode=0
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaf92e8420] Configured with size: 1280x720 | pix_fmt: drm_prime | sw_pix_fmt: nv12
00:00:03 - FFmpeg: [h264_rkmpp @ 0xaaaaf92e8420] Wrote 390 bytes to decoder
00:00:03 - FFmpeg: [h264_rkmpp @ 0xaaaaf92e8420] Received a frame
00:00:03 - SDL Warn (0): Using custom H.264 decoder (H264_DECODER_HINT): h264_rkmpp
00:00:03 - SDL Info (0): FFmpeg-based video decoder chosen
00:00:03 - Qt Warning: 启用远程桌面鼠标模式可能会导致游戏出现问题。
00:00:03 - Qt Info: Processing new PC "DESKTOP-Q072ICM.local." from mDNS with local address "192.168.1.70:47989"
00:00:03 - Qt Info: Executing request: "http://192.168.1.70:47989/serverinfo?uniqueid=0123456789ABCDEF&uuid=384e05c9dbdc467aa7c65964c14160df"
00:00:03 - Qt Info: Executing request: "https://192.168.1.70:47984/serverinfo?uniqueid=95da1945b8736669&uuid=3a95f785091741c090fdffd7d56979e7"
00:00:04 - Qt Info: Gamepad mappings are up to date
00:00:06 - Qt Info: Found "gamecontrollerdb.txt" at "/home/armbian/.cache/Moonlight Game Streaming Project/Moonlight/gamecontrollerdb.txt"
00:00:06 - SDL Info (0): Loaded 436 new gamepad mappings
00:00:06 - Qt Info: Executing request: "https://192.168.1.70:47984/resume?uniqueid=95da1945b8736669&uuid=b7dffe4902d54022a33fa19a3cf2b331&appid=881448767&mode=2560x1440x30&additionalStates=1&sops=1&rikey=REDACTED&rikeyid=REDACTED&localAudioPlayMode=1&surroundAudioInfo=196610&remoteControllersBitmap=0&gcmap=0&gcpersist=0&corever=1"
00:00:07 - Qt Info: Launch response: "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root status_code=\"200\"><sessionUrl0>rtspenc://192.168.1.70:48010</sessionUrl0><resume>1</resume></root>"
00:00:07 - Qt Info: Found matching interface: "wlan0" "88:00:33:77:30:B6" QFlags<QNetworkInterface::InterfaceFlag>(IsUp|IsRunning|CanBroadcast|CanMulticast)
00:00:07 - Qt Info: Interface Type: QNetworkInterface::Wifi
00:00:07 - Qt Info: Interface MTU: 1500
00:00:07 - SDL Info (0): RTSP port: 48010
00:00:07 - SDL Info (0): Initializing platform...
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Resolving host name...
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Initializing audio stream...
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Starting RTSP handshake...
00:00:07 - SDL Info (0): Reference frame invalidation is not supported by this host
00:00:07 - SDL Info (0): Audio port: 48000
00:00:07 - SDL Info (0): Video port: 47998
00:00:07 - SDL Info (0): Control port: 47999
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Initializing control stream...
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Initializing video stream...
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Initializing input stream...
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Starting control stream...
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Starting video stream...
00:00:07 - SDL Info (0): Video stream is 2560x1440x30 (format 0x1)
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Starting audio stream...
00:00:07 - SDL Info (0): Received first video packet after 0 ms
00:00:07 - SDL Info (0): Desired audio buffer: 720 samples (5760 bytes)
00:00:07 - SDL Info (0): Obtained audio buffer: 720 samples (5760 bytes)
00:00:07 - SDL Info (0): SDL audio driver: pulseaudio
00:00:07 - SDL Info (0): Audio stream has 2 channels
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Starting input stream...
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Qt UI screen is at (0,0)
00:00:07 - SDL Info (0): SDL found matching display 0
00:00:07 - SDL Info (0): Found display mode with desktop resolution: 2560x1440x60
00:00:08 - SDL Info (0): Video decode unit queue overflow
00:00:08 - SDL Info (0): IDR frame request sent
00:00:08 - SDL Info (0): Waiting for IDR frame
00:00:08 - SDL Info (0): Recreating renderer for window event: 1 (0 0)
00:00:08 - SDL Info (0): V-sync disabled
00:00:08 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:08 - SDL Info (0): GPU driver: rockchip
00:00:08 - SDL Info (0): Direct rendering via DRM is disabled
00:00:08 - SDL Info (0): DRM backend supports exporting EGLImage
00:00:08 - SDL Info (0): Video decode unit queue overflow
00:00:08 - SDL Info (0): IDR frame request sent
00:00:08 - SDL Info (0): Waiting for IDR frame
00:00:08 - SDL Info (0): Color buffer is: R8G8B8A0
00:00:08 - SDL Info (0): Using DRM renderer
00:00:08 - FFmpeg: [h264_mp4toannexb @ 0xaaaaf96e2d90] The input looks like it is Annex B already
mpp[54250]: mpp_info: mpp version: 7916c3c author: Xiaoxu Chen 2026-10-28 fix[utils]: Fix AVC cu_map allocation stride
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaaf99a26d0] Picked up an existing RKMPP hardware device
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaaf99a26d0] Wrote 390 bytes to decoder
00:00:09 - FFmpeg: [h264_rkmpp @ 0xaaaaf99a26d0] Wrote 390 bytes to decoder
00:00:09 - FFmpeg: [h264_rkmpp @ 0xaaaaf99a26d0] Noticed an info change
00:00:09 - FFmpeg: [h264_rkmpp @ 0xaaaaf99a26d0] Decoder options: deint=true afbc=0 fast_parse=true buf_mode=0
00:00:09 - FFmpeg: [h264_rkmpp @ 0xaaaaf99a26d0] Configured with size: 1280x720 | pix_fmt: drm_prime | sw_pix_fmt: nv12
00:00:09 - FFmpeg: [h264_rkmpp @ 0xaaaaf99a26d0] Wrote 390 bytes to decoder
00:00:09 - FFmpeg: [h264_rkmpp @ 0xaaaaf99a26d0] Received a frame
00:00:09 - SDL Info (0): Not reusing test decoder for h264_rkmpp
00:00:09 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:09 - SDL Info (0): GPU driver: rockchip
00:00:09 - SDL Info (0): Direct rendering via DRM is disabled
00:00:09 - SDL Info (0): DRM backend supports exporting EGLImage
00:00:09 - SDL Info (0): Color buffer is: R8G8B8A0
00:00:09 - SDL Info (0): Frame pacing disabled: target 60 Hz with 30 FPS stream
00:00:09 - SDL Info (0): Using DRM renderer
00:00:09 - FFmpeg: [h264_mp4toannexb @ 0xaaaaf96f1610] The input looks like it is Annex B already
mpp[54250]: mpp_info: mpp version: 7916c3c author: Xiaoxu Chen 2026-10-28 fix[utils]: Fix AVC cu_map allocation stride
00:00:09 - FFmpeg: [h264_rkmpp @ 0xaaaaf99a26d0] Picked up an existing RKMPP hardware device
00:00:09 - SDL Warn (0): Unable to set render thread to high priority: setpriority() failed
00:00:09 - SDL Info (0): Using H.264 SPS fixup
00:00:09 - SDL Info (0): Renderer 'EGL/GLES' with 'DRM' backend chosen
00:00:09 - SDL Warn (0): Using custom H.264 decoder (H264_DECODER_HINT): h264_rkmpp
00:00:09 - SDL Info (0): FFmpeg-based video decoder chosen
00:00:09 - FFmpeg: [h264_rkmpp @ 0xaaaaf99a26d0] Wrote 46776 bytes to decoder
00:00:09 - FFmpeg: [h264_rkmpp @ 0xaaaaf99a26d0] Wrote 19256 bytes to decoder
00:00:09 - FFmpeg: [h264_rkmpp @ 0xaaaaf99a26d0] Wrote 15128 bytes to decoder
00:00:09 - FFmpeg: [h264_rkmpp @ 0xaaaaf99a26d0] Wrote 16504 bytes to decoder
00:00:09 - FFmpeg: [h264_rkmpp @ 0xaaaaf99a26d0] Noticed an info change
00:00:09 - FFmpeg: [h264_rkmpp @ 0xaaaaf99a26d0] Decoder options: deint=true afbc=0 fast_parse=true buf_mode=0
00:00:09 - FFmpeg: [h264_rkmpp @ 0xaaaaf99a26d0] Configured with size: 2560x1440 | pix_fmt: drm_prime | sw_pix_fmt: nv12
00:00:09 - SDL Info (0): Dropping window event during flush: 6 (2560 1440)
00:00:09 - SDL Info (0): IDR frame request sent
00:00:09 - FFmpeg: [h264_rkmpp @ 0xaaaaf99a26d0] Received a frame
00:00:09 - SDL Info (0): EGLRenderer: EGLImage pixel format: 179
00:00:09 - Qt Info: Found "egl.vert" at ":/data/egl.vert"
00:00:09 - Qt Info: Found "egl_opaque.frag" at ":/data/egl_opaque.frag"
00:00:09 - Qt Info: Found "egl.vert" at ":/data/egl.vert"
00:00:09 - Qt Info: Found "egl_overlay.frag" at ":/data/egl_overlay.frag"
00:02:20 - SDL Info (0): Detected quit key combo
00:02:20 - SDL Info (0): Quit event received
00:02:20 - SDL Info (0): Raising 3 keys
00:02:20 - SDL Info (0):
Global video stats
------------------
Incoming frame rate from network: 23.56 FPS
Decoding frame rate: 23.56 FPS
Rendering frame rate: 23.46 FPS
Host processing latency min/max/average: 29.7/145.8/46.8 ms
Frames dropped by your network connection: 0.00%
Frames dropped due to network jitter: 0.10%
Average network latency: 4 ms (variance: 2 ms)
Average decoding time: 9.11 ms
Average frame queue delay: 2.39 ms
Average rendering time (including monitor V-sync latency): 5.41 ms
00:02:20 - SDL Info (0): Stopping input stream...
00:02:20 - SDL Info (0): done
00:02:20 - Qt Info: Latest supported GFE server: "99.99.99.99"
00:02:20 - SDL Info (0): Stopping audio stream...
00:02:20 - SDL Info (0): No audio traffic was ever received from the host!
00:02:20 - SDL Info (0): ENet wait interrupted
00:02:20 - SDL Info (0): Control stream connection failed: 4
00:02:20 - SDL Info (0): done
00:02:20 - SDL Info (0): Stopping video stream...
00:02:21 - SDL Info (0): done
00:02:21 - SDL Info (0): Stopping control stream...
00:02:21 - Qt Info: Found "gamecontrollerdb.txt" at "/home/armbian/.cache/Moonlight Game Streaming Project/Moonlight/gamecontrollerdb.txt"
00:02:21 - SDL Info (0): Loaded 436 new gamepad mappings
00:02:21 - SDL Info (0): ENet peer acknowledged disconnection
00:02:21 - SDL Info (0): done
00:02:21 - SDL Info (0): Cleaning up input stream...
00:02:21 - SDL Info (0): done
00:02:21 - SDL Info (0): Cleaning up video stream...
00:02:21 - SDL Info (0): done
00:02:21 - SDL Info (0): Cleaning up control stream...
00:02:21 - SDL Info (0): done
00:02:21 - SDL Info (0): Cleaning up audio stream...
00:02:21 - SDL Info (0): done
00:02:21 - SDL Info (0): Cleaning up platform...
00:02:21 - SDL Info (0): done

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

View File

@ -0,0 +1,240 @@
00:00:00 - SDL Info (0): Compiled with SDL 2.30.0
00:00:00 - SDL Info (0): Running with SDL 2.30.0
00:00:00 - Qt Info: Successfully loaded translation for "zh_CN"
00:00:00 - Qt Info: Loaded unique ID from settings: "95da1945b8736669"
00:00:00 - Qt Warning: qrc:/gui/main.qml:13:1: QML ApplicationWindow: ToolTip must be attached to an Item
00:00:01 - Qt Info: Found "gamecontrollerdb.txt" at "/home/armbian/.cache/Moonlight Game Streaming Project/Moonlight/gamecontrollerdb.txt"
00:00:01 - SDL Info (0): Loaded 436 new gamepad mappings
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:9
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:47009
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:47998
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:47999
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:48000
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:48002
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:48010
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:9
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:47009
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:47998
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:47999
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:48000
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:48002
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:48010
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:9
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:47009
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:47998
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:47999
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:48000
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:48002
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:48010
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:9
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:47009
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:47998
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:47999
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:48000
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:48002
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:48010
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:9
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:47009
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:47998
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:47999
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:48000
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:48002
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:48010
00:00:01 - Qt Debug: Current Moonlight version: "6.2.0"
00:00:01 - Qt Info: Discovered mDNS host: "DESKTOP-Q072ICM.local."
00:00:01 - Qt Info: "DESKTOP-Q072ICM" is now online at "192.168.1.70:47989"
00:00:01 - Qt Info: Found "ModeSeven.ttf" at ":/data/ModeSeven.ttf"
00:00:01 - SDL Info (0): Qt UI screen is at (0,0)
00:00:01 - SDL Info (0): SDL found matching display 0
00:00:01 - Qt Info: Server GPU: ""
00:00:01 - Qt Info: Server GFE version: "3.23.0.74"
00:00:01 - SDL Info (0): Video bitrate: 30000 kbps
00:00:01 - SDL Info (0): Audio channel count: 2
00:00:01 - SDL Info (0): Audio channel mask: 3
00:00:02 - SDL Info (0): Desired audio buffer: 720 samples (5760 bytes)
00:00:02 - SDL Info (0): Obtained audio buffer: 720 samples (5760 bytes)
00:00:02 - SDL Info (0): SDL audio driver: pulseaudio
00:00:02 - Qt Info: Found "gamecontrollerdb.txt" at "/home/armbian/.cache/Moonlight Game Streaming Project/Moonlight/gamecontrollerdb.txt"
00:00:02 - SDL Info (0): Loaded 436 new gamepad mappings
00:00:02 - SDL Info (0): V-sync disabled
00:00:02 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:02 - SDL Info (0): GPU driver: rockchip
00:00:02 - SDL Info (0): Direct rendering via DRM is disabled
00:00:02 - SDL Info (0): DRM backend supports exporting EGLImage
00:00:02 - SDL Info (0): Color buffer is: R8G8B8A0
00:00:02 - SDL Info (0): Using DRM renderer
00:00:02 - FFmpeg: [h264_mp4toannexb @ 0xaaaaefd8db30] The input looks like it is Annex B already
mpp[52715]: mpp_info: mpp version: 7916c3c author: Xiaoxu Chen 2026-10-28 fix[utils]: Fix AVC cu_map allocation stride
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaef6fce10] Picked up an existing RKMPP hardware device
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaef6fce10] Wrote 390 bytes to decoder
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaef6fce10] Wrote 390 bytes to decoder
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaef6fce10] Noticed an info change
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaef6fce10] Decoder options: deint=true afbc=0 fast_parse=true buf_mode=0
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaef6fce10] Configured with size: 1280x720 | pix_fmt: drm_prime | sw_pix_fmt: nv12
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaef6fce10] Wrote 390 bytes to decoder
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaef6fce10] Received a frame
00:00:02 - SDL Warn (0): Using custom H.264 decoder (H264_DECODER_HINT): h264_rkmpp
00:00:02 - SDL Info (0): FFmpeg-based video decoder chosen
00:00:02 - SDL Info (0): V-sync disabled
00:00:02 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:02 - SDL Info (0): GPU driver: rockchip
00:00:02 - SDL Info (0): Direct rendering via DRM is disabled
00:00:02 - SDL Info (0): DRM backend supports exporting EGLImage
00:00:02 - SDL Info (0): Color buffer is: R8G8B8A0
00:00:02 - SDL Info (0): Using DRM renderer
00:00:02 - FFmpeg: [h264_mp4toannexb @ 0xaaaaf01e0290] The input looks like it is Annex B already
mpp[52715]: mpp_info: mpp version: 7916c3c author: Xiaoxu Chen 2026-10-28 fix[utils]: Fix AVC cu_map allocation stride
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaef6fce10] Picked up an existing RKMPP hardware device
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaef6fce10] Wrote 390 bytes to decoder
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaef6fce10] Wrote 390 bytes to decoder
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaef6fce10] Noticed an info change
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaef6fce10] Decoder options: deint=true afbc=0 fast_parse=true buf_mode=0
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaef6fce10] Configured with size: 1280x720 | pix_fmt: drm_prime | sw_pix_fmt: nv12
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaef6fce10] Wrote 390 bytes to decoder
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaaef6fce10] Received a frame
00:00:02 - SDL Warn (0): Using custom H.264 decoder (H264_DECODER_HINT): h264_rkmpp
00:00:02 - SDL Info (0): FFmpeg-based video decoder chosen
00:00:02 - Qt Warning: 启用远程桌面鼠标模式可能会导致游戏出现问题。
00:00:03 - Qt Info: Processing new PC "DESKTOP-Q072ICM.local." from mDNS with local address "192.168.1.70:47989"
00:00:03 - Qt Info: Executing request: "http://192.168.1.70:47989/serverinfo?uniqueid=0123456789ABCDEF&uuid=bde19ca4ac6f4527a834eac086ade60d"
00:00:03 - Qt Info: Executing request: "https://192.168.1.70:47984/serverinfo?uniqueid=95da1945b8736669&uuid=29837995715346aea2f683aa39046423"
00:00:05 - Qt Info: Latest supported GFE server: "99.99.99.99"
00:00:06 - Qt Info: Found "gamecontrollerdb.txt" at "/home/armbian/.cache/Moonlight Game Streaming Project/Moonlight/gamecontrollerdb.txt"
00:00:06 - SDL Info (0): Loaded 436 new gamepad mappings
00:00:06 - Qt Info: Executing request: "https://192.168.1.70:47984/resume?uniqueid=95da1945b8736669&uuid=910b4365f6664f5a894c7e3a58542e6c&appid=881448767&mode=2560x1440x30&additionalStates=1&sops=1&rikey=REDACTED&rikeyid=REDACTED&localAudioPlayMode=1&surroundAudioInfo=196610&remoteControllersBitmap=0&gcmap=0&gcpersist=0&corever=1"
00:00:06 - Qt Info: Launch response: "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root status_code=\"200\"><sessionUrl0>rtspenc://192.168.1.70:48010</sessionUrl0><resume>1</resume></root>"
00:00:06 - Qt Info: Found matching interface: "wlan0" "88:00:33:77:30:B6" QFlags<QNetworkInterface::InterfaceFlag>(IsUp|IsRunning|CanBroadcast|CanMulticast)
00:00:06 - Qt Info: Interface Type: QNetworkInterface::Wifi
00:00:06 - Qt Info: Interface MTU: 1500
00:00:06 - SDL Info (0): RTSP port: 48010
00:00:06 - SDL Info (0): Initializing platform...
00:00:06 - SDL Info (0): done
00:00:06 - SDL Info (0): Resolving host name...
00:00:06 - SDL Info (0): done
00:00:06 - SDL Info (0): Initializing audio stream...
00:00:06 - SDL Info (0): done
00:00:06 - SDL Info (0): Starting RTSP handshake...
00:00:06 - SDL Info (0): Reference frame invalidation is not supported by this host
00:00:06 - SDL Info (0): Audio port: 48000
00:00:06 - SDL Info (0): Video port: 47998
00:00:06 - SDL Info (0): Control port: 47999
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Initializing control stream...
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Initializing video stream...
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Initializing input stream...
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Starting control stream...
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Starting video stream...
00:00:07 - SDL Info (0): Video stream is 2560x1440x30 (format 0x1)
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Starting audio stream...
00:00:07 - Qt Info: Gamepad mappings are up to date
00:00:07 - SDL Info (0): Received first video packet after 0 ms
00:00:07 - SDL Info (0): Desired audio buffer: 720 samples (5760 bytes)
00:00:07 - SDL Info (0): Obtained audio buffer: 720 samples (5760 bytes)
00:00:07 - SDL Info (0): SDL audio driver: pulseaudio
00:00:07 - SDL Info (0): Audio stream has 2 channels
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Starting input stream...
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Qt UI screen is at (0,0)
00:00:07 - SDL Info (0): SDL found matching display 0
00:00:07 - SDL Info (0): Found display mode with desktop resolution: 2560x1440x60
00:00:07 - SDL Info (0): Video decode unit queue overflow
00:00:07 - SDL Info (0): IDR frame request sent
00:00:07 - SDL Info (0): Waiting for IDR frame
00:00:07 - SDL Info (0): Recreating renderer for window event: 1 (0 0)
00:00:07 - SDL Info (0): V-sync enabled
00:00:07 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:07 - SDL Info (0): GPU driver: rockchip
00:00:07 - SDL Info (0): Direct rendering via DRM is disabled
00:00:07 - SDL Info (0): DRM backend supports exporting EGLImage
00:00:08 - SDL Info (0): Video decode unit queue overflow
00:00:08 - SDL Info (0): IDR frame request sent
00:00:08 - SDL Info (0): Waiting for IDR frame
00:00:08 - SDL Info (0): Color buffer is: R8G8B8A0
00:00:08 - SDL Info (0): Using DRM renderer
00:00:08 - FFmpeg: [h264_mp4toannexb @ 0xaaaaefcb7f90] The input looks like it is Annex B already
mpp[52715]: mpp_info: mpp version: 7916c3c author: Xiaoxu Chen 2026-10-28 fix[utils]: Fix AVC cu_map allocation stride
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaaef6fce10] Picked up an existing RKMPP hardware device
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaaef6fce10] Wrote 390 bytes to decoder
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaaef6fce10] Wrote 390 bytes to decoder
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaaef6fce10] Noticed an info change
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaaef6fce10] Decoder options: deint=true afbc=0 fast_parse=true buf_mode=0
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaaef6fce10] Configured with size: 1280x720 | pix_fmt: drm_prime | sw_pix_fmt: nv12
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaaef6fce10] Wrote 390 bytes to decoder
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaaef6fce10] Received a frame
00:00:08 - SDL Info (0): Not reusing test decoder for h264_rkmpp
00:00:08 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:08 - SDL Info (0): GPU driver: rockchip
00:00:08 - SDL Info (0): Direct rendering via DRM is disabled
00:00:08 - SDL Info (0): DRM backend supports exporting EGLImage
00:00:08 - SDL Info (0): Video decode unit queue overflow
00:00:08 - SDL Info (0): IDR frame request sent
00:00:08 - SDL Info (0): Waiting for IDR frame
00:00:08 - SDL Info (0): Color buffer is: R8G8B8A0
00:00:08 - SDL Info (0): Frame pacing: target 60 Hz with 30 FPS stream
00:00:08 - SDL Info (0): Using DRM renderer
00:00:08 - FFmpeg: [h264_mp4toannexb @ 0xaaaaefca77e0] The input looks like it is Annex B already
mpp[52715]: mpp_info: mpp version: 7916c3c author: Xiaoxu Chen 2026-10-28 fix[utils]: Fix AVC cu_map allocation stride
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaaef6fce10] Picked up an existing RKMPP hardware device
00:00:08 - SDL Info (0): Using H.264 SPS fixup
00:00:08 - SDL Warn (0): Unable to set render thread to high priority: setpriority() failed
00:00:08 - SDL Info (0): Renderer 'EGL/GLES' with 'DRM' backend chosen
00:00:08 - SDL Warn (0): Using custom H.264 decoder (H264_DECODER_HINT): h264_rkmpp
00:00:08 - SDL Info (0): FFmpeg-based video decoder chosen
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaaef6fce10] Wrote 53656 bytes to decoder
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaaef6fce10] Noticed an info change
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaaef6fce10] Decoder options: deint=true afbc=0 fast_parse=true buf_mode=0
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaaef6fce10] Configured with size: 2560x1440 | pix_fmt: drm_prime | sw_pix_fmt: nv12
00:00:08 - SDL Info (0): Dropping window event during flush: 6 (2560 1440)
00:00:08 - SDL Info (0): IDR frame request sent
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaaef6fce10] Received a frame
00:00:08 - SDL Info (0): EGLRenderer: EGLImage pixel format: 179
00:00:08 - Qt Info: Found "egl.vert" at ":/data/egl.vert"
00:00:08 - Qt Info: Found "egl_opaque.frag" at ":/data/egl_opaque.frag"
00:00:08 - Qt Info: Found "egl.vert" at ":/data/egl.vert"
00:00:08 - Qt Info: Found "egl_overlay.frag" at ":/data/egl_overlay.frag"
00:02:26 - SDL Info (0): Raising 3 keys
00:02:26 - SDL Info (0): Detected quit key combo
00:02:26 - SDL Info (0): Quit event received
00:02:26 - SDL Info (0):
Global video stats
------------------
Incoming frame rate from network: 24.21 FPS
Decoding frame rate: 24.21 FPS
Rendering frame rate: 23.29 FPS
Host processing latency min/max/average: 24.8/86.1/46.2 ms
Frames dropped by your network connection: 0.00%
Frames dropped due to network jitter: 3.02%
Average network latency: 9 ms (variance: 6 ms)
Average decoding time: 8.24 ms
Average frame queue delay: 31.95 ms
Average rendering time (including monitor V-sync latency): 4.19 ms
00:02:26 - SDL Info (0): Stopping input stream...
00:02:26 - SDL Info (0): done
00:02:26 - SDL Info (0): Stopping audio stream...
00:02:26 - SDL Info (0): No audio traffic was ever received from the host!
00:02:26 - SDL Info (0): ENet wait interrupted
00:02:26 - SDL Info (0): Control stream connection failed: 4
00:02:26 - SDL Info (0): done
00:02:26 - SDL Info (0): Stopping video stream...
00:02:26 - SDL Info (0): done
00:02:26 - SDL Info (0): Stopping control stream...
00:02:26 - SDL Info (0): ENet peer acknowledged disconnection
00:02:26 - SDL Info (0): done
00:02:26 - SDL Info (0): Cleaning up input stream...
00:02:26 - SDL Info (0): done
00:02:26 - SDL Info (0): Cleaning up video stream...
00:02:26 - SDL Info (0): done
00:02:26 - SDL Info (0): Cleaning up control stream...
00:02:26 - SDL Info (0): done
00:02:26 - SDL Info (0): Cleaning up audio stream...
00:02:26 - SDL Info (0): done
00:02:26 - SDL Info (0): Cleaning up platform...
00:02:26 - SDL Info (0): done
00:02:26 - Qt Info: Found "gamecontrollerdb.txt" at "/home/armbian/.cache/Moonlight Game Streaming Project/Moonlight/gamecontrollerdb.txt"
00:02:26 - SDL Info (0): Loaded 436 new gamepad mappings

View File

@ -0,0 +1,240 @@
00:00:00 - SDL Info (0): Compiled with SDL 2.30.0
00:00:00 - SDL Info (0): Running with SDL 2.30.0
00:00:00 - Qt Info: Successfully loaded translation for "zh_CN"
00:00:00 - Qt Info: Loaded unique ID from settings: "95da1945b8736669"
00:00:00 - Qt Warning: qrc:/gui/main.qml:13:1: QML ApplicationWindow: ToolTip must be attached to an Item
00:00:01 - Qt Info: Found "gamecontrollerdb.txt" at "/home/armbian/.cache/Moonlight Game Streaming Project/Moonlight/gamecontrollerdb.txt"
00:00:01 - SDL Info (0): Loaded 436 new gamepad mappings
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:9
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:47009
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:47998
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:47999
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:48000
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:48002
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:48010
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:9
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:47009
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:47998
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:47999
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:48000
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:48002
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:48010
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:9
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:47009
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:47998
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:47999
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:48000
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:48002
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:48010
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:9
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:47009
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:47998
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:47999
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:48000
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:48002
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:48010
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:9
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:47009
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:47998
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:47999
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:48000
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:48002
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:48010
00:00:01 - Qt Debug: Current Moonlight version: "6.2.0"
00:00:01 - Qt Info: Discovered mDNS host: "DESKTOP-Q072ICM.local."
00:00:01 - Qt Info: "DESKTOP-Q072ICM" is now online at "192.168.1.70:47989"
00:00:01 - Qt Info: Found "ModeSeven.ttf" at ":/data/ModeSeven.ttf"
00:00:02 - SDL Info (0): Qt UI screen is at (0,0)
00:00:02 - SDL Info (0): SDL found matching display 0
00:00:02 - Qt Info: Server GPU: ""
00:00:02 - Qt Info: Server GFE version: "3.23.0.74"
00:00:02 - SDL Info (0): Video bitrate: 30000 kbps
00:00:02 - SDL Info (0): Audio channel count: 2
00:00:02 - SDL Info (0): Audio channel mask: 3
00:00:02 - SDL Info (0): Desired audio buffer: 720 samples (5760 bytes)
00:00:02 - SDL Info (0): Obtained audio buffer: 720 samples (5760 bytes)
00:00:02 - SDL Info (0): SDL audio driver: pulseaudio
00:00:02 - Qt Info: Found "gamecontrollerdb.txt" at "/home/armbian/.cache/Moonlight Game Streaming Project/Moonlight/gamecontrollerdb.txt"
00:00:02 - SDL Info (0): Loaded 436 new gamepad mappings
00:00:02 - SDL Info (0): V-sync disabled
00:00:02 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:02 - SDL Info (0): GPU driver: rockchip
00:00:02 - SDL Info (0): Direct rendering via DRM is disabled
00:00:02 - SDL Info (0): DRM backend supports exporting EGLImage
00:00:02 - SDL Info (0): Color buffer is: R8G8B8A0
00:00:02 - SDL Info (0): Using DRM renderer
00:00:02 - FFmpeg: [h264_mp4toannexb @ 0xaaaac0ba40c0] The input looks like it is Annex B already
mpp[56346]: mpp_info: mpp version: 7916c3c author: Xiaoxu Chen 2026-10-28 fix[utils]: Fix AVC cu_map allocation stride
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaac0530820] Picked up an existing RKMPP hardware device
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaac0530820] Wrote 390 bytes to decoder
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaac0530820] Wrote 390 bytes to decoder
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaac0530820] Noticed an info change
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaac0530820] Decoder options: deint=true afbc=0 fast_parse=true buf_mode=0
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaac0530820] Configured with size: 1280x720 | pix_fmt: drm_prime | sw_pix_fmt: nv12
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaac0530820] Wrote 390 bytes to decoder
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaac0530820] Received a frame
00:00:02 - SDL Warn (0): Using custom H.264 decoder (H264_DECODER_HINT): h264_rkmpp
00:00:02 - SDL Info (0): FFmpeg-based video decoder chosen
00:00:02 - SDL Info (0): V-sync disabled
00:00:02 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:02 - SDL Info (0): GPU driver: rockchip
00:00:02 - SDL Info (0): Direct rendering via DRM is disabled
00:00:02 - SDL Info (0): DRM backend supports exporting EGLImage
00:00:02 - SDL Info (0): Color buffer is: R8G8B8A0
00:00:02 - SDL Info (0): Using DRM renderer
00:00:02 - FFmpeg: [h264_mp4toannexb @ 0xaaaac0c0e890] The input looks like it is Annex B already
mpp[56346]: mpp_info: mpp version: 7916c3c author: Xiaoxu Chen 2026-10-28 fix[utils]: Fix AVC cu_map allocation stride
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaac0530820] Picked up an existing RKMPP hardware device
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaac0530820] Wrote 390 bytes to decoder
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaac0530820] Wrote 390 bytes to decoder
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaac0530820] Noticed an info change
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaac0530820] Decoder options: deint=true afbc=0 fast_parse=true buf_mode=0
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaac0530820] Configured with size: 1280x720 | pix_fmt: drm_prime | sw_pix_fmt: nv12
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaac0530820] Wrote 390 bytes to decoder
00:00:02 - FFmpeg: [h264_rkmpp @ 0xaaaac0530820] Received a frame
00:00:02 - SDL Warn (0): Using custom H.264 decoder (H264_DECODER_HINT): h264_rkmpp
00:00:02 - SDL Info (0): FFmpeg-based video decoder chosen
00:00:02 - Qt Warning: 启用远程桌面鼠标模式可能会导致游戏出现问题。
00:00:03 - Qt Info: Processing new PC "DESKTOP-Q072ICM.local." from mDNS with local address "192.168.1.70:47989"
00:00:03 - Qt Info: Executing request: "http://192.168.1.70:47989/serverinfo?uniqueid=0123456789ABCDEF&uuid=60ec9920646340b7a621736f9ae3ef0f"
00:00:03 - Qt Info: Executing request: "https://192.168.1.70:47984/serverinfo?uniqueid=95da1945b8736669&uuid=9ff5b4f5a4e34249a2e35f84ea1114b4"
00:00:05 - Qt Info: Latest supported GFE server: "99.99.99.99"
00:00:06 - Qt Info: Found "gamecontrollerdb.txt" at "/home/armbian/.cache/Moonlight Game Streaming Project/Moonlight/gamecontrollerdb.txt"
00:00:06 - SDL Info (0): Loaded 436 new gamepad mappings
00:00:06 - Qt Info: Executing request: "https://192.168.1.70:47984/resume?uniqueid=95da1945b8736669&uuid=1217e2a33f3e46c282856a4e5d12ee0d&appid=881448767&mode=2560x1440x30&additionalStates=1&sops=1&rikey=REDACTED&rikeyid=REDACTED&localAudioPlayMode=1&surroundAudioInfo=196610&remoteControllersBitmap=0&gcmap=0&gcpersist=0&corever=1"
00:00:06 - Qt Info: Launch response: "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root status_code=\"200\"><sessionUrl0>rtspenc://192.168.1.70:48010</sessionUrl0><resume>1</resume></root>"
00:00:06 - Qt Info: Found matching interface: "wlan0" "88:00:33:77:30:B6" QFlags<QNetworkInterface::InterfaceFlag>(IsUp|IsRunning|CanBroadcast|CanMulticast)
00:00:06 - Qt Info: Interface Type: QNetworkInterface::Wifi
00:00:06 - Qt Info: Interface MTU: 1500
00:00:06 - SDL Info (0): RTSP port: 48010
00:00:06 - SDL Info (0): Initializing platform...
00:00:06 - SDL Info (0): done
00:00:06 - SDL Info (0): Resolving host name...
00:00:06 - SDL Info (0): done
00:00:06 - SDL Info (0): Initializing audio stream...
00:00:06 - SDL Info (0): done
00:00:06 - SDL Info (0): Starting RTSP handshake...
00:00:07 - SDL Info (0): Reference frame invalidation is not supported by this host
00:00:07 - SDL Info (0): Audio port: 48000
00:00:07 - SDL Info (0): Video port: 47998
00:00:07 - SDL Info (0): Control port: 47999
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Initializing control stream...
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Initializing video stream...
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Initializing input stream...
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Starting control stream...
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Starting video stream...
00:00:07 - SDL Info (0): Video stream is 2560x1440x30 (format 0x1)
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Starting audio stream...
00:00:07 - SDL Info (0): Desired audio buffer: 720 samples (5760 bytes)
00:00:07 - SDL Info (0): Obtained audio buffer: 720 samples (5760 bytes)
00:00:07 - SDL Info (0): SDL audio driver: pulseaudio
00:00:07 - SDL Info (0): Audio stream has 2 channels
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Starting input stream...
00:00:07 - SDL Info (0): done
00:00:07 - SDL Info (0): Received first video packet after 0 ms
00:00:07 - SDL Info (0): Qt UI screen is at (0,0)
00:00:07 - SDL Info (0): SDL found matching display 0
00:00:07 - SDL Info (0): Found display mode with desktop resolution: 2560x1440x60
00:00:07 - SDL Info (0): Recreating renderer for window event: 1 (0 0)
00:00:07 - SDL Info (0): V-sync enabled
00:00:07 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:07 - SDL Info (0): GPU driver: rockchip
00:00:07 - SDL Info (0): Direct rendering via DRM is disabled
00:00:07 - SDL Info (0): DRM backend supports exporting EGLImage
00:00:07 - SDL Info (0): Video decode unit queue overflow
00:00:07 - SDL Info (0): IDR frame request sent
00:00:07 - SDL Info (0): Waiting for IDR frame
00:00:08 - SDL Info (0): Color buffer is: R8G8B8A0
mpp[56346]: mpp_info: mpp version: 7916c3c author: Xiaoxu Chen 2026-10-28 fix[utils]: Fix AVC cu_map allocation stride
00:00:08 - SDL Info (0): Using DRM renderer
00:00:08 - FFmpeg: [h264_mp4toannexb @ 0xaaaac1032530] The input looks like it is Annex B already
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaac0530820] Picked up an existing RKMPP hardware device
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaac0530820] Wrote 390 bytes to decoder
00:00:08 - SDL Info (0): Video decode unit queue overflow
00:00:08 - SDL Info (0): IDR frame request sent
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaac0530820] Wrote 390 bytes to decoder
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaac0530820] Noticed an info change
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaac0530820] Decoder options: deint=true afbc=0 fast_parse=true buf_mode=0
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaac0530820] Configured with size: 1280x720 | pix_fmt: drm_prime | sw_pix_fmt: nv12
00:00:08 - SDL Info (0): Waiting for IDR frame
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaac0530820] Wrote 390 bytes to decoder
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaac0530820] Received a frame
00:00:08 - SDL Info (0): Not reusing test decoder for h264_rkmpp
00:00:08 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:08 - SDL Info (0): GPU driver: rockchip
00:00:08 - SDL Info (0): Direct rendering via DRM is disabled
00:00:08 - SDL Info (0): DRM backend supports exporting EGLImage
00:00:08 - SDL Info (0): Color buffer is: R8G8B8A0
00:00:08 - SDL Info (0): Frame pacing disabled: target 60 Hz with 30 FPS stream
00:00:08 - SDL Info (0): Using DRM renderer
00:00:08 - FFmpeg: [h264_mp4toannexb @ 0xaaaac0ee99b0] The input looks like it is Annex B already
mpp[56346]: mpp_info: mpp version: 7916c3c author: Xiaoxu Chen 2026-10-28 fix[utils]: Fix AVC cu_map allocation stride
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaac0530820] Picked up an existing RKMPP hardware device
00:00:08 - SDL Warn (0): Unable to set render thread to high priority: setpriority() failed
00:00:08 - SDL Info (0): Using H.264 SPS fixup
00:00:08 - SDL Info (0): Renderer 'EGL/GLES' with 'DRM' backend chosen
00:00:08 - SDL Warn (0): Using custom H.264 decoder (H264_DECODER_HINT): h264_rkmpp
00:00:08 - SDL Info (0): FFmpeg-based video decoder chosen
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaac0530820] Wrote 45400 bytes to decoder
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaac0530820] Wrote 15128 bytes to decoder
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaac0530820] Wrote 15128 bytes to decoder
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaac0530820] Noticed an info change
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaac0530820] Decoder options: deint=true afbc=0 fast_parse=true buf_mode=0
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaac0530820] Configured with size: 2560x1440 | pix_fmt: drm_prime | sw_pix_fmt: nv12
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaac0530820] Wrote 15128 bytes to decoder
00:00:08 - SDL Info (0): Dropping window event during flush: 6 (2560 1440)
00:00:08 - SDL Info (0): IDR frame request sent
00:00:08 - FFmpeg: [h264_rkmpp @ 0xaaaac0530820] Received a frame
00:00:08 - SDL Info (0): EGLRenderer: EGLImage pixel format: 179
00:00:08 - Qt Info: Found "egl.vert" at ":/data/egl.vert"
00:00:08 - Qt Info: Found "egl_opaque.frag" at ":/data/egl_opaque.frag"
00:00:08 - Qt Info: Found "egl.vert" at ":/data/egl.vert"
00:00:08 - Qt Info: Found "egl_overlay.frag" at ":/data/egl_overlay.frag"
00:02:33 - SDL Info (0): Raising 3 keys
00:02:33 - SDL Info (0): Detected quit key combo
00:02:33 - SDL Info (0): Quit event received
00:02:33 - SDL Info (0):
Global video stats
------------------
Incoming frame rate from network: 23.26 FPS
Decoding frame rate: 23.26 FPS
Rendering frame rate: 22.63 FPS
Host processing latency min/max/average: 34.4/110.6/47.5 ms
Frames dropped by your network connection: 0.00%
Frames dropped due to network jitter: 2.23%
Average network latency: 13 ms (variance: 8 ms)
Average decoding time: 8.28 ms
Average frame queue delay: 28.93 ms
Average rendering time (including monitor V-sync latency): 4.14 ms
00:02:34 - Qt Info: Gamepad mappings are up to date
00:02:34 - SDL Info (0): Stopping input stream...
00:02:34 - SDL Info (0): done
00:02:34 - SDL Info (0): Stopping audio stream...
00:02:34 - SDL Info (0): No audio traffic was ever received from the host!
00:02:34 - SDL Info (0): ENet wait interrupted
00:02:34 - SDL Info (0): Control stream connection failed: 4
00:02:34 - SDL Info (0): done
00:02:34 - SDL Info (0): Stopping video stream...
00:02:34 - Qt Info: Found "gamecontrollerdb.txt" at "/home/armbian/.cache/Moonlight Game Streaming Project/Moonlight/gamecontrollerdb.txt"
00:02:34 - SDL Info (0): Loaded 436 new gamepad mappings
00:02:34 - SDL Info (0): done
00:02:34 - SDL Info (0): Stopping control stream...
00:02:34 - SDL Info (0): ENet peer acknowledged disconnection
00:02:34 - SDL Info (0): done
00:02:34 - SDL Info (0): Cleaning up input stream...
00:02:34 - SDL Info (0): done
00:02:34 - SDL Info (0): Cleaning up video stream...
00:02:34 - SDL Info (0): done
00:02:34 - SDL Info (0): Cleaning up control stream...
00:02:34 - SDL Info (0): done
00:02:34 - SDL Info (0): Cleaning up audio stream...
00:02:34 - SDL Info (0): done
00:02:34 - SDL Info (0): Cleaning up platform...
00:02:34 - SDL Info (0): done

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 MiB

View File

@ -0,0 +1,300 @@
00:00:00 - SDL Info (0): Compiled with SDL 2.30.0
00:00:00 - SDL Info (0): Running with SDL 2.30.0
00:00:00 - Qt Info: Successfully loaded translation for "zh_CN"
00:00:00 - Qt Info: Loaded unique ID from settings: "95da1945b8736669"
00:00:01 - Qt Warning: qrc:/gui/main.qml:13:1: QML ApplicationWindow: ToolTip must be attached to an Item
00:00:01 - Qt Warning: qrc:/gui/NavigableMessageDialog.qml:32:9: QML Image: Error decoding: qrc:/res/baseline-error_outline-24px.svg: Unsupported image format
00:00:01 - Qt Warning: qrc:/gui/NavigableMessageDialog.qml:32:9: QML Image: Error decoding: qrc:/res/baseline-help_outline-24px.svg: Unsupported image format
00:00:01 - Qt Warning: qrc:/gui/NavigableMessageDialog.qml:32:9: QML Image: Error decoding: qrc:/res/baseline-error_outline-24px.svg: Unsupported image format
00:00:01 - Qt Warning: qrc:/gui/NavigableMessageDialog.qml:32:9: QML Image: Error decoding: qrc:/res/baseline-error_outline-24px.svg: Unsupported image format
00:00:01 - Qt Warning: qrc:/gui/NavigableMessageDialog.qml:32:9: QML Image: Error decoding: qrc:/res/baseline-error_outline-24px.svg: Unsupported image format
00:00:01 - Qt Warning: qrc:/gui/NavigableMessageDialog.qml:32:9: QML Image: Error decoding: qrc:/res/baseline-error_outline-24px.svg: Unsupported image format
00:00:01 - Qt Warning: file:///home/armbian/vdi-build/rkmpp-experiment/deps/usr/lib/aarch64-linux-gnu/qt5/qml/QtQuick/Controls.2/Material/ToolButton.qml: QML IconImage: Error decoding: qrc:/res/settings.svg: Unsupported image format
00:00:01 - Qt Warning: file:///home/armbian/vdi-build/rkmpp-experiment/deps/usr/lib/aarch64-linux-gnu/qt5/qml/QtQuick/Controls.2/Material/ToolButton.qml: QML IconImage: Error decoding: qrc:/res/ic_videogame_asset_white_48px.svg: Unsupported image format
00:00:01 - Qt Warning: file:///home/armbian/vdi-build/rkmpp-experiment/deps/usr/lib/aarch64-linux-gnu/qt5/qml/QtQuick/Controls.2/Material/ToolButton.qml: QML IconImage: Error decoding: qrc:/res/question_mark.svg: Unsupported image format
00:00:01 - Qt Warning: file:///home/armbian/vdi-build/rkmpp-experiment/deps/usr/lib/aarch64-linux-gnu/qt5/qml/QtQuick/Controls.2/Material/ToolButton.qml: QML IconImage: Error decoding: qrc:/res/update.svg: Unsupported image format
00:00:01 - Qt Warning: file:///home/armbian/vdi-build/rkmpp-experiment/deps/usr/lib/aarch64-linux-gnu/qt5/qml/QtQuick/Controls.2/Material/ToolButton.qml: QML IconImage: Error decoding: qrc:/res/ic_add_to_queue_white_48px.svg: Unsupported image format
00:00:01 - Qt Warning: file:///home/armbian/vdi-build/rkmpp-experiment/deps/usr/lib/aarch64-linux-gnu/qt5/qml/QtQuick/Controls.2/Material/ToolButton.qml: QML IconImage: Error decoding: qrc:/res/discord.svg: Unsupported image format
00:00:01 - Qt Warning: file:///home/armbian/vdi-build/rkmpp-experiment/deps/usr/lib/aarch64-linux-gnu/qt5/qml/QtQuick/Controls.2/Material/ToolButton.qml: QML IconImage: Error decoding: qrc:/res/arrow_left.svg: Unsupported image format
00:00:01 - Qt Warning: file:///home/armbian/vdi-build/rkmpp-experiment/deps/usr/lib/aarch64-linux-gnu/qt5/qml/QtQuick/Controls.2/Material/ToolButton.qml: QML IconImage: Error decoding: qrc:/res/settings.svg: Unsupported image format
00:00:01 - Qt Warning: file:///home/armbian/vdi-build/rkmpp-experiment/deps/usr/lib/aarch64-linux-gnu/qt5/qml/QtQuick/Controls.2/Material/ToolButton.qml: QML IconImage: Error decoding: qrc:/res/settings.svg: Unsupported image format
00:00:01 - Qt Warning: file:///home/armbian/vdi-build/rkmpp-experiment/deps/usr/lib/aarch64-linux-gnu/qt5/qml/QtQuick/Controls.2/Material/ToolButton.qml: QML IconImage: Error decoding: qrc:/res/settings.svg: Unsupported image format
00:00:01 - Qt Warning: file:///home/armbian/vdi-build/rkmpp-experiment/deps/usr/lib/aarch64-linux-gnu/qt5/qml/QtQuick/Controls.2/Material/ToolButton.qml: QML IconImage: Error decoding: qrc:/res/settings.svg: Unsupported image format
00:00:01 - Qt Warning: file:///home/armbian/vdi-build/rkmpp-experiment/deps/usr/lib/aarch64-linux-gnu/qt5/qml/QtQuick/Controls.2/Material/ToolButton.qml: QML IconImage: Error decoding: qrc:/res/settings.svg: Unsupported image format
00:00:01 - Qt Warning: file:///home/armbian/vdi-build/rkmpp-experiment/deps/usr/lib/aarch64-linux-gnu/qt5/qml/QtQuick/Controls.2/Material/ToolButton.qml: QML IconImage: Error decoding: qrc:/res/settings.svg: Unsupported image format
00:00:01 - Qt Warning: file:///home/armbian/vdi-build/rkmpp-experiment/deps/usr/lib/aarch64-linux-gnu/qt5/qml/QtQuick/Controls.2/Material/ToolButton.qml: QML IconImage: Error decoding: qrc:/res/question_mark.svg: Unsupported image format
00:00:01 - Qt Warning: file:///home/armbian/vdi-build/rkmpp-experiment/deps/usr/lib/aarch64-linux-gnu/qt5/qml/QtQuick/Controls.2/Material/ToolButton.qml: QML IconImage: Error decoding: qrc:/res/question_mark.svg: Unsupported image format
00:00:01 - Qt Warning: file:///home/armbian/vdi-build/rkmpp-experiment/deps/usr/lib/aarch64-linux-gnu/qt5/qml/QtQuick/Controls.2/Material/ToolButton.qml: QML IconImage: Error decoding: qrc:/res/question_mark.svg: Unsupported image format
00:00:01 - Qt Warning: file:///home/armbian/vdi-build/rkmpp-experiment/deps/usr/lib/aarch64-linux-gnu/qt5/qml/QtQuick/Controls.2/Material/ToolButton.qml: QML IconImage: Error decoding: qrc:/res/question_mark.svg: Unsupported image format
00:00:01 - Qt Warning: file:///home/armbian/vdi-build/rkmpp-experiment/deps/usr/lib/aarch64-linux-gnu/qt5/qml/QtQuick/Controls.2/Material/ToolButton.qml: QML IconImage: Error decoding: qrc:/res/question_mark.svg: Unsupported image format
00:00:01 - Qt Warning: file:///home/armbian/vdi-build/rkmpp-experiment/deps/usr/lib/aarch64-linux-gnu/qt5/qml/QtQuick/Controls.2/Material/ToolButton.qml: QML IconImage: Error decoding: qrc:/res/question_mark.svg: Unsupported image format
00:00:01 - Qt Warning: file:///home/armbian/vdi-build/rkmpp-experiment/deps/usr/lib/aarch64-linux-gnu/qt5/qml/QtQuick/Controls.2/Material/ToolButton.qml: QML IconImage: Error decoding: qrc:/res/settings.svg: Unsupported image format
00:00:01 - Qt Warning: file:///home/armbian/vdi-build/rkmpp-experiment/deps/usr/lib/aarch64-linux-gnu/qt5/qml/QtQuick/Controls.2/Material/ToolButton.qml: QML IconImage: Error decoding: qrc:/res/settings.svg: Unsupported image format
00:00:01 - Qt Warning: file:///home/armbian/vdi-build/rkmpp-experiment/deps/usr/lib/aarch64-linux-gnu/qt5/qml/QtQuick/Controls.2/Material/ToolButton.qml: QML IconImage: Error decoding: qrc:/res/settings.svg: Unsupported image format
00:00:01 - Qt Warning: file:///home/armbian/vdi-build/rkmpp-experiment/deps/usr/lib/aarch64-linux-gnu/qt5/qml/QtQuick/Controls.2/Material/ToolButton.qml: QML IconImage: Error decoding: qrc:/res/settings.svg: Unsupported image format
00:00:01 - Qt Warning: file:///home/armbian/vdi-build/rkmpp-experiment/deps/usr/lib/aarch64-linux-gnu/qt5/qml/QtQuick/Controls.2/Material/ToolButton.qml: QML IconImage: Error decoding: qrc:/res/settings.svg: Unsupported image format
00:00:01 - Qt Warning: file:///home/armbian/vdi-build/rkmpp-experiment/deps/usr/lib/aarch64-linux-gnu/qt5/qml/QtQuick/Controls.2/Material/ToolButton.qml: QML IconImage: Error decoding: qrc:/res/settings.svg: Unsupported image format
00:00:01 - Qt Warning: file:///home/armbian/vdi-build/rkmpp-experiment/deps/usr/lib/aarch64-linux-gnu/qt5/qml/QtQuick/Controls.2/Material/ToolButton.qml: QML IconImage: Error decoding: qrc:/res/question_mark.svg: Unsupported image format
00:00:01 - Qt Warning: file:///home/armbian/vdi-build/rkmpp-experiment/deps/usr/lib/aarch64-linux-gnu/qt5/qml/QtQuick/Controls.2/Material/ToolButton.qml: QML IconImage: Error decoding: qrc:/res/question_mark.svg: Unsupported image format
00:00:01 - Qt Warning: file:///home/armbian/vdi-build/rkmpp-experiment/deps/usr/lib/aarch64-linux-gnu/qt5/qml/QtQuick/Controls.2/Material/ToolButton.qml: QML IconImage: Error decoding: qrc:/res/question_mark.svg: Unsupported image format
00:00:01 - Qt Warning: file:///home/armbian/vdi-build/rkmpp-experiment/deps/usr/lib/aarch64-linux-gnu/qt5/qml/QtQuick/Controls.2/Material/ToolButton.qml: QML IconImage: Error decoding: qrc:/res/question_mark.svg: Unsupported image format
00:00:01 - Qt Warning: file:///home/armbian/vdi-build/rkmpp-experiment/deps/usr/lib/aarch64-linux-gnu/qt5/qml/QtQuick/Controls.2/Material/ToolButton.qml: QML IconImage: Error decoding: qrc:/res/question_mark.svg: Unsupported image format
00:00:01 - Qt Warning: file:///home/armbian/vdi-build/rkmpp-experiment/deps/usr/lib/aarch64-linux-gnu/qt5/qml/QtQuick/Controls.2/Material/ToolButton.qml: QML IconImage: Error decoding: qrc:/res/question_mark.svg: Unsupported image format
00:00:01 - Qt Info: Found "gamecontrollerdb.txt" at "/home/armbian/.cache/Moonlight Game Streaming Project/Moonlight/gamecontrollerdb.txt"
00:00:01 - SDL Info (0): Loaded 436 new gamepad mappings
00:00:02 - Qt Warning: qrc:/gui/NavigableMessageDialog.qml:32:9: QML Image: Error decoding: qrc:/res/baseline-help_outline-24px.svg: Unsupported image format
00:00:02 - Qt Warning: qrc:/gui/NavigableMessageDialog.qml:32:9: QML Image: Error decoding: qrc:/res/baseline-error_outline-24px.svg: Unsupported image format
00:00:02 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:9
00:00:02 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:47009
00:00:02 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:47998
00:00:02 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:47999
00:00:02 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:48000
00:00:02 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:48002
00:00:02 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:48010
00:00:02 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:9
00:00:02 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:47009
00:00:02 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:47998
00:00:02 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:47999
00:00:02 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:48000
00:00:02 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:48002
00:00:02 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:48010
00:00:02 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:9
00:00:02 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:47009
00:00:02 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:47998
00:00:02 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:47999
00:00:02 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:48000
00:00:02 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:48002
00:00:02 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:48010
00:00:02 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:9
00:00:02 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:47009
00:00:02 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:47998
00:00:02 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:47999
00:00:02 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:48000
00:00:02 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:48002
00:00:02 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:48010
00:00:02 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:9
00:00:02 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:47009
00:00:02 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:47998
00:00:02 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:47999
00:00:02 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:48000
00:00:02 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:48002
00:00:02 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:48010
00:00:02 - Qt Info: "DESKTOP-Q072ICM" is now online at "192.168.1.70:47989"
00:00:02 - Qt Debug: Current Moonlight version: "6.2.0"
00:00:02 - Qt Info: Found "ModeSeven.ttf" at ":/data/ModeSeven.ttf"
00:00:02 - Qt Warning: file:///home/armbian/vdi-build/rkmpp-experiment/deps/usr/lib/aarch64-linux-gnu/qt5/qml/QtQuick/Controls.2/Material/ToolButton.qml: QML IconImage: Error decoding: qrc:/res/arrow_left.svg: Unsupported image format
00:00:02 - Qt Warning: file:///home/armbian/vdi-build/rkmpp-experiment/deps/usr/lib/aarch64-linux-gnu/qt5/qml/QtQuick/Controls.2/Material/ToolButton.qml: QML IconImage: Error decoding: qrc:/res/arrow_left.svg: Unsupported image format
00:00:02 - Qt Warning: file:///home/armbian/vdi-build/rkmpp-experiment/deps/usr/lib/aarch64-linux-gnu/qt5/qml/QtQuick/Controls.2/Material/ToolButton.qml: QML IconImage: Error decoding: qrc:/res/arrow_left.svg: Unsupported image format
00:00:02 - Qt Warning: file:///home/armbian/vdi-build/rkmpp-experiment/deps/usr/lib/aarch64-linux-gnu/qt5/qml/QtQuick/Controls.2/Material/ToolButton.qml: QML IconImage: Error decoding: qrc:/res/arrow_left.svg: Unsupported image format
00:00:02 - Qt Info: Discovered mDNS host: "DESKTOP-Q072ICM.local."
00:00:03 - SDL Info (0): Qt UI screen is at (0,0)
00:00:03 - SDL Info (0): SDL found matching display 0
00:00:03 - Qt Info: Server GPU: ""
00:00:03 - Qt Info: Server GFE version: "3.23.0.74"
00:00:03 - SDL Info (0): Video bitrate: 30000 kbps
00:00:03 - SDL Info (0): Audio channel count: 2
00:00:03 - SDL Info (0): Audio channel mask: 3
00:00:03 - SDL Info (0): Desired audio buffer: 720 samples (5760 bytes)
00:00:03 - SDL Info (0): Obtained audio buffer: 720 samples (5760 bytes)
00:00:03 - SDL Info (0): SDL audio driver: pulseaudio
00:00:03 - Qt Info: Found "gamecontrollerdb.txt" at "/home/armbian/.cache/Moonlight Game Streaming Project/Moonlight/gamecontrollerdb.txt"
00:00:03 - SDL Info (0): Loaded 436 new gamepad mappings
00:00:03 - SDL Info (0): V-sync disabled
00:00:03 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:03 - SDL Info (0): GPU driver: rockchip
00:00:03 - SDL Info (0): Direct rendering via DRM is disabled
00:00:03 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:03 - SDL Info (0): GPU driver: rockchip
00:00:03 - SDL Info (0): Direct rendering via DRM is disabled
00:00:03 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:03 - SDL Info (0): GPU driver: rockchip
00:00:03 - SDL Info (0): Direct rendering via DRM is disabled
00:00:03 - SDL Info (0): Using DRM renderer
00:00:03 - FFmpeg: [h264_mp4toannexb @ 0xaaaacc36b700] The input looks like it is Annex B already
mpp[44667]: mpp_info: mpp version: 7916c3c author: Xiaoxu Chen 2026-10-28 fix[utils]: Fix AVC cu_map allocation stride
00:00:03 - FFmpeg: [h264_rkmpp @ 0xaaaacb767aa0] Picked up an existing RKMPP hardware device
00:00:03 - FFmpeg: [h264_rkmpp @ 0xaaaacb767aa0] Wrote 390 bytes to decoder
00:00:03 - FFmpeg: [h264_rkmpp @ 0xaaaacb767aa0] Noticed an info change
00:00:03 - FFmpeg: [h264_rkmpp @ 0xaaaacb767aa0] Decoder options: deint=true afbc=0 fast_parse=true buf_mode=0
00:00:03 - FFmpeg: [h264_rkmpp @ 0xaaaacb767aa0] Configured with size: 1280x720 | pix_fmt: drm_prime | sw_pix_fmt: nv12
00:00:03 - FFmpeg: [h264_rkmpp @ 0xaaaacb767aa0] Wrote 390 bytes to decoder
00:00:03 - FFmpeg: [h264_rkmpp @ 0xaaaacb767aa0] Received a frame
00:00:03 - SDL Info (0): Selected hwframe->swframe format: 23 (mapping: yes)
00:00:03 - SDL Warn (0): Using custom H.264 decoder (H264_DECODER_HINT): h264_rkmpp
00:00:03 - SDL Info (0): FFmpeg-based video decoder chosen
00:00:03 - SDL Info (0): V-sync disabled
00:00:03 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:03 - SDL Info (0): GPU driver: rockchip
00:00:03 - SDL Info (0): Direct rendering via DRM is disabled
00:00:03 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:03 - SDL Info (0): GPU driver: rockchip
00:00:03 - SDL Info (0): Direct rendering via DRM is disabled
00:00:03 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:03 - SDL Info (0): GPU driver: rockchip
00:00:03 - SDL Info (0): Direct rendering via DRM is disabled
00:00:03 - SDL Info (0): Using DRM renderer
00:00:03 - FFmpeg: [h264_mp4toannexb @ 0xaaaacc3369a0] The input looks like it is Annex B already
mpp[44667]: mpp_info: mpp version: 7916c3c author: Xiaoxu Chen 2026-10-28 fix[utils]: Fix AVC cu_map allocation stride
00:00:03 - FFmpeg: [h264_rkmpp @ 0xaaaacb767aa0] Picked up an existing RKMPP hardware device
00:00:03 - FFmpeg: [h264_rkmpp @ 0xaaaacb767aa0] Wrote 390 bytes to decoder
00:00:03 - FFmpeg: [h264_rkmpp @ 0xaaaacb767aa0] Wrote 390 bytes to decoder
00:00:03 - FFmpeg: [h264_rkmpp @ 0xaaaacb767aa0] Noticed an info change
00:00:03 - FFmpeg: [h264_rkmpp @ 0xaaaacb767aa0] Decoder options: deint=true afbc=0 fast_parse=true buf_mode=0
00:00:03 - FFmpeg: [h264_rkmpp @ 0xaaaacb767aa0] Configured with size: 1280x720 | pix_fmt: drm_prime | sw_pix_fmt: nv12
00:00:03 - FFmpeg: [h264_rkmpp @ 0xaaaacb767aa0] Wrote 390 bytes to decoder
00:00:03 - FFmpeg: [h264_rkmpp @ 0xaaaacb767aa0] Received a frame
00:00:03 - SDL Info (0): Selected hwframe->swframe format: 23 (mapping: yes)
00:00:03 - SDL Warn (0): Using custom H.264 decoder (H264_DECODER_HINT): h264_rkmpp
00:00:03 - SDL Info (0): FFmpeg-based video decoder chosen
00:00:03 - Qt Warning: 启用远程桌面鼠标模式可能会导致游戏出现问题。
00:00:05 - Qt Info: Gamepad mappings are up to date
00:00:06 - Qt Info: Processing new PC "DESKTOP-Q072ICM.local." from mDNS with local address "192.168.1.70:47989"
00:00:06 - Qt Info: Executing request: "http://192.168.1.70:47989/serverinfo?uniqueid=0123456789ABCDEF&uuid=38035ae211ee431ab78b9142e0450ce3"
00:00:06 - Qt Info: Executing request: "https://192.168.1.70:47984/serverinfo?uniqueid=95da1945b8736669&uuid=3f6cd9485a3b4e4c92fe07f7076ea0cf"
00:00:08 - Qt Info: Found "gamecontrollerdb.txt" at "/home/armbian/.cache/Moonlight Game Streaming Project/Moonlight/gamecontrollerdb.txt"
00:00:08 - SDL Info (0): Loaded 436 new gamepad mappings
00:00:08 - Qt Info: Executing request: "https://192.168.1.70:47984/resume?uniqueid=95da1945b8736669&uuid=21acc81568604fefac1fa259037e9792&appid=881448767&mode=2560x1440x20&additionalStates=1&sops=1&rikey=REDACTED&rikeyid=REDACTED&localAudioPlayMode=1&surroundAudioInfo=196610&remoteControllersBitmap=0&gcmap=0&gcpersist=0&corever=1"
00:00:08 - Qt Info: Launch response: "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root status_code=\"200\"><sessionUrl0>rtspenc://192.168.1.70:48010</sessionUrl0><resume>1</resume></root>"
00:00:08 - Qt Info: Found matching interface: "wlan0" "88:00:33:77:30:B6" QFlags<QNetworkInterface::InterfaceFlag>(IsUp|IsRunning|CanBroadcast|CanMulticast)
00:00:08 - Qt Info: Interface Type: QNetworkInterface::Wifi
00:00:08 - Qt Info: Interface MTU: 1500
00:00:08 - SDL Info (0): RTSP port: 48010
00:00:08 - SDL Info (0): Initializing platform...
00:00:08 - SDL Info (0): done
00:00:08 - SDL Info (0): Resolving host name...
00:00:08 - SDL Info (0): done
00:00:08 - SDL Info (0): Initializing audio stream...
00:00:08 - SDL Info (0): done
00:00:08 - SDL Info (0): Starting RTSP handshake...
00:00:08 - SDL Info (0): Reference frame invalidation is not supported by this host
00:00:08 - SDL Info (0): Audio port: 48000
00:00:08 - SDL Info (0): Video port: 47998
00:00:08 - SDL Info (0): Control port: 47999
00:00:08 - SDL Info (0): done
00:00:08 - SDL Info (0): Initializing control stream...
00:00:08 - SDL Info (0): done
00:00:08 - SDL Info (0): Initializing video stream...
00:00:08 - SDL Info (0): done
00:00:08 - SDL Info (0): Initializing input stream...
00:00:08 - SDL Info (0): done
00:00:08 - SDL Info (0): Starting control stream...
00:00:08 - SDL Info (0): done
00:00:08 - SDL Info (0): Starting video stream...
00:00:08 - SDL Info (0): Video stream is 2560x1440x20 (format 0x1)
00:00:08 - SDL Info (0): done
00:00:08 - SDL Info (0): Starting audio stream...
00:00:08 - SDL Info (0): Received first video packet after 0 ms
00:00:08 - SDL Info (0): Desired audio buffer: 720 samples (5760 bytes)
00:00:08 - SDL Info (0): Obtained audio buffer: 720 samples (5760 bytes)
00:00:08 - SDL Info (0): SDL audio driver: pulseaudio
00:00:08 - SDL Info (0): Audio stream has 2 channels
00:00:08 - SDL Info (0): done
00:00:08 - SDL Info (0): Starting input stream...
00:00:08 - SDL Info (0): done
00:00:09 - SDL Info (0): Qt UI screen is at (0,0)
00:00:09 - SDL Info (0): SDL found matching display 0
00:00:09 - SDL Info (0): Found display mode with video resolution: 2560x1440x60
00:00:09 - SDL Info (0): Video decode unit queue overflow
00:00:09 - SDL Info (0): IDR frame request sent
00:00:09 - SDL Info (0): Waiting for IDR frame
00:00:11 - SDL Info (0): Video decode unit queue overflow
00:00:11 - SDL Info (0): IDR frame request sent
00:00:11 - SDL Info (0): Waiting for IDR frame
00:00:13 - SDL Info (0): Video decode unit queue overflow
00:00:13 - SDL Info (0): IDR frame request sent
00:00:13 - SDL Info (0): Waiting for IDR frame
00:00:14 - SDL Info (0): Recreating renderer for window event: 1 (0 0)
00:00:14 - SDL Info (0): V-sync enabled
00:00:14 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:14 - SDL Info (0): GPU driver: rockchip
00:00:14 - SDL Info (0): Direct rendering via DRM is disabled
00:00:14 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:14 - SDL Info (0): GPU driver: rockchip
00:00:14 - SDL Info (0): Direct rendering via DRM is disabled
00:00:14 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:14 - SDL Info (0): GPU driver: rockchip
00:00:14 - SDL Info (0): Direct rendering via DRM is disabled
00:00:15 - SDL Info (0): Video decode unit queue overflow
00:00:15 - SDL Info (0): IDR frame request sent
00:00:15 - SDL Info (0): Waiting for IDR frame
00:00:15 - SDL Info (0): Using DRM renderer
00:00:15 - FFmpeg: [h264_mp4toannexb @ 0xaaaacc468440] The input looks like it is Annex B already
mpp[44667]: mpp_info: mpp version: 7916c3c author: Xiaoxu Chen 2026-10-28 fix[utils]: Fix AVC cu_map allocation stride
00:00:15 - FFmpeg: [h264_rkmpp @ 0xaaaacb767aa0] Picked up an existing RKMPP hardware device
00:00:15 - FFmpeg: [h264_rkmpp @ 0xaaaacb767aa0] Wrote 390 bytes to decoder
00:00:15 - FFmpeg: [h264_rkmpp @ 0xaaaacb767aa0] Wrote 390 bytes to decoder
00:00:15 - FFmpeg: [h264_rkmpp @ 0xaaaacb767aa0] Noticed an info change
00:00:15 - FFmpeg: [h264_rkmpp @ 0xaaaacb767aa0] Decoder options: deint=true afbc=0 fast_parse=true buf_mode=0
00:00:15 - FFmpeg: [h264_rkmpp @ 0xaaaacb767aa0] Configured with size: 1280x720 | pix_fmt: drm_prime | sw_pix_fmt: nv12
00:00:16 - FFmpeg: [h264_rkmpp @ 0xaaaacb767aa0] Wrote 390 bytes to decoder
00:00:16 - FFmpeg: [h264_rkmpp @ 0xaaaacb767aa0] Received a frame
00:00:16 - SDL Info (0): Selected hwframe->swframe format: 23 (mapping: yes)
00:00:16 - SDL Info (0): Not reusing test decoder for h264_rkmpp
00:00:16 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:16 - SDL Info (0): GPU driver: rockchip
00:00:16 - SDL Info (0): Direct rendering via DRM is disabled
00:00:16 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:16 - SDL Info (0): GPU driver: rockchip
00:00:16 - SDL Info (0): Direct rendering via DRM is disabled
mpp[44667]: mpp_info: mpp version: 7916c3c author: Xiaoxu Chen 2026-10-28 fix[utils]: Fix AVC cu_map allocation stride
00:00:16 - SDL Info (0): Frame pacing: target 60 Hz with 20 FPS stream
00:00:16 - SDL Info (0): SDL renderer backend: opengles2
00:00:16 - SDL Info (0): SDL renderer backend requires main thread rendering
00:00:16 - SDL Info (0): Using DRM renderer
00:00:16 - FFmpeg: [h264_mp4toannexb @ 0xaaaaccea90d0] The input looks like it is Annex B already
00:00:16 - FFmpeg: [h264_rkmpp @ 0xaaaacb767aa0] Picked up an existing RKMPP hardware device
00:00:16 - SDL Info (0): Using H.264 SPS fixup
00:00:16 - SDL Info (0): Renderer 'SDL' with 'DRM' backend chosen
00:00:16 - SDL Warn (0): Using custom H.264 decoder (H264_DECODER_HINT): h264_rkmpp
00:00:16 - SDL Info (0): FFmpeg-based video decoder chosen
00:00:16 - FFmpeg: [h264_rkmpp @ 0xaaaacb767aa0] Wrote 184376 bytes to decoder
00:00:16 - FFmpeg: [h264_rkmpp @ 0xaaaacb767aa0] Noticed an info change
00:00:16 - FFmpeg: [h264_rkmpp @ 0xaaaacb767aa0] Decoder options: deint=true afbc=0 fast_parse=true buf_mode=0
00:00:16 - FFmpeg: [h264_rkmpp @ 0xaaaacb767aa0] Configured with size: 2560x1440 | pix_fmt: drm_prime | sw_pix_fmt: nv12
00:00:16 - SDL Info (0): Dropping window event during flush: 6 (2560 1440)
00:00:16 - SDL Info (0): IDR frame request sent
00:00:16 - FFmpeg: [h264_rkmpp @ 0xaaaacb767aa0] Wrote 77048 bytes to decoder
00:00:16 - FFmpeg: [h264_rkmpp @ 0xaaaacb767aa0] Wrote 101816 bytes to decoder
00:00:16 - FFmpeg: [h264_rkmpp @ 0xaaaacb767aa0] Wrote 129336 bytes to decoder
00:00:16 - FFmpeg: [h264_rkmpp @ 0xaaaacb767aa0] Received a frame
00:00:16 - SDL Info (0): Selected hwframe->swframe format: 23 (mapping: yes)
00:02:40 - SDL Info (0): Raising 3 keys
00:02:40 - SDL Info (0): Detected quit key combo
00:02:40 - SDL Info (0): Quit event received
00:02:40 - SDL Info (0):
Global video stats
------------------
Incoming frame rate from network: 8.72 FPS
Decoding frame rate: 8.72 FPS
Rendering frame rate: 8.61 FPS
Host processing latency min/max/average: 25.8/35.9/30.7 ms
Frames dropped by your network connection: 0.00%
Frames dropped due to network jitter: 0.24%
Average network latency: 2 ms (variance: 0 ms)
Average decoding time: 16.89 ms
Average frame queue delay: 1.07 ms
Average rendering time (including monitor V-sync latency): 44.80 ms
00:02:40 - SDL Info (0): Stopping input stream...
00:02:40 - SDL Info (0): done
00:02:40 - SDL Info (0): Stopping audio stream...
00:02:40 - SDL Info (0): No audio traffic was ever received from the host!
00:02:40 - SDL Info (0): ENet wait interrupted
00:02:40 - SDL Info (0): Control stream connection failed: 4
00:02:40 - SDL Info (0): done
00:02:40 - SDL Info (0): Stopping video stream...
00:02:40 - Qt Info: Found "gamecontrollerdb.txt" at "/home/armbian/.cache/Moonlight Game Streaming Project/Moonlight/gamecontrollerdb.txt"
00:02:40 - SDL Info (0): Loaded 436 new gamepad mappings
00:02:40 - SDL Info (0): done
00:02:40 - SDL Info (0): Stopping control stream...
00:02:40 - SDL Info (0): ENet peer acknowledged disconnection
00:02:40 - SDL Info (0): done
00:02:40 - SDL Info (0): Cleaning up input stream...
00:02:40 - SDL Info (0): done
00:02:40 - SDL Info (0): Cleaning up video stream...
00:02:40 - SDL Info (0): done
00:02:40 - SDL Info (0): Cleaning up control stream...
00:02:40 - SDL Info (0): done
00:02:40 - SDL Info (0): Cleaning up audio stream...
00:02:40 - SDL Info (0): done
00:02:40 - SDL Info (0): Cleaning up platform...
00:02:40 - SDL Info (0): done

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

View File

@ -0,0 +1,250 @@
00:00:00 - SDL Info (0): Compiled with SDL 2.33.0
00:00:00 - SDL Info (0): Running with SDL 2.33.0
00:00:00 - Qt Info: Successfully loaded translation for "zh_CN"
00:00:00 - Qt Info: Loaded unique ID from settings: "95da1945b8736669"
00:00:00 - Qt Warning: qrc:/gui/main.qml:13:1: QML ApplicationWindow: ToolTip must be attached to an Item
00:00:01 - Qt Info: Found "gamecontrollerdb.txt" at "/home/armbian/.cache/Moonlight Game Streaming Project/Moonlight/gamecontrollerdb.txt"
00:00:01 - SDL Info (0): Loaded 435 new gamepad mappings
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:9
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:47009
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:47998
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:47999
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:48000
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:48002
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.255:48010
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:9
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:47009
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:47998
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:47999
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:48000
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:48002
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 192.168.1.70:48010
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:9
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:47009
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:47998
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:47999
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:48000
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:48002
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 255.255.255.255:48010
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:9
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:47009
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:47998
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:47999
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:48000
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:48002
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via 60.21.96.193:48010
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:9
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:47009
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:47998
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:47999
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:48000
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:48002
00:00:01 - Qt Info: Sent WoL packet to DESKTOP-Q072ICM via ff02::1%wlan0:48010
00:00:01 - Qt Debug: Current Moonlight version: "6.2.0"
00:00:01 - Qt Info: "DESKTOP-Q072ICM" is now online at "192.168.1.70:47989"
00:00:01 - Qt Info: Found "ModeSeven.ttf" at ":/data/ModeSeven.ttf"
00:00:01 - Qt Info: Discovered mDNS host: "DESKTOP-Q072ICM.local."
00:00:01 - SDL Info (0): Qt UI screen is at (0,0)
00:00:01 - SDL Info (0): SDL found matching display 0
00:00:01 - Qt Info: Server GPU: ""
00:00:01 - Qt Info: Server GFE version: "3.23.0.74"
00:00:01 - SDL Info (0): Video bitrate: 30000 kbps
00:00:01 - SDL Info (0): Audio channel count: 2
00:00:01 - SDL Info (0): Audio channel mask: 3
00:00:01 - SDL Info (0): Desired audio buffer: 720 samples (5760 bytes)
00:00:01 - SDL Info (0): Obtained audio buffer: 720 samples (5760 bytes)
00:00:01 - SDL Info (0): SDL audio driver: pulseaudio
00:00:02 - Qt Info: Found "gamecontrollerdb.txt" at "/home/armbian/.cache/Moonlight Game Streaming Project/Moonlight/gamecontrollerdb.txt"
00:00:02 - SDL Info (0): Loaded 435 new gamepad mappings
00:00:02 - SDL Info (0): V-sync disabled
00:00:02 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:02 - SDL Info (0): GPU driver: rockchip
00:00:02 - SDL Info (0): Direct rendering via DRM is disabled
00:00:02 - SDL Info (0): DRM backend supports exporting EGLImage
00:00:02 - SDL Info (0): Color buffer is: R8G8B8A0
00:00:02 - SDL Info (0): Using DRM renderer
00:00:02 - FFmpeg: [h264 @ 0xaaaabb28ac40] nal_unit_type: 7(SPS), nal_ref_idc: 3
00:00:02 - FFmpeg: [h264 @ 0xaaaabb28ac40] nal_unit_type: 8(PPS), nal_ref_idc: 3
00:00:02 - FFmpeg: [h264 @ 0xaaaabb28ac40] nal_unit_type: 5(IDR), nal_ref_idc: 3
00:00:02 - FFmpeg: [h264 @ 0xaaaabb28ac40] nal_unit_type: 5(IDR), nal_ref_idc: 3
00:00:02 - FFmpeg: [h264 @ 0xaaaabb28ac40] nal_unit_type: 5(IDR), nal_ref_idc: 3
00:00:02 - FFmpeg: [h264 @ 0xaaaabb28ac40] nal_unit_type: 5(IDR), nal_ref_idc: 3
00:00:02 - FFmpeg: [h264 @ 0xaaaabb28ac40] Decoding VUI
00:00:02 - FFmpeg: [h264 @ 0xaaaabb28ac40] Format drm_prime chosen by get_format().
00:00:02 - FFmpeg: [h264 @ 0xaaaabb28ac40] Invalid setup for format drm_prime: missing configuration.
00:00:02 - FFmpeg: [h264 @ 0xaaaabb28ac40] Format drm_prime not usable, retrying get_format() without it.
00:00:02 - FFmpeg: [h264 @ 0xaaaabb28ac40] Format yuv420p chosen by get_format().
00:00:02 - FFmpeg: [h264 @ 0xaaaabb28ac40] Reinit context to 1280x720, pix_fmt: yuv420p
00:00:02 - SDL Warn (0): EGLImage export requires hardware-backed frames
00:00:02 - SDL Warn (0): Backend failed to export EGL image for test frame
00:00:02 - SDL Warn (0): Test decode failed (testRenderFrame)
00:00:02 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:02 - SDL Info (0): GPU driver: rockchip
00:00:02 - SDL Info (0): Direct rendering via DRM is disabled
00:00:02 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:02 - SDL Info (0): GPU driver: rockchip
00:00:02 - SDL Info (0): Direct rendering via DRM is disabled
00:00:02 - SDL Info (0): Using DRM renderer
00:00:02 - FFmpeg: [h264 @ 0xaaaabb28ac40] nal_unit_type: 7(SPS), nal_ref_idc: 3
00:00:02 - FFmpeg: [h264 @ 0xaaaabb28ac40] nal_unit_type: 8(PPS), nal_ref_idc: 3
00:00:02 - FFmpeg: [h264 @ 0xaaaabb28ac40] nal_unit_type: 5(IDR), nal_ref_idc: 3
00:00:02 - FFmpeg: [h264 @ 0xaaaabb28ac40] nal_unit_type: 5(IDR), nal_ref_idc: 3
00:00:02 - FFmpeg: [h264 @ 0xaaaabb28ac40] nal_unit_type: 5(IDR), nal_ref_idc: 3
00:00:02 - FFmpeg: [h264 @ 0xaaaabb28ac40] nal_unit_type: 5(IDR), nal_ref_idc: 3
00:00:02 - FFmpeg: [h264 @ 0xaaaabb28ac40] Decoding VUI
00:00:02 - FFmpeg: [h264 @ 0xaaaabb28ac40] Format yuv420p chosen by get_format().
00:00:02 - FFmpeg: [h264 @ 0xaaaabb28ac40] Reinit context to 1280x720, pix_fmt: yuv420p
00:00:02 - SDL Info (0): FFmpeg-based video decoder chosen
00:00:02 - SDL Info (0): Encoder configured for 4 slices per frame
00:00:02 - Qt Warning: 启用远程桌面鼠标模式可能会导致游戏出现问题。
00:00:02 - Qt Warning: 你选择的用于强制软件解码的设置可能会导致流式传输性能不佳。
00:00:03 - Qt Info: Processing new PC "DESKTOP-Q072ICM.local." from mDNS with local address "192.168.1.70:47989"
00:00:03 - Qt Info: Executing request: "http://192.168.1.70:47989/serverinfo?uniqueid=0123456789ABCDEF&uuid=6962458dceb442b4b6bd8028e70a3b36"
00:00:03 - Qt Info: Executing request: "https://192.168.1.70:47984/serverinfo?uniqueid=95da1945b8736669&uuid=24015164fe774f5790b5e26dcbdac0a3"
00:00:04 - Qt Info: Gamepad mappings are up to date
00:00:05 - Qt Info: Found "gamecontrollerdb.txt" at "/home/armbian/.cache/Moonlight Game Streaming Project/Moonlight/gamecontrollerdb.txt"
00:00:05 - SDL Info (0): Loaded 435 new gamepad mappings
00:00:05 - Qt Info: Executing request: "https://192.168.1.70:47984/resume?uniqueid=95da1945b8736669&uuid=49737f9390044dc28228a93b794837cb&appid=881448767&mode=2560x1440x20&additionalStates=1&sops=1&rikey=REDACTED&rikeyid=REDACTED&localAudioPlayMode=0&surroundAudioInfo=196610&remoteControllersBitmap=0&gcmap=0&gcpersist=0&corever=1"
00:00:06 - Qt Info: Launch response: "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root status_code=\"200\"><sessionUrl0>rtspenc://192.168.1.70:48010</sessionUrl0><resume>1</resume></root>"
00:00:06 - Qt Info: Found matching interface: "wlan0" "88:00:33:77:30:B6" QFlags<QNetworkInterface::InterfaceFlag>(IsUp|IsRunning|CanBroadcast|CanMulticast)
00:00:06 - Qt Info: Interface Type: QNetworkInterface::Wifi
00:00:06 - Qt Info: Interface MTU: 1500
00:00:06 - SDL Info (0): RTSP port: 48010
00:00:06 - SDL Info (0): Initializing platform...
00:00:06 - SDL Info (0): done
00:00:06 - SDL Info (0): Resolving host name...
00:00:06 - SDL Info (0): done
00:00:06 - SDL Info (0): Initializing audio stream...
00:00:06 - SDL Info (0): done
00:00:06 - SDL Info (0): Starting RTSP handshake...
00:00:06 - SDL Info (0): Reference frame invalidation is not supported by this host
00:00:06 - SDL Info (0): Audio port: 48000
00:00:06 - SDL Info (0): Video port: 47998
00:00:06 - SDL Info (0): Control port: 47999
00:00:06 - SDL Info (0): done
00:00:06 - SDL Info (0): Initializing control stream...
00:00:06 - SDL Info (0): done
00:00:06 - SDL Info (0): Initializing video stream...
00:00:06 - SDL Info (0): done
00:00:06 - SDL Info (0): Initializing input stream...
00:00:06 - SDL Info (0): done
00:00:06 - SDL Info (0): Starting control stream...
00:00:06 - SDL Info (0): done
00:00:06 - SDL Info (0): Starting video stream...
00:00:06 - SDL Info (0): Video stream is 2560x1440x20 (format 0x1)
00:00:06 - SDL Info (0): done
00:00:06 - SDL Info (0): Starting audio stream...
00:00:06 - SDL Info (0): Desired audio buffer: 720 samples (5760 bytes)
00:00:06 - SDL Info (0): Obtained audio buffer: 720 samples (5760 bytes)
00:00:06 - SDL Info (0): SDL audio driver: pulseaudio
00:00:06 - SDL Info (0): Received first video packet after 0 ms
00:00:06 - SDL Info (0): Audio stream has 2 channels
00:00:06 - SDL Info (0): done
00:00:06 - SDL Info (0): Starting input stream...
00:00:06 - SDL Info (0): done
00:00:06 - SDL Info (0): Qt UI screen is at (0,0)
00:00:06 - SDL Info (0): SDL found matching display 0
00:00:06 - SDL Info (0): Found display mode with desktop resolution: 2560x1440x60
00:00:06 - SDL Info (0): Recreating renderer for window event: 1 (0 0)
00:00:06 - SDL Info (0): V-sync enabled
00:00:06 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:06 - SDL Info (0): GPU driver: rockchip
00:00:06 - SDL Info (0): Direct rendering via DRM is disabled
00:00:06 - SDL Info (0): DRM backend supports exporting EGLImage
00:00:07 - SDL Info (0): Video decode unit queue overflow
00:00:07 - SDL Info (0): IDR frame request sent
00:00:07 - SDL Info (0): Waiting for IDR frame
00:00:07 - SDL Info (0): Color buffer is: R8G8B8A0
00:00:07 - SDL Info (0): Frame pacing: target 60 Hz with 20 FPS stream
00:00:07 - SDL Info (0): Using DRM renderer
00:00:07 - FFmpeg: [h264 @ 0xaaaabb28ac40] nal_unit_type: 7(SPS), nal_ref_idc: 3
00:00:07 - FFmpeg: [h264 @ 0xaaaabb28ac40] nal_unit_type: 8(PPS), nal_ref_idc: 3
00:00:07 - FFmpeg: [h264 @ 0xaaaabb28ac40] nal_unit_type: 5(IDR), nal_ref_idc: 3
00:00:07 - FFmpeg: [h264 @ 0xaaaabb28ac40] nal_unit_type: 5(IDR), nal_ref_idc: 3
00:00:07 - FFmpeg: [h264 @ 0xaaaabb28ac40] nal_unit_type: 5(IDR), nal_ref_idc: 3
00:00:07 - FFmpeg: [h264 @ 0xaaaabb28ac40] nal_unit_type: 5(IDR), nal_ref_idc: 3
00:00:07 - FFmpeg: [h264 @ 0xaaaabb28ac40] Decoding VUI
00:00:07 - SDL Warn (0): Unable to set render thread to high priority: setpriority() failed
00:00:07 - FFmpeg: [h264 @ 0xaaaabb28ac40] Format drm_prime chosen by get_format().
00:00:07 - FFmpeg: [h264 @ 0xaaaabb28ac40] Invalid setup for format drm_prime: missing configuration.
00:00:07 - FFmpeg: [h264 @ 0xaaaabb28ac40] Format drm_prime not usable, retrying get_format() without it.
00:00:07 - FFmpeg: [h264 @ 0xaaaabb28ac40] Format yuv420p chosen by get_format().
00:00:07 - FFmpeg: [h264 @ 0xaaaabb28ac40] Reinit context to 1280x720, pix_fmt: yuv420p
00:00:07 - SDL Warn (0): EGLImage export requires hardware-backed frames
00:00:07 - SDL Warn (0): Backend failed to export EGL image for test frame
00:00:07 - SDL Warn (0): Test decode failed (testRenderFrame)
00:00:07 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:07 - SDL Info (0): GPU driver: rockchip
00:00:07 - SDL Info (0): Direct rendering via DRM is disabled
00:00:07 - SDL Info (0): Opened DRM render node: /dev/dri/renderD128
00:00:07 - SDL Info (0): GPU driver: rockchip
00:00:07 - SDL Info (0): Direct rendering via DRM is disabled
00:00:07 - SDL Info (0): Frame pacing: target 60 Hz with 20 FPS stream
00:00:07 - SDL Info (0): SDL renderer backend: opengles2
00:00:07 - SDL Info (0): SDL renderer backend requires main thread rendering
00:00:07 - SDL Info (0): Using DRM renderer
00:00:07 - FFmpeg: [h264 @ 0xaaaabb28ac40] nal_unit_type: 7(SPS), nal_ref_idc: 3
00:00:07 - FFmpeg: [h264 @ 0xaaaabb28ac40] nal_unit_type: 8(PPS), nal_ref_idc: 3
00:00:07 - FFmpeg: [h264 @ 0xaaaabb28ac40] nal_unit_type: 5(IDR), nal_ref_idc: 3
00:00:07 - FFmpeg: [h264 @ 0xaaaabb28ac40] nal_unit_type: 5(IDR), nal_ref_idc: 3
00:00:07 - FFmpeg: [h264 @ 0xaaaabb28ac40] nal_unit_type: 5(IDR), nal_ref_idc: 3
00:00:07 - FFmpeg: [h264 @ 0xaaaabb28ac40] nal_unit_type: 5(IDR), nal_ref_idc: 3
00:00:07 - FFmpeg: [h264 @ 0xaaaabb28ac40] Decoding VUI
00:00:07 - FFmpeg: [h264 @ 0xaaaabb28ac40] Format yuv420p chosen by get_format().
00:00:07 - FFmpeg: [h264 @ 0xaaaabb28ac40] Reinit context to 1280x720, pix_fmt: yuv420p
00:00:07 - SDL Info (0): Test decode successful
00:00:07 - SDL Info (0): Using H.264 SPS fixup
00:00:07 - SDL Info (0): Renderer 'SDL' with 'DRM' backend chosen
00:00:07 - SDL Info (0): FFmpeg-based video decoder chosen
00:00:07 - FFmpeg: [h264 @ 0xaaaabb28ac40] nal_unit_type: 7(SPS), nal_ref_idc: 3
00:00:07 - FFmpeg: [h264 @ 0xaaaabb28ac40] nal_unit_type: 8(PPS), nal_ref_idc: 3
00:00:07 - FFmpeg: [h264 @ 0xaaaabb28ac40] nal_unit_type: 5(IDR), nal_ref_idc: 3
00:00:07 - FFmpeg: [h264 @ 0xaaaabb28ac40] nal_unit_type: 5(IDR), nal_ref_idc: 3
00:00:07 - FFmpeg: [h264 @ 0xaaaabb28ac40] nal_unit_type: 5(IDR), nal_ref_idc: 3
00:00:07 - FFmpeg: [h264 @ 0xaaaabb28ac40] nal_unit_type: 5(IDR), nal_ref_idc: 3
00:00:07 - FFmpeg: [h264 @ 0xaaaabb28ac40] Decoding VUI
00:00:07 - FFmpeg: [h264 @ 0xaaaabb28ac40] Format yuvj420p chosen by get_format().
00:00:07 - FFmpeg: [h264 @ 0xaaaabb28ac40] Reinit context to 2560x1440, pix_fmt: yuvj420p
00:00:07 - SDL Info (0): Dropping window event during flush: 6 (2560 1440)
00:00:07 - SDL Info (0): IDR frame request sent
00:01:54 - SDL Info (0): Raising 3 keys
00:01:54 - SDL Info (0): Detected quit key combo
00:01:54 - SDL Info (0): Quit event received
00:01:54 - SDL Info (0):
Global video stats
------------------
Incoming frame rate from network: 17.16 FPS
Decoding frame rate: 17.16 FPS
Rendering frame rate: 17.07 FPS
Host processing latency min/max/average: 24.1/53.8/33.6 ms
Frames dropped by your network connection: 0.00%
Frames dropped due to network jitter: 0.44%
Average network latency: 11 ms (variance: 7 ms)
Average decoding time: 14.07 ms
Average frame queue delay: 0.95 ms
Average rendering time (including monitor V-sync latency): 8.38 ms
00:01:54 - SDL Info (0): Stopping input stream...
00:01:54 - SDL Info (0): done
00:01:54 - SDL Info (0): Stopping audio stream...
00:01:54 - SDL Info (0): No audio traffic was ever received from the host!
00:01:54 - SDL Info (0): ENet wait interrupted
00:01:54 - SDL Info (0): Control stream connection failed: 4
00:01:54 - Qt Info: Found "gamecontrollerdb.txt" at "/home/armbian/.cache/Moonlight Game Streaming Project/Moonlight/gamecontrollerdb.txt"
00:01:54 - SDL Info (0): done
00:01:54 - SDL Info (0): Stopping video stream...
00:01:54 - SDL Info (0): Loaded 435 new gamepad mappings
00:01:54 - SDL Info (0): done
00:01:54 - SDL Info (0): Stopping control stream...
00:01:54 - SDL Info (0): ENet peer acknowledged disconnection
00:01:54 - SDL Info (0): done
00:01:54 - SDL Info (0): Cleaning up input stream...
00:01:54 - SDL Info (0): done
00:01:54 - SDL Info (0): Cleaning up video stream...
00:01:54 - SDL Info (0): done
00:01:54 - SDL Info (0): Cleaning up control stream...
00:01:54 - SDL Info (0): done
00:01:54 - SDL Info (0): Cleaning up audio stream...
00:01:54 - Qt Warning: stream 1 finished with error: "Connection closed"
00:01:54 - SDL Info (0): done
00:01:54 - SDL Info (0): Cleaning up platform...
00:01:54 - SDL Info (0): done

View File

@ -0,0 +1,49 @@
# GTX 965M 重启故障诊断(2026-11-02)
## 结论
未找到已验证有效的重启后 NVENC 恢复方案。所有实验配置已恢复,VM100 可继续使用软件编码回退;VM101/102 全程保持运行。
此前582.78、DXGI与NVENC确实工作过;此轮故障状态为Windows Code43、nvlddmkm停止、nvidia-smi失败、Sunshine回退libx264。不能以设备管理器显示型号或PnP暂时OK作为恢复成功的依据。
## 原始配置与备份
宿主机备份目录:`/root/vdi-gpu-recovery-20261102/`,包含100.conf、vfio.conf、ROM及PCI信息。
- hostpci0:`0000:01:00.0,pcie=1,rombar=1,romfile=gtx965m-pci.rom`
- args:`-set device.hostpci0.x-pci-sub-vendor-id=0x1558 -set device.hostpci0.x-pci-sub-device-id=0x6557`
- GPU:10de:13d9,子系统1558:6557,总线01仅此设备。
- 原ROM SHA256:`080d9765337a5ea3bceefb1f632f073e14b09d215ef44b885e2d97cb04d27160`
- `/etc/modprobe.d/vfio.conf`:`options vfio-pci ids=10de:13d9 disable_idle_d3=1`,本轮未修改该文件。
- Windows快速启动原值HiberbootEnabled=1;本轮临时关闭后无收益,已恢复1。
## 实验与结果
| 实验 | 结果 |
|---|---|
| 关闭Windows快速启动,VM完整停止/启动 | Code43仍存在 |
| 临时disable_idle_d3=N,再解绑/重绑VFIO | D0 active、runtime_usage=1;无法证明完成电源周期 |
| 干净卸载并重载仅vfio_pci模块,disable_idle_d3=0 | 引用计数1→0;实测runtime suspended、D3cold;启动VM后D0,但Code43/NVML失败仍存在 |
| 原供体ROM校验和修正副本 | Windows Guest Agent未上线,未保留 |
| 本机既有sysfs ROM副本 | Windows启动但Code43/NVML失败 |
| 本机ROM+已确认D3cold电源周期 | 同样失败,未保留 |
没有写PMCSR、没有刷写显卡固件、没有重启宿主机、没有卸载KVM或VFIO核心模块;仅在VM100停止且无VFIO使用者时重载vfio_pci。最终模块参数已恢复Y,原ROM配置已恢复。
## ROM证据与局限
1. 当前原始供体ROM为184320字节:传统BIOS镜像110080字节,PCIR ID10de:13d9,镜像和模256为1;第二UEFI镜像74240字节仍为10de:13d8。版本84.04.22.00.11。这些是明确的不一致,但不能认定为唯一故障原因;VM使用SeaBIOS,UEFI ID不匹配不等同于此次启动必然失败。
2. 既有本机sysfs ROM为110592字节,10de:13d9、校验和0、版本84.04.2B.00.13,字符串含HWDIAG。尚未确认是完整的、适配此板卡的生产版固件;不能只凭校验和正常就当作可靠替代。
3. 两份ROM均未刷入硬件。测试副本留在宿主机,当前VM不使用它们。
## 下一步所需条件
- 优先由运维/设备厂商提供该CLEVO板卡的生产版GM204M/13D9 vBIOS及适配依据,保留原件后再验证。
- 如需要宿主机冷启动、内核/VFIO升级或平台固件实验,先安排维护窗口,备份全部VM与宿主启动配置;不能影响其他VM而不协调。
- 当前证据只证明D3cold电源周期可实现,并不证明它能够修复此显卡;不要添加反复复位/重启任务充当永久修复。
## 验收标准
nvidia-smi成功、DXGI枚举NVIDIA、Sunshine实际选择h264_nvenc、真实串流有编码利用率;随后Windows重启和VM停启后重复通过。2K显示、20FPS配置和正常Windows单光标应同时保留。
参考:[Linux PCI](https://docs.kernel.org/PCI/pci.html)、[VFIO](https://docs.kernel.org/driver-api/vfio.html)、[PCI sysfs](https://docs.kernel.org/PCI/sysfs-pci.html)、[Proxmox qm](https://pve.proxmox.com/pve-docs/qm.1.html)。

View File

@ -0,0 +1,62 @@
# 独立光标二次开发设计与接入条件
状态:源码核实完成,尚未实现 Sunshine/Moonlight 的独立光标通道,不应标记为已部署。当前保留单个 Windows 远程白色光标。
## 已核实的实际路径
- 盒子固定 Moonlight Qt 6.2.0,现有 absolute mouse 输入仍经 moonlight-common-c 的可靠输入通道发送。
- 当前 RKMPP/EGL 路径使用 PacerRender 独立线程;实际诊断会话没有主线程 render 调用,输入优先调度不会改变这个渲染路径。
- Sunshine `input.cpp` 的 Ctrl+Alt+Shift+N 直接翻转全局 `display_cursor`。`video.cpp` 将其地址传入 display capture。它没有按会话的目标状态、确认或租约,不能作为可靠的独立光标协议。
- Windows Desktop Duplication 可能返回独立光标形状,也可能返回已含光标的画面;不能假定所有显示设备都能从视频中无损移除光标。
- Windows 当前没有现成的 Sunshine C++ 构建环境。因此本轮可以构建盒子客户端、验证输入和刷新率,但不能把未构建的服务端补丁当成已完成联调。
参考:[Sunshine input.cpp](https://github.com/LizardByte/Sunshine/blob/master/src/input.cpp)、[video.cpp](https://github.com/LizardByte/Sunshine/blob/master/src/video.cpp)、[Windows RAM capture](https://github.com/LizardByte/Sunshine/blob/master/src/platform/windows/display_ram.cpp)、[Microsoft Desktop Duplication 光标说明](https://learn.microsoft.com/en-us/windows/win32/direct3ddxgi/desktop-dup-api)。master 仅用于核实设计,实际修改须先固定现场 Sunshine 版本对应提交。
## 实施方式
在 Sunshine 与 moonlight-common-c/Moonlight 间扩展现有加密控制通道;不另外开放未经认证的 UDP 光标端口。默认仍使用远程视频光标,仅在双方协商并确认支持后启用。新增消息必须有协议版本、会话标识、显示配置代数及严格的大小校验。
| 消息 | 必要内容与作用 |
| --- | --- |
| 能力协商 | 支持形状类型、最大尺寸、显隐/视频帧交接能力;旧客户端保持原行为 |
| 光标形状 | 形状版本、尺寸、热点、像素/掩码格式;形状变化时发送并缓存 |
| 光标状态 | 状态序号、形状版本、显隐、坐标、显示区域及缩放配置代数 |
| 交接请求/确认 | 明确目标模式,携带首个采用该模式的视频帧 ID;不能使用无确认的 toggle |
| 位置校正 | 服务端主动移动与最近输入序号关联;用户持续移动时不能用旧位置反复拉回 |
| 心跳/结束 | 会话租约、显式结束;连接丢失时服务端自动恢复视频光标 |
光标移动由盒子的本地指针立即显示,形状和显隐仍取自服务端。窗口、按钮响应和内容更新继续走视频,所以独立光标不等于窗口拖动零延迟。
## 单光标交接
1. 服务端确认当前捕获后端可独立控制光标,客户端收到并成功创建当前形状;否则保持远程模式。
2. 服务端在明确的视频帧边界停止混合光标,并发出该帧 ID。客户端显示到这个边界后才开启本地光标,避免旧视频仍有光标时出现双指针。
3. 结束独立模式时反向交接,在开始包含远程光标的视频帧上隐藏本地光标。
4. 辅助状态超时、形状不支持、捕获设备更换、显示缩放改变、解码器重建、第二路会话接入时,执行确认后的回退。控制连接完全断开且无法继续交接时结束串流,返回选择页。
5. 不能通过替换 Windows 全局鼠标主题为透明图片实现;不能把普通箭头覆盖在视频光标上。
心跳和租约先按 250ms/1000ms 做实验参数,最终值由 Wi-Fi 抖动及故障恢复测试决定。现有全局 display_cursor 还须改为与会话/捕获生命周期一致的状态,防止多个客户端互相覆盖。
## Windows 特殊情况
- 处理彩色 alpha、单色 AND/XOR 和 masked-color;不支持的形状明确回退。不能把 XOR 像素简单当透明像素。
- 热点随流画面缩放映射,窗口信箱区域不发送越界输入;切换分辨率后废弃旧代数的光标消息。
- 服务端隐藏指针、文字选择、拖动缩放、忙碌动画必须正确;锁屏/UAC 桌面切换不能继续显示过期光标。
- SDL 硬件指针操作留在主线程;网络线程仅提交有界状态,禁止直接调用 SDL_SetCursor/释放正在使用的 cursor。
- 本地移动与远程主动 warp 分开处理,避免拖动时抖动、回弹;点击仍使用已修复的按钮坐标/输入顺序。
## 必须通过的验收
| 场景 | 要求 |
| --- | --- |
| 移动/拖动/右键/快速双击 | 单光标、点击准确、无丢失的按键释放 |
| 箭头/文字/调整大小/忙碌/隐藏/自定义 | 形状、热点及显隐正确;不支持时可靠回退 |
| 100%/125%/150% 缩放、分辨率切换 | 无偏移;旧代数消息失效 |
| 辅助消息停止、控制断开、服务器重启 | 无持久双光标或无光标状态 |
| 窗口失焦、鼠标离开、重新捕获 | 不锁死本地系统指针;恢复后坐标正确 |
| 旧服务端/客户端、多会话 | 不误启用;保持原有远程模式 |
| 高速摄像对照 | 分别报告指针移动、点击响应、拖窗内容更新的 P50/P95 |
## 下一阶段开始条件
固定现场 Sunshine 版本及源码提交,在独立构建目录准备可复现 Windows 构建,备份原安装并在测试实例验证后,再修改双方协议和捕获交接。不得为部署光标实验重装当前 Windows、刷 GPU ROM 或中断其他虚拟机。

View File

@ -0,0 +1,51 @@
# 鼠标点击与画面跳转优化(2026-11-03)
本轮针对用户反馈的“鼠标拖动/点击有残影、点击后画面跳转慢”做了输入队列和低延迟呈现优化。已有单白色 Windows 远程光标、显示器开关自动恢复和 RKMPP/EGL 客户端均保留。
## 现场根因
1. **点击位置顺序会被旧的绝对鼠标移动批次覆盖。** Moonlight 上游为了减少包数,会让一个尚未发送的绝对鼠标包持续吸收后续位置。高速移动后点击时,点击包与位置包在网络队列中的边界不明确,画面中的 Windows 控件可能在旧位置响应。32 次左右交替点击的实测中,修改前收到 32 条点击记录,其中第 1、13 条落在错误的一侧(30/32 正确)。这是延迟体感之外的可重复顺序错误。
2. **鼠标移动合并会扫描 SDL 队列。** 原逻辑只按 `SDL_MOUSEMOTION` 类型取事件,可能跨过按钮/键盘/窗口事件,把点击后的移动提前合并。修改后只消费紧邻且属于同一鼠标设备/窗口/按键状态的移动,遇到边界立即停止,每次最多处理 64 条,避免输入线程长时间占用。
3. **低延迟模式的解码帧积压。** 当前服务端仍为软件 `libx264`、约 30 FPS;盒子已使用 `h264_rkmpp` + `drm_prime` + EGL/GLES。修改后的非 VSync pacing 呈现队列可以丢弃尚未呈现的等待帧,只保留最新等待帧,减少画面落后于点击的时间。正在呈现的帧、上一帧延迟释放和解码参考帧不会被释放。
## 实现
- `terminal/moonlight/patches/0001-vdi-input-and-latest-frame.patch`
- SDL 输入事件按边界合并。
- 绝对鼠标按钮使用该按钮事件的坐标先入队。
- `VDI_LATEST_FRAME=1` 且未启用 VSync pacing 时只替换等待呈现帧;默认 wrapper 开启,smooth/pacing 档保持上游行为。
- `terminal/moonlight/patches/0002-vdi-absolute-click-barrier.patch`
- 每个点击封住前一位置批次,点击后的移动进入新批次。
- 发送线程只解除自己包的“可吸收新位置”状态,不误清除点击后新批次。
- `terminal/kiosk-shell/scripts/vdi-moonlight-rkmpp` 默认 `VDI_LATEST_FRAME=1`,仍不创建本地黑光标、不叠加第二个光标。
- `tools/build-rkmpp-client.sh` 固定 Moonlight/MPP/FFmpeg 提交,构建前检查并幂等应用补丁;出现源码漂移会失败,不强行覆盖。
- `tools/set-desktop-responsiveness.ps1` 已在 Windows 登录用户会话执行:备份原设置,关闭窗口缩放动画、菜单等待从 400ms 改为 100ms;通过 `SystemParametersInfoW` 设置并读回校验成功,临时执行任务已删除。失败时脚本会自动恢复。
- 盒子显示守护改读 Xorg 当前配置 `xrandr --current`,保留热插拔恢复,避免每 2 秒重新探测 EDID/显示模式引发 vendor 驱动时钟日志;对应 9 个场景测试通过。
- 用户明确蓝框发生于盒子登录/选择桌面页:QLabel 继承 QFrame,原 `QFrame:hover` 蓝框会作用于文字。移除该悬停规则,卡片样式限定到对象名,移除登录输入框的蓝色焦点边框。实际悬停截图文字/卡片区域亮蓝色像素从 8,302 降到 0,按钮仍可正常使用。
## 自动化与现场测试
| 测试 | 结果 |
|---|---|
| SDL 事件边界、64 条上限、触摸鼠标隔离、最新帧 helper | 通过 |
| 绝对输入 1,000 轮“位置→位置→按下→位置→释放→位置” | 通过 |
| AddressSanitizer 版本上述 native 测试 | 通过,无内存错误 |
| 修改前 32 次交替点击 | 30/32 正确,错误序号 1、13 |
| 修改后 32 次交替点击 | 32/32 正确 |
| 修改后真实 RKMPP/EGL 串流 | 日志确认 `VDI latest-frame queue: enabled`、`h264_rkmpp`、2560×1440 DRM PRIME |
| 配对对照串流 | 原版:28.93 接收/28.48 渲染 FPS,队列 3.39ms,解码 10.49ms,呈现 6.84ms;补丁:28.40/28.09 FPS,队列 2.14ms,解码 7.96ms,呈现 6.12ms |
| 会话连续性 | 测试退出后没有遗留测试串流;显示守护 active;盒子仍 2560×1440 |
对照数据不是严格实验室基准:两段会话的网络、Windows 软件编码负载和页面内容会波动。补丁最明确的收益是点击顺序正确和队列深度下降约 1.25ms;它不能把当前服务端软件编码变成 NVENC,也不能保证端到端零延迟。测试期间出现过一次 Wi-Fi 从 completed 到 disconnected 后自动重连,受影响的数据已单独保留,未作为性能结论。
## Windows 桌面跳转动画
执行前 Windows 登录用户状态为 `DragFullWindows=1`、`MouseTrails=0`、`MinAnimate=1`、`MenuShowDelay=400`。已将窗口动画改为 0、子菜单等待改为 100ms,API 读回校验成功,保留完整窗口拖动和原远程单光标。原值备份到 `%LOCALAPPDATA%\VDI\desktop-responsiveness-before-20261103.json`,恢复使用同一脚本的 `-Restore`。这些设置只减少 Windows 自身的动画和子菜单等待,不代表网页加载或网络响应变快。API 依据为 [Microsoft SystemParametersInfoW](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-systemparametersinfow)。
## 当前状态与回退
补丁客户端已接入默认 wrapper,启用最新帧队列。kiosk 为移除蓝色悬停框做了局部编译、CTest 3/3、原监控器拉起新版页面;未运行完整部署脚本,未重启盒子、VM 或宿主。UI 和 wrapper 备份为 `~/vdi-terminal/backups/input-rendering-20261103-114542/`。补丁源码、测试和构建说明均在 `terminal/moonlight/`,证据在 `docs/evidence/input-latency-20261103/`。
如需临时回退客户端,下次启动 wrapper 时设置 `VDI_RKMPP_CLIENT=/home/armbian/vdi-build/rkmpp-experiment/build/moonlight/app/moonlight.before-input-20261103`、`VDI_LATEST_FRAME=0`。旧二进制 SHA256 为 `a3575f86b9ebfd3b9f2a6ae4c73b057b2c8cd489cc44549a8838ff459c5e89dc`,新二进制为 `35de7b1a4ade583823b23b5f2e012307f6d0a3848c8eb97bd6d4de9660afa00f`。回退后重新连接并查看统计;不要直接覆盖运行中的 ELF。
下一步为用户真实鼠标拖窗/右键/快速双击体验验收;严格延迟需通过高速摄像或外部触发测输入到屏幕 P50/P95。当前数据不能宣称“无延迟”,只能确认点击排序和客户端排队得到改善。

View File

@ -0,0 +1,67 @@
# Moonlight 客户端渲染 profile
## 目的
统一 `kiosk-shell` 产品入口与现场调试入口的 Moonlight 呈现参数,避免测试时只改了
`vdi-moonlight` 脚本而正式页面仍使用另一套 VSync、Frame Pacing 和解码器配置。
代码默认 profile 是 `smooth`;RK3528现场在硬解与EGL验证通过后,通过render.conf
选择了 `low-latency` 和2K30。软件基线和其他未验证设备仍使用smooth。
不把关闭同步当成通用修复,现场对照与风险见 `rendering-execution-20261102.md`。
## 产品入口环境变量
这些变量由 `kiosk-shell` 和 `vdi-moonlight` 调试启动器读取,重启串流进程后生效:
```text
VDI_STREAM_PROFILE=smooth # 默认,VSync + Frame Pacing
VDI_STREAM_PROFILE=low-latency # 关闭 VSync + Frame Pacing,减少呈现等待
VDI_STREAM_PROFILE=diagnostic # smooth + Moonlight 性能叠图
VDI_STREAM_STATS=1 # 独立开启叠图,可同时比较smooth和low-latency
VDI_MOONLIGHT_DECODER=software # 系统客户端默认;RKMPP现场配置使用 hardware
VDI_MOONLIGHT_CODEC=H.264 # 当前默认,先不切换 HEVC/AV1
VDI_MOONLIGHT_PROGRAM=... # 可指定独立构建的Moonlight启动器,不覆盖系统二进制
VDI_SDL_FORCE_EGL=1 # 仅现场验证 SDL X11 EGL 时设置
VDI_SDL_VIDEODRIVER=wayland # 仅实验;正式入口的X11窗口激活逻辑尚需适配
```
每次会话启动时,最终 profile、解码器、编解码器、同步开关、SDL renderer 和完整参数
会写入 `~/vdi-terminal/logs/moonlight-YYYYMMDD.log` 的 `[VDI launch]` 段落。
## A/B 顺序
1. 先恢复并确认 Sunshine 使用 `h264_nvenc`,否则客户端 A/B 不能说明服务端问题已经解决。
2. 1080p60:比较 `smooth` 与 `low-latency`,两组都设置 `VDI_STREAM_STATS=1` 收集 queue/render/jitter。
3. RK3528 硬解与 EGL/GLES 现场路径已验证;后续仍需单独完成 2K60 验收,不能由 2K30 结果推断。
4. 任何 profile 都必须保留 `--absolute-mouse`;当前已解决的双光标行为不应回退。
## GPU 重启故障边界
`gpu-restart-diagnosis-20261102.md` 已确认当前没有经过验证的重启后软件恢复办法。profile
只改变客户端呈现,不会修复 Windows Code 43、NVML 失败或 Sunshine 回退 `libx264`。
GPU 修复仍需设备厂商提供匹配的 GM204M/13D9 生产版 vBIOS,并在维护窗口内按验收标准
重复验证 `nvidia-smi`、DXGI、`h264_nvenc` 和 Windows/VM 重启后的持久性。
## RK3528现场配置与回退
`~/.config/vdi-terminal/render.conf` 当前内容:
```ini
profile=low-latency
stats=0
program=/home/armbian/vdi-terminal/bin/vdi-moonlight-rkmpp
decoder=hardware
codec=H.264
```
Windows桌面卡当前请求2560x1440@30、30Mbps,实际持续动画约23FPS;
虚拟屏仍为30Hz。私有构建位于 `~/vdi-build/rkmpp-experiment`,不要删除该目录。
目前是用户目录内的POC部署,尚未打包为完整OTA镜像。
如现场发现关闭同步导致明显撕裂,可先将profile改为smooth,并将桌面卡FPS改回20。
如需彻底退回系统客户端,退出串流后将render.conf改名保存,并恢复
`desktops.before-rkmpp-20261102.json` 为desktops.json,然后重新启动kiosk受管栈。
系统 `/usr/bin/moonlight-qt` 未被覆盖,不需要卸载MPP或替换系统FFmpeg。
设备访问规则是 `/etc/udev/rules.d/70-vdi-rockchip-video.rules`,限定video组0660;
部署工具会安装并重载规则。udev匹配已验证,本轮未重启盒子做重启后串流复验。

View File

@ -0,0 +1,33 @@
# 鼠标与拖窗优化实施计划及结果(2026-11-03)
## 目标与边界
降低鼠标输入等待和画面更新延迟,保留单个 Windows 白色光标、正确点击位置、完整窗口拖动及现有显示器恢复功能。用实测决定是否启用,不能将帧间隔、客户端统计或本地光标响应称为端到端零延迟。
现场初检:盒子实际启动 2560×1440 / 30 FPS / RKMPP / EGL;Windows GTX 965M 仍 Code 43,Sunshine 实际 libx264,静态画面最低目标约 15 FPS。没有可直接构建 Sunshine 的现成 Windows C++ 工具链。
## 执行顺序
1. **记录基线。** 保存当前配置、二进制校验及串流日志,确认 GPU、虚拟屏刷新率、网络和解码路径。静态画面重复帧不能作为动态画面性能基准。
2. **验证刷新率整条链路。** 用临时测试窗口对比虚拟屏/串流 30 与 60 FPS;修改必须支持只读查询、枚举、测试、临时应用和恢复。只有动态画面实测改善且解码/丢帧可接受,才更改默认配置;否则恢复 2K30。
3. **改进 Moonlight 输入调度。** 检查主线程呈现阻塞输入的问题。允许帧呈现前先处理紧邻的有限数量输入,保持输入间原始顺序、窗口/焦点边界及工作量上限;增加可关闭的输入队列年龄与呈现阻塞统计。编译、自动化边界测试及真实串流对照后决定是否启用。
4. **核实独立光标的落地条件。** 必须同步光标形状/热点/显隐、单光标交接、缩放及重连回退。Sunshine 现有 Ctrl+Alt+Shift+N 是全局开关,没有按会话确认,不能据此可靠实现断线回退;不能只叠加本地箭头后宣称完成。先形成与实际源码相符的协议和验收要求,具备服务端构建条件后才能集成双方修改并验收。
5. **交付与现场恢复。** 移除临时测试任务/窗口,恢复正常云桌面连接;记录实际部署状态、测试结果、回退命令和未完成项。
## 验收
- 输入:快速交替点击无错位;双击、右键、拖动中的按下/释放顺序保持正确;失焦及退出快捷键正常。
- 调度:窗口和焦点事件不能越过;高频鼠标不能无限拖延视频;禁用新开关可恢复旧调度。
- 视频:相同动态测试源、相同分辨率/码率下记录接收/渲染 FPS、主机处理、解码、排队、呈现及网络丢帧;避免用空闲画面的平均 FPS 下结论。
- 光标:只有一个指针;文字/缩放/忙碌形状、显隐正确;断线/辅助通道故障不能无光标或双光标。
- 严格输入到屏幕延迟留待高速摄像/外部触发验证,客户端软件统计仅衡量其中一段。
## GPU 前置条件
本轮不重启宿主、不刷 ROM、不动 VM101/102。Code 43 仍需按现有运维方案排查,修复后再验收实际 NVIDIA D3D11 和 NVENC;不能只设置 encoder=nvenc 就认定修复。
## 执行结果
代码修改、自动化测试和现场配对串流对照已完成,结果见
`docs/input-rendering-optimization-20261103.md`。当前状态为:点击排序和客户端排队已改善,
仍需用户对真实拖窗、右键、快速双击进行体验验收;严格的输入到显示延迟仍需高速摄像或外部触发测量。

View File

@ -0,0 +1,168 @@
# Windows 云桌面渲染优化执行记录(2026-11-02)
## 执行顺序
1. 复核 GPU、实际编码器、客户机解码器、显示刷新率,保存原始证据。
2. 用持续动画做同步参数 A/B;排除静态桌面的按需发帧影响。
3. 在独立目录接通 MPP、RKMPP、DRM PRIME,先验证真实视频解码,再验证 Moonlight 串流。
4. 只有真实串流通过后才启用新客户端,保留系统 Moonlight 的回退入口。
5. GPU/NVENC 恢复后再做 1080p60、1440p30/60 和输入到屏幕延迟验收。
## 当前 GPU 证据
本轮经 Guest Agent 重新采集:GTX 965M 的 ConfigManagerErrorCode=43,NVML 查询失败,
DXGI 没有枚举到 NVIDIA 适配器,Sunshine 的最新实际编码器为 `libx264`。配置已是
`sw_preset=ultrafast`,当前 Windows 虚拟屏为 2560x1440@30。
没有再次复位设备、重载 VFIO、替换 ROM 或重启宿主机。本轮未改变其他 VM。
仍没有证据确认唯一故障原因;匹配此板卡的生产版 vBIOS 或另一块可稳定直通的 GPU
是下一轮服务端验证的候选条件,而非已完成修复。
验收工具更新为 `tools/validate-sunshine-nvenc.ps1` + `tools/probe-nvidia-d3d.cs`:
实际创建 NVIDIA D3D11 设备、检查 PnP 错误码、检查最新一次实际编码器创建及时间,
并核验 NVENC 会话与编码利用率。不会把启动阶段的编码器探测记录当作实际串流。
## 同步参数 A/B
环境:系统 Moonlight 6.2.0,H.264 软件解码,2560x1440@20、30Mbps,输出约60Hz,
MATE compositor 已关闭,SDL OpenGL ES 2。Windows 用
`tools/stream-motion-test.html` 持续移动条纹与棋盘;源 RAF 约30 FPS。
125% DPI 下页面显示逻辑2048x1152,视频流和 HDMI 仍是物理2560x1440。
下表来自两段完整会话结束日志,包含启动/退出阶段,时长不同;属于现场初步对照,
不构成严格统计学基准。原始日志与叠图保存在 `evidence/moonlight-20261102/`。
| 指标 | smooth | low-latency |
|---|---:|---:|
| 接收/解码 FPS | 17.16 | 17.07 |
| 渲染 FPS | 17.07 | 17.01 |
| 主机处理平均 ms | 33.6 | 35.4 |
| 网络丢帧 | 0.00% | 0.00% |
| jitter 分类丢帧 | 0.44% | 0.29% |
| 网络延迟平均 ms | 11 | 11 |
| 解码平均 ms | 14.07 | 16.96 |
| 帧队列平均 ms | 0.95 | 1.14 |
| 呈现平均 ms(含同步) | 8.38 | 10.87 |
系统客户端软件解码的对照中,关闭同步没有改善帧率或排队,因此软件基线保留 smooth。上述耗时
不能直接相加当作端到端输入延迟;后续须用高速摄像/外部触发测量 P50/P95。
日志中的启动测试 EGLImage 导出失败和单次队列溢出,不能单独证明持续运行时故障。
最终选中的系统路径是软件视频帧上传后的 SDL 呈现;`Using DRM renderer` 也不等于
已经使用 VPU 或直接扫描输出。
## RKMPP 已验证部分
- 为 `/dev/mpp_service`、`/dev/rga`、`/dev/dma_heap/*` 增加 video 组读写权限;
持久化规则为 `terminal/kiosk-shell/etc/70-vdi-rockchip-video.rules`。
- 普通用户执行 MPP H.264 初始化,create/init/destroy 全部返回0。
- 从固定提交构建 MPP 和 FFmpeg-Rockchip 6.1,目录是
`/home/armbian/vdi-build/rkmpp-experiment`;依赖只下载解包,不安装或升级系统包。
- 用 `generate-h264-sample.c` 生成60帧2560x1440 H.264样本。`h264_rkmpp` 全部解出,0错误。
- CPU NV12输出耗时2.620秒;`-hwaccel rkmpp -hwaccel_output_format drm_prime` 输出耗时
0.290秒,CPU时间0.120秒,日志明确为 DRM PRIME 帧,0解码错误。
样本纹理简单且测试期间有编译负载;这些数字仅证明硬解/帧导出可工作,不能替代
Moonlight 真实串流、显示呈现、复杂内容或2K60验收。
## 产品接入点
`VDI_STREAM_STATS=1` 独立于 profile,可公平比较两档。解码器覆盖只接受
software/hardware/auto;RKMPP通过 `H264_DECODER_HINT=h264_rkmpp` 选择,不把
`h264_rkmpp` 当作 Moonlight `--video-decoder` 的值。
`VDI_MOONLIGHT_PROGRAM` 可指定独立客户端启动器。`vdi-kiosk-start` 支持读取
`~/.config/vdi-terminal/render.conf` 的 allowlist 字段,不执行配置文件:
```ini
profile=smooth
stats=0
program=/home/armbian/vdi-terminal/bin/vdi-moonlight-rkmpp
decoder=hardware
codec=H.264
```
文件不存在时沿用系统客户端。上述为 smooth 档示例;本机实际部署档位见下表后说明。
## 构建与页面接入修正
私有客户端固定为 Moonlight v6.2.0 `de2467e433821664cdd2224aad8c89a625be1ad9`,
MPP `7916c3cc000fefc0bdf96636b7d54fe174724f44`,FFmpeg-Rockchip 6.1
`797387de1c9caa9170100d7217ee093d1897f750`。复现入口为
`tools/build-rkmpp-client.sh`,仅在盒子的用户目录下载、解包和构建依赖。
- Qt 5 构建需要显式为上游 `drm.h` 补入 `<optional>`,脚本幂等应用。
- 补齐 EGL 开发依赖,重新执行 qmake 功能探测,并在缺少 HAVE_EGL 时终止构建。
- qmake 改变功能开关不会自动使旧对象失效;构建脚本记录编译/链接参数指纹,
参数变化时清理应用对象,防止“探测有 EGL、实际对象无 EGL”。
- RKMPP 使用独立测试解码器,上游成功路径不输出旧的 `Test decode successful`,
而输出 `Not reusing test decoder for h264_rkmpp`。页面就绪解析同时兼容两者,
仍要求实际 renderer 已选中,并在连接失败时拒绝进入就绪状态。
- 私有启动器设置 QML、Qt 插件和共享库目录,系统 Moonlight 不被覆盖。
第一轮真实串流已输出 2560x1440 的 `h264_rkmpp / drm_prime`,但显示选中 SDL,
并出现 `Selected hwframe->swframe ... (mapping: yes)`,因此该轮不作为零拷贝验收。
对应证据为 `rkmpp-stale-sdl.txt` 与 `rkmpp-first.png`,包含构建负载和启动阶段。
另已核查用户注册表:`MouseTrails=0`、`DragFullWindows=1`,不通过添加第二个光标
或重新设置透明光标来掩盖视频延迟。
## 后续顺序与验收要求
1. 先验证硬解实际串流与 EGL 呈现,记录持续动画下的接收、解码、呈现 FPS,
解码/排队/呈现耗时及丢帧;没有通过则保留系统软件客户端默认入口。
2. 通过后接入页面启动链,验证过场层退出、快捷键回列表、再次连接及持久配置。
保留2K20现有配置作为基线,只有实测更好才提高请求帧率。
3. 服务端 GPU 修复需匹配板卡的生产 ROM 或可稳定直通的替代设备,并重复通过
PnP、NVML、DXGI/D3D11、真实 NVENC 以及重启后的验收。
4. 服务端恢复后按1080p60、1440p30、1440p60逐档验证,并同步虚拟屏刷新率。
1440p60还需要将当前30Hz虚拟屏调整到60Hz,不能只改客户端FPS参数。
5. 用高速摄像或外部触发测输入到显示的P50/P95,另外观察快速拖窗与光标残影。
如延迟仍主要来自光标随视频传输,再评估服务端光标位置/形状侧通道与客户端
单光标显示的二次开发,需同时保证隐藏视频中的旧光标,不能直接叠加本地光标。
客户端应优先接通硬解与显示路径;镜像内安装补帧/运动插值插件不能修复 GPU Code 43,
也不能代替真实输入响应。当前不把插帧作为低延迟方案。
## 真实串流对照与现场选择
清理旧对象后,日志明确选择 `Renderer 'EGL/GLES' with 'DRM' backend chosen`,
实际解码尺寸2560x1440、`h264_rkmpp`、`drm_prime`,呈现使用 EGLImage。
未见实际运行路径的 hwframe→swframe 映射回退。四组均为持续动画、30Mbps、
源RAF30FPS、终端HDMI约60Hz、服务端libx264;均为约2分钟会话,统计包含启动/退出。
会话按顺序进行,网络与服务端负载会波动,不能当作严格控制变量的实验室基准。
| 客户端/请求档位 | 接收/解码 FPS | 呈现 FPS | 主机平均 ms | 解码 ms | 队列 ms | 呈现 ms | 网络/jitter丢帧 |
|---|---:|---:|---:|---:|---:|---:|---|
| 系统软件解码 / 2K20 smooth(先前基线) | 17.16 | 17.07 | 33.6 | 14.07 | 0.95 | 8.38 | 0% / 0.44% |
| RKMPP+EGL / 2K20 smooth | 19.14 | 18.97 | 38.4 | 10.53 | 2.78 | 2.54 | 0% / 0.20% |
| RKMPP+EGL / 2K30 smooth | 24.21 | 23.29 | 46.2 | 8.24 | 31.95 | 4.19 | 0% / 3.02% |
| RKMPP+EGL / 2K30 low-latency | 23.56 | 23.46 | 46.8 | 9.11 | 2.39 | 5.41 | 0% / 0.10% |
| RKMPP+EGL / 2K30 VSync开、Frame Pacing关 | 23.26 | 22.63 | 47.5 | 8.28 | 28.93 | 4.14 | 0% / 2.23% |
对应原始统计分别为 `rkmpp-egl-20-smooth.txt`、`rkmpp-egl-30-smooth.txt`、
`rkmpp-egl-30-lowlatency.txt`、`rkmpp-egl-30-vsync-no-pacing.txt`,均在证据目录中。
本机选择2K30、`profile=low-latency`、RKMPP硬解、H.264,常态关闭叠图。
这是在当前设备上的取舍:相较2K30 smooth,平均帧队列少约30ms;关闭VSync存在
撕裂风险,需要现场动态观察。保留2K20 smooth作为平稳显示的回退档,不将其删除。
截图可见单个白色远程光标,但静态截图不能证明快速移动没有残影或输入延迟为零。
当前会话平均呈现仍只有约23FPS,未达到请求的30FPS;服务端GPU故障和libx264路径
仍未修复。不能将这一轮称为2K60、NVENC恢复或“鼠标无延迟”验收通过。
## 正式入口部署验证
已运行 `tools/deploy_kiosk.sh` 同步、编译、CTest、安装和重启盒子的kiosk受管栈;
CTest 2/2通过。render.conf选择上述私有硬解客户端,桌面卡请求帧率持久保存为30,
原文件备份在盒子 `~/.config/vdi-terminal/desktops.before-rkmpp-20261102.json`。
两次从实际列表页点击Windows连接,日志分别在约10.1秒、9.7秒进入stream_ready,
均明确选中 `EGL/GLES + DRM`、`h264_rkmpp`,过场层退出后画面可见。
`Ctrl+Alt+Shift+Q` 正常退出code=0并回列表,再次连接通过;没有遗留第二条串流。
配置已经写入现有自启链,但本轮未重启盒子、VM或宿主机;不声称完成重启后验收。
截图 `kiosk-rkmpp-session.png`、`kiosk-rkmpp-disconnect.png`、
`kiosk-rkmpp-reconnect.png` 保留了产品入口验证。单白光标可见,未修改原光标策略。
自动化拖窗未形成可计量的动态验收结果,仍需现场鼠标操作与外部摄像测量。
专用Edge测试浏览器已关闭,临时VDIRenderBench任务已删除,未关闭其他浏览器。

View File

@ -55,6 +55,11 @@ target_link_libraries(vdi-kiosk-monitor PRIVATE Threads::Threads)
if(BUILD_TESTING) if(BUILD_TESTING)
find_package(Qt5 REQUIRED COMPONENTS Test) find_package(Qt5 REQUIRED COMPONENTS Test)
if(UNIX)
find_package(Python3 REQUIRED COMPONENTS Interpreter)
add_test(NAME display-guard COMMAND ${Python3_EXECUTABLE}
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_display_guard.py)
endif()
add_executable(test-moonlight-session add_executable(test-moonlight-session
tests/test_moonlight_session.cpp tests/test_moonlight_session.cpp

View File

@ -0,0 +1,4 @@
# RK3528 vendor-kernel media interfaces. Members of video may use the VPU.
KERNEL=="mpp_service", GROUP="video", MODE="0660"
KERNEL=="rga", GROUP="video", MODE="0660"
SUBSYSTEM=="dma_heap", GROUP="video", MODE="0660"

View File

@ -18,6 +18,7 @@
# NVENC重启故障及各档性能记录见 docs/moonlight-kiosk-20261028.md。 # NVENC重启故障及各档性能记录见 docs/moonlight-kiosk-20261028.md。
# frame-pacing 1=开启帧率匀速(--frame-pacing),0=关闭(--no-frame-pacing) # frame-pacing 1=开启帧率匀速(--frame-pacing),0=关闭(--no-frame-pacing)
# performance-overlay 1=显示性能叠图(调试用) # performance-overlay 1=显示性能叠图(调试用)
# profile smooth / low-latency / diagnostic;为空时保留下方显式开关
# hang-timeout 串流假死判定时间(秒),0 表示关闭该检测 # hang-timeout 串流假死判定时间(秒),0 表示关闭该检测
host=192.168.1.70 host=192.168.1.70
port=47984 port=47984
@ -34,6 +35,7 @@ absolute-mouse=1
vsync=1 vsync=1
frame-pacing=1 frame-pacing=1
performance-overlay=0 performance-overlay=0
profile=smooth
retry=3 retry=3
retry-delay=5 retry-delay=5
hang-timeout=90 hang-timeout=90

View File

@ -0,0 +1,14 @@
[Unit]
Description=VDI HDMI mode recovery after monitor power cycle (X11 POC)
[Service]
Type=simple
Environment=DISPLAY=:0
Environment=XAUTHORITY=%h/.Xauthority
ExecStart=%h/vdi-terminal/bin/vdi-display-guard
Restart=on-failure
RestartSec=5
TimeoutStopSec=15
[Install]
WantedBy=default.target

View File

@ -0,0 +1,170 @@
#!/usr/bin/env python3
"""Restore this RK3528 terminal's verified HDMI timing after X11 hotplug."""
import argparse
import fcntl
import os
from pathlib import Path
import re
import signal
import subprocess
import sys
import time
from dataclasses import dataclass
OUTPUT = "HDMI-1"
MODE = "2560x1440_60_fixed297"
# The vendor PHY rejects the EDID's 241.70 MHz timing. Keep the verified PLL.
TIMING = "297.00 2560 2608 2640 2720 1440 1443 1448 1820 +HSync -VSync".split()
POLL_SECONDS = 2
SETTLE_SECONDS = 2
def log(message):
print(time.strftime("%Y-%m-%d %H:%M:%S"), message, flush=True)
def xrandr(*args):
result = subprocess.run(["xrandr", *args], capture_output=True, text=True,
timeout=10, check=False)
if result.returncode:
raise RuntimeError((result.stderr or result.stdout).strip()[:400])
return result.stdout
@dataclass
class DisplayState:
connected: bool
geometry: str
active_mode: str
modes: set
defined: bool
@property
def healthy(self):
return (self.connected and self.geometry == "2560x1440+0+0"
and self.active_mode == MODE)
def parse_state(query):
connected, geometry, active = False, "", ""
modes, defined, in_output = set(), False, False
for line in query.splitlines():
fields = line.split()
if not fields:
continue
if fields[0] == MODE:
defined = True # Includes a globally defined but detached mode.
if not line[0].isspace():
in_output = fields[0] == OUTPUT
if in_output:
connected = len(fields) > 1 and fields[1] == "connected"
geometry = next((f for f in fields[2:]
if re.fullmatch(r"\d+x\d+\+\d+\+\d+", f)), "")
elif in_output and len(fields) > 1 and re.match(r"^\d+(?:\.\d+)?[+*]*$", fields[1]):
modes.add(fields[0])
if "*" in " ".join(fields[1:]):
active = fields[0]
return DisplayState(connected, geometry, active, modes, defined)
class Guard:
def __init__(self, runner=xrandr, reporter=log):
self.run = runner
self.log = reporter
self.bad_since = None
self.next_retry = 0
self.failures = 0
self.last_status = None
def report(self, status):
if status != self.last_status:
self.log(status)
self.last_status = status
def step(self, now):
try:
# Xorg already receives DRM hotplug events. Read its current state
# without probing every EDID/mode: the vendor driver logs clock
# warnings for those probes, adding unnecessary work while streaming.
state = parse_state(self.run("--current"))
except (OSError, RuntimeError, subprocess.TimeoutExpired) as error:
self.bad_since = None
self.report("X11 unavailable; waiting: " + str(error)[:400])
return False
if not state.connected:
self.bad_since = None
self.next_retry = 0
self.failures = 0
self.report(OUTPUT + " disconnected; no mode changes")
return False
if state.healthy:
self.bad_since = None
self.next_retry = 0
self.failures = 0
self.report("healthy: " + MODE)
return True
self.report("mode drift: " + (state.active_mode or "off") + " " + state.geometry)
if self.bad_since is None:
self.bad_since = now
if now - self.bad_since < SETTLE_SECONDS or now < self.next_retry:
return False
try:
if not state.defined:
self.run("--newmode", MODE, *TIMING)
if MODE not in state.modes:
self.run("--addmode", OUTPUT, MODE)
self.run("--output", OUTPUT, "--mode", MODE, "--pos", "0x0")
if not parse_state(self.run("--current")).healthy:
raise RuntimeError("mode was not retained after apply")
except (OSError, RuntimeError, subprocess.TimeoutExpired) as error:
self.failures = min(self.failures + 1, 6)
delay = min(60, 2 ** self.failures)
# Base backoff on completion, including a slow/timed-out modeset.
self.next_retry = time.monotonic() + delay
self.log("restore failed; retry in %ds: %s" % (delay, str(error)[:400]))
return False
self.bad_since = None
self.next_retry = 0
self.failures = 0
self.report("restored: " + MODE + " (stream process untouched)")
return True
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--once", action="store_true",
help="initial display recovery with a 20s retry window, then exit")
args = parser.parse_args()
os.environ.setdefault("DISPLAY", ":0")
os.environ.setdefault("XAUTHORITY", str(Path.home() / ".Xauthority"))
runtime = Path(os.environ.get("XDG_RUNTIME_DIR", str(Path.home() / ".cache/vdi-terminal")))
runtime.mkdir(parents=True, exist_ok=True)
# Same lock for startup and the systemd service. Never run competing guards.
with (runtime / "vdi-display-guard.lock").open("a") as lock:
try:
fcntl.flock(lock, fcntl.LOCK_EX | fcntl.LOCK_NB)
except BlockingIOError:
log("display guard already running")
return 0
stop = False
def request_stop(signum, frame):
nonlocal stop
stop = True
signal.signal(signal.SIGTERM, request_stop)
signal.signal(signal.SIGINT, request_stop)
guard = Guard()
deadline = time.monotonic() + 20
while not stop:
if guard.step(time.monotonic()) and args.once:
return 0
if args.once and time.monotonic() >= deadline:
return 1
time.sleep(POLL_SECONDS)
return 0
if __name__ == "__main__":
sys.exit(main())

View File

@ -3,26 +3,28 @@
export DISPLAY="${DISPLAY:-:0}" export DISPLAY="${DISPLAY:-:0}"
export XAUTHORITY="${XAUTHORITY:-/home/armbian/.Xauthority}" export XAUTHORITY="${XAUTHORITY:-/home/armbian/.Xauthority}"
# Match the local output to the 2K Moonlight stream. # Optional verified rendering deployment. Parse an allowlist as data; never
# This kernel rejects the monitor's 241.70 MHz timing but accepts the 297 MHz # source/eval configuration. Explicit environment overrides the saved defaults.
# PLL rate. Longer vertical blanking produces 2560x1440 at approximately 60 Hz. render_conf="${VDI_RENDER_CONF:-$HOME/.config/vdi-terminal/render.conf}"
# HDMI can appear a few seconds after the desktop autostart entry runs. if [ -r "$render_conf" ]; then
: >/tmp/vdi-display-mode.log while IFS='=' read -r key value || [ -n "$key" ]; do
mode="2560x1440_60_fixed297" case "$key" in
for _ in $(seq 1 20); do profile) export VDI_STREAM_PROFILE="${VDI_STREAM_PROFILE:-$value}" ;;
if xrandr --query 2>>/tmp/vdi-display-mode.log | grep -q '^HDMI-1 connected'; then stats) export VDI_STREAM_STATS="${VDI_STREAM_STATS:-$value}" ;;
xrandr --newmode "$mode" 297.00 \ program) export VDI_MOONLIGHT_PROGRAM="${VDI_MOONLIGHT_PROGRAM:-$value}" ;;
2560 2608 2640 2720 1440 1443 1448 1820 \ decoder) export VDI_MOONLIGHT_DECODER="${VDI_MOONLIGHT_DECODER:-$value}" ;;
+HSync -VSync >>/tmp/vdi-display-mode.log 2>&1 || true codec) export VDI_MOONLIGHT_CODEC="${VDI_MOONLIGHT_CODEC:-$value}" ;;
xrandr --addmode HDMI-1 "$mode" >>/tmp/vdi-display-mode.log 2>&1 || true esac
if xrandr --output HDMI-1 --mode "$mode" >>/tmp/vdi-display-mode.log 2>&1; then done < "$render_conf"
break fi
fi
xrandr --output HDMI-1 --mode 1920x1080 --rate 60 \ # Use the same idempotent recovery for boot and HDMI hotplug. The user service
>>/tmp/vdi-display-mode.log 2>&1 || true # supervises ongoing recovery; a singleton lock prevents competing instances.
fi "$(dirname "$0")/vdi-display-guard" --once >>/tmp/vdi-display-mode.log 2>&1 || true
sleep 1 if ! systemctl --user start vdi-display-guard.service >>/tmp/vdi-display-mode.log 2>&1; then
done echo 'WARNING: display guard service unavailable; only boot recovery active' \
>>/tmp/vdi-display-mode.log
fi
exec /home/armbian/vdi-terminal/bin/vdi-kiosk-monitor -- \ exec /home/armbian/vdi-terminal/bin/vdi-kiosk-monitor -- \
/home/armbian/vdi-terminal/bin/kiosk-shell /home/armbian/vdi-terminal/bin/kiosk-shell

View File

@ -3,7 +3,7 @@
# #
# 职责: # 职责:
# 1. 读取本地配置(主机、应用、分辨率、帧率、码率、编解码) # 1. 读取本地配置(主机、应用、分辨率、帧率、码率、编解码)
# 2. 以软件解码拉起 moonlight-qt,全屏串流云桌面 # 2. 按配置拉起 Moonlight,全屏串流云桌面
# 3. 写心跳文件,供 vdi-kiosk-monitor 判断是否假死 # 3. 写心跳文件,供 vdi-kiosk-monitor 判断是否假死
# 4. 检测串流假死(CPU 与网络均无流量)并杀掉重连 # 4. 检测串流假死(CPU 与网络均无流量)并杀掉重连
# #
@ -12,7 +12,8 @@
# #
# 说明:RK3528 当前没有可用的 V4L2 request/m2m 硬解设备,moonlight-qt 的 # 说明:RK3528 当前没有可用的 V4L2 request/m2m 硬解设备,moonlight-qt 的
# --video-decoder auto 会选到 h264_v4l2m2m 并报 "Could not find a valid device", # --video-decoder auto 会选到 h264_v4l2m2m 并报 "Could not find a valid device",
# 因此配置里显式指定 decoder=software。接入 MPP/VPU 硬解后再改回 auto。 # 因此系统客户端默认 decoder=software;验证后的独立 RKMPP 客户端
# 通过 VDI_MOONLIGHT_PROGRAM 与 decoder=hardware 显式启用。
set -u set -u
@ -38,9 +39,10 @@ DECODER="software"
DISPLAY_MODE="fullscreen" DISPLAY_MODE="fullscreen"
AUDIO=1 AUDIO=1
ABSOLUTE_MOUSE=1 ABSOLUTE_MOUSE=1
VSYNC=0 VSYNC=1
FRAME_PACING=0 FRAME_PACING=1
PERFORMANCE_OVERLAY=0 PERFORMANCE_OVERLAY=0
PROFILE=""
RETRY=3 RETRY=3
RETRY_DELAY=5 RETRY_DELAY=5
HANG_TIMEOUT=90 HANG_TIMEOUT=90
@ -76,6 +78,7 @@ load_config() {
vsync) VSYNC="$value" ;; vsync) VSYNC="$value" ;;
frame-pacing) FRAME_PACING="$value" ;; frame-pacing) FRAME_PACING="$value" ;;
performance-overlay) PERFORMANCE_OVERLAY="$value" ;; performance-overlay) PERFORMANCE_OVERLAY="$value" ;;
profile) PROFILE="$value" ;;
retry) RETRY="$value" ;; retry) RETRY="$value" ;;
retry-delay) RETRY_DELAY="$value" ;; retry-delay) RETRY_DELAY="$value" ;;
hang-timeout) HANG_TIMEOUT="$value" ;; hang-timeout) HANG_TIMEOUT="$value" ;;
@ -84,6 +87,33 @@ load_config() {
done < "$CONF" done < "$CONF"
} }
apply_profile() {
case "$PROFILE" in
smooth)
VSYNC=1
FRAME_PACING=1
;;
low-latency)
VSYNC=0
FRAME_PACING=0
;;
diagnostic)
VSYNC=1
FRAME_PACING=1
PERFORMANCE_OVERLAY=1
;;
"")
# 兼容旧配置:没有profile时保留moonlight.conf中的显式开关。
;;
*)
log "未知串流 profile=$PROFILE,回退 smooth"
PROFILE=smooth
VSYNC=1
FRAME_PACING=1
;;
esac
}
# 默认路由出接口的累计收字节数,用于判断串流是否还有数据流入 # 默认路由出接口的累计收字节数,用于判断串流是否还有数据流入
rx_bytes() { rx_bytes() {
iface=$(awk '$2=="00000000" {print $1; exit}' /proc/net/route) iface=$(awk '$2=="00000000" {print $1; exit}' /proc/net/route)
@ -145,7 +175,7 @@ disable_screensaver() {
build_cmd() { build_cmd() {
# moonlight-qt stream 只接受 <host> <app> 位置参数,没有 --port 选项, # moonlight-qt stream 只接受 <host> <app> 位置参数,没有 --port 选项,
# 服务端端口由 moonlight 自身按 GameStream 协议协商。 # 服务端端口由 moonlight 自身按 GameStream 协议协商。
CMD="moonlight-qt stream $HOST $APP" CMD="${VDI_MOONLIGHT_PROGRAM:-moonlight-qt} stream $HOST $APP"
CMD="$CMD --resolution ${WIDTH}x${HEIGHT}" CMD="$CMD --resolution ${WIDTH}x${HEIGHT}"
CMD="$CMD --fps $FPS" CMD="$CMD --fps $FPS"
CMD="$CMD --bitrate $BITRATE" CMD="$CMD --bitrate $BITRATE"
@ -155,7 +185,7 @@ build_cmd() {
CMD="$CMD --keep-awake" CMD="$CMD --keep-awake"
[ "$ABSOLUTE_MOUSE" = "1" ] && CMD="$CMD --absolute-mouse" [ "$ABSOLUTE_MOUSE" = "1" ] && CMD="$CMD --absolute-mouse"
[ "$AUDIO" = "1" ] && CMD="$CMD --audio-on-host" || CMD="$CMD --no-audio-on-host" [ "$AUDIO" = "1" ] && CMD="$CMD --audio-on-host" || CMD="$CMD --no-audio-on-host"
# 低延迟开关:默认关闭 vsync 与 frame-pacing,削减帧队列/呈现延迟 # 按profile选择同步策略;默认保持当前稳定档。
[ "$VSYNC" = "1" ] && CMD="$CMD --vsync" || CMD="$CMD --no-vsync" [ "$VSYNC" = "1" ] && CMD="$CMD --vsync" || CMD="$CMD --no-vsync"
[ "$FRAME_PACING" = "1" ] && CMD="$CMD --frame-pacing" || CMD="$CMD --no-frame-pacing" [ "$FRAME_PACING" = "1" ] && CMD="$CMD --frame-pacing" || CMD="$CMD --no-frame-pacing"
[ "$PERFORMANCE_OVERLAY" = "1" ] && CMD="$CMD --performance-overlay" [ "$PERFORMANCE_OVERLAY" = "1" ] && CMD="$CMD --performance-overlay"
@ -163,7 +193,7 @@ build_cmd() {
run_stream() { run_stream() {
build_cmd build_cmd
log "启动串流: $CMD" log "启动串流 profile=${PROFILE:-config} decoder=$DECODER codec=$CODEC vsync=$VSYNC frame-pacing=$FRAME_PACING renderer=${SDL_RENDER_DRIVER:-} video-driver=${SDL_VIDEODRIVER:-}: $CMD"
# shellcheck disable=SC2086 # shellcheck disable=SC2086
$CMD >> "$LOG_FILE" 2>&1 & $CMD >> "$LOG_FILE" 2>&1 &
ML_PID=$! ML_PID=$!
@ -220,6 +250,19 @@ stop)
esac esac
load_config load_config
PROFILE="${VDI_STREAM_PROFILE:-$PROFILE}"
apply_profile
DECODER="${VDI_MOONLIGHT_DECODER:-$DECODER}"
CODEC="${VDI_MOONLIGHT_CODEC:-$CODEC}"
case "$DECODER" in
software|hardware|auto) ;;
*) log "未知解码器 $DECODER,回退 software"; DECODER=software ;;
esac
case "$CODEC" in
H.264|HEVC|AV1|auto) ;;
*) log "未知视频编码 $CODEC,回退 H.264"; CODEC=H.264 ;;
esac
PERFORMANCE_OVERLAY="${VDI_STREAM_STATS:-$PERFORMANCE_OVERLAY}"
if [ -z "$HOST" ]; then if [ -z "$HOST" ]; then
log "配置缺失或缺少 host: $CONF" log "配置缺失或缺少 host: $CONF"
exit 2 exit 2
@ -227,6 +270,10 @@ fi
export DISPLAY="${VDI_DISPLAY:-:0}" export DISPLAY="${VDI_DISPLAY:-:0}"
export XAUTHORITY="${VDI_XAUTHORITY:-$HOME/.Xauthority}" export XAUTHORITY="${VDI_XAUTHORITY:-$HOME/.Xauthority}"
export SDL_RENDER_DRIVER="${VDI_SDL_RENDER_DRIVER:-opengles2}"
export SDL_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR="${VDI_SDL_BYPASS_COMPOSITOR:-1}"
[ -n "${VDI_SDL_FORCE_EGL:-}" ] && export SDL_VIDEO_X11_FORCE_EGL="$VDI_SDL_FORCE_EGL"
[ -n "${VDI_SDL_VIDEODRIVER:-}" ] && export SDL_VIDEODRIVER="$VDI_SDL_VIDEODRIVER"
disable_screensaver disable_screensaver
kill_stale kill_stale

View File

@ -0,0 +1,20 @@
#!/bin/sh
# Select explicitly after RKMPP decode + real stream validation. Does not replace
# the distribution Moonlight or add a second cursor.
set -eu
task_root="${VDI_RKMPP_BUILD_ROOT:-$HOME/vdi-build/rkmpp-experiment}"
client="${VDI_RKMPP_CLIENT:-$task_root/build/moonlight/app/moonlight}"
if [ ! -x "$client" ] || [ ! -r /dev/mpp_service ] || [ ! -w /dev/mpp_service ]; then
echo 'RKMPP client or device access unavailable' >&2
exit 78
fi
export LD_LIBRARY_PATH="$task_root/runtime/lib:$task_root/deps/usr/lib/aarch64-linux-gnu${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
export QML2_IMPORT_PATH="$task_root/deps/usr/lib/aarch64-linux-gnu/qt5/qml${QML2_IMPORT_PATH:+:$QML2_IMPORT_PATH}"
export QT_PLUGIN_PATH="$task_root/deps/usr/lib/aarch64-linux-gnu/qt5/plugins${QT_PLUGIN_PATH:+:$QT_PLUGIN_PATH}"
export GL_IS_SLOW="${GL_IS_SLOW:-0}"
export H264_DECODER_HINT=h264_rkmpp
export HEVC_DECODER_HINT=hevc_rkmpp
# Only affects unpaced rendering in the patched client. Leave the last presented
# frame and decoder references intact; replace only waiting decoded frames.
export VDI_LATEST_FRAME="${VDI_LATEST_FRAME:-1}"
exec "$client" "$@"

View File

@ -82,10 +82,10 @@ void DesktopListPage::rebuildCards() {
for (const DesktopInfo& d : desktops_) { for (const DesktopInfo& d : desktops_) {
auto* card = new QFrame(this); auto* card = new QFrame(this);
card->setObjectName(QStringLiteral("desktopCard"));
card->setMinimumHeight(96); card->setMinimumHeight(96);
card->setStyleSheet(QStringLiteral( card->setStyleSheet(QStringLiteral(
"QFrame { background: #1a2233; border: 1px solid #2b3654; border-radius: 10px; }" "QFrame#desktopCard { background: #1a2233; border: 1px solid #2b3654; border-radius: 10px; }"
"QFrame:hover { border: 1px solid #2f6feb; }"
"QLabel { border: none; background: transparent; }")); "QLabel { border: none; background: transparent; }"));
auto* row = new QHBoxLayout(card); auto* row = new QHBoxLayout(card);

View File

@ -64,7 +64,6 @@ void MainWindow::setupUi() {
QStringLiteral("QWidget { background: #0f1420; color: #e6e9ef; }" QStringLiteral("QWidget { background: #0f1420; color: #e6e9ef; }"
"QLineEdit { background: #1a2233; border: 1px solid #2b3654; " "QLineEdit { background: #1a2233; border: 1px solid #2b3654; "
"border-radius: 4px; padding: 8px; color: #e6e9ef; }" "border-radius: 4px; padding: 8px; color: #e6e9ef; }"
"QLineEdit:focus { border: 1px solid #2f6feb; }"
"QPushButton { background: #232d44; border: 1px solid #2b3654; " "QPushButton { background: #232d44; border: 1px solid #2b3654; "
"border-radius: 6px; color: #e6e9ef; }" "border-radius: 6px; color: #e6e9ef; }"
"QPushButton:hover { background: #2b3654; }")); "QPushButton:hover { background: #2b3654; }"));
@ -289,11 +288,8 @@ void MainWindow::onEditDesktopRequested(const QString& desktopId) {
} }
bool MainWindow::startMoonlightSession(const ConnectionTicket& ticket, quint64 attempt) { bool MainWindow::startMoonlightSession(const ConnectionTicket& ticket, quint64 attempt) {
MoonlightSession::Options opts; moonlightSession_->setOptions(MoonlightSession::optionsFromEnvironment(
opts.decoder = QStringLiteral("software"); QProcessEnvironment::systemEnvironment()));
opts.videoCodec = QStringLiteral("H.264");
opts.audioOnHost = true;
moonlightSession_->setOptions(opts);
phaseClock_.restart(); phaseClock_.restart();
connectionPhase_ = ConnectionPhase::kProcessStart; connectionPhase_ = ConnectionPhase::kProcessStart;

View File

@ -14,7 +14,11 @@ constexpr int kReadyStableMs = 750;
constexpr int kTerminateGraceMs = 2000; constexpr int kTerminateGraceMs = 2000;
bool isTestDecodeLine(const QByteArray& line) { bool isTestDecodeLine(const QByteArray& line) {
return line.toLower().contains("test decode successful"); const QByteArray lower = line.toLower();
// Hardware decoders use a separate test context. Upstream logs this only
// after that context has successfully decoded and validated a test frame.
return lower.contains("test decode successful") ||
lower.contains("not reusing test decoder for ");
} }
bool isRendererLine(const QByteArray& line) { bool isRendererLine(const QByteArray& line) {
@ -105,6 +109,66 @@ void MoonlightSession::setOptions(const Options& options) {
options_ = options; options_ = options;
} }
MoonlightSession::Options MoonlightSession::optionsFromEnvironment(
const QProcessEnvironment& environment) {
Options options;
const QString profile = environment.value(QStringLiteral("VDI_STREAM_PROFILE"));
if (profile == QStringLiteral("low-latency")) {
options.profile = profile;
options.vsync = false;
options.framePacing = false;
} else if (profile == QStringLiteral("diagnostic")) {
options.profile = profile;
options.performanceOverlay = true;
}
// Statistics must be independently selectable for a fair profile A/B test.
if (environment.contains(QStringLiteral("VDI_STREAM_STATS"))) {
options.performanceOverlay = environment.value(QStringLiteral("VDI_STREAM_STATS")) == QStringLiteral("1");
}
const QString decoder = environment.value(QStringLiteral("VDI_MOONLIGHT_DECODER"));
if (QStringList{QStringLiteral("software"), QStringLiteral("hardware"),
QStringLiteral("auto")}.contains(decoder)) {
options.decoder = decoder;
}
const QString codec = environment.value(QStringLiteral("VDI_MOONLIGHT_CODEC"));
if (QStringList{QStringLiteral("H.264"), QStringLiteral("HEVC"),
QStringLiteral("AV1"), QStringLiteral("auto")}.contains(codec)) {
options.videoCodec = codec;
}
const QString program = environment.value(QStringLiteral("VDI_MOONLIGHT_PROGRAM"));
if (!program.isEmpty()) {
options.program = program;
}
return options;
}
QStringList MoonlightSession::buildStreamArguments(const ConnectionTicket& ticket,
const Options& options) {
const int bitrateKbps = ticket.width >= 2560 ? 30000 : 20000;
QStringList args;
args << QStringLiteral("stream")
<< ticket.endpoint
<< ticket.app
<< QStringLiteral("--resolution")
<< QStringLiteral("%1x%2").arg(ticket.width).arg(ticket.height)
<< QStringLiteral("--fps") << QString::number(ticket.fps)
<< QStringLiteral("--bitrate") << QString::number(bitrateKbps)
<< QStringLiteral("--display-mode") << QStringLiteral("fullscreen")
<< QStringLiteral("--video-codec") << options.videoCodec
<< QStringLiteral("--video-decoder") << options.decoder
<< QStringLiteral("--absolute-mouse")
<< QStringLiteral("--keep-awake")
<< (options.vsync ? QStringLiteral("--vsync") : QStringLiteral("--no-vsync"))
<< (options.framePacing ? QStringLiteral("--frame-pacing")
: QStringLiteral("--no-frame-pacing"));
if (options.performanceOverlay) {
args << QStringLiteral("--performance-overlay");
}
args << (options.audioOnHost ? QStringLiteral("--audio-on-host")
: QStringLiteral("--no-audio-on-host"));
return args;
}
bool MoonlightSession::isRunning() const { bool MoonlightSession::isRunning() const {
return process_->state() != QProcess::NotRunning; return process_->state() != QProcess::NotRunning;
} }
@ -156,34 +220,26 @@ bool MoonlightSession::start(const ConnectionTicket& ticket, EventCallback callb
readyTimer_->stop(); readyTimer_->stop();
killTimer_->stop(); killTimer_->stop();
process_->setProgram(QStringLiteral("moonlight-qt")); process_->setProgram(options_.program);
QProcessEnvironment environment = QProcessEnvironment::systemEnvironment(); QProcessEnvironment environment = QProcessEnvironment::systemEnvironment();
environment.insert(QStringLiteral("GL_IS_SLOW"), QStringLiteral("0")); environment.insert(QStringLiteral("GL_IS_SLOW"), QStringLiteral("0"));
environment.insert(QStringLiteral("SDL_RENDER_DRIVER"), QStringLiteral("opengles2")); environment.insert(QStringLiteral("SDL_RENDER_DRIVER"),
environment.value(QStringLiteral("VDI_SDL_RENDER_DRIVER"), QStringLiteral("opengles2")));
// Xorg下绕过桌面合成器;Wayland/KMS部署时可通过SDL_VIDEODRIVER切换,
// 不在客户端里硬编码会话类型,避免当前Xorg镜像无法启动。
environment.insert(QStringLiteral("SDL_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR"),
environment.value(QStringLiteral("VDI_SDL_BYPASS_COMPOSITOR"), QStringLiteral("1")));
const QString forceEgl = qEnvironmentVariable("VDI_SDL_FORCE_EGL");
if (!forceEgl.isEmpty()) {
environment.insert(QStringLiteral("SDL_VIDEO_X11_FORCE_EGL"), forceEgl);
}
const QString sdlVideoDriver = qEnvironmentVariable("VDI_SDL_VIDEODRIVER");
if (!sdlVideoDriver.isEmpty()) {
environment.insert(QStringLiteral("SDL_VIDEODRIVER"), sdlVideoDriver);
}
process_->setProcessEnvironment(environment); process_->setProcessEnvironment(environment);
const int bitrateKbps = ticket.width >= 2560 ? 30000 : 20000; const QStringList args = buildStreamArguments(ticket, options_);
QStringList args;
args << QStringLiteral("stream")
<< ticket.endpoint
<< ticket.app
<< QStringLiteral("--resolution")
<< QStringLiteral("%1x%2").arg(ticket.width).arg(ticket.height)
<< QStringLiteral("--fps") << QString::number(ticket.fps)
<< QStringLiteral("--bitrate") << QString::number(bitrateKbps)
<< QStringLiteral("--display-mode") << QStringLiteral("fullscreen")
<< QStringLiteral("--video-codec") << options_.videoCodec
<< QStringLiteral("--video-decoder") << options_.decoder
<< QStringLiteral("--absolute-mouse")
<< QStringLiteral("--keep-awake");
args << (options_.vsync ? QStringLiteral("--vsync") : QStringLiteral("--no-vsync"));
args << (options_.framePacing ? QStringLiteral("--frame-pacing")
: QStringLiteral("--no-frame-pacing"));
if (options_.performanceOverlay) {
args << QStringLiteral("--performance-overlay");
}
args << (options_.audioOnHost ? QStringLiteral("--audio-on-host")
: QStringLiteral("--no-audio-on-host"));
process_->setArguments(args); process_->setArguments(args);
const QString logDir = QDir::homePath() + QStringLiteral("/vdi-terminal/logs"); const QString logDir = QDir::homePath() + QStringLiteral("/vdi-terminal/logs");
@ -191,6 +247,23 @@ bool MoonlightSession::start(const ConnectionTicket& ticket, EventCallback callb
logPath_ = logDir + QStringLiteral("/moonlight-%1.log") logPath_ = logDir + QStringLiteral("/moonlight-%1.log")
.arg(QDate::currentDate().toString(QStringLiteral("yyyyMMdd"))); .arg(QDate::currentDate().toString(QStringLiteral("yyyyMMdd")));
// 把最终生效的环境和参数写入日志,避免只看Moonlight叠图时无法判断
// 产品入口到底使用了哪一套呈现策略。
QFile launchLog(logPath_);
if (launchLog.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) {
QTextStream stream(&launchLog);
stream << "\n[VDI launch]\n"
<< "profile=" << options_.profile << "\n"
<< "program=" << options_.program << "\n"
<< "decoder=" << options_.decoder << "\n"
<< "codec=" << options_.videoCodec << "\n"
<< "vsync=" << (options_.vsync ? "1" : "0") << "\n"
<< "frame-pacing=" << (options_.framePacing ? "1" : "0") << "\n"
<< "renderer=" << environment.value(QStringLiteral("SDL_RENDER_DRIVER")) << "\n"
<< "video-driver=" << environment.value(QStringLiteral("SDL_VIDEODRIVER")) << "\n"
<< "args=" << args.join(QLatin1Char(' ')) << "\n";
}
process_->start(); process_->start();
return true; return true;
} }

View File

@ -8,6 +8,8 @@
#include <QByteArray> #include <QByteArray>
#include <QProcess> #include <QProcess>
#include <QProcessEnvironment>
#include <QStringList>
#include <QString> #include <QString>
#include <functional> #include <functional>
@ -37,7 +39,13 @@ class MoonlightSession : public QObject {
Q_OBJECT Q_OBJECT
public: public:
// 产品入口与调试脚本遵循相同的profile语义。
// smooth:优先稳定呈现,适合当前2K20/2K30;
// low-latency:关闭客户端额外的同步等待,适合1080p60 A/B;
// diagnostic:在smooth基础上打开Moonlight性能叠图。
struct Options { struct Options {
QString program = QStringLiteral("moonlight-qt");
QString profile = QStringLiteral("smooth");
bool vsync = true; bool vsync = true;
bool framePacing = true; bool framePacing = true;
bool performanceOverlay = false; bool performanceOverlay = false;
@ -64,6 +72,9 @@ public:
~MoonlightSession() override; ~MoonlightSession() override;
void setOptions(const Options& options); void setOptions(const Options& options);
static Options optionsFromEnvironment(const QProcessEnvironment& environment);
static QStringList buildStreamArguments(const ConnectionTicket& ticket,
const Options& options);
bool start(const ConnectionTicket& ticket, EventCallback callback); bool start(const ConnectionTicket& ticket, EventCallback callback);
void stop(); void stop();
bool isRunning() const; bool isRunning() const;

View File

@ -0,0 +1,140 @@
"""Failure and hotplug scenarios; no real display or sleep required."""
from pathlib import Path
import runpy
import unittest
from unittest.mock import patch
guard_module = runpy.run_path(str(Path(__file__).resolve().parents[1] / "scripts/vdi-display-guard"))
Guard = guard_module["Guard"]
MODE = guard_module["MODE"]
class FakeRandR:
def __init__(self):
self.connected = True
self.defined = True
self.attached = True
self.active = "1920x1440"
self.writes = []
self.fail_apply = False
self.query_error = False
self.keep_wrong_mode = False
def __call__(self, *args):
if args == ("--current",):
if self.query_error:
raise RuntimeError("Can't open display :0")
status = "connected primary " + ("2560x1440+0+0" if self.active == MODE else "1920x1440+0+0")
if not self.connected:
status = "disconnected"
query = "Screen 0: current 1920 x 1440\nHDMI-1 " + status + " (normal)\n"
if self.connected:
query += " 1920x1440 75.00" + ("*" if self.active != MODE else "") + "\n"
if self.attached:
query += " " + MODE + " 60.00" + ("*" if self.active == MODE else "") + "\n"
if self.defined and (not self.attached or not self.connected):
query += " " + MODE + " (0x189) 297.000MHz +HSync -VSync\n"
query += " h: width 2560 start 2608\n v: height 1440 start 1443\n"
return query
self.writes.append(args)
if args[0] == "--newmode":
if self.defined:
raise RuntimeError("BadName: duplicate mode")
self.defined = True
elif args[0] == "--addmode":
assert self.defined
self.attached = True
elif args[0] == "--output":
if self.fail_apply:
raise RuntimeError("Configure crtc failed")
assert self.attached
if not self.keep_wrong_mode:
self.active = MODE
return ""
class DisplayGuardTests(unittest.TestCase):
def setUp(self):
self.xr = FakeRandR()
self.logs = []
self.guard = Guard(self.xr, self.logs.append)
def tick(self, now):
with patch("time.monotonic", return_value=now):
return self.guard.step(now)
def test_mode_drift_restores_after_settling(self):
self.assertFalse(self.tick(0))
self.assertEqual(self.xr.writes, [])
self.assertTrue(self.tick(2))
self.assertEqual(len(self.xr.writes), 1)
self.assertEqual(self.xr.active, MODE)
def test_healthy_display_does_not_modeset_or_repeat_logs(self):
self.xr.active = MODE
for now in range(0, 100, 2):
self.assertTrue(self.tick(now))
self.assertEqual(self.xr.writes, [])
self.assertEqual(len(self.logs), 1)
def test_disconnected_never_writes_and_reconnect_settles(self):
self.tick(0)
self.xr.connected = False
for now in range(2, 20, 2):
self.assertFalse(self.tick(now))
self.assertEqual(self.xr.writes, [])
self.xr.connected = True
self.assertFalse(self.tick(20))
self.assertTrue(self.tick(22))
def test_new_x_server_recreates_and_attaches_mode(self):
self.xr.defined = self.xr.attached = False
self.tick(0)
self.assertTrue(self.tick(2))
self.assertEqual([w[0] for w in self.xr.writes], ["--newmode", "--addmode", "--output"])
def test_hotplug_detached_mode_is_not_created_twice(self):
self.xr.attached = False
self.tick(0)
self.assertTrue(self.tick(2))
self.assertEqual([w[0] for w in self.xr.writes], ["--addmode", "--output"])
def test_late_desktop_settings_overwrite_is_corrected_again(self):
self.tick(0)
self.assertTrue(self.tick(2))
self.xr.active = "1920x1440"
self.assertFalse(self.tick(4))
self.assertTrue(self.tick(6))
self.assertEqual(len(self.xr.writes), 2)
def test_modeset_failure_backs_off_and_eventually_recovers(self):
self.xr.fail_apply = True
self.tick(0)
self.tick(2) # retry at 4
self.tick(4) # retry at 8
self.tick(6) # no write
self.assertEqual(len(self.xr.writes), 2)
self.xr.fail_apply = False
self.assertTrue(self.tick(8))
self.assertEqual(len(self.xr.writes), 3)
def test_apply_success_must_be_verified(self):
self.xr.keep_wrong_mode = True
self.tick(0)
self.assertFalse(self.tick(2))
self.assertIn("not retained", self.logs[-1])
def test_x11_unavailable_does_not_write_and_then_recovers(self):
self.xr.query_error = True
for now in range(0, 20, 2):
self.assertFalse(self.tick(now))
self.assertEqual(self.xr.writes, [])
self.assertEqual(len(self.logs), 1)
self.xr.query_error = False
self.assertFalse(self.tick(20))
self.assertTrue(self.tick(22))
if __name__ == "__main__":
unittest.main()

View File

@ -10,7 +10,11 @@ class MoonlightSessionTest : public QObject {
private slots: private slots:
void parsesSplitReadyMarkers(); void parsesSplitReadyMarkers();
void requiresBothReadyMarkers(); void requiresBothReadyMarkers();
void acceptsSeparateHardwareTestDecoder();
void rejectsSecondStart(); void rejectsSecondStart();
void buildsConsistentStreamArguments();
void selectsProfileWithoutLosingStats();
void rejectsInvalidDecoderOverride();
}; };
void MoonlightSessionTest::parsesSplitReadyMarkers() { void MoonlightSessionTest::parsesSplitReadyMarkers() {
@ -38,6 +42,19 @@ void MoonlightSessionTest::requiresBothReadyMarkers() {
QVERIFY(!parser.isReady()); QVERIFY(!parser.isReady());
} }
void MoonlightSessionTest::acceptsSeparateHardwareTestDecoder() {
MoonlightOutputParser parser;
parser.append("Using custom H.264 decoder (H264_DECODER_HINT): h264_rkmpp\n");
QVERIFY(!parser.isReady());
parser.append("Not reusing test decoder for h264_rkmpp\n");
QVERIFY(parser.hasTestDecode());
QVERIFY(!parser.isReady());
parser.append("Renderer 'EGL' with 'DRM' backend chosen\n");
QVERIFY(parser.isReady());
parser.append("Connection terminated: -1\n");
QVERIFY(!parser.isReady());
}
void MoonlightSessionTest::rejectsSecondStart() { void MoonlightSessionTest::rejectsSecondStart() {
QTemporaryDir tempDir; QTemporaryDir tempDir;
QVERIFY(tempDir.isValid()); QVERIFY(tempDir.isValid());
@ -90,5 +107,61 @@ void MoonlightSessionTest::rejectsSecondStart() {
qputenv("PATH", oldPath); qputenv("PATH", oldPath);
} }
void MoonlightSessionTest::buildsConsistentStreamArguments() {
ConnectionTicket ticket;
ticket.endpoint = QStringLiteral("192.168.1.70");
ticket.app = QStringLiteral("Desktop");
ticket.width = 2560;
ticket.height = 1440;
ticket.fps = 30;
MoonlightSession::Options options;
options.profile = QStringLiteral("low-latency");
options.decoder = QStringLiteral("software");
options.videoCodec = QStringLiteral("H.264");
options.vsync = false;
options.framePacing = false;
options.performanceOverlay = true;
const QStringList args = MoonlightSession::buildStreamArguments(ticket, options);
QVERIFY(args.contains(QStringLiteral("--resolution")));
QVERIFY(args.contains(QStringLiteral("2560x1440")));
QVERIFY(args.contains(QStringLiteral("--fps")));
QVERIFY(args.contains(QStringLiteral("30")));
QVERIFY(args.contains(QStringLiteral("--bitrate")));
QVERIFY(args.contains(QStringLiteral("30000")));
QVERIFY(args.contains(QStringLiteral("--no-vsync")));
QVERIFY(args.contains(QStringLiteral("--no-frame-pacing")));
QVERIFY(args.contains(QStringLiteral("--performance-overlay")));
QVERIFY(args.contains(QStringLiteral("--absolute-mouse")));
}
void MoonlightSessionTest::selectsProfileWithoutLosingStats() {
QProcessEnvironment environment;
environment.insert(QStringLiteral("VDI_STREAM_PROFILE"), QStringLiteral("low-latency"));
environment.insert(QStringLiteral("VDI_STREAM_STATS"), QStringLiteral("1"));
auto options = MoonlightSession::optionsFromEnvironment(environment);
QVERIFY(!options.vsync);
QVERIFY(!options.framePacing);
QVERIFY(options.performanceOverlay);
environment.insert(QStringLiteral("VDI_STREAM_PROFILE"), QStringLiteral("smooth"));
options = MoonlightSession::optionsFromEnvironment(environment);
QVERIFY(options.vsync);
QVERIFY(options.framePacing);
QVERIFY(options.performanceOverlay);
}
void MoonlightSessionTest::rejectsInvalidDecoderOverride() {
QProcessEnvironment environment;
environment.insert(QStringLiteral("VDI_MOONLIGHT_DECODER"), QStringLiteral("h264_rkmpp"));
environment.insert(QStringLiteral("VDI_STREAM_PROFILE"), QStringLiteral("invalid"));
auto options = MoonlightSession::optionsFromEnvironment(environment);
QCOMPARE(options.decoder, QStringLiteral("software"));
QCOMPARE(options.profile, QStringLiteral("smooth"));
environment.insert(QStringLiteral("VDI_MOONLIGHT_DECODER"), QStringLiteral("hardware"));
options = MoonlightSession::optionsFromEnvironment(environment);
QCOMPARE(options.decoder, QStringLiteral("hardware"));
}
QTEST_GUILESS_MAIN(MoonlightSessionTest) QTEST_GUILESS_MAIN(MoonlightSessionTest)
#include "test_moonlight_session.moc" #include "test_moonlight_session.moc"

View File

@ -0,0 +1,40 @@
# VDI Moonlight 交互优化补丁
本目录维护当前 RK3528 / Xorg POC 私有客户端的源码修改,不替换系统 Moonlight。
基线:Moonlight Qt v6.2.0 `de2467e433821664cdd2224aad8c89a625be1ad9`,其检出的 moonlight-common-c 子模块保持对应版本。MPP、FFmpeg 版本仍由 `tools/build-rkmpp-client.sh` 固定。
## 补丁
- `0001-vdi-input-and-latest-frame.patch` 在 Moonlight Qt 根目录应用。鼠标移动只合并队首连续事件,遇到按钮、键盘、窗口、呈现事件或其他鼠标设备立即停止;每次最多额外合并 64 个事件。绝对模式在发送按键前使用该按键事件的坐标。低延迟队列可选地把已等待的解码帧替换成新帧。
- `0002-vdi-absolute-click-barrier.patch` 在 `moonlight-common-c/moonlight-common-c` 中应用。鼠标按钮封住此前的位置批次,后续移动只能进入新批次;发送线程只锁定自己的批次,避免旧包出队时误清除新批次。所有包依旧走原可靠鼠标通道,保留 1ms 合并限流和原坐标边界修正。
- `0003-vdi-input-priority.patch` 在 Qt 根目录应用。可选地让帧就绪后的连续输入先执行,最多 32 条或 2ms,不能跨窗口/焦点/其他事件。`VDI_INPUT_PRIORITY=1` 才启用,默认关闭。另提供 `VDI_INPUT_TIMING=1` 的汇总统计,区分 SDL 输入派发年龄与主线程呈现调用耗时,不代表端到端延迟。
2026-11-03 的现场 RKMPP/EGL 使用独立 PacerRender 线程,诊断会话主线程 render 调用数为 0;因此第三补丁的新调度没有已证明的现场收益,未启用。诊断候选二进制保存为 `moonlight.input-priority-20261103`;默认客户端已恢复到本轮前 SHA256 `35de7b1a4ade583823b23b5f2e012307f6d0a3848c8eb97bd6d4de9660afa00f`。详细计划/初测限制见 `docs/mouse-optimization-plan-20261103.md`,独立光标接入设计见 `docs/independent-cursor-design-20261103.md`。
`VDI_LATEST_FRAME=1` 只在没有 VSync pacing source 的呈现队列生效。最多保留一个待呈现解码帧,丢弃数计入原 `pacerDroppedFrames`。不丢压缩包,不改变 H.264 参考链,也不提前释放正在呈现或延迟释放的上一帧。未设置或设为 `0` 时保留上游帧队列策略;kiosk 私有 wrapper 默认设为 `1`。smooth 档仍使用原 pacing 行为。
这些补丁不增加本地光标,不隐藏 Windows 光标,不改变控制协议。远程光标仍随视频显示,其延迟仍受服务器捕获/编码、网络、解码和显示影响。
## 构建与测试
在盒子上运行构建器时,将本目录的 `patches/` 一起复制过去,通过 `VDI_MOONLIGHT_PATCH_DIR` 指定目录。构建器先检查固定提交,再检查补丁:已完整应用则跳过;上下文不匹配则失败,不强行覆盖其他修改。
```bash
VDI_BUILD_STAGE=moonlight \
VDI_MOONLIGHT_PATCH_DIR="$HOME/vdi-build/rkmpp-experiment/patches" \
bash tools/build-rkmpp-client.sh
```
`tests/` 的文件复制到盒子 `$VDI_RKMPP_BUILD_ROOT/latency-tests/` 后运行:
```bash
bash tools/test-moonlight-latency.sh
VDI_TEST_SANITIZE=1 ASAN_OPTIONS=detect_leaks=1 bash tools/test-moonlight-latency.sh
```
测试直接包含实际修改后的 SDL helper、AVFrame 队列 helper 与 `InputStream.c`,并链接客户端实际使用的 native 队列/线程库。覆盖跨点击合并、键盘/呈现边界、工作量上限、触摸隔离、200 帧的积压替换、已呈现帧所有权及 1,000 轮“移动→按下→移动→释放→移动”的发送线程滞后场景。测试显式启用断言,避免上游 release 头文件的 NDEBUG 使检查失效。
新增 `test_input_priority.cpp` 验证优先调度不越过焦点/窗口/退出/解码器重置事件,保持输入 FIFO,隔离其他窗口与合成触摸,并验证数量与时间限制。普通与 ASAN 版本均通过。当前 RKMPP/EGL 没有主线程呈现事件,新调度开关不能用作该路径的性能提升宣传。
现场数据、局限与完整回退入口见 `docs/input-rendering-optimization-20261103.md`。

View File

@ -0,0 +1,271 @@
--- a/app/streaming/input/mouse.cpp
+++ b/app/streaming/input/mouse.cpp
@@ -1,4 +1,5 @@
#include "input.h"
+#include "vdi_mouse_batch.h"
#include <Limelight.h>
#include "SDL_compat.h"
@@ -84,6 +85,11 @@
button = BUTTON_RIGHT;
}
+ // Button coordinates are captured with this event, not a later mouse state.
+ if (m_AbsoluteMouseMode) {
+ sendAbsoluteMousePosition(event->x, event->y);
+ }
+
LiSendMouseButtonEvent(event->state == SDL_PRESSED ?
BUTTON_ACTION_PRESS :
BUTTON_ACTION_RELEASE,
@@ -101,81 +107,78 @@
return;
}
- // Batch all pending mouse motion events to save CPU time
- Sint32 x = event->x, y = event->y, xrel = event->xrel, yrel = event->yrel;
- SDL_Event nextEvent;
- while (SDL_PeepEvents(&nextEvent, 1, SDL_GETEVENT, SDL_MOUSEMOTION, SDL_MOUSEMOTION) > 0) {
- event = &nextEvent.motion;
-
- // Ignore synthetic mouse events
- if (event->which != SDL_TOUCH_MOUSEID) {
- x = event->x;
- y = event->y;
- xrel += event->xrel;
- yrel += event->yrel;
- }
- }
+ // Coalesce only adjacent motions. Never consume motion past a click/key
+ // or render event, and bound work so a fast mouse cannot starve rendering.
+ SDL_MouseMotionEvent batched = *event;
+ vdiBatchMouseMotion(batched);
+ Sint32 x = batched.x, y = batched.y;
+ Sint32 xrel = batched.xrel, yrel = batched.yrel;
// We should not reference the original event anymore
event = nullptr;
if (m_AbsoluteMouseMode) {
- int windowWidth, windowHeight;
- SDL_GetWindowSize(m_Window, &windowWidth, &windowHeight);
-
- SDL_Rect src, dst;
- bool mouseInVideoRegion;
-
- src.x = src.y = 0;
- src.w = m_StreamWidth;
- src.h = m_StreamHeight;
-
- dst.x = dst.y = 0;
- dst.w = windowWidth;
- dst.h = windowHeight;
-
- // Use the stream and window sizes to determine the video region
- StreamUtils::scaleSourceToDestinationSurface(&src, &dst);
-
- mouseInVideoRegion = isMouseInVideoRegion(x, y, windowWidth, windowHeight);
-
- // Clamp motion to the video region
- x = qMin(qMax(x - dst.x, 0), dst.w);
- y = qMin(qMax(y - dst.y, 0), dst.h);
-
- // Send the mouse position update if one of the following is true:
- // a) it is in the video region now
- // b) it just left the video region (to ensure the mouse is clamped to the video boundary)
- // c) a mouse button is still down from before the cursor left the video region (to allow smooth dragging)
- Uint32 buttonState = SDL_GetMouseState(nullptr, nullptr);
- if (buttonState == 0) {
- if (m_PendingMouseButtonsAllUpOnVideoRegionLeave) {
- if (m_NeedsManualCaptureOnLeave) {
- // Stop capturing the mouse now
- SDL_CaptureMouse(SDL_FALSE);
- }
- m_PendingMouseButtonsAllUpOnVideoRegionLeave = false;
- }
- }
- if (mouseInVideoRegion || m_MouseWasInVideoRegion || m_PendingMouseButtonsAllUpOnVideoRegionLeave) {
- LiSendMousePositionEvent((short)x, (short)y, dst.w, dst.h);
- }
-
- // Adjust the cursor visibility if applicable
- if (mouseInVideoRegion ^ m_MouseWasInVideoRegion) {
- SDL_ShowCursor((mouseInVideoRegion && m_MouseCursorCapturedVisibilityState == SDL_DISABLE) ? SDL_DISABLE : SDL_ENABLE);
- if (!mouseInVideoRegion && buttonState != 0) {
- // If we still have a button pressed on leave, wait for that to come up
- // before we stop sending mouse position events.
- m_PendingMouseButtonsAllUpOnVideoRegionLeave = true;
- }
- }
-
- m_MouseWasInVideoRegion = mouseInVideoRegion;
+ sendAbsoluteMousePosition(x, y);
}
else {
LiSendMouseMoveEvent(xrel, yrel);
}
+}
+
+void SdlInputHandler::sendAbsoluteMousePosition(Sint32 x, Sint32 y)
+{
+ int windowWidth, windowHeight;
+ SDL_GetWindowSize(m_Window, &windowWidth, &windowHeight);
+
+ SDL_Rect src, dst;
+ bool mouseInVideoRegion;
+
+ src.x = src.y = 0;
+ src.w = m_StreamWidth;
+ src.h = m_StreamHeight;
+
+ dst.x = dst.y = 0;
+ dst.w = windowWidth;
+ dst.h = windowHeight;
+
+ // Use the stream and window sizes to determine the video region
+ StreamUtils::scaleSourceToDestinationSurface(&src, &dst);
+
+ mouseInVideoRegion = isMouseInVideoRegion(x, y, windowWidth, windowHeight);
+
+ // Clamp motion to the video region
+ x = qMin(qMax(x - dst.x, 0), dst.w);
+ y = qMin(qMax(y - dst.y, 0), dst.h);
+
+ // Send the mouse position update if one of the following is true:
+ // a) it is in the video region now
+ // b) it just left the video region (to ensure the mouse is clamped to the video boundary)
+ // c) a mouse button is still down from before the cursor left the video region (to allow smooth dragging)
+ Uint32 buttonState = SDL_GetMouseState(nullptr, nullptr);
+ if (buttonState == 0) {
+ if (m_PendingMouseButtonsAllUpOnVideoRegionLeave) {
+ if (m_NeedsManualCaptureOnLeave) {
+ // Stop capturing the mouse now
+ SDL_CaptureMouse(SDL_FALSE);
+ }
+ m_PendingMouseButtonsAllUpOnVideoRegionLeave = false;
+ }
+ }
+ if (mouseInVideoRegion || m_MouseWasInVideoRegion || m_PendingMouseButtonsAllUpOnVideoRegionLeave) {
+ LiSendMousePositionEvent((short)x, (short)y, dst.w, dst.h);
+ }
+
+ // Adjust the cursor visibility if applicable
+ if (mouseInVideoRegion ^ m_MouseWasInVideoRegion) {
+ SDL_ShowCursor((mouseInVideoRegion && m_MouseCursorCapturedVisibilityState == SDL_DISABLE) ? SDL_DISABLE : SDL_ENABLE);
+ if (!mouseInVideoRegion && buttonState != 0) {
+ // If we still have a button pressed on leave, wait for that to come up
+ // before we stop sending mouse position events.
+ m_PendingMouseButtonsAllUpOnVideoRegionLeave = true;
+ }
+ }
+
+ m_MouseWasInVideoRegion = mouseInVideoRegion;
}
void SdlInputHandler::handleMouseWheelEvent(SDL_MouseWheelEvent* event)
--- a/app/streaming/input/input.h
+++ b/app/streaming/input/input.h
@@ -95,6 +95,8 @@
void handleMouseButtonEvent(SDL_MouseButtonEvent* event);
void handleMouseMotionEvent(SDL_MouseMotionEvent* event);
+
+ void sendAbsoluteMousePosition(Sint32 x, Sint32 y);
void handleMouseWheelEvent(SDL_MouseWheelEvent* event);
--- /dev/null
+++ b/app/streaming/input/vdi_mouse_batch.h
@@ -0,0 +1,22 @@
+#pragma once
+#include <SDL.h>
+
+// Only the SDL main thread consumes events; other threads may append events.
+inline void vdiBatchMouseMotion(SDL_MouseMotionEvent& motion)
+{
+ for (int i = 0; i < 64; ++i) {
+ SDL_Event next;
+ if (SDL_PeepEvents(&next, 1, SDL_PEEKEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT) != 1 ||
+ next.type != SDL_MOUSEMOTION || next.motion.which != motion.which ||
+ next.motion.windowID != motion.windowID || next.motion.state != motion.state) {
+ break;
+ }
+ if (SDL_PeepEvents(&next, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT) != 1) {
+ break;
+ }
+ motion.x = next.motion.x;
+ motion.y = next.motion.y;
+ motion.xrel += next.motion.xrel;
+ motion.yrel += next.motion.yrel;
+ }
+}
--- a/app/streaming/video/ffmpeg-renderers/pacer/pacer.cpp
+++ b/app/streaming/video/ffmpeg-renderers/pacer/pacer.cpp
@@ -1,4 +1,5 @@
#include "pacer.h"
+#include "vdi_latest_frame.h"
#include "streaming/streamutils.h"
#ifdef Q_OS_WIN32
@@ -34,6 +35,7 @@
m_VsyncThread(nullptr),
m_DeferredFreeFrame(nullptr),
m_Stopping(false),
+ m_LatestFrameOnly(qEnvironmentVariableIntValue("VDI_LATEST_FRAME") == 1),
m_VsyncSource(nullptr),
m_VsyncRenderer(renderer),
m_MaxVideoFps(0),
@@ -178,7 +180,14 @@
void Pacer::enqueueFrameForRenderingAndUnlock(AVFrame *frame)
{
- dropFrameForEnqueue(m_RenderQueue);
+ if (m_LatestFrameOnly && m_VsyncSource == nullptr) {
+ // Drop only decoded, never presented frames. Keep the decoder reference
+ // chain and the deferred free of the last presented frame intact.
+ m_VideoStats->pacerDroppedFrames += vdiDiscardQueuedFrames(m_RenderQueue);
+ }
+ else {
+ dropFrameForEnqueue(m_RenderQueue);
+ }
m_RenderQueue.enqueue(frame);
m_FrameQueueLock.unlock();
@@ -261,6 +270,8 @@
bool Pacer::initialize(SDL_Window* window, int maxVideoFps, bool enablePacing)
{
+ SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "VDI latest-frame queue: %s",
+ (m_LatestFrameOnly && !enablePacing) ? "enabled" : "disabled");
m_MaxVideoFps = maxVideoFps;
m_DisplayFps = StreamUtils::getDisplayRefreshRate(window);
m_RendererAttributes = m_VsyncRenderer->getRendererAttributes();
--- a/app/streaming/video/ffmpeg-renderers/pacer/pacer.h
+++ b/app/streaming/video/ffmpeg-renderers/pacer/pacer.h
@@ -68,6 +68,7 @@
SDL_Thread* m_VsyncThread;
AVFrame* m_DeferredFreeFrame;
bool m_Stopping;
+ bool m_LatestFrameOnly;
IVsyncSource* m_VsyncSource;
IFFmpegRenderer* m_VsyncRenderer;
--- /dev/null
+++ b/app/streaming/video/ffmpeg-renderers/pacer/vdi_latest_frame.h
@@ -0,0 +1,16 @@
+#pragma once
+#include <QQueue>
+extern "C" {
+#include <libavutil/frame.h>
+}
+
+inline unsigned vdiDiscardQueuedFrames(QQueue<AVFrame*>& queue)
+{
+ unsigned dropped = 0;
+ while (!queue.isEmpty()) {
+ AVFrame* stale = queue.dequeue();
+ av_frame_free(&stale);
+ ++dropped;
+ }
+ return dropped;
+}

View File

@ -0,0 +1,143 @@
--- a/src/InputStream.c
+++ b/src/InputStream.c
@@ -86,11 +86,16 @@
int deltaX, deltaY;
bool dirty; // Update ready to send (queued packet holder in packetQueue)
} currentRelativeMouseState;
-static struct {
- int x, y;
- int width, height;
- bool dirty; // Update ready to send (queued packet holder in packetQueue)
-} currentAbsoluteMouseState;
+// Only this packet may absorb newer positions. A button event seals the batch.
+static PPACKET_HOLDER currentQueuedAbsoluteMousePacket;
+
+static void latchAbsoluteMousePacket(PPACKET_HOLDER holder) {
+ PltLockMutex(&batchedInputMutex);
+ if (currentQueuedAbsoluteMousePacket == holder) {
+ currentQueuedAbsoluteMousePacket = NULL;
+ }
+ PltUnlockMutex(&batchedInputMutex);
+}
// Initializes the input stream
int initializeInputStream(void) {
@@ -120,7 +125,7 @@
memset(currentGamepadSensorState, 0, sizeof(currentGamepadSensorState));
memset(&currentRelativeMouseState, 0, sizeof(currentRelativeMouseState));
- memset(&currentAbsoluteMouseState, 0, sizeof(currentAbsoluteMouseState));
+ currentQueuedAbsoluteMousePacket = NULL;
PltCreateMutex(&batchedInputMutex);
return 0;
@@ -444,24 +449,9 @@
now = PltGetMillis();
}
- PltLockMutex(&batchedInputMutex);
-
- // Populate the packet with the latest state
- holder->packet.mouseMoveAbs.x = BE16(currentAbsoluteMouseState.x);
- holder->packet.mouseMoveAbs.y = BE16(currentAbsoluteMouseState.y);
-
- // There appears to be a rounding error in GFE's scaling calculation which prevents
- // the cursor from reaching the far edge of the screen when streaming at smaller
- // resolutions with a higher desktop resolution (like streaming 720p with a desktop
- // resolution of 1080p, or streaming 720p/1080p with a desktop resolution of 4K).
- // Subtracting one from the reference dimensions seems to work around this issue.
- holder->packet.mouseMoveAbs.width = BE16(currentAbsoluteMouseState.width - 1);
- holder->packet.mouseMoveAbs.height = BE16(currentAbsoluteMouseState.height - 1);
-
- // The state change is no longer pending
- currentAbsoluteMouseState.dirty = false;
-
- PltUnlockMutex(&batchedInputMutex);
+ // Payload was filled by the producer under the same mutex. Latch
+ // only our packet; a later batch may already be queued after a click.
+ latchAbsoluteMousePacket(holder);
lastMousePacketTime = now;
}
@@ -780,52 +770,37 @@
}
PltLockMutex(&batchedInputMutex);
-
- // Overwrite the previous mouse location with the new one
- currentAbsoluteMouseState.x = x;
- currentAbsoluteMouseState.y = y;
- currentAbsoluteMouseState.width = referenceWidth;
- currentAbsoluteMouseState.height = referenceHeight;
-
- // Queue a packet holder if this is the only pending absolute mouse event
- if (!currentAbsoluteMouseState.dirty) {
- // Set the dirty flag to claim ownership of inserting the packet holder
- // and unlock to allow other threads to enqueue or process input.
- currentAbsoluteMouseState.dirty = true;
- PltUnlockMutex(&batchedInputMutex);
-
+ holder = currentQueuedAbsoluteMousePacket;
+ bool newPacket = holder == NULL;
+ if (newPacket) {
holder = allocatePacketHolder(0);
if (holder == NULL) {
- currentAbsoluteMouseState.dirty = false;
+ PltUnlockMutex(&batchedInputMutex);
return -1;
}
-
holder->channelId = CTRL_CHANNEL_MOUSE;
-
- // TODO: Send this as unreliable sequenced when we have a delayed reliable retransmission thread
holder->enetPacketFlags = ENET_PACKET_FLAG_RELIABLE;
-
holder->packet.mouseMoveAbs.header.size = BE32(sizeof(NV_ABS_MOUSE_MOVE_PACKET) - sizeof(uint32_t));
holder->packet.mouseMoveAbs.header.magic = LE32(MOUSE_MOVE_ABS_MAGIC);
holder->packet.mouseMoveAbs.unused = 0;
-
- // Remaining fields are set in the input thread based on the latest currentAbsoluteMouseState values
-
+ }
+ holder->packet.mouseMoveAbs.x = BE16(x);
+ holder->packet.mouseMoveAbs.y = BE16(y);
+ // Preserve upstream's far-edge rounding workaround.
+ holder->packet.mouseMoveAbs.width = BE16(referenceWidth - 1);
+ holder->packet.mouseMoveAbs.height = BE16(referenceHeight - 1);
+ err = 0;
+ if (newPacket) {
+ currentQueuedAbsoluteMousePacket = holder;
err = LbqOfferQueueItem(&packetQueue, holder, &holder->entry);
if (err != LBQ_SUCCESS) {
+ currentQueuedAbsoluteMousePacket = NULL;
LC_ASSERT(err == LBQ_BOUND_EXCEEDED);
Limelog("Input queue reached maximum size limit\n");
freePacketHolder(holder);
-
- // We weren't able to insert the entry, so let the next call try again
- currentAbsoluteMouseState.dirty = false;
- }
- }
- else {
- // There's already a packet holder queued to send this event
- PltUnlockMutex(&batchedInputMutex);
- err = 0;
- }
+ }
+ }
+ PltUnlockMutex(&batchedInputMutex);
// This is not thread safe, but it's not a big deal because callers that want to
// use LiSendRelativeMotionAsMousePositionEvent() must not mix these function
@@ -872,7 +847,11 @@
holder->packet.mouseButton.header.magic = LE32(holder->packet.mouseButton.header.magic);
holder->packet.mouseButton.button = (uint8_t)button;
+ PltLockMutex(&batchedInputMutex);
+ // Do not let a later position overwrite the move preceding this click.
+ currentQueuedAbsoluteMousePacket = NULL;
err = LbqOfferQueueItem(&packetQueue, holder, &holder->entry);
+ PltUnlockMutex(&batchedInputMutex);
if (err != LBQ_SUCCESS) {
LC_ASSERT(err == LBQ_BOUND_EXCEEDED);
Limelog("Input queue reached maximum size limit\n");

View File

@ -0,0 +1,179 @@
--- a/app/streaming/session.cpp
+++ b/app/streaming/session.cpp
@@ -39,6 +39,7 @@
#include <QImage>
#include <QGuiApplication>
#include <QCursor>
+#include "input/vdi_input_priority.h"
#include <QScreen>
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
@@ -1962,8 +1963,14 @@
// Hijack this thread to be the SDL main thread. We have to do this
// because we want to suspend all Qt processing until the stream is over.
+ VdiInputPriority vdiInputPriority(qEnvironmentVariableIntValue("VDI_INPUT_PRIORITY") == 1,
+ SDL_CODE_FRAME_READY);
+ VdiInputTiming vdiInputTiming(qEnvironmentVariableIntValue("VDI_INPUT_TIMING") == 1);
+ SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "VDI input priority: %s",
+ qEnvironmentVariableIntValue("VDI_INPUT_PRIORITY") == 1 ? "enabled" : "disabled");
SDL_Event event;
for (;;) {
+ if (!vdiInputPriority.takeDeferred(event, SDL_GetWindowID(m_Window))) {
#if SDL_VERSION_ATLEAST(2, 0, 18) && !defined(STEAM_LINK)
// SDL 2.0.18 has a proper wait event implementation that uses platform
// support to block on events rather than polling on Windows, macOS, X11,
@@ -1995,6 +2002,11 @@
continue;
}
#endif
+ if (vdiInputPriority.deferFrame(event)) {
+ continue;
+ }
+ }
+ vdiInputTiming.observe(event, SDL_GetWindowID(m_Window));
switch (event.type) {
case SDL_QUIT:
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
@@ -2005,7 +2017,9 @@
switch (event.user.code) {
case SDL_CODE_FRAME_READY:
if (m_VideoDecoder != nullptr) {
+ const auto renderStart = vdiInputTiming.startRender();
m_VideoDecoder->renderFrameOnMainThread();
+ vdiInputTiming.endRender(renderStart);
}
break;
case SDL_CODE_FLUSH_WINDOW_EVENT_BARRIER:
@@ -2308,6 +2322,7 @@
}
DispatchDeferredCleanup:
+ vdiInputTiming.report(vdiInputPriority.prioritized());
// Switch back to synchronous logging mode
StreamUtils::exitAsyncLoggingMode();
--- /dev/null
+++ b/app/streaming/input/vdi_input_priority.h
@@ -0,0 +1,121 @@
+#pragma once
+#include <SDL.h>
+#include <array>
+#include <algorithm>
+#include <cstdint>
+
+// SDL main thread only. Inputs may pass one frame-ready notification, never a
+// window/focus/quit/other notification or another frame. Input FIFO is preserved.
+class VdiInputPriority {
+public:
+ VdiInputPriority(bool enabled, Sint32 frameCode)
+ : m_Enabled(enabled), m_FrameCode(frameCode) {}
+
+ bool deferFrame(const SDL_Event& event) {
+ if (!m_Enabled || event.type != SDL_USEREVENT || event.user.code != m_FrameCode)
+ return false;
+ SDL_assert(!m_Pending);
+ m_Frame = event;
+ m_Pending = true;
+ m_Count = 0;
+ m_Start = SDL_GetPerformanceCounter();
+ return true;
+ }
+
+ bool takeDeferred(SDL_Event& event, Uint32 windowId) {
+ if (!m_Pending) return false;
+ SDL_Event next;
+ const auto elapsed = SDL_GetPerformanceCounter() - m_Start;
+ if (m_Count < 32 && elapsed < SDL_GetPerformanceFrequency() / 500 &&
+ SDL_PeepEvents(&next, 1, SDL_PEEKEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT) == 1 &&
+ isInputForWindow(next, windowId) &&
+ SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT) == 1) {
+ ++m_Count;
+ ++m_Prioritized;
+ return true;
+ }
+ event = m_Frame;
+ m_Pending = false;
+ return true;
+ }
+
+ uint64_t prioritized() const { return m_Prioritized; }
+
+ static bool isInputForWindow(const SDL_Event& event, Uint32 windowId) {
+ switch (event.type) {
+ case SDL_MOUSEMOTION:
+ return event.motion.windowID == windowId && event.motion.which != SDL_TOUCH_MOUSEID;
+ case SDL_MOUSEBUTTONDOWN:
+ case SDL_MOUSEBUTTONUP:
+ return event.button.windowID == windowId && event.button.which != SDL_TOUCH_MOUSEID;
+ case SDL_MOUSEWHEEL:
+ return event.wheel.windowID == windowId && event.wheel.which != SDL_TOUCH_MOUSEID;
+ case SDL_KEYDOWN:
+ case SDL_KEYUP:
+ return event.key.windowID == windowId;
+ default:
+ return false;
+ }
+ }
+
+private:
+ bool m_Enabled;
+ Sint32 m_FrameCode;
+ bool m_Pending = false;
+ SDL_Event m_Frame{};
+ unsigned m_Count = 0;
+ Uint64 m_Start = 0;
+ uint64_t m_Prioritized = 0;
+};
+
+// Aggregated only when explicitly requested. Ages are SDL queue/dispatch ages,
+// not network RTT or physical input-to-photon latency. 0.1 ms histogram bins.
+class VdiInputTiming {
+public:
+ explicit VdiInputTiming(bool enabled) : m_Enabled(enabled) {}
+ void observe(const SDL_Event& event, Uint32 windowId) {
+ if (!m_Enabled || !event.common.timestamp ||
+ !VdiInputPriority::isInputForWindow(event, windowId)) return;
+ const Uint32 age = SDL_GetTicks() - event.common.timestamp;
+ // Ignore invalid/future synthetic timestamps; subtraction handles wrap.
+ if (age < 60000) m_Input.add(Uint64(age) * 10);
+ }
+ Uint64 startRender() const { return m_Enabled ? SDL_GetPerformanceCounter() : 0; }
+ void endRender(Uint64 start) {
+ if (m_Enabled) m_Render.add((SDL_GetPerformanceCounter() - start) * 10000 / SDL_GetPerformanceFrequency());
+ }
+ void report(uint64_t prioritized) const {
+ if (!m_Enabled) return;
+ SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
+ "VDI input timing: SDL dispatch age only; prioritized=%llu",
+ (unsigned long long)prioritized);
+ m_Input.report("input dispatch age");
+ m_Render.report("main-thread render call");
+ }
+private:
+ struct Histogram {
+ std::array<uint64_t, 1024> bins{};
+ uint64_t count = 0, total = 0, max = 0;
+ void add(uint64_t tenths) {
+ ++bins[std::min<uint64_t>(tenths, bins.size()-1)];
+ ++count; total += tenths; max = std::max(max, tenths);
+ }
+ double quantile(unsigned percent) const {
+ const uint64_t rank = (count * percent + 99) / 100;
+ uint64_t accumulated = 0;
+ for (size_t i = 0; i < bins.size(); ++i) {
+ accumulated += bins[i];
+ if (accumulated >= rank) return i / 10.0;
+ }
+ return 0;
+ }
+ void report(const char* label) const {
+ SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
+ "VDI %s: samples=%llu avg=%.2f p50=%.1f p95=%.1f max=%.1f ms (percentiles capped at 102.3ms)",
+ label, (unsigned long long)count, count ? total / (10.0*count) : 0,
+ count ? quantile(50) : 0, count ? quantile(95) : 0, max / 10.0);
+ }
+ };
+ bool m_Enabled;
+ Histogram m_Input, m_Render;
+};

View File

@ -0,0 +1,63 @@
// Include the production implementation so batching can be inspected without
// starting a real network connection. Unused transport code is linker-collected.
#include "InputStream.c"
#undef NDEBUG
#include <assert.h>
static PPACKET_HOLDER pop(void) {
PPACKET_HOLDER holder = NULL;
assert(LbqPollQueueElement(&packetQueue, (void**)&holder) == LBQ_SUCCESS);
return holder;
}
static void expectPosition(int x) {
PPACKET_HOLDER holder = pop();
assert(holder->packet.header.magic == LE32(MOUSE_MOVE_ABS_MAGIC));
latchAbsoluteMousePacket(holder);
assert(holder->packet.mouseMoveAbs.x == BE16(x));
assert((uint16_t)holder->packet.mouseMoveAbs.width == (uint16_t)BE16(2559));
freePacketHolder(holder);
}
int main(void) {
AppVersionQuad[0] = 7;
LbqInitializeLinkedBlockingQueue(&packetQueue, MAX_QUEUED_INPUT_PACKETS);
LbqInitializeLinkedBlockingQueue(&packetHolderFreeList, MAX_QUEUED_INPUT_PACKETS);
PltCreateMutex(&batchedInputMutex);
initialized = true;
for (int i = 0; i < 1000; ++i) {
// A deliberately stalled sender must preserve each click's coordinates.
assert(LiSendMousePositionEvent(10, 10, 2560, 1440) == 0);
assert(LiSendMousePositionEvent(20, 20, 2560, 1440) == 0);
assert(LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_LEFT) == 0);
assert(LiSendMousePositionEvent(30, 30, 2560, 1440) == 0);
assert(LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT) == 0);
assert(LiSendMousePositionEvent(40, 40, 2560, 1440) == 0);
expectPosition(20);
PPACKET_HOLDER press = pop();
assert(press->packet.header.magic == LE32(BUTTON_ACTION_PRESS + 1));
freePacketHolder(press);
expectPosition(30);
PPACKET_HOLDER release = pop();
assert(release->packet.header.magic == LE32(BUTTON_ACTION_RELEASE + 1));
freePacketHolder(release);
// Latching an older packet above must not prevent the latest batch
// from still absorbing newer positions.
assert(LiSendMousePositionEvent(50, 50, 2560, 1440) == 0);
expectPosition(50);
PPACKET_HOLDER empty;
assert(LbqPollQueueElement(&packetQueue, (void**)&empty) == LBQ_NO_ELEMENT);
}
initialized = false;
PLINKED_BLOCKING_QUEUE_ENTRY entry = LbqDestroyLinkedBlockingQueue(&packetQueue);
assert(entry == NULL);
entry = LbqDestroyLinkedBlockingQueue(&packetHolderFreeList);
while (entry) {
PLINKED_BLOCKING_QUEUE_ENTRY next = entry->flink;
free(entry->data);
entry = next;
}
PltDeleteMutex(&batchedInputMutex);
puts("PASS: 1000 queued move/press/move/release cycles preserve positions");
return 0;
}

View File

@ -0,0 +1,86 @@
#include "vdi_input_priority.h"
#undef NDEBUG
#include <cassert>
#include <cstdio>
constexpr Sint32 frameCode = 123;
static SDL_Event frame() {
SDL_Event e{}; e.type = SDL_USEREVENT; e.user.code = frameCode; return e;
}
static SDL_Event input(Uint32 type, Uint32 window = 1) {
SDL_Event e{}; e.type = type; e.key.windowID = window; return e;
}
static void push(SDL_Event e) { assert(SDL_PushEvent(&e) == 1); }
static SDL_Event pop() {
SDL_Event e{};
assert(SDL_PeepEvents(&e,1,SDL_GETEVENT,SDL_FIRSTEVENT,SDL_LASTEVENT)==1);
return e;
}
int main() {
assert(SDL_Init(SDL_INIT_EVENTS)==0);
SDL_Event out{};
VdiInputPriority disabled(false, frameCode);
push(input(SDL_MOUSEMOTION));
assert(!disabled.deferFrame(frame()) && !disabled.takeDeferred(out,1));
assert(pop().type == SDL_MOUSEMOTION);
// Only a contiguous input prefix can pass a frame. No focus/quit/decoder
// barrier may be skipped, even if input is waiting further down the queue.
for (Uint32 barrier : {Uint32(SDL_WINDOWEVENT),Uint32(SDL_QUIT),
Uint32(SDL_USEREVENT),Uint32(SDL_RENDER_DEVICE_RESET),
Uint32(SDL_CONTROLLERDEVICEADDED)}) {
VdiInputPriority scheduler(true, frameCode);
push(input(SDL_MOUSEBUTTONDOWN)); push(input(SDL_MOUSEBUTTONUP));
push(input(barrier)); push(input(SDL_KEYDOWN));
assert(scheduler.deferFrame(frame()));
assert(scheduler.takeDeferred(out,1) && out.type==SDL_MOUSEBUTTONDOWN);
assert(scheduler.takeDeferred(out,1) && out.type==SDL_MOUSEBUTTONUP);
assert(scheduler.takeDeferred(out,1) && out.type==SDL_USEREVENT && out.user.code==frameCode);
assert(!scheduler.takeDeferred(out,1));
assert(pop().type==barrier && pop().type==SDL_KEYDOWN);
assert(scheduler.prioritized()==2);
}
// Preserve all input order, including keyboard releases and drag edges.
{
VdiInputPriority scheduler(true,frameCode);
for (Uint32 t : {Uint32(SDL_KEYDOWN),Uint32(SDL_MOUSEMOTION),Uint32(SDL_MOUSEBUTTONDOWN),
Uint32(SDL_MOUSEMOTION),Uint32(SDL_MOUSEBUTTONUP),Uint32(SDL_KEYUP)}) push(input(t));
assert(scheduler.deferFrame(frame()));
for (Uint32 t : {Uint32(SDL_KEYDOWN),Uint32(SDL_MOUSEMOTION),Uint32(SDL_MOUSEBUTTONDOWN),
Uint32(SDL_MOUSEMOTION),Uint32(SDL_MOUSEBUTTONUP),Uint32(SDL_KEYUP)})
assert(scheduler.takeDeferred(out,1) && out.type==t);
assert(scheduler.takeDeferred(out,1) && out.type==SDL_USEREVENT);
}
for (bool synthetic : {false,true}) {
VdiInputPriority scheduler(true,frameCode);
auto e=input(SDL_MOUSEMOTION,synthetic?1:2);
if(synthetic) e.motion.which=SDL_TOUCH_MOUSEID;
push(e); assert(scheduler.deferFrame(frame()));
assert(scheduler.takeDeferred(out,1) && out.type==SDL_USEREVENT);
assert(pop().type==SDL_MOUSEMOTION);
}
// A high-rate input device cannot starve video.
{
VdiInputPriority scheduler(true,frameCode);
for(int i=0;i<1000;++i) push(input(SDL_MOUSEWHEEL));
assert(scheduler.deferFrame(frame()));
unsigned n=0;
while(scheduler.takeDeferred(out,1) && out.type!=SDL_USEREVENT) ++n;
assert(n<=32 && n>0 && out.type==SDL_USEREVENT);
SDL_FlushEvents(SDL_FIRSTEVENT,SDL_LASTEVENT);
}
{
VdiInputPriority scheduler(true,frameCode);
push(input(SDL_MOUSEBUTTONUP));
assert(scheduler.deferFrame(frame())); SDL_Delay(4);
assert(scheduler.takeDeferred(out,1) && out.type==SDL_USEREVENT);
assert(pop().type==SDL_MOUSEBUTTONUP);
}
// Instrumentation never consumes events or changes cursor visibility.
VdiInputTiming timing(true);
auto e=input(SDL_MOUSEMOTION); e.common.timestamp=SDL_GetTicks();
timing.observe(e,1); auto start=timing.startRender(); timing.endRender(start);
timing.report(0);
SDL_Quit();
std::puts("PASS: input FIFO, focus/quit/reset/window barriers, disabled mode, device/window isolation, count/time bounds");
}

View File

@ -0,0 +1,75 @@
#include <SDL.h>
#include <cstdio>
#include "vdi_mouse_batch.h"
#include "vdi_latest_frame.h"
#undef NDEBUG
#include <cassert>
static SDL_Event motion(int x, Uint32 which = 1)
{
SDL_Event event{};
event.type = SDL_MOUSEMOTION;
event.motion.which = which;
event.motion.windowID = 1;
event.motion.x = x;
event.motion.y = 100;
event.motion.xrel = 1;
return event;
}
int main()
{
assert(SDL_Init(SDL_INIT_EVENTS) == 0);
for (Uint32 boundary : {Uint32(SDL_MOUSEBUTTONDOWN), Uint32(SDL_MOUSEBUTTONUP),
Uint32(SDL_KEYDOWN), Uint32(SDL_USEREVENT)}) {
SDL_FlushEvents(SDL_FIRSTEVENT, SDL_LASTEVENT);
SDL_Event first = motion(10), adjacent = motion(20), later = motion(90), barrier{};
barrier.type = boundary;
assert(SDL_PushEvent(&adjacent) == 1);
assert(SDL_PushEvent(&barrier) == 1);
assert(SDL_PushEvent(&later) == 1);
vdiBatchMouseMotion(first.motion);
assert(first.motion.x == 20 && first.motion.xrel == 2);
SDL_Event next;
assert(SDL_PeepEvents(&next, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT) == 1);
assert(next.type == boundary);
assert(SDL_PeepEvents(&next, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT) == 1);
assert(next.motion.x == 90);
}
SDL_FlushEvents(SDL_FIRSTEVENT, SDL_LASTEVENT);
SDL_Event first = motion(0);
for (int i = 1; i <= 200; ++i) {
SDL_Event next = motion(i);
assert(SDL_PushEvent(&next) == 1);
}
vdiBatchMouseMotion(first.motion);
assert(first.motion.x == 64); // Work per dispatch is bounded.
assert(SDL_PeepEvents(nullptr, 0, SDL_PEEKEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT) == 136);
SDL_FlushEvents(SDL_FIRSTEVENT, SDL_LASTEVENT);
first = motion(10);
SDL_Event synthetic = motion(99, SDL_TOUCH_MOUSEID);
assert(SDL_PushEvent(&synthetic) == 1);
vdiBatchMouseMotion(first.motion);
assert(first.motion.x == 10);
AVFrame* presented = av_frame_alloc();
assert(presented);
presented->buf[0] = av_buffer_alloc(16);
assert(presented->buf[0]);
QQueue<AVFrame*> queue;
assert(vdiDiscardQueuedFrames(queue) == 0);
for (int i = 0; i < 200; ++i) {
unsigned dropped = vdiDiscardQueuedFrames(queue);
assert(dropped == (i == 0 ? 0u : 1u));
AVFrame* frame = av_frame_alloc();
assert(frame);
frame->pts = i;
queue.enqueue(frame);
assert(queue.size() == 1 && queue.head()->pts == i);
assert(av_buffer_get_ref_count(presented->buf[0]) == 1);
}
assert(vdiDiscardQueuedFrames(queue) == 1);
av_frame_free(&presented);
SDL_Quit();
std::puts("PASS: SDL event boundaries, bounded motion work, latest decoded frame ownership");
}

View File

@ -0,0 +1,74 @@
#!/bin/bash
# Temporary benchmark stream only. Refuses to replace an existing user stream.
# Run after launching the scoped Windows input benchmark, with VDD mode matched.
set -euo pipefail
task_root="${VDI_RKMPP_BUILD_ROOT:-$HOME/vdi-build/rkmpp-experiment}"
label="${1:?label required}"
fps="${2:?FPS required}"
priority="${3:-0}"
[[ "$label" =~ ^[a-zA-Z0-9-]+$ ]] || exit 2
[[ "$fps" = 30 || "$fps" = 60 ]] || exit 2
[[ "$priority" = 0 || "$priority" = 1 ]] || exit 2
exec 9>"$task_root/mouse-bench.lock"
flock -n 9 || { echo 'Another benchmark is active'; exit 1; }
if pgrep -f '^/home/armbian/vdi-build/rkmpp-experiment/build/moonlight/app/moonlight.* stream ' >/dev/null; then
echo 'A stream is already active; exit it normally before benchmarking' >&2
exit 1
fi
export DISPLAY=:0 XAUTHORITY="$HOME/.Xauthority"
export LD_LIBRARY_PATH="$task_root/runtime/lib:$task_root/deps/usr/lib/aarch64-linux-gnu"
export QML2_IMPORT_PATH="$task_root/deps/usr/lib/aarch64-linux-gnu/qt5/qml"
export QT_PLUGIN_PATH="$task_root/deps/usr/lib/aarch64-linux-gnu/qt5/plugins"
export H264_DECODER_HINT=h264_rkmpp HEVC_DECODER_HINT=hevc_rkmpp
export VDI_LATEST_FRAME=1 VDI_INPUT_TIMING=1 VDI_INPUT_PRIORITY="$priority"
export GL_IS_SLOW=0 SDL_RENDER_DRIVER=opengles2 SDL_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR=1
client="${VDI_RKMPP_CLIENT:-$task_root/build/moonlight/app/moonlight}"
mkdir -p "$task_root/mouse-bench"
log="$task_root/mouse-bench/$label.log"
test ! -e "$log" || { echo 'Label already used; preserve existing evidence'; exit 1; }
child=""
cleanup() {
if [ -n "$child" ] && kill -0 "$child" 2>/dev/null; then
kill -TERM "$child" 2>/dev/null || true
for ((j=0;j<5;j++)); do
kill -0 "$child" 2>/dev/null || break
sleep 1
done
kill -KILL "$child" 2>/dev/null || true
wait "$child" 2>/dev/null || true
fi
}
trap cleanup EXIT
trap 'exit 130' INT
trap 'exit 143' TERM
"$client" stream 192.168.1.70 Desktop --resolution 2560x1440 --fps "$fps" \
--bitrate 30000 --display-mode fullscreen --video-codec H.264 \
--video-decoder hardware --absolute-mouse --keep-awake --no-vsync \
--no-frame-pacing --audio-on-host > "$log" 2>&1 &
child=$!
ready=0
for ((i=0;i<35;i++)); do
if grep -q 'egl_overlay.frag' "$log"; then ready=1; break; fi
kill -0 "$child" || { tail -20 "$log"; exit 1; }
sleep 1
done
test "$ready" = 1 || { echo 'No video readiness'; exit 1; }
echo "Ready: $label; injecting motion"
python3 "$task_root/mouse-bench/inject-mouse-sweep.py"
python3 "$task_root/mouse-bench/inject-input-burst.py"
sleep 12
# Do not send the exit chord into an unrelated foreground application.
focus_pid=$(xdotool getwindowfocus getwindowpid 2>/dev/null || true)
if [ "$focus_pid" != "$child" ]; then
echo 'Stream lost foreground; terminate only benchmark child' >&2
exit 1
fi
xdotool key ctrl+alt+shift+q
for ((i=0;i<15;i++)); do
kill -0 "$child" 2>/dev/null || break
sleep 1
done
kill -0 "$child" 2>/dev/null && { echo 'Stream exit timed out'; exit 1; }
wait "$child"
child=""
grep -E 'VDI input|VDI main-thread|frame rate|Host processing|Frames dropped|Average .*time|Average network|queue delay' "$log"

166
tools/build-rkmpp-client.sh Normal file
View File

@ -0,0 +1,166 @@
#!/bin/bash
# Run on the ARM64 terminal. All sources, libraries and output stay in TASK_ROOT.
# No apt install, system library replacement, desktop restart or sudo is needed.
set -euo pipefail
TASK_ROOT="${VDI_RKMPP_BUILD_ROOT:-$HOME/vdi-build/rkmpp-experiment}"
SDK="$TASK_ROOT/deps/usr"
PREFIX="$TASK_ROOT/runtime"
JOBS="${VDI_BUILD_JOBS:-2}"
mkdir -p "$TASK_ROOT"/{src,debs,build} "$PREFIX"
clone_source() {
local name="$1" ref="$2" url="$3"
if [ ! -d "$TASK_ROOT/src/$name/.git" ]; then
git clone --depth=1 --branch "$ref" "$url" "$TASK_ROOT/src/$name"
fi
test "$(git -C "$TASK_ROOT/src/$name" rev-parse HEAD)" = "$4" || {
echo "Unexpected $name source revision; inspect before building" >&2; exit 1;
}
}
clone_source mpp develop https://github.com/rockchip-linux/mpp.git 7916c3cc000fefc0bdf96636b7d54fe174724f44
clone_source ffmpeg 6.1 https://github.com/nyanmisaka/ffmpeg-rockchip.git 797387de1c9caa9170100d7217ee093d1897f750
clone_source moonlight v6.2.0 https://github.com/moonlight-stream/moonlight-qt.git de2467e433821664cdd2224aad8c89a625be1ad9
git -C "$TASK_ROOT/src/moonlight" submodule update --init --recursive --depth=1
# Versioned VDI interaction patches. Explicit directory supports copying this
# builder to the box without the rest of the repository. Refuse unknown drift.
PATCH_DIR="${VDI_MOONLIGHT_PATCH_DIR:-$(cd "$(dirname "$0")/../terminal/moonlight/patches" && pwd)}"
apply_vdi_patch() {
local source="$1" patch="$2"
test -r "$patch" || { echo "Missing VDI patch: $patch" >&2; exit 1; }
if git -C "$source" apply --reverse --check "$patch" 2>/dev/null; then
return
fi
git -C "$source" apply --check "$patch"
git -C "$source" apply "$patch"
}
apply_vdi_patch "$TASK_ROOT/src/moonlight" "$PATCH_DIR/0001-vdi-input-and-latest-frame.patch"
apply_vdi_patch "$TASK_ROOT/src/moonlight/moonlight-common-c/moonlight-common-c" \
"$PATCH_DIR/0002-vdi-absolute-click-barrier.patch"
apply_vdi_patch "$TASK_ROOT/src/moonlight" "$PATCH_DIR/0003-vdi-input-priority.patch"
# Moonlight 6.2.0 uses std::optional in drm.h but relies on a transitive
# include from Qt 6. Our Qt 5 build needs the standard header explicitly.
export VDI_MOONLIGHT_SOURCE="$TASK_ROOT/src/moonlight"
python3 - <<'PY'
import os
from pathlib import Path
header = Path(os.environ['VDI_MOONLIGHT_SOURCE']) / 'app/streaming/video/ffmpeg-renderers/drm.h'
text = header.read_text()
if '#include <optional>' not in text:
assert '#include <set>' in text
header.write_text(text.replace('#include <set>', '#include <optional>\n#include <set>', 1))
PY
# Download only the required headers and private runtime libraries from the
# configured distribution repository. apt does not install or upgrade anything.
cd "$TASK_ROOT/debs"
apt-get download libdrm-dev libopus-dev libsdl2-dev libsdl2-2.0-0 \
libsdl2-ttf-dev libsdl2-ttf-2.0-0 libudev-dev libxkbcommon-dev \
libegl-dev libgles-dev libgles1 libgbm-dev libwayland-dev libwayland-bin wayland-protocols \
qtdeclarative5-dev qtdeclarative5-dev-tools qt5-qmltooling-plugins \
qtquickcontrols2-5-dev libqt5quickcontrols2-5 libqt5quicktemplates2-5 \
libqt5svg5-dev libqt5svg5 libqt5qmlworkerscript5 libqt5quickparticles5 \
libqt5quickshapes5 libqt5quicktest5 libx264-dev \
qml-module-qtquick2 qml-module-qtquick-window2 qml-module-qtquick-layouts \
qml-module-qtqml-models2 qml-module-qtquick-controls2 qml-module-qtquick-templates2 \
libharfbuzz-dev libfreetype-dev libpng-dev zlib1g-dev libbrotli-dev \
libglib2.0-dev libgraphite2-dev libffi-dev
for package in ./*.deb; do dpkg-deb -x "$package" "$TASK_ROOT/deps"; done
# Relocate pkg-config prefixes, preserving the system /usr and its libraries.
export VDI_PRIVATE_SDK="$SDK"
python3 - <<'PY'
import os
from pathlib import Path
sdk = Path(os.environ['VDI_PRIVATE_SDK'])
for pc in sdk.rglob('*.pc'):
text = pc.read_text()
if str(sdk) not in text:
pc.write_text(text.replace('/usr', str(sdk)))
for pri in sdk.rglob('qt_lib_*.pri'):
pri.write_text(pri.read_text().replace('$$QT_MODULE_LIB_BASE', str(sdk / 'lib/aarch64-linux-gnu'))
.replace('$$QT_MODULE_INCLUDE_BASE', str(sdk / 'include/aarch64-linux-gnu/qt5'))
.replace('$$QT_MODULE_BIN_BASE', str(sdk / 'lib/qt5/bin')))
# A -dev symlink can target a different distro patch version than is installed.
# Link to the existing matching SONAME; never replace the system runtime.
for link in (sdk / 'lib/aarch64-linux-gnu').glob('*.so'):
if link.is_symlink() and not link.exists():
target = Path(os.readlink(link)).name
if '.so.' not in target:
continue
soname = target.split('.so.')[0] + '.so.' + target.split('.so.')[1].split('.')[0]
system_lib = Path('/lib/aarch64-linux-gnu') / soname
if system_lib.exists():
link.unlink()
link.symlink_to(system_lib)
PY
export PKG_CONFIG_PATH="$PREFIX/lib/pkgconfig:$SDK/lib/aarch64-linux-gnu/pkgconfig:$SDK/share/pkgconfig${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH}"
export LD_LIBRARY_PATH="$PREFIX/lib:$SDK/lib/aarch64-linux-gnu${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
export QMAKEPATH="$SDK/lib/aarch64-linux-gnu/qt5"
export QML2_IMPORT_PATH="$SDK/lib/aarch64-linux-gnu/qt5/qml"
export CPLUS_INCLUDE_PATH="$SDK/include/aarch64-linux-gnu:$SDK/include${CPLUS_INCLUDE_PATH:+:$CPLUS_INCLUDE_PATH}"
export C_INCLUDE_PATH="$SDK/include/aarch64-linux-gnu:$SDK/include${C_INCLUDE_PATH:+:$C_INCLUDE_PATH}"
if [ "${VDI_BUILD_STAGE:-all}" != moonlight ]; then
echo '=== build MPP ==='
cmake -S "$TASK_ROOT/src/mpp" -B "$TASK_ROOT/build/mpp" \
-DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="$PREFIX" \
-DRKPLATFORM=ON -DHAVE_DRM=ON -DBUILD_SHARED_LIBS=ON -DBUILD_TEST=OFF
cmake --build "$TASK_ROOT/build/mpp" -j "$JOBS"
cmake --install "$TASK_ROOT/build/mpp"
echo '=== build FFmpeg with RKMPP ==='
mkdir -p "$TASK_ROOT/build/ffmpeg"
cd "$TASK_ROOT/build/ffmpeg"
"$TASK_ROOT/src/ffmpeg/configure" --prefix="$PREFIX" \
--enable-gpl --enable-version3 --enable-shared --disable-static \
--enable-libdrm --enable-rkmpp --disable-rkrga --enable-libx264 \
--disable-doc --disable-debug --disable-autodetect --disable-network \
--disable-everything --enable-avcodec --enable-avformat --enable-avfilter \
--enable-swscale --enable-swresample --enable-ffmpeg --enable-ffprobe \
--enable-decoder=h264,hevc,h264_rkmpp,hevc_rkmpp,rawvideo,wrapped_avframe \
--enable-parser=h264,hevc --enable-demuxer=h264,hevc \
--enable-muxer=h264,null,rawvideo --enable-protocol=file \
--enable-encoder=libx264,wrapped_avframe,rawvideo --enable-indev=lavfi \
--enable-filter=testsrc2,null,format,hwdownload,scale \
--extra-cflags="-I$PREFIX/include -I$SDK/include" \
--extra-ldflags="-L$PREFIX/lib -L$SDK/lib/aarch64-linux-gnu -Wl,-rpath,$PREFIX/lib -Wl,-rpath,$SDK/lib/aarch64-linux-gnu"
make -j "$JOBS"
make install
"$PREFIX/bin/ffmpeg" -hide_banner -decoders | grep rkmpp
fi
echo '=== build Moonlight ==='
mkdir -p "$TASK_ROOT/build/moonlight"
cd "$TASK_ROOT/build/moonlight"
qmake "$TASK_ROOT/src/moonlight/moonlight-qt.pro" \
CONFIG+=release CONFIG+=recheck CONFIG+=disable-libva CONFIG+=disable-libvdpau \
CONFIG+=disable-libplacebo CONFIG+=disable-discord \
"QMAKE_LIBDIR+=$SDK/lib/aarch64-linux-gnu" \
"QMAKE_LIBDIR+=$PREFIX/lib" \
"QMAKE_RPATHDIR+=$SDK/lib/aarch64-linux-gnu" \
"QMAKE_RPATHDIR+=$PREFIX/lib" \
"QMAKE_INCDIR+=$SDK/include/aarch64-linux-gnu/qt5" \
"QMAKE_INCDIR+=$SDK/include/aarch64-linux-gnu" \
"QMAKE_INCDIR+=$SDK/include"
make qmake_all
if ! grep -q -- '-DHAVE_EGL' app/Makefile.Release; then
echo 'EGL renderer missing; refusing to build a client without the DRM PRIME display path' >&2
exit 1
fi
# qmake/make does not invalidate old objects when feature defines change.
# In particular a stale ffmpeg.o can silently omit EGL despite a successful
# configure check. Clean the app whenever its compiler/link flags change.
flags_hash="$(grep -E '^(DEFINES|INCPATH|LIBS|CXXFLAGS)[[:space:]]*=' app/Makefile.Release | sha256sum | cut -d ' ' -f 1)"
if [ "$(cat .vdi-build-flags.sha256 2>/dev/null || true)" != "$flags_hash" ]; then
make -C app -f Makefile.Release clean
printf '%s\n' "$flags_hash" > .vdi-build-flags.sha256
fi
make -j "$JOBS"
echo '=== complete; experimental binary only, production unchanged ==='
echo "$TASK_ROOT/build/moonlight/app/moonlight"
git -C "$TASK_ROOT/src/mpp" rev-parse HEAD
git -C "$TASK_ROOT/src/ffmpeg" rev-parse HEAD
git -C "$TASK_ROOT/src/moonlight" rev-parse HEAD
sha256sum "$TASK_ROOT"/debs/*.deb > "$TASK_ROOT/dependency-sha256.txt"

View File

@ -0,0 +1,62 @@
#!/bin/bash
# Install only X11 display recovery; keep the kiosk/Moonlight session running.
set -euo pipefail
BOX="${VDI_BOX:-armbian@192.168.1.188}"
REPO="$(cd "$(dirname "$0")/.." && pwd)"
SRC="$REPO/terminal/kiosk-shell"
STAGE=$(ssh -o BatchMode=yes -o ConnectTimeout=8 "$BOX" 'mktemp -d /tmp/vdi-display-deploy.XXXXXX')
scp -q "$SRC/scripts/vdi-display-guard" "$SRC/scripts/vdi-kiosk-start" \
"$SRC/etc/vdi-display-guard.service" "$BOX:$STAGE/"
ssh "$BOX" bash -s -- "$STAGE" <<'REMOTE'
set -euo pipefail
stage=$1
backup="$HOME/vdi-terminal/backups/display-guard-$(date +%Y%m%d-%H%M%S)"
mkdir -p "$backup" "$HOME/vdi-terminal/bin" "$HOME/.config/systemd/user"
for file in "$HOME/vdi-terminal/bin/vdi-kiosk-start" \
"$HOME/vdi-terminal/bin/vdi-display-guard" \
"$HOME/.config/systemd/user/vdi-display-guard.service"; do
test ! -f "$file" || cp -p "$file" "$backup/"
done
sed -i 's/\r$//' "$stage/"*
python3 -c 'import ast, sys; ast.parse(open(sys.argv[1]).read())' "$stage/vdi-display-guard"
sh -n "$stage/vdi-kiosk-start"
install -m 0755 "$stage/vdi-display-guard" "$stage/vdi-kiosk-start" "$HOME/vdi-terminal/bin/"
install -m 0644 "$stage/vdi-display-guard.service" "$HOME/.config/systemd/user/"
# Correct only this monitor's known stale layout; preserve all other layouts.
python3 - "$backup" <<'PY'
from pathlib import Path
import shutil
import sys
import xml.etree.ElementTree as ET
path = Path.home() / '.config/monitors.xml'
if path.exists():
tree = ET.parse(path)
changed = False
for output in tree.findall('.//output'):
if (output.get('name') == 'HDMI-1'
and output.findtext('vendor') == 'GWR'
and output.findtext('product') == '0x2708'
and output.findtext('width') == '1920'
and output.findtext('height') == '1440'
and output.findtext('rate') == '75'):
for name, value in [('width', '2560'), ('height', '1440'), ('rate', '60')]:
output.find(name).text = value
changed = True
if changed:
shutil.copy2(path, Path(sys.argv[1]) / 'monitors.xml')
temp = path.with_name('monitors.xml.vdi-new')
tree.write(temp, encoding='utf-8', xml_declaration=True)
temp.replace(path)
print('Updated known stale MATE layout to 2560x1440@60')
PY
systemctl --user daemon-reload
systemctl --user enable vdi-display-guard.service
systemctl --user restart vdi-display-guard.service
systemctl --user is-active vdi-display-guard.service
echo "Backup: $backup"
# Only remove the three files uploaded by this deployment.
rm -- "$stage/vdi-display-guard" "$stage/vdi-kiosk-start" "$stage/vdi-display-guard.service"
rmdir -- "$stage"
REMOTE

View File

@ -15,21 +15,30 @@ echo "==> 检查盒子连通性"
ssh -o ConnectTimeout=8 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$BOX" 'echo "box ok: $(hostname)"' ssh -o ConnectTimeout=8 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$BOX" 'echo "box ok: $(hostname)"'
echo "==> 同步源码到盒子" echo "==> 同步源码到盒子"
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$BOX" 'rm -rf ~/vdi-build/repo/kiosk-shell/src ~/vdi-build/repo/kiosk-shell/tests && mkdir -p ~/vdi-build/repo/kiosk-shell/src ~/vdi-build/repo/kiosk-shell/tests' ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$BOX" 'rm -rf ~/vdi-build/repo/kiosk-shell/src ~/vdi-build/repo/kiosk-shell/tests && mkdir -p ~/vdi-build/repo/kiosk-shell/src ~/vdi-build/repo/kiosk-shell/tests ~/vdi-build/repo/kiosk-shell/scripts'
scp -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$SRC/CMakeLists.txt" "$BOX":~/vdi-build/repo/kiosk-shell/ scp -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$SRC/CMakeLists.txt" "$BOX":~/vdi-build/repo/kiosk-shell/
scp -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$SRC"/src/*.cpp "$SRC"/src/*.h "$BOX":~/vdi-build/repo/kiosk-shell/src/ scp -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$SRC"/src/*.cpp "$SRC"/src/*.h "$BOX":~/vdi-build/repo/kiosk-shell/src/
scp -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$SRC"/tests/*.cpp "$BOX":~/vdi-build/repo/kiosk-shell/tests/ scp -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$SRC"/tests/*.cpp "$BOX":~/vdi-build/repo/kiosk-shell/tests/
scp -q "$SRC/tests/test_display_guard.py" "$BOX":~/vdi-build/repo/kiosk-shell/tests/
scp -q "$SRC/scripts/vdi-display-guard" "$BOX":~/vdi-build/repo/kiosk-shell/scripts/
scp -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$SRC/scripts/vdi-moonlight" "$SRC/scripts/vdi-kiosk-start" "$BOX":~/vdi-terminal/bin/ scp -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$SRC/scripts/vdi-moonlight" "$SRC/scripts/vdi-kiosk-start" "$BOX":~/vdi-terminal/bin/
scp -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$SRC/scripts/vdi-moonlight-rkmpp" "$BOX":~/vdi-terminal/bin/
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$BOX" 'sed -i "s/\r$//" ~/vdi-terminal/bin/vdi-moonlight-rkmpp; chmod +x ~/vdi-terminal/bin/vdi-moonlight-rkmpp'
scp -q "$SRC/etc/70-vdi-rockchip-video.rules" "$BOX":/tmp/70-vdi-rockchip-video.rules
ssh "$BOX" 'sed -i "s/\r$//" /tmp/70-vdi-rockchip-video.rules; sudo -n install -m 0644 /tmp/70-vdi-rockchip-video.rules /etc/udev/rules.d/70-vdi-rockchip-video.rules && sudo -n udevadm control --reload-rules && for device in /dev/mpp_service /dev/rga /dev/dma_heap/*; do test ! -e "$device" || { sudo -n chgrp video "$device" && sudo -n chmod 0660 "$device"; } || exit 1; done'
scp -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$SRC/etc/moonlight.conf" "$BOX":/tmp/vdi-moonlight.conf scp -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$SRC/etc/moonlight.conf" "$BOX":/tmp/vdi-moonlight.conf
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$BOX" 'mkdir -p ~/.config/vdi-terminal; test -f ~/.config/vdi-terminal/moonlight.conf || cp /tmp/vdi-moonlight.conf ~/.config/vdi-terminal/moonlight.conf; rm -f /tmp/vdi-moonlight.conf' ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$BOX" 'mkdir -p ~/.config/vdi-terminal; test -f ~/.config/vdi-terminal/moonlight.conf || cp /tmp/vdi-moonlight.conf ~/.config/vdi-terminal/moonlight.conf; rm -f /tmp/vdi-moonlight.conf'
scp -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$SRC/vdi-kiosk.desktop" "$BOX":~/.config/autostart/vdi-kiosk.desktop scp -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$SRC/vdi-kiosk.desktop" "$BOX":~/.config/autostart/vdi-kiosk.desktop
scp -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$SRC/vdi-moonlight.desktop" "$BOX":~/.config/autostart/vdi-moonlight.desktop scp -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$SRC/vdi-moonlight.desktop" "$BOX":~/.config/autostart/vdi-moonlight.desktop
echo "==> 安装 HDMI 热插拔恢复服务"
bash "$REPO/tools/deploy_display_guard.sh"
echo "==> 在盒子上编译" echo "==> 在盒子上编译"
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$BOX" 'sed -i "s/\r$//" ~/vdi-build/repo/kiosk-shell/src/*.cpp ~/vdi-build/repo/kiosk-shell/src/*.h ~/vdi-build/repo/kiosk-shell/tests/*.cpp ~/vdi-terminal/bin/vdi-moonlight ~/vdi-terminal/bin/vdi-kiosk-start; chmod +x ~/vdi-terminal/bin/vdi-moonlight ~/vdi-terminal/bin/vdi-kiosk-start; cd ~/vdi-build/repo/kiosk-shell && (cmake -G Ninja -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=ON > /tmp/cmake.log 2>&1 || (tail -30 /tmp/cmake.log; exit 1)) && cmake --build build && QT_QPA_PLATFORM=offscreen ctest --test-dir build --output-on-failure' ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$BOX" 'sed -i "s/\r$//" ~/vdi-build/repo/kiosk-shell/src/*.cpp ~/vdi-build/repo/kiosk-shell/src/*.h ~/vdi-build/repo/kiosk-shell/tests/*.cpp ~/vdi-terminal/bin/vdi-moonlight ~/vdi-terminal/bin/vdi-kiosk-start; chmod +x ~/vdi-terminal/bin/vdi-moonlight ~/vdi-terminal/bin/vdi-kiosk-start; cd ~/vdi-build/repo/kiosk-shell && (cmake -G Ninja -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=ON > /tmp/cmake.log 2>&1 || (tail -30 /tmp/cmake.log; exit 1)) && cmake --build build && QT_QPA_PLATFORM=offscreen ctest --test-dir build --output-on-failure'
echo "==> 安装二进制" echo "==> 安装二进制"
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$BOX" 'monitor_pids=$(pgrep -f "^/home/armbian/vdi-terminal/bin/vdi-kiosk-monitor -- " 2>/dev/null || true); test -z "$monitor_pids" || kill $monitor_pids 2>/dev/null || true; pair_pids=$(pgrep -f "^bash -c tail -f .*(pin|pair)_fifo" 2>/dev/null || true); test -z "$pair_pids" || kill $pair_pids 2>/dev/null || true; tail_pids=$(pgrep -f "^tail -f .*(pin|pair)_fifo" 2>/dev/null || true); test -z "$tail_pids" || kill $tail_pids 2>/dev/null || true; rm -f ~/pair_fifo /tmp/pin_fifo; for name in vdi-moonlight moonlight-qt kiosk-shell; do pids=$(pidof "$name" 2>/dev/null || true); test -z "$pids" || kill $pids 2>/dev/null || true; done; for i in $(seq 1 40); do pgrep -f "^/home/armbian/vdi-terminal/bin/vdi-kiosk-monitor -- " >/dev/null 2>&1 || break; sleep 0.2; done; monitor_pids=$(pgrep -f "^/home/armbian/vdi-terminal/bin/vdi-kiosk-monitor -- " 2>/dev/null || true); test -z "$monitor_pids" || kill -9 $monitor_pids 2>/dev/null || true; cp ~/vdi-build/repo/kiosk-shell/build/kiosk-shell ~/vdi-terminal/bin/kiosk-shell && cp ~/vdi-build/repo/kiosk-shell/build/vdi-kiosk-monitor ~/vdi-terminal/bin/vdi-kiosk-monitor && chmod +x ~/vdi-terminal/bin/kiosk-shell ~/vdi-terminal/bin/vdi-kiosk-monitor && ls -la ~/vdi-terminal/bin/' ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$BOX" 'monitor_pids=$(pgrep -f "^/home/armbian/vdi-terminal/bin/vdi-kiosk-monitor -- " 2>/dev/null || true); test -z "$monitor_pids" || kill $monitor_pids 2>/dev/null || true; pair_pids=$(pgrep -f "^bash -c tail -f .*(pin|pair)_fifo" 2>/dev/null || true); test -z "$pair_pids" || kill $pair_pids 2>/dev/null || true; tail_pids=$(pgrep -f "^tail -f .*(pin|pair)_fifo" 2>/dev/null || true); test -z "$tail_pids" || kill $tail_pids 2>/dev/null || true; rm -f ~/pair_fifo /tmp/pin_fifo; for name in vdi-moonlight moonlight-qt moonlight kiosk-shell; do pids=$(pidof "$name" 2>/dev/null || true); test -z "$pids" || kill $pids 2>/dev/null || true; done; for i in $(seq 1 40); do pgrep -f "^/home/armbian/vdi-terminal/bin/vdi-kiosk-monitor -- " >/dev/null 2>&1 || break; sleep 0.2; done; monitor_pids=$(pgrep -f "^/home/armbian/vdi-terminal/bin/vdi-kiosk-monitor -- " 2>/dev/null || true); test -z "$monitor_pids" || kill -9 $monitor_pids 2>/dev/null || true; cp ~/vdi-build/repo/kiosk-shell/build/kiosk-shell ~/vdi-terminal/bin/kiosk-shell && cp ~/vdi-build/repo/kiosk-shell/build/vdi-kiosk-monitor ~/vdi-terminal/bin/vdi-kiosk-monitor && chmod +x ~/vdi-terminal/bin/kiosk-shell ~/vdi-terminal/bin/vdi-kiosk-monitor && ls -la ~/vdi-terminal/bin/'
echo "==> 收敛自启项(只保留 kiosk-shell 一条链)" echo "==> 收敛自启项(只保留 kiosk-shell 一条链)"
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$BOX" 'mkdir -p ~/.config/autostart; rm -f ~/.config/autostart/vdi-kiosk.desktop.bak; sed -i "s/^Hidden=.*/Hidden=true/;s/^X-GNOME-Autostart-enabled=.*/X-GNOME-Autostart-enabled=false/" ~/.config/autostart/vdi-moonlight.desktop 2>/dev/null || true; grep -H . ~/.config/autostart/*.desktop' ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$BOX" 'mkdir -p ~/.config/autostart; rm -f ~/.config/autostart/vdi-kiosk.desktop.bak; sed -i "s/^Hidden=.*/Hidden=true/;s/^X-GNOME-Autostart-enabled=.*/X-GNOME-Autostart-enabled=false/" ~/.config/autostart/vdi-moonlight.desktop 2>/dev/null || true; grep -H . ~/.config/autostart/*.desktop'

View File

@ -0,0 +1,54 @@
// Generate a deterministic 1440p H.264 clip without any display/capture dependency.
// Link against the isolated FFmpeg libavcodec/libavutil built for the terminal.
#include <stdio.h>
#include <string.h>
#include <libavcodec/avcodec.h>
#include <libavutil/opt.h>
static int write_packets(AVCodecContext *encoder, AVPacket *packet, FILE *output) {
int result;
while ((result = avcodec_receive_packet(encoder, packet)) == 0) {
if (fwrite(packet->data, 1, packet->size, output) != (size_t)packet->size) return -1;
av_packet_unref(packet);
}
return result == AVERROR(EAGAIN) || result == AVERROR_EOF ? 0 : result;
}
int main(int argc, char **argv) {
if (argc != 2) return 2;
const AVCodec *codec = avcodec_find_encoder_by_name("libx264");
AVCodecContext *encoder = avcodec_alloc_context3(codec);
AVFrame *frame = av_frame_alloc();
AVPacket *packet = av_packet_alloc();
FILE *output = fopen(argv[1], "wb");
if (!codec || !encoder || !frame || !packet || !output) return 1;
encoder->width = frame->width = 2560;
encoder->height = frame->height = 1440;
encoder->pix_fmt = frame->format = AV_PIX_FMT_YUV420P;
encoder->time_base = (AVRational){1, 30};
encoder->framerate = (AVRational){30, 1};
encoder->max_b_frames = 0;
encoder->thread_count = 2;
av_opt_set(encoder->priv_data, "preset", "ultrafast", 0);
av_opt_set(encoder->priv_data, "tune", "zerolatency", 0);
if (avcodec_open2(encoder, codec, NULL) < 0 || av_frame_get_buffer(frame, 32) < 0) return 1;
for (int i = 0; i < 60; i++) {
if (av_frame_make_writable(frame) < 0) return 1;
for (int y = 0; y < frame->height; y++) {
memset(frame->data[0] + y * frame->linesize[0], 32 + (y + i * 4) % 190, frame->width);
}
for (int plane = 1; plane < 3; plane++) {
for (int y = 0; y < frame->height / 2; y++) {
memset(frame->data[plane] + y * frame->linesize[plane], 128, frame->width / 2);
}
}
frame->pts = i;
if (avcodec_send_frame(encoder, frame) < 0 || write_packets(encoder, packet, output) < 0) return 1;
}
if (avcodec_send_frame(encoder, NULL) < 0 || write_packets(encoder, packet, output) < 0) return 1;
if (fclose(output) != 0) return 1;
av_packet_free(&packet);
av_frame_free(&frame);
avcodec_free_context(&encoder);
return 0;
}

View File

@ -0,0 +1,26 @@
"""X11 test only: inject 32 alternating left/right clicks into the bench window."""
import ctypes
x11 = ctypes.CDLL("libX11.so.6")
xtest = ctypes.CDLL("libXtst.so.6")
x11.XOpenDisplay.argtypes = [ctypes.c_char_p]
x11.XOpenDisplay.restype = ctypes.c_void_p
x11.XFlush.argtypes = [ctypes.c_void_p]
x11.XCloseDisplay.argtypes = [ctypes.c_void_p]
xtest.XTestFakeMotionEvent.argtypes = [ctypes.c_void_p, ctypes.c_int,
ctypes.c_int, ctypes.c_int, ctypes.c_ulong]
xtest.XTestFakeButtonEvent.argtypes = [ctypes.c_void_p, ctypes.c_uint,
ctypes.c_int, ctypes.c_ulong]
display = x11.XOpenDisplay(None)
if not display:
raise RuntimeError("X11 unavailable")
try:
for index in range(32):
x = 640 if index % 2 == 0 else 1920
assert xtest.XTestFakeMotionEvent(display, -1, x, 600, 0)
assert xtest.XTestFakeButtonEvent(display, 1, 1, 0)
assert xtest.XTestFakeButtonEvent(display, 1, 0, 0)
x11.XFlush(display)
finally:
x11.XCloseDisplay(display)
print("Injected 32 clicks, expected L,R alternating; final pointer on R")

View File

@ -0,0 +1,31 @@
"""X11 benchmark only: 20 seconds of 125 Hz motion, no buttons or keys."""
import ctypes
import math
import time
x11 = ctypes.CDLL("libX11.so.6")
xtest = ctypes.CDLL("libXtst.so.6")
x11.XOpenDisplay.argtypes = [ctypes.c_char_p]
x11.XOpenDisplay.restype = ctypes.c_void_p
x11.XFlush.argtypes = [ctypes.c_void_p]
x11.XCloseDisplay.argtypes = [ctypes.c_void_p]
xtest.XTestFakeMotionEvent.argtypes = [ctypes.c_void_p, ctypes.c_int,
ctypes.c_int, ctypes.c_int, ctypes.c_ulong]
display = x11.XOpenDisplay(None)
if not display:
raise RuntimeError("X11 unavailable")
start = time.monotonic()
count = 0
try:
while time.monotonic() - start < 20:
elapsed = time.monotonic() - start
x = round(1280 + 1000 * math.sin(elapsed * 4))
y = round(720 + 450 * math.cos(elapsed * 3))
if not xtest.XTestFakeMotionEvent(display, -1, x, y, 0):
raise RuntimeError("Motion injection failed")
x11.XFlush(display)
count += 1
time.sleep(max(0, start + count / 125 - time.monotonic()))
finally:
x11.XCloseDisplay(display)
print(f"Injected {count} motion events in {time.monotonic()-start:.2f}s")

View File

@ -0,0 +1,85 @@
# Temporary interactive test window; exits after ten minutes. No system settings.
$ErrorActionPreference = 'Stop'
$benchDir = 'C:\ProgramData\VDI\input-bench-20261103'
New-Item -ItemType Directory -Force $benchDir | Out-Null
Set-Content -LiteralPath "$benchDir\pid.txt" -Value $PID
Add-Type -ReferencedAssemblies System.Windows.Forms,System.Drawing -TypeDefinition @'
using System;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows.Forms;
public class VDIInputBenchForm : Form {
[DllImport("user32.dll")] public static extern bool SetProcessDPIAware();
[DllImport("winmm.dll")] public static extern uint timeBeginPeriod(uint period);
[DllImport("winmm.dll")] public static extern uint timeEndPeriod(uint period);
readonly Stopwatch watch = Stopwatch.StartNew();
readonly Timer timer = new Timer();
readonly string folder;
int paints, clicks;
long lastReport;
long lastFrameIndex = -1;
public VDIInputBenchForm(string path) {
folder = path;
Text = "VDI Input Latency Bench";
FormBorderStyle = FormBorderStyle.None;
Bounds = Screen.PrimaryScreen.Bounds;
TopMost = true;
DoubleBuffered = true;
File.WriteAllText(Path.Combine(folder,"clicks.csv"), "ms,x,y,target\n");
// A WinForms 16ms timer can quantize to ~31ms at the default timer
// resolution and accidentally cap the *source* at 32FPS. Pace by an
// absolute monotonic frame index, not accumulated timer ticks.
timer.Interval = 1;
timer.Tick += delegate {
if(watch.Elapsed.TotalMinutes >= 10) { Close(); return; }
long frameIndex = watch.ElapsedTicks * 60 / Stopwatch.Frequency;
if(frameIndex != lastFrameIndex) { lastFrameIndex = frameIndex; Invalidate(); }
};
timer.Start();
}
protected override void OnMouseDown(MouseEventArgs e) {
base.OnMouseDown(e);
string target = e.X < Width/2 ? "L" : "R";
File.AppendAllText(Path.Combine(folder,"clicks.csv"),
watch.ElapsedMilliseconds+","+e.X+","+e.Y+","+target+"\n");
++clicks;
Invalidate();
}
protected override void OnPaint(PaintEventArgs e) {
base.OnPaint(e);
long ms = watch.ElapsedMilliseconds;
e.Graphics.Clear(Color.FromArgb(16,24,39));
using(Brush left = new SolidBrush(Color.FromArgb(35,85,130)))
using(Brush right = new SolidBrush(Color.FromArgb(50,115,90))) {
e.Graphics.FillRectangle(left,50,180,Width/2-100,Height-260);
e.Graphics.FillRectangle(right,Width/2+50,180,Width/2-100,Height-260);
}
int x = (int)((ms*0.6)%(Width+100))-100;
e.Graphics.FillRectangle(Brushes.Gold,x,0,60,Height);
using(Font font = new Font("Consolas",24)) {
e.Graphics.DrawString("VDI test: moving bars + ordered clicks | "+clicks+" clicks | "+ms+" ms",
font,Brushes.White,70,40);
e.Graphics.DrawString("LEFT",font,Brushes.White,Width/4-50,Height/2);
e.Graphics.DrawString("RIGHT",font,Brushes.White,Width*3/4-50,Height/2);
}
++paints;
if(ms-lastReport>=1000) {
File.WriteAllText(Path.Combine(folder,"status.txt"),
"width="+Width+" height="+Height+" paints="+paints+" elapsed_ms="+ms+" clicks="+clicks);
lastReport=ms;
}
}
protected override void OnFormClosed(FormClosedEventArgs e) {
timer.Stop(); timer.Dispose(); base.OnFormClosed(e);
}
}
'@
[VDIInputBenchForm]::SetProcessDPIAware() | Out-Null
$timerResult=[VDIInputBenchForm]::timeBeginPeriod(1)
try {
[System.Windows.Forms.Application]::Run((New-Object VDIInputBenchForm($benchDir)))
} finally {
if($timerResult -eq 0) { [VDIInputBenchForm]::timeEndPeriod(1) | Out-Null }
}

67
tools/probe-nvidia-d3d.cs Normal file
View File

@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace VdiDiagnostics {
public class AdapterResult {
public string Name;
public uint VendorId;
public int DeviceResult;
}
// Enumerate the actual DXGI adapters and create a D3D11 device on each NVIDIA
// adapter. A WMI/PnP model name alone does not prove that D3D is operational.
public static class D3DProbe {
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct AdapterDesc {
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] public string Description;
public uint VendorId, DeviceId, SubSysId, Revision;
public UIntPtr DedicatedVideoMemory, DedicatedSystemMemory, SharedSystemMemory;
public long AdapterLuid;
}
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate int EnumAdapters(IntPtr factory, uint index, out IntPtr adapter);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate int GetDesc(IntPtr adapter, out AdapterDesc desc);
[DllImport("dxgi.dll")]
private static extern int CreateDXGIFactory1(ref Guid iid, out IntPtr factory);
[DllImport("d3d11.dll")]
private static extern int D3D11CreateDevice(IntPtr adapter, uint driverType,
IntPtr software, uint flags, IntPtr levels, uint levelCount, uint sdkVersion,
out IntPtr device, out uint featureLevel, out IntPtr context);
public static AdapterResult[] Check() {
var results = new List<AdapterResult>();
var iid = new Guid("770aae78-f26f-4dba-a829-253c83d1b387");
IntPtr factory;
Marshal.ThrowExceptionForHR(CreateDXGIFactory1(ref iid, out factory));
try {
var table = Marshal.ReadIntPtr(factory);
var enumerate = (EnumAdapters)Marshal.GetDelegateForFunctionPointer(
Marshal.ReadIntPtr(table, 7 * IntPtr.Size), typeof(EnumAdapters));
for (uint i = 0; i < 32; i++) {
IntPtr adapter;
int hr = enumerate(factory, i, out adapter);
if (hr == unchecked((int)0x887A0002)) break;
Marshal.ThrowExceptionForHR(hr);
try {
var descMethod = (GetDesc)Marshal.GetDelegateForFunctionPointer(
Marshal.ReadIntPtr(Marshal.ReadIntPtr(adapter), 8 * IntPtr.Size), typeof(GetDesc));
AdapterDesc desc;
Marshal.ThrowExceptionForHR(descMethod(adapter, out desc));
if (desc.VendorId != 0x10de) continue;
IntPtr device, context;
uint level;
hr = D3D11CreateDevice(adapter, 0, IntPtr.Zero, 0, IntPtr.Zero,
0, 7, out device, out level, out context);
if (context != IntPtr.Zero) Marshal.Release(context);
if (device != IntPtr.Zero) Marshal.Release(device);
results.Add(new AdapterResult { Name = desc.Description,
VendorId = desc.VendorId, DeviceResult = hr });
} finally { Marshal.Release(adapter); }
}
} finally { Marshal.Release(factory); }
return results.ToArray();
}
}
}

View File

@ -0,0 +1,55 @@
"""Start/status/stop only the temporary VDI input benchmark through VM100's agent."""
import argparse
import base64
from pathlib import Path
import runpy
import sys
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("action", choices=["start", "status", "stop"])
args = parser.parse_args()
tools_dir = Path(__file__).resolve().parent
term = runpy.run_path(str(tools_dir / "pve_term_exec.py"))
vm = runpy.run_path(str(tools_dir / "pve_vm.py"))
ticket, csrf = term["login"]()
state = vm["api"]("/api2/json/nodes/starhe/qemu/100/status/current", ticket=ticket)
if state.get("status") != "running":
sys.exit("VM100 is not running; no benchmark task changed")
folder = r"C:\ProgramData\VDI\input-bench-20261103"
prefix = "$ErrorActionPreference='Stop'; $folder='" + folder + "'; "
if args.action == "start":
encoded = base64.b64encode((tools_dir / "input-latency-bench.ps1").read_bytes()).decode()
command = prefix + r"""
New-Item -ItemType Directory -Force $folder | Out-Null
if (Get-ScheduledTask -TaskName VDIInputLatencyBench -ErrorAction SilentlyContinue) { throw 'Benchmark task already exists; stop it first' }
[IO.File]::WriteAllBytes("$folder\bench.ps1",[Convert]::FromBase64String('""" + encoded + r"""'))
$action=New-ScheduledTaskAction -Execute powershell.exe -Argument "-NoProfile -ExecutionPolicy Bypass -STA -WindowStyle Hidden -File $folder\bench.ps1"
$principal=New-ScheduledTaskPrincipal -UserId test -LogonType Interactive -RunLevel Limited
$settings=New-ScheduledTaskSettingsSet -ExecutionTimeLimit (New-TimeSpan -Minutes 10)
Register-ScheduledTask -TaskName VDIInputLatencyBench -Action $action -Principal $principal -Settings $settings | Out-Null
Start-ScheduledTask -TaskName VDIInputLatencyBench
'Benchmark launched'
"""
elif args.action == "status":
command = prefix + r"""
Get-Content "$folder\status.txt" -ErrorAction SilentlyContinue
Get-Content "$folder\clicks.csv" -ErrorAction SilentlyContinue
Get-ScheduledTaskInfo -TaskName VDIInputLatencyBench | Select-Object LastTaskResult | ConvertTo-Json -Compress
"""
else:
command = prefix + r"""
Stop-ScheduledTask -TaskName VDIInputLatencyBench -ErrorAction SilentlyContinue
Unregister-ScheduledTask -TaskName VDIInputLatencyBench -Confirm:$false -ErrorAction SilentlyContinue
if (Test-Path "$folder\pid.txt") {
$benchPid=[int](Get-Content "$folder\pid.txt")
$process=Get-CimInstance Win32_Process -Filter "ProcessId=$benchPid"
if ($process.CommandLine -like '*input-bench-20261103*') { Stop-Process -Id $benchPid -ErrorAction SilentlyContinue }
}
'Benchmark stopped; other applications untouched'
"""
out, error = vm["agent"](ticket, csrf, ["powershell.exe", "-NoProfile", "-Command", command])
print(out)
if error:
print(error, file=sys.stderr)
sys.exit(1)

View File

@ -0,0 +1,61 @@
"""Run the scoped VDD mode probe in VM100's already logged-in user session."""
import argparse
import base64
from pathlib import Path
import runpy
import sys
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("action", choices=["Query", "List", "Apply", "Restore"])
parser.add_argument("--hz", type=int, default=60)
args = parser.parse_args()
if not 24 <= args.hz <= 240:
parser.error("--hz must be in 24..240")
root = Path(__file__).resolve().parent
term = runpy.run_path(str(root / "pve_term_exec.py"))
vm = runpy.run_path(str(root / "pve_vm.py"))
ticket, csrf = term["login"]()
state = vm["api"]("/api2/json/nodes/starhe/qemu/100/status/current", ticket=ticket)
if state.get("status") != "running":
sys.exit("VM100 is not running; no task or display configuration changed")
payload = base64.b64encode((root / "set-vdi-display-mode.ps1").read_bytes()).decode()
command = r"""
$ErrorActionPreference='Stop'
$folder='C:\ProgramData\VDI\mouse-optimization'
$task='VDIMouseDisplayProbe'
if(Get-ScheduledTask -TaskName $task -ErrorAction SilentlyContinue) { throw 'Probe task already exists' }
$user=(Get-CimInstance Win32_ComputerSystem).UserName
if(-not $user) { throw 'No interactive user' }
New-Item -ItemType Directory -Force $folder | Out-Null
$acl=Get-Acl -LiteralPath $folder
$rule=New-Object Security.AccessControl.FileSystemAccessRule($user,'Modify','ContainerInherit,ObjectInherit','None','Allow')
$acl.SetAccessRule($rule)
Set-Acl -LiteralPath $folder -AclObject $acl
[IO.File]::WriteAllBytes("$folder\mode.ps1",[Convert]::FromBase64String('__VDI_PAYLOAD__'))
$run="try { & '$folder\mode.ps1' -Action __VDI_ACTION__ -RefreshRate __VDI_HZ__ | Out-File -Encoding utf8 -Width 300 '$folder\mode-result.txt' } catch { `$_ | Out-String | Out-File -Encoding utf8 -Width 300 '$folder\mode-result.txt'; exit 1 }"
$encoded=[Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($run))
$action=New-ScheduledTaskAction -Execute powershell.exe -Argument "-NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -EncodedCommand $encoded"
$principal=New-ScheduledTaskPrincipal -UserId $user -LogonType Interactive -RunLevel Limited
$settings=New-ScheduledTaskSettingsSet -ExecutionTimeLimit (New-TimeSpan -Minutes 1)
Register-ScheduledTask -TaskName $task -Action $action -Principal $principal -Settings $settings | Out-Null
try {
Start-ScheduledTask -TaskName $task
Start-Sleep -Seconds 2
for($i=0;$i -lt 20;$i++) {
if((Get-ScheduledTask -TaskName $task).State -ne 'Running') { break }
Start-Sleep -Seconds 1
}
if((Get-ScheduledTask -TaskName $task).State -eq 'Running') { throw 'Probe timed out' }
Get-Content "$folder\mode-result.txt"
'task_result='+(Get-ScheduledTaskInfo -TaskName $task).LastTaskResult
} finally {
Stop-ScheduledTask -TaskName $task -ErrorAction SilentlyContinue
Unregister-ScheduledTask -TaskName $task -Confirm:$false
}
""".replace("__VDI_ACTION__", args.action).replace("__VDI_HZ__", str(args.hz)).replace("__VDI_PAYLOAD__", payload)
out, error = vm["agent"](ticket, csrf, ["powershell.exe", "-NoProfile", "-Command", command])
print(out)
if error or "task_result=0" not in out:
print(error, file=sys.stderr)
sys.exit(1)

View File

@ -0,0 +1,52 @@
param([switch]$Restore)
# Run in the logged-in desktop user session, not the Guest Agent's Session 0.
$ErrorActionPreference = 'Stop'
$directory = Join-Path $env:LOCALAPPDATA 'VDI'
New-Item -ItemType Directory -Force $directory | Out-Null
$backup = Join-Path $directory 'desktop-responsiveness-before-20261103.json'
Add-Type @'
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
public static class VDIVisualResponse {
[StructLayout(LayoutKind.Sequential)] struct Animation { public uint size; public int enabled; }
[DllImport("user32.dll", EntryPoint="SystemParametersInfoW", SetLastError=true)]
static extern bool SpiAnimation(uint action, uint size, ref Animation data, uint flags);
[DllImport("user32.dll", EntryPoint="SystemParametersInfoW", SetLastError=true)]
static extern bool SpiGet(uint action, uint unused, out uint value, uint flags);
[DllImport("user32.dll", EntryPoint="SystemParametersInfoW", SetLastError=true)]
static extern bool SpiSet(uint action, uint value, IntPtr unused, uint flags);
static void Check(bool result) { if(!result) throw new Win32Exception(Marshal.GetLastWin32Error()); }
public static int AnimationEnabled() {
Animation data = new Animation { size=8 };
Check(SpiAnimation(0x0048,8,ref data,0)); return data.enabled;
}
public static uint MenuDelay() { uint value; Check(SpiGet(0x006A,0,out value,0)); return value; }
public static void Set(int animation, uint delay) {
Animation data = new Animation { size=8, enabled=animation };
Check(SpiAnimation(0x0049,8,ref data,3));
Check(SpiSet(0x006B,delay,IntPtr.Zero,3));
}
}
'@
$before = @{ animation=[VDIVisualResponse]::AnimationEnabled(); menuDelay=[VDIVisualResponse]::MenuDelay() }
if ($Restore) {
$target = Get-Content -LiteralPath $backup -Raw | ConvertFrom-Json
} else {
if (-not (Test-Path -LiteralPath $backup)) {
$before | ConvertTo-Json | Set-Content -LiteralPath $backup -Encoding UTF8
}
$target = @{ animation=0; menuDelay=100 }
}
try {
[VDIVisualResponse]::Set([int]$target.animation,[uint32]$target.menuDelay)
$after = @{ animation=[VDIVisualResponse]::AnimationEnabled(); menuDelay=[VDIVisualResponse]::MenuDelay() }
if ($after.animation -ne $target.animation -or $after.menuDelay -ne $target.menuDelay) {
throw 'Desktop preferences were not retained'
}
@{ before=$before; after=$after; backup=$backup; restored=[bool]$Restore } |
ConvertTo-Json -Depth 4 | Set-Content -LiteralPath (Join-Path $directory 'desktop-responsiveness-result.json') -Encoding UTF8
} catch {
[VDIVisualResponse]::Set([int]$before.animation,[uint32]$before.menuDelay)
throw
}

View File

@ -0,0 +1,111 @@
param(
[ValidateSet('Query', 'List', 'Apply', 'Restore')][string]$Action = 'Query',
[ValidateRange(640, 7680)][int]$Width = 2560,
[ValidateRange(480, 4320)][int]$Height = 1440,
[ValidateRange(24, 240)][int]$RefreshRate = 60,
[string]$BackupPath = 'C:\ProgramData\VDI\mouse-optimization\display-before.json'
)
$ErrorActionPreference = 'Stop'
# Run in the logged-in desktop session. Apply is temporary (no registry update).
# Never assumes DISPLAY1, and refuses ambiguous active virtual displays.
Add-Type -TypeDefinition @'
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
public static class VdiModeProbe {
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct Device {
public int cb;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] public string Name;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] public string Description;
public int Flags;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] public string Id;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] public string Key;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct Mode {
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] public string name;
public short spec, driver, size, extra;
public int fields, x, y, orientation, fixedOutput;
public short color, duplex, yres, tt, collate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] public string form;
public short logPixels;
public int bpp, width, height, flags, hz, icmMethod, icmIntent, media, dither,
reserved1, reserved2, panWidth, panHeight;
}
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
static extern bool EnumDisplayDevices(string name, uint index, ref Device dev, uint flags);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
static extern bool EnumDisplaySettings(string name, int index, ref Mode mode);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
static extern int ChangeDisplaySettingsEx(string name, ref Mode mode, IntPtr window, uint flags, IntPtr param);
public static string Find() {
string found = null;
for (uint i = 0; ; i++) {
var d = new Device(); d.cb = Marshal.SizeOf(typeof(Device));
if (!EnumDisplayDevices(null, i, ref d, 0)) return found;
if ((d.Flags & 1) == 0 || d.Description.IndexOf("Virtual Display Driver", StringComparison.OrdinalIgnoreCase) < 0) continue;
if (found != null) throw new InvalidOperationException("Multiple active virtual displays; select manually");
found = d.Name;
}
}
public static Mode Current(string name) {
var m = new Mode(); m.size = (short)Marshal.SizeOf(typeof(Mode));
if (!EnumDisplaySettings(name, -1, ref m)) throw new InvalidOperationException("Cannot query mode");
return m;
}
public static Mode[] List(string name) {
var modes = new List<Mode>();
for(int i=0; ; ++i) {
var m = new Mode(); m.size = (short)Marshal.SizeOf(typeof(Mode));
if (!EnumDisplaySettings(name, i, ref m)) return modes.ToArray();
modes.Add(m);
}
}
public static void Apply(string name, int w, int h, int hz, int bpp) {
foreach(var m0 in List(name)) {
var m = m0;
if(m.width != w || m.height != h || m.hz != hz || m.bpp != bpp) continue;
m.fields = 0x80000 | 0x100000 | 0x400000 | 0x40000;
int result = ChangeDisplaySettingsEx(name, ref m, IntPtr.Zero, 2, IntPtr.Zero);
if(result != 0) throw new InvalidOperationException("Mode test failed: " + result);
result = ChangeDisplaySettingsEx(name, ref m, IntPtr.Zero, 0, IntPtr.Zero);
if(result != 0) throw new InvalidOperationException("Mode apply failed: " + result);
var actual = Current(name);
if(actual.width != w || actual.height != h || actual.hz != hz || actual.bpp != bpp)
throw new InvalidOperationException("Mode read-back mismatch");
return;
}
throw new InvalidOperationException("Requested mode not advertised");
}
}
'@
$device = [VdiModeProbe]::Find()
if (-not $device) { throw 'No active Virtual Display Driver in this session' }
$current = [VdiModeProbe]::Current($device)
if ($Action -eq 'List') {
[VdiModeProbe]::List($device) | Where-Object { $_.width -eq $Width -and $_.height -eq $Height } |
Select-Object width,height,hz,bpp | ConvertTo-Json -Compress
exit 0
}
if ($Action -eq 'Apply') {
if (-not (Test-Path -LiteralPath $BackupPath)) {
New-Item -ItemType Directory -Force (Split-Path $BackupPath) | Out-Null
@{device=$device; width=$current.width; height=$current.height; hz=$current.hz; bpp=$current.bpp} |
ConvertTo-Json | Set-Content -LiteralPath $BackupPath
}
try {
[VdiModeProbe]::Apply($device,$Width,$Height,$RefreshRate,$current.bpp)
} catch {
[VdiModeProbe]::Apply($device,$current.width,$current.height,$current.hz,$current.bpp)
throw
}
}
if ($Action -eq 'Restore') {
$before = Get-Content -LiteralPath $BackupPath -Raw | ConvertFrom-Json
if ($before.device -ne $device) { throw 'Display identity changed; inspect before restoring' }
[VdiModeProbe]::Apply($device,$before.width,$before.height,$before.hz,$before.bpp)
}
$current = [VdiModeProbe]::Current($device)
@{device=$device; width=$current.width; height=$current.height; hz=$current.hz; bpp=$current.bpp; action=$Action} |
ConvertTo-Json -Compress

View File

@ -0,0 +1,39 @@
<!doctype html>
<meta charset="utf-8">
<title>VDI stream motion test</title>
<style>
html, body { margin: 0; overflow: hidden; background: #101827; color: white; font: 24px monospace; }
canvas { display: block; width: 100vw; height: 100vh; }
#stats { position: fixed; right: 24px; top: 20px; background: #000c; padding: 12px; }
</style>
<canvas id="scene"></canvas><div id="stats"></div>
<script>
// Deterministic moving bars + checkerboard: creates continuous desktop damage.
// Read the source RAF rate separately from the Moonlight stream/render rate.
const canvas = document.getElementById('scene');
const context = canvas.getContext('2d', { alpha: false });
const stats = document.getElementById('stats');
let count = 0, last = performance.now(), sourceFps = 0;
function render(now) {
if (canvas.width !== innerWidth || canvas.height !== innerHeight) {
canvas.width = innerWidth; canvas.height = innerHeight;
}
const width = canvas.width, height = canvas.height;
context.fillStyle = '#101827'; context.fillRect(0, 0, width, height);
const offset = Math.floor(now * 0.12) % 128;
for (let y = height / 2; y < height; y += 128) {
for (let x = -128; x < width; x += 128) {
context.fillStyle = (Math.round((x + 128) / 128) + Math.floor(y / 128)) % 2 ? '#28517a' : '#132c46';
context.fillRect(x + offset, y, 126, 126);
}
}
const x = (now * 0.6) % (width + 100) - 100;
context.fillStyle = '#ffcf40'; context.fillRect(x, 0, 80, height);
context.fillStyle = '#ffffff'; context.fillRect(width - x, 0, 8, height);
count++;
if (now - last >= 1000) { sourceFps = count * 1000 / (now - last); count = 0; last = now; }
stats.textContent = `${width}x${height} | source RAF ${sourceFps.toFixed(1)} FPS | ${Math.floor(now)} ms`;
requestAnimationFrame(render);
}
requestAnimationFrame(render);
</script>

View File

@ -0,0 +1,31 @@
#!/bin/bash
# Run against the actual patched source and private runtime on the ARM64 box.
set -euo pipefail
b="${VDI_RKMPP_BUILD_ROOT:-$HOME/vdi-build/rkmpp-experiment}"
sdk="$b/deps/usr"
export LD_LIBRARY_PATH="$b/runtime/lib:$sdk/lib/aarch64-linux-gnu${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
export PKG_CONFIG_PATH="$b/runtime/lib/pkgconfig:$sdk/lib/aarch64-linux-gnu/pkgconfig:$sdk/share/pkgconfig"
export CPLUS_INCLUDE_PATH="$sdk/include/aarch64-linux-gnu:$sdk/include"
export C_INCLUDE_PATH="$sdk/include/aarch64-linux-gnu:$sdk/include"
sanitize=()
if [ "${VDI_TEST_SANITIZE:-0}" = 1 ]; then
sanitize=(-fsanitize=address -g)
fi
g++ "${sanitize[@]}" -std=c++17 -fPIC -UNDEBUG "$b/latency-tests/test_latency.cpp" \
-I"$b/src/moonlight/app/streaming/input" \
-I"$b/src/moonlight/app/streaming/video/ffmpeg-renderers/pacer" \
-I"$b/runtime/include" $(pkg-config --cflags --libs Qt5Core sdl2) \
-L"$b/runtime/lib" -lavutil -o "$b/latency-tests/test_latency"
"$b/latency-tests/test_latency"
g++ "${sanitize[@]}" -std=c++17 -fPIC -UNDEBUG "$b/latency-tests/test_input_priority.cpp" \
-I"$b/src/moonlight/app/streaming/input" $(pkg-config --cflags --libs sdl2) \
-o "$b/latency-tests/test_input_priority"
"$b/latency-tests/test_input_priority"
gcc "${sanitize[@]}" -std=gnu11 -ffunction-sections -fdata-sections -Wl,--gc-sections -UNDEBUG \
-I"$b/src/moonlight/moonlight-common-c/moonlight-common-c/src" \
-I"$b/src/moonlight/moonlight-common-c/moonlight-common-c/enet/include" \
"$b/latency-tests/test_absolute_input.c" \
"$b/build/moonlight/moonlight-common-c/libmoonlight-common-c.a" \
-lpthread -lcrypto -o "$b/latency-tests/test_absolute_input"
"$b/latency-tests/test_absolute_input"

View File

@ -0,0 +1,105 @@
param(
[string]$SunshineLogPath = "",
[int]$MaxLogAgeMinutes = 30
)
# 只读验收脚本:不重启 VM、设备、VFIO 或 Sunshine,不修改任何配置。
# 退出码 0 才表示当前状态满足“可继续做串流性能验收”的前置条件。
$ErrorActionPreference = "Stop"
$ok = $true
function Report([string]$Name, [bool]$Passed, [string]$Detail) {
$state = if ($Passed) { "PASS" } else { "FAIL" }
Write-Output ("[{0}] {1}: {2}" -f $state, $Name, $Detail)
}
$nvidiaCommand = Get-Command nvidia-smi -ErrorAction SilentlyContinue
if ($null -eq $nvidiaCommand) {
Report "nvidia-smi" $false "命令不存在"
$ok = $false
} else {
$ErrorActionPreference = 'Continue'
$gpuText = & $nvidiaCommand.Source --query-gpu=name,driver_version,pstate --format=csv,noheader 2>&1
$queryExitCode = $LASTEXITCODE
$ErrorActionPreference = 'Stop'
if ($queryExitCode -ne 0 -or [string]::IsNullOrWhiteSpace(($gpuText -join ""))) {
Report "nvidia-smi" $false (($gpuText -join " ").Trim())
$ok = $false
} else {
Report "nvidia-smi" $true (($gpuText -join " ").Trim())
}
}
try {
$displayAdapters = @(Get-CimInstance Win32_VideoController |
Where-Object { $_.Name -match "NVIDIA|GeForce|Quadro|Tesla" })
$healthy = @($displayAdapters | Where-Object { $_.ConfigManagerErrorCode -eq 0 }).Count -gt 0
Report "NVIDIA PnP" $healthy (($displayAdapters | ForEach-Object { "$($_.Name): code=$($_.ConfigManagerErrorCode)" }) -join "; ")
$ok = $ok -and $healthy
if (-not ('VdiDiagnostics.D3DProbe' -as [type])) {
Add-Type -Path (Join-Path $PSScriptRoot 'probe-nvidia-d3d.cs')
}
$dxgi = @([VdiDiagnostics.D3DProbe]::Check())
$healthy = @($dxgi | Where-Object { $_.DeviceResult -eq 0 }).Count -gt 0
$detail = if ($dxgi.Count) { ($dxgi | ForEach-Object { '{0}: HRESULT=0x{1:X8}' -f $_.Name,$_.DeviceResult }) -join '; ' } else { 'DXGI did not enumerate an NVIDIA adapter' }
Report "NVIDIA DXGI + D3D11" $healthy $detail
$ok = $ok -and $healthy
} catch {
Report "NVIDIA DXGI + D3D11" $false $_.Exception.Message
$ok = $false
}
if ([string]::IsNullOrWhiteSpace($SunshineLogPath)) {
$candidates = @(
"C:\Program Files\Sunshine\config\sunshine.log",
"C:\ProgramData\Sunshine\config\sunshine.log"
)
$SunshineLogPath = $candidates | Where-Object { Test-Path -LiteralPath $_ } | Select-Object -First 1
}
if ([string]::IsNullOrWhiteSpace($SunshineLogPath) -or -not (Test-Path -LiteralPath $SunshineLogPath)) {
Report "Sunshine encoder" $false "找不到 sunshine.log;不能证明实际使用 h264_nvenc"
$ok = $false
} else {
# Encoder discovery/probing can mention both NVENC and x264. Inspect only
# the most recent actual creation, with a timestamp, never the entire history.
$pattern = '\[(?<time>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+)\].*Creating encoder \[(?<encoder>[^\]]+)\]'
$matches = [regex]::Matches((Get-Content -LiteralPath $SunshineLogPath -Raw), $pattern)
$healthy = $false
$detail = '没有实际编码器创建记录;请连接Moonlight并播放测试动画'
if ($matches.Count -gt 0) {
$entry = $matches[$matches.Count - 1]
$encoder = $entry.Groups['encoder'].Value
$createdAt = [datetime]::Parse($entry.Groups['time'].Value, [Globalization.CultureInfo]::InvariantCulture)
$ageMinutes = ((Get-Date) - $createdAt).TotalMinutes
$healthy = $encoder -eq 'h264_nvenc' -and $ageMinutes -ge 0 -and $ageMinutes -le $MaxLogAgeMinutes
$detail = '{0}, created {1}, age {2:N1} min' -f $encoder,$createdAt,$ageMinutes
}
Report "Sunshine active encoder" $healthy $detail
$ok = $ok -and $healthy
}
if ($nvidiaCommand) {
$ErrorActionPreference = 'Continue'
$activity = & $nvidiaCommand.Source --query-gpu=encoder.stats.sessionCount,utilization.encoder --format=csv,noheader,nounits 2>&1
$queryExitCode = $LASTEXITCODE
$ErrorActionPreference = 'Stop'
$healthy = $false
if ($queryExitCode -eq 0) {
foreach ($row in $activity) {
if ([string]$row -match '^\s*(\d+),\s*(\d+)\s*$') {
if ([int]$Matches[1] -gt 0 -and [int]$Matches[2] -gt 0) { $healthy = $true }
}
}
}
Report "NVENC session/utilization" $healthy ($activity -join '; ')
$ok = $ok -and $healthy
}
if ($ok) {
Write-Output "GPU/NVENC 前置验收通过:可以继续做 Moonlight 帧率与延迟测试。"
exit 0
}
Write-Output "GPU/NVENC 前置验收失败:不要把当前状态作为硬编码性能结果。"
exit 1