Dawn Stream building for real media
Without CMake media gates, Dawn Stream uses a stub WebRTC adapter: signaling and input work, but the browser receives no real video. This chapter covers enabling real encode/send paths.
Third-party SDKs must stay outside the source tree. .gitignore guards Gems/DawnStream/3rdParty/—never copy SDK headers or binaries into the repo.
Runtime pick order
At run time the peer factory chooses: native > wrapper > stub.
| Route | CMake gate | Typical encode |
|---|---|---|
| B (native) | LY_DAWNSTREAM_WEBRTC_NATIVE_ENABLED | Hardware (NVENC/…) when available, else soft fallbacks |
| A (wrapper) | LY_DAWNSTREAM_LIBWEBRTC_ENABLED | Software H.264 inside the wrapper |
| Stub | both off (default) | No media |
Both A and B may be enabled together; native wins when present.
Route A: libwebrtc wrapper
Pinned package:
webrtc-sdk/libwebrtc release libwebrtc.m144.7559.09. Deploy the unzipped package outside the repo, then configure:
cmake -B build/windows -S . -DLY_DAWNSTREAM_LIBWEBRTC_ENABLED=ON `
-DLY_DAWNSTREAM_LIBWEBRTC_PACKAGE_PATH=C:/path/to/libwebrtc-package
Expected layout and ABI notes (including the mandatory RTC_DESKTOP_DEVICE alignment): Gems/DawnStream/Code/cmake/3rdParty/Findlibwebrtc.cmake. You can also point the env var DAWNSTREAM_LIBWEBRTC_PACKAGE at the package root.
After rebuild, confirm libwebrtc DLL/deps deploy next to the launcher and that ps_dumpStats shows non-zero capture/send FPS once a viewer is connected.
Route B: native libwebrtc + hardware encode
Resolve a native libwebrtc package from outside the tree. The first supported layout is the WebRTC drop inside a UE5 installation:
cmake -B build/windows -S . -DLY_DAWNSTREAM_WEBRTC_NATIVE_ENABLED=ON `
-DLY_DAWNSTREAM_WEBRTC_NATIVE_PACKAGE_PATH=C:/path/to/UE/Engine/Source/ThirdParty
Layout and CRT constraints (profile/release, /MD): Findwebrtcnative.cmake.
NVENC (optional)
# …plus:
-DLY_DAWNSTREAM_NVENC_ENABLED=ON
Findnvenc.cmake resolves header-only NVENC (nvEncodeAPI.h) from outside the repo. At session start the runtime probes the driver and falls back (e.g. VP8/VP9 or other encode paths) when unavailable.
Encoder probe order when the corresponding gates/platforms are available:
NVENC → AMF → VAAPI (Linux) → VideoToolbox (macOS) → MediaFoundation (Windows) → libvpx VP8/VP9
Capture paths and zero-copy
Default capture is GPU/CPU readback (Atom FrameCapture), with optional GPU RGBA→I420 (Video.GpuColorConvert, default true; falls back to CPU).
Zero-copy (Video.ZeroCopyCapture, --dawnstream-zero-copy-capture) is off by default. It requires NVENC + DX12 and can accumulate a driver-side host memory pool that is not returned on session teardown—repeated viewer reconnects may grow process memory without bound. Prefer the default readback path for long-lived demos and reconnect loops. Any zero-copy failure falls back to readback automatically.
ps_dumpStats reports capPath=zerocopy|readback for the active path.
Default capture target: CapturePassHierarchy=["MainPipeline","CopyToSwapChain"], CaptureSlot="Output" (final composite including UI). Launcher window pipelines may rename the root pass; the runtime remaps the first hierarchy element when needed. If video stays black with a real adapter, verify this hierarchy—see
Diagnostics.
Confirm real media
- Rebuild with Route A and/or B enabled; restart the launcher with streaming flags from Getting started.
- Connect a viewer; expect video in the browser.
- Run
ps_dumpStats:
capFps/sendFpsshould be non-zero.- Bitrate should climb within your min/max window.
capPathshould match your zero-copy setting (usuallyreadback).
- Optionally enable
Diagnostics.LogStatsor--dawnstream-stats-csvfor a time series.
If the player connects but stays black, you are almost certainly still on stub—or capture/codec negotiation failed.
Next steps
- Signaling — production WSS / TURN alongside real media.
- Configuration — bitrate, resolution, capture pass keys.
- Deployment — NVENC concurrency and public checklist.