功能:支持真实 2K 串流与重启持久化并优化渲染
变更详情:真2K串流与重启持久化,优化客户端渲染和帧率配置 三端统一2560x1440,盒子使用297MHz HDMI时序并保留1080p回退;Windows脚本动态定位VDD恢复2K。串流默认2K20/30Mbps,使用GLES2,设置页支持20/24FPS及自定义值。保持Windows正常光标,记录NVENC阶段性实测和GPU重启后Code43未恢复的限制。
This commit is contained in:
1 parent
4f9565a768
commit
e47b01beec
11 files changed
+198
-36
No files matched your search
@@ -19,14 +19,14 @@ ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$BOX" 'rm -rf ~
|
||||
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"/tests/*.cpp "$BOX":~/vdi-build/repo/kiosk-shell/tests/
|
||||
scp -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$SRC/scripts/vdi-moonlight" "$BOX":~/vdi-terminal/bin/vdi-moonlight
|
||||
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/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'
|
||||
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
|
||||
|
||||
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; chmod +x ~/vdi-terminal/bin/vdi-moonlight; 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 "==> 安装二进制"
|
||||
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/'
|
||||
@@ -35,7 +35,7 @@ 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'
|
||||
|
||||
echo "==> 启动受管栈并验证"
|
||||
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$BOX" 'rm -f /tmp/vdi-kiosk.heartbeat; nohup env DISPLAY=:0 XAUTHORITY=/home/armbian/.Xauthority /home/armbian/vdi-terminal/bin/vdi-kiosk-monitor -- /home/armbian/vdi-terminal/bin/kiosk-shell > /tmp/vdi-monitor.log 2>&1 & sleep 8; echo "--- 进程 ---"; pgrep -af "vdi-kiosk-monitor|kiosk-shell|moonlight-qt" | grep -v pgrep; echo "--- 看门狗日志 ---"; tail -5 /tmp/vdi-monitor.log; echo "--- 心跳 ---"; cat /tmp/vdi-kiosk.heartbeat 2>/dev/null; echo'
|
||||
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$BOX" 'rm -f /tmp/vdi-kiosk.heartbeat; nohup env DISPLAY=:0 XAUTHORITY=/home/armbian/.Xauthority /home/armbian/vdi-terminal/bin/vdi-kiosk-start > /tmp/vdi-monitor.log 2>&1 & sleep 8; echo "--- 进程 ---"; pgrep -af "vdi-kiosk-monitor|kiosk-shell|moonlight-qt" | grep -v pgrep; echo "--- 看门狗日志 ---"; tail -5 /tmp/vdi-monitor.log; echo "--- 心跳 ---"; cat /tmp/vdi-kiosk.heartbeat 2>/dev/null; echo'
|
||||
|
||||
echo "==> 抓屏确认当前界面(应为桌面列表)"
|
||||
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$BOX" 'DISPLAY=:0 xwd -root -silent' 2>/dev/null | python "$REPO/tools/xwd2png.py" /tmp/kiosk-login.png && echo "captured /tmp/kiosk-login.png"
|
||||
@@ -0,0 +1,81 @@
|
||||
$ErrorActionPreference = 'Stop'
|
||||
Add-Type @'
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
public static class VdiDisplayMode {
|
||||
[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() {
|
||||
for (uint i = 0; ; i++) {
|
||||
var d = new Device();
|
||||
d.cb = Marshal.SizeOf(typeof(Device));
|
||||
if (!EnumDisplayDevices(null, i, ref d, 0)) return null;
|
||||
if ((d.Flags & 1) != 0 && d.Description.IndexOf("Virtual Display Driver", StringComparison.OrdinalIgnoreCase) >= 0)
|
||||
return d.Name;
|
||||
}
|
||||
}
|
||||
public static string Current(string name) {
|
||||
var m = new Mode();
|
||||
m.size = (short)Marshal.SizeOf(typeof(Mode));
|
||||
if (!EnumDisplaySettings(name, -1, ref m)) return "unavailable";
|
||||
return m.width + "x" + m.height + "@" + m.hz;
|
||||
}
|
||||
public static int Apply(string name) {
|
||||
for (int i = 0; ; i++) {
|
||||
var m = new Mode();
|
||||
m.size = (short)Marshal.SizeOf(typeof(Mode));
|
||||
if (!EnumDisplaySettings(name, i, ref m)) return -99;
|
||||
if (m.width == 2560 && m.height == 1440 && m.hz == 30) {
|
||||
m.fields = 0x80000 | 0x100000 | 0x400000;
|
||||
int test = ChangeDisplaySettingsEx(name, ref m, IntPtr.Zero, 2, IntPtr.Zero);
|
||||
if (test != 0) return test;
|
||||
return ChangeDisplaySettingsEx(name, ref m, IntPtr.Zero, 1, IntPtr.Zero);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
'@
|
||||
$log = 'C:/ProgramData/VDI/set-2k-result.txt'
|
||||
try {
|
||||
for ($i = 0; $i -lt 12; $i++) {
|
||||
$dev = [VdiDisplayMode]::Find()
|
||||
if ($dev) {
|
||||
$result = [VdiDisplayMode]::Apply($dev)
|
||||
$mode = [VdiDisplayMode]::Current($dev)
|
||||
if ($result -eq 0 -and $mode -eq '2560x1440@30') {
|
||||
"$(Get-Date -Format o) device=$dev result=0 mode=$mode" | Set-Content $log
|
||||
exit 0
|
||||
}
|
||||
}
|
||||
Start-Sleep 5
|
||||
}
|
||||
throw "2K mode not applied: device=$dev result=$result mode=$mode"
|
||||
} catch {
|
||||
"$(Get-Date -Format o) ERROR $_" | Set-Content $log
|
||||
exit 1
|
||||
}
|
||||
Reference in new issue
Block a user