Skip to content

feat(windows): RemoteIdd capture backend and WebRTC pairing kind - #4

Merged
mlopezsegura merged 5 commits into
masterfrom
feature/remote-idd
Oct 30, 2026
Merged

mlopezsegura merged 5 commits into
masterfrom
feature/remote-idd

Conversation

@mlopezsegura

@mlopezsegura mlopezsegura commented Oct 30, 2026 •

Copy link
Copy Markdown
Collaborator

Description

Sunshine side of OpenStreamMS RemoteIdd, the seat display driver, plus the latest master.

  • RemoteIdd capture backend (capture = remoteidd, Windows): reads the frames that the OpenStreamMS RemoteIdd driver publishes through a shared texture, instead of duplicating a desktop. It is only used when explicitly requested, never by auto-detection.
  • Frames sent as they arrive, capped at the client's fps, so a seat composed at 250 Hz is not resampled.
  • User token when running as SYSTEM: RemoteIdd capture runs Sunshine as SYSTEM inside the seat session; apps are launched with that session's user token, not the console's.
  • Pairing kind in GET /api/pin: each pending pairing carries kind (moonlight or webrtc), so a frontend can tell a Moonlight client from a Moonlight WebRTC TV waiting for a PIN.
  • Merge of the current origin/master (upstream LizardByte changes up to 2026-10-30), no conflicts.

Screenshot

Issues Fixed or Closed

Roadmap Issues

Testing

  • Built sunshine and test_sunshine with msys2 UCRT64 (Release, cmake-build-webrtc).
  • test_sunshine --gtest_filter='ConfigHttpTest.*:*WebRtc*:*Webrtc*:*TvAuth*:*webrtc*': 93 tests passed. PairingRestApiListsAuthenticatedPendingRequests now checks kind.
  • The webrtc kind has no automated test: it needs the WebRTC TV signaling server running.
  • RemoteIdd capture was validated manually on a real OpenStreamMS seat, including the UAC secure desktop.
  • The full test suite and lb-update-clang-format were not run.

Type of Change

  • feat: New feature (non-breaking change which adds functionality)
  • fix: Bug fix (non-breaking change which fixes an issue)
  • docs: Documentation only changes
  • style: Changes that do not affect the meaning of the code (white-space, formatting, missing semicolons, etc.)
  • refactor: Code change that neither fixes a bug nor adds a feature
  • perf: Code change that improves performance
  • test: Adding missing tests or correcting existing tests
  • build: Changes that affect the build system or external dependencies
  • ci: Changes to CI configuration files and scripts
  • chore: Other changes that don't modify src or test files
  • revert: Reverts a previous commit
  • BREAKING CHANGE: Introduces a breaking change (can be combined with any type above)

Checklist

  • Code follows the style guidelines of this project
  • Code has been self-reviewed
  • Code has been commented, particularly in hard-to-understand areas
  • Code docstring/documentation-blocks for new or existing methods/components have been added or updated
  • Tests have been added or updated for new or modified functionality, including regression tests for bug fixes

AI Usage

See our AI usage policy.

  • AI tools were used while preparing this PR

This pull request was generated by Claude Code, Claude Opus 5.5

🤖 Generated with Claude Code

mlopezsegura and others added 5 commits October 26, 2026 23:50
New capture method "remoteidd" for OpenStreamMS seats. Instead of Desktop
Duplication or WGC, it reads the frames that the OpenStreamMS RemoteIdd
display driver publishes for the current session: a shared texture (NT handle
+ keyed mutex) announced through a named slot with a seqlock. The texture is
copied into the capture image and released right away, so the driver never
waits for the encoder.

- Only selected with capture = remoteidd; never part of auto-detection.
- Requires a hardware encoder and SDR (IddCx 1.4 swapchains are 8-bit BGRA).
- src/platform/windows/remoteidd/ is a copy of the contract and consumer from
  OpenStreamMS/Native/RemoteIdd; change it there and copy it back.
- Tests: hand-off across devices, texture recreation on resize, publisher
  never blocking on a busy consumer, and the real backend capturing a 240 Hz
  producer (481/480 frames, no reinit).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
When the display refreshes much faster than the client asks for (an RDP seat
composing at 250 Hz for a 60 fps stream), pacing by display ticks repeats or
drops frames. Capture each frame when it arrives and cap the rate with
frame_rate_limiter_t; hold back a frame that comes too early.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Running as SYSTEM inside an RDP seat (needed for the RemoteIdd backend),
retrieve_users_token took the console session's user. Use the session the
process runs in, and fall back to the console only from session 0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each pending pairing listed by GET /api/pin now carries a kind:
"moonlight" for a Moonlight client and "webrtc" for a Moonlight WebRTC
TV, so a frontend can say which device is waiting for a PIN.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@mlopezsegura

Copy link
Copy Markdown
Collaborator Author

This pull request was generated by Claude Code, Claude Opus 5.5

@mlopezsegura
mlopezsegura merged commit 897a3b4 into master Oct 30, 2026
3 checks passed
@mlopezsegura
mlopezsegura deleted the feature/remote-idd branch October 30, 2026 21:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant