docs(research): add iroh suite deep-dive references for iroh, irpc, iroh-blobs, iroh-gossip, iroh-live, and iroh-docs

This commit is contained in:
2026-06-10 12:34:30 +00:00
parent 6e71d1f306
commit 5bb5e1064c
49 changed files with 9923 additions and 0 deletions

View File

@@ -0,0 +1,95 @@
# iroh-live: Network Signals and Adaptive Bitrate
## NetworkSignals
Produced by polling iroh QUIC connection stats. Consumed by `VideoTrack::enable_adaptation()` to decide when to switch video renditions.
```rust
pub struct NetworkSignals {
pub rtt: Duration, // Round-trip time to remote peer
pub loss_rate: f64, // Recent packet loss rate (0.0..=1.0), 200ms delta window
pub available_bps: u64, // Estimated available bandwidth (cwnd * 8 / rtt)
pub congestion_events: u64, // Monotonically increasing congestion counter
}
```
### Production
`spawn_signal_producer()` in `iroh-live/src/util.rs` polls every 200ms:
1. Gets connection paths via `conn.paths().get()`
2. Finds the selected path (`is_selected()`)
3. Reads path stats (`lost_packets`, `udp_tx.datagrams`, `cwnd`) and RTT
4. Computes delta-based loss rate: `delta_lost / (delta_sent + delta_lost)`
5. Estimates bandwidth: `cwnd * 8 * 1e9 / rtt_ns`
6. Writes to `watch::Sender<NetworkSignals>`
Also: `spawn_stats_recorder()` records into `NetStats` for the debug overlay (RTT, loss%, bandwidth in/out, path type).
## Adaptive Rendition Algorithm
Located in `moq-media/src/adaptive.rs`. The algorithm evaluates `NetworkSignals` against configured thresholds and produces `Decision` values.
### Configuration (`AdaptiveConfig`)
| Parameter | Default | Description |
|-----------|---------|-------------|
| `upgrade_hold` | 4s | Sustained good conditions before upgrade probe |
| `downgrade_hold` | 500ms | Sustained bad conditions before downgrade |
| `probe_duration` | 3s | How long a probe runs before committing |
| `probe_cooldown` | 8s | Cooldown after a failed probe |
| `post_downgrade_cooldown` | 4s | Cooldown after any downgrade |
| `loss_downgrade` | 10% | Loss rate threshold for downgrade |
| `loss_emergency` | 20% | Loss rate for immediate drop to lowest |
| `loss_good` | 2% | Loss rate considered "good" |
| `loss_probe_abort` | 5% | Loss rate that aborts an active probe |
| `bw_downgrade_ratio` | 85% | Bandwidth utilization ceiling for downgrade |
| `bw_probe_headroom` | 120% | Required excess bandwidth for probe |
| `check_interval` | 200ms | How often adaptation task checks signals |
### Decision Logic
```
1. Emergency: loss >= 20% AND not already lowest → Drop to lowest immediately
2. Downgrade check:
- bandwidth_stressed (available < current_bitrate * 85%) OR loss >= 10%
- sustained for downgrade_hold (500ms) → Downgrade(next_lower)
3. Upgrade check:
- Already at highest → Hold
- Within post_downgrade_cooldown (4s) → Hold
- Within probe_cooldown (8s) → Hold
- bandwidth_headroom (available >= next_higher_bitrate * 120%) AND loss <= 2%
- sustained for upgrade_hold (4s) → StartProbe(next_higher)
4. Otherwise: Hold
```
### Probe Lifecycle
When `StartProbe(idx)` is decided:
1. Create a new decoder pipeline for the higher rendition
2. Write frames to the same `FrameSender` (seamless switch for the consumer)
3. Monitor signals during the probe period
4. If `should_abort_probe()` (loss ≥ 5% or new congestion events) → abort, drop probe pipeline, cooldown 8s
5. If probe duration (3s) passes without abort → commit, replace current pipeline
### Rendition Ranking
```rust
pub fn rank_renditions(renditions: &BTreeMap<String, VideoConfig>) -> Vec<RankedRendition>
```
Sorts by pixel count descending (highest quality = index 0). Each `RankedRendition` carries name, pixels, bitrate_bps, width, height.
### RenditionMode
```rust
pub enum RenditionMode {
Auto, // Algorithm-driven switching
Fixed(String), // Pin to a specific rendition
}
```
Controlled via `VideoTrack::set_rendition_mode()`. In Fixed mode, the algorithm switches directly to the named rendition without probing.