Key protocol differences — based on draft-sharabayko-srt-01 and QuicFeed v2.1 test results
| SRT | QuicFeed | |
|---|---|---|
| Architecture | Single ordered stream per connection | Independent QUIC stream per file |
| HoL blocking | Yes, up to drop timeout — a lost packet stalls delivery within that SRT stream until retransmitted or the TLPKTDROP timeout expires (user-configurable: 20–8000ms), whichever comes first. A lost packet on one SRT stream doesn't stall other SRT streams | No — a lost packet on one stream doesn't stall other streams |
| Impact | A dropped video init segment blocks all subsequent audio/video segments until retransmitted or timed out; the HOL block is bounded by the configured packet drop timeout | A dropped .m4s segment only delays that one file; other segments flow through |
This is the most fundamental architectural difference. SRT's HOL blocking is bounded — TLPKTDROP releases the block once the packet drop timeout expires (configured via the latency setting), so the stall is not indefinite. However, even bounded HOL blocking means all data behind the lost packet is delayed by up to the timeout period, whereas QuicFeed's per-stream architecture means only the affected file is delayed. Test results validated this: zero file delivery errors even under 2% loss + 50ms jitter on both sides simultaneously.
| SRT | QuicFeed | |
|---|---|---|
| Binding | 4-tuple: source IP + port, dest IP + port | QUIC Connection ID (independent of IP/port) |
| Migration | Connection dies if IP or port changes | Supported — 60s idle timeout + 5s keep-alive; session survives network interface changes |
| Multipath | "Reserved for future" in the spec | Phase 1 (hitless failover) supported; Phase 2 (active multipath) awaiting quinn RFC 9443 |
SRT's bonding/multipath is still a framework stub. QuicFeed configures connection migration with max_idle_timeout(60s) and keep_alive_interval(5s), enabling hitless failover when a TX changes network interfaces mid-stream.
| SRT | QuicFeed | |
|---|---|---|
| Initial connection | 2-phase handshake (Induction + Conclusion) over UDP, then key exchange | QUIC 1-RTT handshake (TLS 1.3 integrated) |
| Reconnection | Full handshake required again | 0-RTT resumption — first packet can carry both setup and data |
| Anti-DoS | SYN cookie (MD5 of host+port+time) | QUIC built-in retry tokens and address validation |
SRT's handshake is at minimum 2 round trips before data flows. QuicFeed implements 0-RTT session resumption: TX caches up to 256 session tickets and attempts into_0rtt() on reconnect, falling back to 1-RTT if no ticket is available.
| SRT | QuicFeed | |
|---|---|---|
| Method | AES-CTR with app-level key wrapping | TLS 1.3 built into QUIC — encrypts everything including most headers |
| Key exchange | Custom KM messages, AES Key Wrap | Standard TLS 1.3 key exchange (ECDHE) |
| What's encrypted | Payload only — SRT headers are in the clear | Nearly everything — only connection ID and some flags are visible |
| Key rotation | Manual SEK refresh | TLS 1.3 key update mechanism |
| Authentication | Password-based (derives KEK from passphrase) | TLS certificate + worker auth (namespace+password) |
SRT's encryption is bolted on top. QUIC's encryption is structural — an observer can't even see packet sequence numbers.
| SRT | QuicFeed | |
|---|---|---|
| Mechanism | NAK-based — receiver lists lost sequence numbers | ACK-based — sender detects loss from ACK gaps and timers |
| Granularity | Per-packet within a single stream | Per-packet, per-stream — retransmission on stream X doesn't affect stream Y |
| Too-late drop | TLPKTDROP: receiver drops packets past TSBPD deadline | TLPKTDROP implemented — RX drops files arriving past playout deadline |
| Absolute delay floor | TLPKTDROP only (post-arrival) | --max-transfer-time — kills slow QUIC streams via STOP_SENDING during transfer, enforcing an absolute delay floor before data even arrives |
SRT's NAK-based approach means the receiver drives retransmission. QUIC's approach means the sender drives it. --max-transfer-time enforces an absolute delay floor by sending STOP_SENDING to abort streams mid-transfer — if a segment isn't fully received within the deadline, the stream is killed, saving bandwidth on doomed retransmissions. Combined with TLPKTDROP (--latency), this guarantees no segment stalls the pipeline beyond the configured deadline. SRT cannot replicate this per-stream kill with its single-stream architecture.
| SRT | QuicFeed | |
|---|---|---|
| Live mode | LiveCC — rate-limited by configured max bandwidth | LiveCC — media-aware controller with BDP floor and gentle backoff |
| Feedback signal | Receiver reports available buffer size in ACK packets | ACK-based + RX buffer feedback via QUIC datagrams (1/sec) |
| Jitter response | Absorbs jitter in TSBPD buffer | Ignores jitter — only reacts to actual packet loss with 0.85x decrease |
QuicFeed's LiveCC replaces quinn's default Cubic with a custom controller:
window() never returns below target_rate * smoothed_rtt, preventing CWND collapse--max-bitrate flag (default 40 Mbps)| SRT | QuicFeed | |
|---|---|---|
| Approach | TSBPD — configurable latency budget negotiated at handshake | TSBPD implemented — --latency flag configures jitter buffer with playout scheduling |
| Clock sync | Drift compensation via ACK/ACKACK | Connection-relative timestamps; no clock drift compensation yet |
| Late arrivals | TLPKTDROP discards packets past deadline | TLPKTDROP — files past origin_time + latency are dropped |
Each segment is its own QUIC stream, and QUIC delivers bytes reliably and in order within each stream. With LL-HLS or L3D-DASH enabled, the RX parses ~33ms CMAF fragments as they arrive within the stream and writes them as part files immediately — no waiting for the full segment. This enables sub-second glass-to-glass latency, comparable to SRT's TSBPD-buffered delivery but with per-stream independence.
RX sends buffer feedback to TX every second via QUIC datagrams: buffer depth, buffer bytes, drops, timeouts, and average TX time.
| SRT | QuicFeed | |
|---|---|---|
| Stream independence | Each SRT socket is an independent connection | Multiple independent streams within one QUIC connection |
| Stream typing | No built-in differentiation | Wire format v2: StreamType (Video, Audio, Metadata) auto-classified |
| Overhead | Each stream = separate handshake + congestion state | One handshake, shared congestion state, independent delivery |
v1: [u16 name_len][name][u64 data_len][data]
v2: [u8 version=0x02][u8 stream_type][u16 name_len][name][u64 timestamp_us][u64 data_len][data]
| SRT Feature | QuicFeed Status | Notes |
|---|---|---|
| Packet loss recovery (ARQ) | Matched | QUIC ACK-based retransmission, per-stream |
| Jitter buffer (TSBPD) | Matched | --latency flag, BinaryHeap playout scheduling |
| Too-late packet drop | Matched | Files past playout deadline dropped and counted |
| Per-stream transfer timeout | Exceeded | --max-transfer-time kills slow streams; SRT can't do per-stream kill |
| Congestion control (LiveCC) | Matched | BDP floor + 0.85x backoff; outperforms Cubic under jitter |
| Encryption | Exceeded | TLS 1.3 built-in; encrypts headers, not just payload |
| Latency management | Matched | Connection-relative timestamps + jitter buffer |
| Connection migration | Exceeded | QUIC CIDs survive IP/port changes; SRT connections die |
| 0-RTT reconnection | Exceeded | Near-instant session resumption; SRT requires full re-handshake |
| Multi-stream media mapping | Exceeded | Wire format v2 stream types; SRT has no stream-level multiplexing |
| HoL blocking elimination | Exceeded | One stream per file; SRT has bounded HOL blocking (up to drop timeout) on a single ordered stream |
| Clock drift compensation | Gap | SRT syncs via ACK/ACKACK; QuicFeed uses connection-relative only |
| Receiver buffer feedback | Matched | RX sends buffer report to TX every second via QUIC datagrams |
| Multipath bonding | Partial | Phase 1 hitless failover works; active-active blocked on quinn RFC 9443 |
12 of 14 features matched or exceeded. 1 minor gap remains. 1 partially implemented.
| Phase | Impairment | RTT | CWND | Files/60s | Throughput |
|---|---|---|---|---|---|
| Baseline | None | 28ms | 444KB | — | ~4.4 Mbps |
| 1 | 2% loss | 27ms | Stable | 349 | ~4.5 Mbps |
| 2 | 2% bursty loss | 26ms | Stable | 350 | ~4.4 Mbps |
| 3 | 50ms delay | 126ms | Stable | 347 | ~4.1 Mbps |
| 4 | 50ms + 20ms jitter | 122ms | 7KB | 117 | ~1.3 Mbps |
| 5 | 10 Mbit cap | 73ms | Stable | 341 | ~4.4 Mbps |
| 6 | Combined | 107ms | Low | 126 | ~1.5 Mbps |
| Phase | Impairment | RTT | CWND | Files/60s | Throughput |
|---|---|---|---|---|---|
| Baseline | None | 27ms | 1,071KB | — | ~4.9 Mbps |
| 1 | 2% loss | 24ms | 122KB | 350 | ~5.1 Mbps |
| 2 | 2% bursty loss | 27ms | 363KB | 345 | ~5.0 Mbps |
| 3 | 50ms delay | 128ms | 642KB | 353 | ~5.1 Mbps |
| 4 | 50ms + 20ms jitter | 82ms | 424KB | 353 | ~5.2 Mbps |
| 5 | 10 Mbit cap | 100ms | 512KB | 351 | ~4.9 Mbps |
| 6 | Combined | 97ms | 453KB | 352 | ~5.3 Mbps |
Zero file delivery errors across all phases.
Phase 4 (jitter) — the critical fix: v1 CWND collapsed from 444KB to 7KB, throughput dropped 75% to 1.3 Mbps. v2 CWND held at 424KB, throughput steady at 5.2 Mbps — 4x improvement. LiveCC's BDP floor prevented the collapse entirely.
Phase 6 (combined) — real-world conditions: v1 delivered 126 files at 1.5 Mbps. v2 delivered 352 files at 5.3 Mbps — 3.5x throughput improvement.
--max-transfer-time kills slow streams via STOP_SENDING