Skip to main content

Module abr

Module abr 

Source
Expand description

Closed-loop rate control inside the QoS ceiling (PLAN.md §1.3).

A pure, deterministic controller stepped once per second with what the transport and the pilot measured. It never exceeds the profile ceiling and never goes below 25 % of it; it moves the request to the publisher (video-config) and Seyd’s own FEC rates.

Rules, in priority order:

  1. FEC follows measured loss, burst-first. Cellular loss arrives in bursts, and a block of 8 data chunks with k = 1 (the 15 % default) dies to any burst of two. So the first response to any measurable loss (≥ 0.2 % over the last 5 s) is k = 2 (25 %), then k = 3 at ≥ 2 % (38 %) and k = 4 at ≥ 5 % (50 %). Keyframe parity is at least delta + 10 (they are larger and losing one costs a GOP). FEC steps up immediately and steps down one level only after 5 clean seconds.
  2. Raising FEC is paid for by the video rate. The link constrains total bytes, so the bitrate request is scaled by (1 + profile_fec) / (1 + fec) — the on-wire budget stays what the profile promised.
  3. Residual loss (≥ 2 frames/s genuinely lost after FEC — timed-out frames whose chunks arrived late are jitter and are not counted) without any latency signal is a loss problem, not a congestion problem: step FEC up one level instead of cutting the rate (measured: cutting on residual loss alone sawtooths 25 % down / 10 % up forever on a lossy-but-uncongested link). Only when FEC is already at its top level does residual loss cut the bitrate.
  4. Congestion: AIMD with latency gating. A backlog drop is the primary signal and cuts 25 % at once. Latency is secondary: the median of the last 3 RTT samples must exceed min_rtt + budget/2 for 2 consecutive seconds, and the sample right after a keyframe went out is ignored (on a ~1.5 Mbps uplink a 45 KB IDR is 240 ms of queue by itself — measured as 80–94 ms RTT spikes that used to trigger cuts). Raise 10 % after 5 consecutive clean seconds. Cuts are at most one per 5 s.
  5. Emission hysteresis. A bitrate decision is emitted at most every 5 s and only for ≥ 10 % changes (encoders hate churn); FEC changes are emitted as soon as they happen; FEC steps down one level only after 10 clean seconds. A steady decision never moves the bitrate: the reason that moved the target is carried until it is emitted.
  6. At the floor and still congested for 5 s → suggested_fps = 15.

Structs§

AbrController
Decision
Sample

Functions§

effective_ceiling_kbps
The profile’s ceiling, lowered to the publisher’s own maximum when the host declared one (0 = none).