User Story
Problem Description
When the host network adapter operates at 1 Gbps (1000BASE-T) and streams to a client with a downstream bottleneck—such as:
- Physical 100 Mbps links / shallow switch buffers, OR
- Gigabit USB Ethernet adapters plugged into USB 2.0 host ports (e.g., Xiaomi Mi TV Stick 4K, Chromecast, Fire TV),
Moonlight experiences severe stuttering, packet loss, and frequent session disconnects.
Even if the Ethernet link negotiates at 1 Gbps end-to-end, the host flushes video frames at the full 1 Gbps wire rate in sub-millisecond microbursts. When these 1 Gbps bursts hit the dongle, its internal FIFO buffer overflows trying to serialize data over the slower USB 2.0 bus (~250 Mbps practical limit), causing immediate UDP tail drops and high jitter.
Empirical Evidence & Proof
-
Physical Link Rate Test (The definitive proof):
- When forcing the host's physical network adapter to 100 Mbps Full Duplex via Windows device properties (
*SpeedDuplex):- The streaming becomes 100% smooth and stable, even at high bitrates (up to 80 Mbps).
- Because the host PHY physically clocks bits at 100 MHz, the burst rate never exceeds 100 Mbps, comfortably fitting within the client's USB 2.0 bus bandwidth.
- When switching the host back to 1 Gbps, the exact same stream immediately drops packets and lags due to 1 Gbps microbursts.
- When forcing the host's physical network adapter to 100 Mbps Full Duplex via Windows device properties (
-
Current
video_max_batch_size_kbLimitation:- Setting
video_max_batch_size_kb = 16flushes smaller chunks, but each chunk is still emitted at 1 Gbps line speed (~120 µs) because standard Windows sleep/yield timers lack sub-millisecond precision to space packets evenly across the frame interval.
- Setting
-
Host Logs during 1 Gbps Bursts:
Info: AMF: creating native encoder session 2560x1440@60 codec=2 bitrate=78988kbps (active=1) Warning: Skipping FEC for abnormally large encoded frame (needed 5 FEC blocks) Info: CLIENT DISCONNECTED
Proposed Feature / Solution
Implement a sub-millisecond UDP packet pacing / token-bucket traffic shaper in the video transport send loop:
-
Packet Spacing across Frame Budget:
- Space packets evenly over the frame budget (e.g., across 16.6 ms for 60 FPS) based on a target pacing rate: $$\text{Inter-Packet Interval} = \frac{\text{Packet Size (bits)}}{\text{Pacing Rate (bps)}}$$
-
High-Resolution Timing on Windows:
- Use
CreateWaitableTimerExWwithCREATE_WAITABLE_TIMER_HIGH_RESOLUTION(available since Windows 10 build 1803) or a hybridQueryPerformanceCounterspin-wait for sub-millisecond intervals.
- Use
-
Exposed Config Options (
sunshine.conf):pacing_enabled = true / falsepacing_max_rate_mbps = <integer>(e.g.,80,90,100to emulate 100M line-rate pacing on a 1 Gbps NIC without crippling the host's download speeds for other apps).
Environment Details
- Host OS: Windows 11 / 10 x64
- Host GPU: AMD Radeon RX 7700 XT (AMF native pipeline)
- Host NIC: Realtek PCIe GbE Family Controller (1 Gbps)
- Vibepollo Version: v2.0.0 / v2.0.1
- Client: Moonlight Android TV (Xiaomi Mi TV Stick 4K with USB 3.0 Gigabit dongle on USB 2.0 OTG port)
Acceptance Criteria
Acceptance Criteria
-
Frame Packet Distribution (Pacing):
- Outgoing video UDP packets are evenly distributed across the frame interval (~16.6 ms for 60 FPS) rather than being flushed simultaneously onto the socket in an unmetered 1 ms burst.
- The instantaneous transmission rate does not exceed the configured/negotiated pacing ceiling (e.g., 80–100 Mbps).
-
Host Link Speed Independence:
- The host network adapter can remain permanently set to 1 Gbps (1000BASE-T) with full bandwidth available for non-streaming host workloads (downloads, web browsing, local transfers).
-
Zero Packet Loss on 100M / USB 2.0 Bottlenecks:
- When streaming to a client connected via a 100 Mbps port or a Gigabit adapter over USB 2.0, Moonlight reports 0% network frame loss / tail drops during steady-state gameplay.
- Host logs no longer trigger
Warning: Skipping FEC for abnormally large encoded framedue to sudden socket buffer overruns.
-
Minimal Host Latency Overhead:
- The high-resolution pacing timer adds negligible host-side delay (< 1 ms extra pipeline latency).
-
Configurability & Safety:
- Pacing can be configured or toggled in
sunshine.conf(e.g.,pacing_enabled,pacing_max_rate_mbps). - Users on full Gigabit/10G end-to-end setups can disable or increase the pacing limit to maintain unconstrained throughput.
- Pacing can be configured or toggled in
Story Points
3
Priority
Medium
Notes / Additional Context
No response
Activity
0No activity yet.