1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
//! Bandwidth-adaptive layer selection ().
//!
//! Each subscriber gets a [] that watches per-tick BWE
//! readings and adjusts [][crate::client::Client::desired_layer]
//! with LiveKit-style hysteresis: 3 consecutive ticks above the next-tier
//! threshold to upgrade, immediate downgrade, hysteretic audio-only mode.
//!
//! Also provides advanced bandwidth estimation ().
//!
//! Implements a GoogCC-inspired congestion controller with:
//! - Kalman-filtered TWCC inter-arrival delay estimation
//! - Loss-based rate control
//! - Per-subscriber state combining both signals with native GCC + client hint ceilings
//!
//! Ported from .
pub use ;
pub use PacerAction;
pub use SubscriberPacer;
/// Below this egress BWE, the pacer enters its `suspended` sub-state and emits
/// `PacerAction::SuspendVideo`. Audio at this BWE is below the Opus narrow-band
/// budget (~8 kbps); forwarding it burns the link without delivering speech.
/// Phase 7 wires the per-client fanout filter that drops video frames for
/// suspended subscribers.
pub const SUSPEND_VIDEO_BPS: u64 = 10_000;
/// Below this egress BWE, video is suspended (audio-only mode) --- bits/s.
pub const AUDIO_ONLY_BPS: u64 = 80_000;
/// Minimum BWE to sustain the LOW ("q") simulcast layer --- bits/s.
pub const LOW_MIN_BPS: u64 = 150_000;
/// Minimum BWE to sustain the MEDIUM ("h") simulcast layer --- bits/s.
pub const MEDIUM_MIN_BPS: u64 = 350_000;
/// Minimum BWE to sustain the HIGH ("f") simulcast layer --- bits/s.
pub const HIGH_MIN_BPS: u64 = 700_000;
/// Consecutive ticks below `SUSPEND_VIDEO_BPS` required before the pacer
/// enters its `suspended` sub-state. Asymmetric with `UPGRADE_STREAK`:
/// entry mistakes cause a visible video gap, so a small (2-tick) debounce
/// rejects single-tick TWCC spikes without delaying real-congestion response.
///
/// Effective response latency: `SUSPEND_STREAK × tick_interval`. At the
/// nominal TWCC tick rate of ~50 ms, suspend-entry takes ≈100 ms; at the
/// 100 ms BandwidthEstimate cadence, ≈200 ms. Tune in tandem with tick
/// rate when revising.
///
/// Edge case: under sustained alternating-tick loss (e.g., a 50 % periodic
/// drop pattern at the tick frequency), `SUSPEND_STREAK` never fires
/// because the streak resets on every recovered tick. The `audio_only`
/// path via `AUDIO_ONLY_BPS` then catches the BWE collapse instead. This
/// is intentional: a 2-tick debounce that does NOT clear on intervening
/// good ticks would re-introduce the spike-trigger problem this guard
/// exists to prevent.
///
/// Exposed `pub` (not `pub(crate)`) so integration tests in `tests/` can
/// import it without hardcoding the literal. Documented `#[doc(hidden)]`
/// because it is not part of the public stable API surface; behavioural
/// invariants observable through `Propagated::SuspendVideo` are the
/// stable contract, not this constant.
pub const SUSPEND_STREAK: u8 = 2;
/// Ticks above next tier required before upgrading (prevents thrash).
pub const UPGRADE_STREAK: u8 = 3;
pub use BandwidthEstimator;
pub use GoogCcEstimator;