Moonlight Embedded is an open source client for Sunshine and NVIDIA GameStream for embedded Linux systems, like Raspberry Pi, CuBox-i and ODROID. Moonlight allows you to stream your full collection of games and applications from your PC to other devices to play them remotely.
Moonlight also has PC, Android, and iOS clients.
More information about installing and running Moonlight Embedded is available on the wiki.
Please check the wiki and old bug reports before submitting a new bug report.
Bugs can be reported to the issue tracker.
Moonlight-common-c is the shared codebase between different Moonlight implementations
- Fork us
- Write code
- Send Pull Requests
This adds a hardware-accelerated video backend for embedded Linux devices that use the V4L2 stateless Request API for hardware decode and KMS/DRM atomic modesetting for display. Tested on RK3399 (rkvdec) running LibreELEC.
Network → moonlight-embedded decode thread
↓
FFmpeg (codec: h264/hevc)
hwaccel: AV_HWDEVICE_TYPE_DRM
get_format → AV_PIX_FMT_DRM_PRIME
↓
V4L2 Request API (rkvdec / hantro / cedrus)
/dev/media0 + /dev/video2
↓
AVDRMFrameDescriptor (NV12 dma-buf)
↓ av_frame_clone (holds buffer ref across vsync)
Display thread (separate from decode thread)
↓
drmModeAtomicCommit (blocking, overlay plane)
card1 / Rockchip VOP / KMS atomic
The decode thread is non-blocking — it pushes frames to a single-slot queue and immediately returns. The display thread blocks on vsync, ensuring the network/control pipeline is never stalled by display timing.
av_frame_clone is used to hold a reference to the DRM PRIME buffer while it
is being scanned out by the display controller. Releasing the frame before the
next vsync causes the buffer to be returned to the V4L2 pool while it is still
on-screen, producing black flicker on every other frame.
On startup, all active KMS planes on the CRTC except the video overlay are blanked (FB_ID=0 AND CRTC_ID=0 in the same atomic commit) to hide the Linux framebuffer console.
Any device where:
- FFmpeg can use
AV_HWDEVICE_TYPE_DRMwith a V4L2 Request API decoder - The kernel exposes a DRM/KMS atomic interface
Known working:
- RK3399 (rkvdec) — H.264, HEVC via
/dev/media0+/dev/video2 - Should work on any device supported by LibreELEC's patched FFmpeg with V4L2 Request hwaccel (RK3588, Allwinner, Amlogic with appropriate kernel)
The backend probes /dev/media* and /dev/video* at runtime to find a
device that supports the requested pixel format — no hardcoded paths.
Requires: libdrm, libavcodec, libavutil (with DRM hwaccel support)
cmake -DENABLE_FFMPEG_DRM=ON ...CMakeLists.txt checks for DRM_LIBRARY and AVCODEC_FOUND before enabling
the backend. If the system FFmpeg lacks DRM hwaccel support, it will be
skipped silently.
| Metric | Result |
|---|---|
| Decode time | ~2.7 ms average (rkvdec) |
| Frame drops | 0.00% |
| Network latency | 1 ms |
CPU load during streaming is minimal — all decode is handled by rkvdec, display is a single drmModeAtomicCommit per frame.
src/video/ffmpeg_drm.c— new backend (this file)src/platform.h— addedFFMPEG_DRMto platform enumsrc/platform.c— dispatch forFFMPEG_DRMinplatform_check,platform_get_video,platform_prefers_codec,platform_namesrc/video/video.h— extern declaration fordecoder_callbacks_ffmpeg_drmCMakeLists.txt—ENABLE_FFMPEG_DRMoption, updatedFATAL_ERRORguard to not require legacy backends whenFFMPEG_DRMis available
moonlight stream -platform ffmpeg_drm -app "Desktop"Or set it as the default in moonlight.conf:
[Moonlight]
platform = ffmpeg_drm