Skip to content

feat: streaming#182

Merged
ReenigneArcher merged 19 commits into
masterfrom
dev2
May 24, 2026
Merged

feat: streaming#182
ReenigneArcher merged 19 commits into
masterfrom
dev2

Conversation

@ReenigneArcher
Copy link
Copy Markdown
Member

@ReenigneArcher ReenigneArcher commented Apr 20, 2026

Description

This PR adds the initial streaming.

TODO:

  • change stats overlay to display stats at end of stream... this is because with the overlay enabled the performance is very bad
  • fix sonar issues
  • fix CI builds

Screenshot

Issues Fixed or Closed

Roadmap Issues

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
  • Unit tests have been added or updated for any new or modified functionality

AI Usage

  • None: No AI tools were used in creating this PR
  • Light: AI provided minor assistance (formatting, simple suggestions)
  • Moderate: AI helped with code generation or debugging specific parts
  • Heavy: AI generated most or all of the code changes

Move video decode work off the render loop by adding a prioritized SDL worker thread for video decoding and refactor decode logic. Introduce run_video_decode_thread, decode_video_decode_unit, receive/publish helpers, packet buffering and frame-versioning to avoid unnecessary copies and only upload textures when a new frame or size change occurs. Expose submit_video_decode_unit as a thin wrapper and mark pull-renderer capability; add proper start/stop/join handling for the decoder thread. Add controllerMutex and a separate input polling thread to safely read/send controller snapshots and detect stream-exit combo (with a fallback poll when the thread can't start). Misc: SDL texture/format handling, resource cleanup updates, and various safety/validation checks and logging.
Move/rename the existing .github/copilot-instructions.md file to AGENTS.md. File contents are unchanged (100% similarity); this is purely a rename to relocate or rebrand the instructions file.
Update streaming defaults and improve video decode handling for lower-latency playback.

Key changes:
- Change default stream settings: framerate moved from 20 -> 30 and bitrate from 1500kbps -> 1000kbps (client_state, settings_storage, session constants and tests updated).
- Reduce exposed stream resolution presets and favor low-latency small presets (startup/video_mode.cpp) and simplify default selection to pick low-latency NTSC/PAL presets. Unit tests updated accordingly.
- Add decode-queue dropping support: new drop_queued_video_decode_units, has_unrendered_video_frame, droppedDecodeUnitCount counter, and logging for dropped frames (ffmpeg_stream_backend.{cpp,h}). The video decode loop now drops queued decode units before decoding and requests IDR when needed.
- Improve FFmpeg codec behavior by setting low-delay / output-corrupt flags, fast/show-all flags, and stricter error recognition; zero dropped count on reset and include dropped counts in overlay status.
- Tweak render loop timing: faster present polling when decoded video exists and performance overlay is disabled; adjust default packet size to 1392.

Files touched include src/app/*, src/startup/video_mode.cpp, src/streaming/ffmpeg_stream_backend.* and src/streaming/session.cpp, plus tests reflecting the new defaults and presets.
Introduce a mutex to logging::Logger and guard getters, setters and log paths (added should_log_unlocked) to make logging safe for concurrent use; add a unit test to verify bounded retained buffer under concurrent logging. Add NXDK-specific direct framebuffer presentation: new helpers (build_unscaled_destination, rectangles_match, xbox framebuffer format/bytes helpers), a render_latest_video_frame_to_framebuffer path, presentScaleContext and bookkeeping fields in VideoState, and attempt direct presentation when allowed. Also filter/normalize noisy connection logs in session (high-volume message suppression and connection_log_level) and update render_latest_video_frame API to accept an allowDirectFramebuffer flag with a default. Misc: free presentScaleContext on reset and minor includes/headers updates.
Add a new playAudioOnXbox setting with UI/menu toggle and persistence (default: false). Wire the new setting through client state, settings storage, main startup, and unit tests.

Enhance FFmpeg/streaming behavior to support disabling Xbox-side audio decode/playback: add FfmpegStreamBackend::set_audio_playback_enabled, short-circuit Opus decode when disabled, expose capability flags, and avoid unnecessary audio work. Improve audio buffering by reusing an output buffer vector and tracking queued bytes.

Make several decoder and runtime improvements to reduce latency and robustness: lower FFmpeg log level and ignore a noisy message, add codec skip flags, yield briefly in the decoder loop, track per-frame decode timing/queue/age and expose it in the overlay, request IDR frames after idle video periods, adjust thread priorities (scoped RAII helper), and change default packet size.

Also: expand stream bitrate options and introduce DEFAULT_STREAM_BITRATE_KBPS constant; minor UI text tweak and updated unit tests to account for the new setting.
Switch video timestamping from SDL ticks to platform microseconds (PltGetMicroseconds): rename lastDecodedFrameTicks -> lastDecodedFrameUs, change milliseconds_since_last_decoded_video_frame to accept microseconds, and persist microsecond timestamps. Tighten decode logic: avoid decoding non-IDR frames after dropped frames, mark need for IDR, and append "waiting_for_idr" to drop logs. Remove unused build_unscaled_destination and use build_letterboxed_destination for rendering. Add presentation helpers: select_stream_presentation_video_mode and ScopedStreamVideoMode (NXDK-only) to optionally switch output mode for stream presentation and use the active mode when initializing UI resources and configuring stream launch parameters. Minor reorder of idle/IDR checks to use the new time API.
Switch stream-resolution settings from fixed presets to detected Xbox video modes and add encoder-aware filtering. Introduces filter_stream_video_modes_for_encoder_settings() to hide SD wide-width modes unless VIDEO_WIDESCREEN is set, and overloads choose_default_stream_video_mode() to prefer a detected mode (or smallest available) with a canonical fallback. initialize_stream_video_mode_settings() now accepts encoder settings and handles empty mode lists, and select_stream_presentation_video_mode() is simplified to use the chosen stream mode when available. Updated comments/labels and adjusted unit tests to match new mode list, defaults, and behavior.
@LizardByte LizardByte deleted a comment from sonarqubecloud Bot May 23, 2026
Add explanatory comments for several compatibility macros in ffmpeg_compat.h and share.h (ENOSYS, O_BINARY, F_SETFD, FD_CLOEXEC, CP_ACP, CP_UTF8, MB_ERR_INVALID_CHARS, WC_ERR_INVALID_CHARS, SH_DENYNO) to clarify their purpose for FFmpeg/nxdk builds. Also add an extern "C" declaration (with doc comment) for PltGetMicroseconds in ffmpeg_stream_backend.cpp and session.cpp so the platform monotonic clock is visible to moonlight-common-c. These are documentation and forward-declaration changes to improve maintainability and cross-module compatibility; no behavioral changes intended.
Rename cmake variables to explicit *wrapper* names and set ffmpeg_cc_shell_path / ffmpeg_cxx_shell_path to invoke the wrapper via `sh`. Update ffmpeg-nxdk-cc.sh and ffmpeg-nxdk-cxx.sh to correctly handle `-o` and `-o<file>` forms, create output directories when needed, touch the output file, and try to mark it executable. These changes ensure the nxdk ffmpeg wrappers are invoked reliably and produce expected output files during build.
@codecov
Copy link
Copy Markdown

codecov Bot commented May 23, 2026

Codecov Report

❌ Patch coverage is 70.05814% with 103 lines in your changes missing coverage. Please review.
✅ Project coverage is 63.05%. Comparing base (62f0e7d) to head (f215558).
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
src/network/host_pairing.cpp 61.60% 7 Missing and 41 partials ⚠️
src/app/client_state.cpp 54.36% 23 Missing and 24 partials ⚠️
src/app/settings_storage.cpp 92.15% 0 Missing and 4 partials ⚠️
src/startup/video_mode.cpp 90.47% 1 Missing and 3 partials ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #182      +/-   ##
==========================================
+ Coverage   62.41%   63.05%   +0.64%     
==========================================
  Files          32       32              
  Lines        4898     5235     +337     
  Branches     2185     2385     +200     
==========================================
+ Hits         3057     3301     +244     
- Misses        910      931      +21     
- Partials      931     1003      +72     
Flag Coverage Δ
Linux 63.38% <71.91%> (+0.73%) ⬆️
macOS 49.96% <47.70%> (-0.04%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/app/client_state.h 97.87% <100.00%> (+0.37%) ⬆️
src/logging/logger.cpp 79.32% <100.00%> (+1.39%) ⬆️
src/logging/logger.h 80.00% <ø> (ø)
src/network/host_pairing.h 0.00% <ø> (ø)
src/streaming/stats_overlay.cpp 100.00% <ø> (ø)
src/app/settings_storage.cpp 75.19% <92.15%> (+8.03%) ⬆️
src/startup/video_mode.cpp 60.71% <90.47%> (+29.76%) ⬆️
src/app/client_state.cpp 66.98% <54.36%> (-1.11%) ⬇️
src/network/host_pairing.cpp 45.46% <61.60%> (+1.59%) ⬆️

Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 62f0e7d...f215558. Read the comment docs.

Modularize and clean up streaming and session code: extract helper structs and functions in session.cpp (StreamStartAttemptContext, ActiveStreamLoopContext, TextLineLayout), add assign_status_message, and split stream startup and active-loop logic into run_stream_start_attempt, run_stream_start_with_rtsp_fallback, run_active_stream_loop and related helpers. Improve controller handling (open/close helpers, fallback polling), implement RTSP session URL fallback retry, and centralize input-thread lifecycle and rendering/polling behavior.

Also applied numerous style and safety improvements across the codebase: use if-with-init and compact conditionals, add NOSONAR annotations to silence specific static analysis warnings in ffmpeg_stream_backend, make several const-correctness and type simplifications (remove unnecessary casts), refactor render_text_line to accept a layout struct, and minor cleanups in main.cpp, host_pairing.cpp, ffmpeg_stream_backend.{cpp,h}, and ui/shell_screen.cpp. These changes are intended to improve readability, maintainability, and static-analysis cleanliness without changing external behavior.
Unset the MSYS2_ARG_CONV_EXCL environment variable in the cmake nxdk ffmpeg preparation and in both ffmpeg-nxdk-cc.sh and ffmpeg-nxdk-cxx.sh scripts. This prevents MSYS2 argument/path conversion from interfering with nxdk/FFmpeg build steps and helps ensure consistent behavior in the build environment.
Update session.cpp to accept std::string_view in assign_status_message and use string::assign to copy the view, improving clarity and avoiding implicit conversions. Add copy_controller_device_event to safely copy SDL controller device events and use it in pump_stream_events when opening/closing controllers. Simplify StreamStartAttemptContext usage by moving its initialization into an if-with-initializer. In tests, add expect_unique_id_request, expect_unauthenticated_unique_id_request, and expect_authenticated_unique_id_request helpers and refactor repetitive EXPECT_* checks to use these helpers for clearer, less duplicated assertions.
Modularize and harden the FFmpeg-for-Xbox build logic: extract validation, revision/signature computation, shell path conversion, configure-args composition, Windows MSYS2 command runner, and the rebuild routine into helper functions. The main moonlight_prepare_xbox_ffmpeg now validates inputs, computes a rebuild signature from sources and wrapper files, and only rebuilds when needed. Also make MSYS2 configure invocation more robust in GetOpenSSL by concatenating the configure script, and tighten CMake formatting. Update ffmpeg wrapper scripts to set CDPATH='' when resolving script_dir to avoid unexpected path resolution behavior on some shells.
Replace direct WIN32 checks with CMAKE_HOST_WIN32 across CMake scripts and centralize MSYS2 shell lookup. Calls to the hardcoded C:/msys64/msys2_shell.cmd were removed in favor of _moonlight_get_windows_msys2_shell, and several nxdk-related functions now use CMAKE_HOST_WIN32 to detect a Windows host. Modified files: cmake/moonlight-dependencies.cmake, cmake/msys2.cmake, cmake/nxdk.cmake. This makes host detection and MSYS2 resolution more robust (e.g. when cross-compiling) and avoids embedding a fixed MSYS2 path.
Add an end-of-stream performance summary display and update related settings/labels. This change introduces rendering helpers (render_text_lines, render_stream_end_statistics_frame, show_stream_end_statistics) plus a polling loop to wait for user input before leaving the summary screen. The in-stream overlay handling was simplified (removed per-frame overlay blend) and stream-frame rendering calls were updated to the new signature that uses StreamUiResources. A new poll interval constant (STREAM_END_STATS_POLL_MILLISECONDS) was added. Settings text and persistence comment for show_performance_stats were updated to reflect the new end-of-stream semantics, and playAudioOnXbox default was changed to true; unit tests adjusted accordingly. Misc docs/comments were tweaked to match the new behavior.
Add tests to increase coverage for settings UI, storage defaults, and stats formatting:

- tests/unit/app/client_state_test.cpp: add DisplaySettingsCanToggleXboxAudioAndEndStreamStats to verify toggling "Play Audio on Xbox" and "Show End Stream Stats" updates state, status messages, and persistence flags.
- tests/unit/app/settings_storage_test.cpp: include playAudioOnXbox in the saved defaults and assert loaded value is false.
- tests/unit/streaming/stats_overlay_test.cpp: add FormatsPartiallyAvailableMetricGroups to validate overlay line formatting when some metrics are missing.

These tests ensure toggles, default persistence, and stats overlay formatting behave correctly with partial data.
@sonarqubecloud
Copy link
Copy Markdown

Introduce 60 FPS streaming support and related behavior changes. Added DEFAULT_STREAM_FRAMERATE (30) and extended STREAM_FRAMERATE_OPTIONS to include 60; initialize settings.streamFramerate from the default constant and make cycle_stream_framerate fall back to the default when the current value is invalid. Bumped MAX_STREAM_FPS to 60 in the streaming session constants. Updated unit tests to expect the default 30 FPS and added a test that verifies cycling includes 60 FPS and that invalid values reset to the default.
@ReenigneArcher ReenigneArcher merged commit 7465b91 into master May 24, 2026
15 checks passed
@ReenigneArcher ReenigneArcher deleted the dev2 branch May 24, 2026 02:07
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