Repository navigation
Integrate reviewed v2.1 changes into main - #61
Merged
Merged
Conversation
added 30 commits
October 3, 2026 04:17
The video settings had grown into about fifteen interdependent controls, partly repeated in the toolbar, with hidden constraints (H.265 not over WebRTC, the tallest portrait profile only as H.265 Direct, H.264 not at 2304 lines, frame-rate caps per size) discovered only through errors or silent clamping, and the limits kept in three places. - lib/video-model.ts (pure, unit-tested): the capabilities the server reports, the draft being edited, the delivered frame rate, the monitor refresh that follows it, validation with reasons, presets, and what applying changes (EDID rewrite, player reload). - Profiles: Recommended, Sharpest, Smooth, Lowest latency, Compatible, Low traffic. Each adapts to the device and browser, keeps a portrait monitor and Cube/Lite receivers as they are, and states why it cannot apply. Settings that match none are Custom. - Settings > Video: input, stream and monitor summary (sizes, rates, codec, transport); profiles; Manual settings with the monitor (portrait profiles in the same list), the stream (transport, codec, resolution, FPS with the delivered rate, bitrate) and Advanced. Unavailable choices stay visible and disabled with the reason. Before applying, the page says when the monitor will switch (and to what) and when it reloads. - Shared settings are applied with one validated request (POST /api/vm/video); users still choose only the transport and the Direct playback of their own browser. - The toolbar menu shows what is streamed and switches profiles; its resolution/FPS/quality submenus and the unused codec, mode and frame-detection menus are removed. - H.265 over WebRTC: the browser decoder decides again (RTCRtpReceiver.getCapabilities), as before ad5750a. - docs/VIDEO.md describes profiles, refresh following the frame rate, the limits and the API. Measured on the device (2560x1440@50 source): Low traffic wrote NanoKVM-monitor-1080-30.bin, the source switched to 1920x1080 at 30 Hz and the encoder delivered 30 fps; restoring the previous settings brought the source back to QHD50. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Landscape rates: 720p 120/60/30, 1080p 100/75/60/30, 1440p 60/50/40/30, 2160p 30. 1080p100 and 1440p60 use CVT reduced blanking (235.5 and 241.5 MHz, within the 250 MHz range limit). - Auto (NanoKVM-final-video-profiles.bin) is 1920x1080 at 100 Hz; QHD and UHD become explicit choices. - Portrait profiles per rate, as landscape: 720x1280 120/60/30, 1080x1920 100/75/60/30, 1296x2304 and 1440x2560 60/50/30 (NanoKVM-portrait-<w>x<h>-<hz>.bin, CVT reduced blanking with the established portrait sync). The established files and timings keep their bytes. - 1080p120 was tried: at 285.5 MHz (1142 Mbit/s per MIPI lane) VI reported receive errors until the VIP clocks were raised to the vendor overdrive values, and the encoder then delivered about 109 fps, so 1080p is offered at 100 Hz (942 Mbit/s per lane, stock VIP clocks). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Frame-rate tiers (Go and capture_rate.hpp): 720p 120, 1080p 100, QHD 60, larger 30 fps. With the video overclock the encoder sustains about 250 Mpix/s (QHD60, UHD30); at 1080p a fixed per-frame cost limits it to about 109 fps, so 1080p is offered at 100. - The third VPSS buffer and pipelined encoding follow the pixel rate (size x fps above QHD50) instead of the size; a 64 MiB pool keeps two buffers at QHD, where a third does not fit. - Auto is 1920x1080 at up to 100 Hz wherever the EDID is written live; QHD and UHD are explicit choices. Portrait profiles follow the stream rate like landscape (1080x1920 up to 100, 1296x2304 and 1440x2560 up to 60 Hz); 1440x2560 H.265 is also offered over WebRTC. - Bitrate for motion, for every size and rate: about 0.05 bit per pixel with H.265 and 1.5 times that with H.264, rounded up to an offered value (adds 8 and 12 Mbit/s): 1080p100 12, QHD60 12, UHD30 15 Mbit/s. Presets derive it (Sharpest 20, Low traffic 1 stay fixed), the manual settings show it as a hint, and the factory default is 100 fps, 12 Mbit/s, matching Recommended. - Presets: Balanced (2560x1440 at 60) replaces Smooth (1080p75, now covered by Recommended). - docs/VIDEO.md updated. Measured (overclocked kernel, H.265, Chrome): 1080p100 input 100 Hz, encoder 100 fps, 98 delivered, stock VIP clocks, no VI errors; 2560x1440@60: 60 fps; 1080p120 (1142 Mbit/s per MIPI lane) needed the vendor overdrive VIP clocks and still delivered about 108 fps. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With the 128 MiB CMA pool, 3840x2160 failed on cold boots: the encoder could not allocate its last reference buffers (about 16 MiB) because Linux had borrowed the free CMA pages and they could not be migrated back (cma_alloc_fail grew, the native SendFrame failed, the copy fallback could not create its pool, and the channel was recreated in a loop). Two of four consecutive cold boots had no video; switching to 4K at run time worked. - A third boot image per board, <board>-uhd.sd: the same kernel with a 128 MiB fixed carveout. CMA stays the default; the 64 MiB fixed mode is unchanged. nanokvm-activate-kernel accepts "uhd". - 3840x2160 (monitor profile, stream limit, capture) needs a pool of at least 128 MiB that is not reusable: SupportsUHD in the server and check_res in libkvm. Elsewhere it is offered as unavailable with the "video-memory" reason, which now names the 4K memory mode. - The memory API lists the installed modes and reports the real pool size; the memory page offers CMA, Fixed 64 MiB and 4K 128 MiB. - zram gains an "auto" size, half of the Linux memory (API sizeMiB 0). The 4K mode leaves Linux about 105 MiB, so there it defaults to zram auto unless memory.conf says otherwise. Measured (pcie, 3840x2160@30 H.265, OpenSBI 1.9): CMA cold boots 2 of 4 with video; a 128 MiB fixed carveout booted with video, 117 MiB of video memory in use, no VB pool errors, MemTotal 104 MiB. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
/usr/lib/nanokvm/boot held a 9 MiB FIT for every board and video memory mode (133 MiB with the 4K mode). They share the kernel and initramfs and differ only in the device tree, so the package now carries one template, the device trees (padded to 32 KiB, one layout for all) and the SHA-256 of each image the build made: 9.5 MiB. - build.sh still runs mkimage for every image (images/boot-fit) and fit-layout.py checks that substituting the device tree and its image hash into the template reproduces each one byte for byte. - compose-fit (shell, dd and sha256sum) rebuilds an image on the device and replaces the output only when it matches the build's hash. nanokvm-activate-kernel and the personal image builder use it. - The FIT description no longer names the board, so all images have the same layout. - The server looks for <board>[-mode].dtb to list the video memory modes. Checked: compose-fit output equals mkimage's pcie-uhd image; activation tests cover the composed image, a corrupted device tree and the uhd mode. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Out-of-place requests made the H.265 + CryptoDMA hang rarer, not
impossible: 1920x1080@100 H.265 over WebRTC with hardware SRTP still hung
after 6 to 17 minutes. A device stand (HDMI capture, VPSS and H.265 encoding
from the application, 1250 AES-CTR requests of 1216 bytes per second) varied
the DMA_CTRL burst limits:
write burst 16 (vendor secure boot): mean time to hang about 48 s
write burst 6 (vendor Linux driver): about 78 s at 1080p100, 63 s at UHD
write burst 4: no hang in 15 min; no hang in 13 min
of 3840x2160 H.265 WebRTC
The encoder fed from memory without capture or scaling did not hang with
bursts of 6 in 10 minutes, and read-only (hash) requests never hung, so long
CryptoDMA writes into a DDR already busy with capture, scaling and encoding
are the trigger. Read bursts stay at 16. Throughput costs 2.6 %: 22371
instead of 22968 requests of 1216 bytes per second; 3840x2160 WebRTC uses
about 1500.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The kernel enables XTheadVector for user space. These patches from #46 (by Codex) make the T-Head vector state handling correct on the C906: - 0032: riscv_v_is_on() also checks the legacy XTheadVector status field. - 0033: vendor extension headers usable from assembly. - 0034: the trap entry clears the legacy vector status as well, so a preempted task cannot leave the vector unit enabled in the kernel. The opt-in vector kernel backends of #46 (usercopy, checksums, ChaCha, CRC; 0036/0037) and their tools are not included: on the NanoKVM they did not help. Loopback TCP with the vector usercopy measured 33.8 MiB/s against 34.5 without it; the kernel copies sockets, pipes and files in 4 KiB pages, below its 16 KiB threshold. #46's own WireGuard comparisons showed no general gain either. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
0039 adds CONFIG_RISCV_C906_LZ4_DECOMPRESS: the LZ4 decompressor copies complete wild-copy spans with aligned 64-bit loads and stores on the C906, keeping the forward order for overlapping matches. Enabled in the NanoKVM kernel. tools/c906-lz4 holds the qualification tools. Same code as in #47; its Kconfig hunk is regenerated for a tree without the #46 vector backends, which it used as context. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review of #59: - The full SD image builder still required usr/lib/nanokvm/boot/detect.sd, which the compact kernel package no longer has. It now composes boot.sd with compose-fit. test-alpine-sd-image-boot.py runs the builder on a compact-layout fixture (stub f2fs tools) and checks the FAT boot.sd; it fails without this change. - The zram switch and the recompression switch sent the computed Auto size (for example 52 MiB), which the API rejects, or turned Auto into a manual size when it matched an offered one. Both send 0 for Auto now (swapRequestSize, with tests). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
4K video memory mode (128 MiB fixed) and a 10 MiB kernel boot payload
Video settings: profiles, capabilities, refresh following fps, H.265 WebRTC
Release line: remove private data, keep watchdog across app restarts, out-of-place CryptoDMA
perf(rustdesk): reuse framing buffers and detached XSalsa20-Poly1305 (split from #47)
c906: XTheadVector context fixes and aligned LZ4 decompression (replaces #46)
3840x2160 at up to 30 fps with a video overclock
dormancygrace
added a commit
that referenced
this pull request
Oct 6, 2026
Integrate reviewed v2.1 changes into main
dormancygrace
added a commit
that referenced
this pull request
Oct 6, 2026
Integrate reviewed v2.1 changes into main
dormancygrace
added a commit
that referenced
this pull request
Oct 6, 2026
Integrate reviewed v2.1 changes into main
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Consolidate the existing v2.1 release branch and the reviewed changes from #52, #53, #55, #56 and the #57–#59 stack into main, retaining the dependency updates already merged into main.
The combined change includes the out-of-place/burst-4 CryptoDMA fix, watchdog lifecycle fixes, RustDesk framing buffer reuse, C906 vector-context and aligned LZ4 changes, and the video/4K memory and compact boot-payload work.
Integration fixes:
Validation of the final combined tree:
-tags teststubpassed.No full production firmware rebuild, device installation or new hardware soak test is claimed by this integration. Obsolete remote branches are removed after consolidation; v3 remains a separate development branch. No archival tags are retained, as requested.