#590

Eclipse co-op host support (GPU HEVC co-op encoder hooks, Co-op Pane, co-op tuning, Quit for Remote Monitor/Input)

DraftPreceptorOfMagicwants to merge intofrom

Hi Nonary, thank you for Vibepollo. Someone asked whether our host additions work with Vibepollo, so we built them on Vibepollo 2.0.0 and are offering the functional part back here. None of our naming or branding is included — no product names, artwork, web UI, installer text or update-check changes.

Context

Eclipse is a Moonlight client (LG webOS TVs, Windows and Linux) that can stream two PCs into one screen for couch co-op, as well as ordinary single-PC streaming. Eclipse was called Aurora until September 2026 — which is why some identifiers in this change (auroraGpuHevc, aurora-link.exe, [AURORA-…] log tags) still use that name: they are what Eclipse clients send or read, so they are kept as-is. The same goes for umbraCoop, umbraMonitorOff and UmbraCaps, named after Umbra, Eclipse's Apollo-based host.

Announcement and discussion: https://www.reddit.com/r/MoonlightStreaming/s/pcGJPZ02bf

Why co-op needs a custom encoder

Eclipse composes the two hosts into one HEVC picture: each host encodes its half of the screen as a slice, and the client splices the slices together under a single SPS/PPS. That only decodes if both encoders agree on every field the decoder reads — above all the CTB size. NVENC codes HEVC with 32×32 CTBs and AMD's AMF with 64×64, and neither exposes a way to change it. We measured this in a live co-op run: a 3840×1088 pane was 120×34 CTBs from NVENC and 60×17 from AMF, and the AMD pane could not be spliced at all.

So mixed-vendor (NVIDIA + AMD) and AMD + AMD co-op use a GPU HEVC co-op encoder (built separately from Eclipse's repository, GPL-3.0) that codes CTB32 / minCB16 on any GPU. Here it is an encode device that is used only when a session asks for it (auroraGpuHevc=1) and only if the encoder DLLs are installed in gpu-hevc\ (packaging option SUNSHINE_GPU_HEVC_DIR, off by default). Ordinary streams never touch it.

What this adds

Everything below is inert unless a client asks for it, except the items under General behaviour changes.

  • GPU HEVC co-op encode device (gpu_hevc_device.inc, aurora_gpu_hevc.h, hooks in video.cpp / display_vram.cpp / rtsp.cpp), plus a clean restart when its GPU runtime is lost after sleep.
  • Built-in "Co-op Pane" app (virtual display), hidden from /applist unless the client sends umbraCoop=1 or it is running; resumed panes are resized to the new request.
  • Per-launch co-op tuning (umbraCoop=1 only): periodic GOP (gop_length), NVENC constrained encoding / one slice per CTB row / H.264 Main profile options, AMF intra refresh option (amd_intra_refresh_mb, unset = off).
  • serverinfo: UmbraCaps (feature bits Eclipse checks) and SessionLocked; /umbralog: the tail of the host log for a paired client's support bundle, with secret-looking lines removed.
  • Wired-NIC pinning (auroraWiredMac, reverted when the session ends) and host monitor off while streaming (umbraMonitorOff, restored when the last client leaves).
  • Capture-loss recovery: re-asserts the session's display mode after repeated ACCESS_LOST.
  • Eclipse Link (aurora-link.exe): Eclipse's host companion (controller bridge, audio-cable visibility), installed with the application and its own "Eclipse Link" firewall exclusion.

General behaviour changes (please review)

  • /cancel (Quit) releases the caller's Remote Monitor / Remote Input role, the way the Disconnect Monitor / Disconnect Input controls do. Before, a client whose session was Remote Monitor got cancel=1 while the role stayed held, so a client without those control tiles could not end it.
  • FFmpeg AMF (amdvce_ffmpeg): restores ffmpeg's own loop-filter default (the ctx->flags = 0 reset turned deblocking off), and uses a 2-frame VBV instead of 1 frame (AMD documents 1.1–3 frames for LCVBR).
  • Built-in apps (Virtual Display, Co-op Pane) receive the global prep/state commands, like apps.json apps.
  • Client do/undo commands run without a console window.

Testing

  • Built and packaged on Windows x64 (MSYS2 UCRT64, Vibepollo's CI configure) as part of our Vibepollo-based host, and installed on three PCs (RTX 4070, RTX 3070, Radeon RX Vega).
  • This branch is the same code applied to current master (f0078288): a full build of all targets with Vibepollo's CI configuration (MSYS2 UCRT64, WebRTC on, .NET 10 SDK for the Playnite plugin) succeeds on Windows x64.
  • Tested live on those three PCs streaming to Eclipse on an LG TV, as our Vibepollo-based release (2.0.0-umbra.1); the issues found there are fixed in this branch and no further issues were found.
  • Opened as a draft so you can see the scope first. Happy to split it into smaller PRs (for example the /cancel fix and the AMF changes on their own) if you prefer.

🤖 Generated with Claude Code

https://claude.ai/code/session_01HMexTBKmK5T2K6eB8HSDco

Activity

1

This pull request is a draft

Merging is unavailable until it is marked ready for review.