Skip to content

Vendor and trim the WebRTC stack - #8163

Merged
moq-bot[bot] merged 24 commits into
mainfrom
quest/m1/webrtc-vendor
Nov 7, 2026
Merged

moq-bot[bot] merged 24 commits into
mainfrom
quest/m1/webrtc-vendor

Conversation

@kixelated

@kixelated kixelated commented Nov 7, 2026 •

Copy link
Copy Markdown
Collaborator

Finishes quest/m1/webrtc-vendor.md: moq-webrtc builds str0m, dimpl, is, and sctp-proto from private modules under rs/moq-webrtc/src/vendor, trimmed to what MoQ uses, DTLS 1.2 only, with no crates.io copy of the stack left in Cargo.lock.

What changed

Vendored unchanged first (31cff5a09e), so every later commit diffs against upstream:

  • str0m at dc317173, with str0m-proto 0.7.0, is 0.11.1, str0m-aws-lc-rs 0.6.0, and the test-only str0m-netem 0.4.0 from that revision
  • dimpl 0.9.0 (c17b3b8), sctp-proto 0.10.7
  • License files kept beside str0m (covering its repository's other crates, which ship none), dimpl, sctp_proto, and webrtc-rs's Apache notice on str0m/packet. vendor/mod.rs records every upstream version.

Wired in (9e34275256): crate-root paths become crate::vendor::<crate>::, upstream cargo features resolve to all()/any() (since cleaned out), dimpl and sctp-proto log through tracing, and the upstream suites run as moq-webrtc unit tests. The vendored modules opt out of the workspace lints rather than churning upstream code.

Removed, per the plan:

  • str0m: GCC bandwidth estimation (bwe/), the leaky pacer and its controller, send-side probes and padding, the TWCC send register; H.266, RED, DTMF/telephone-event, G.711/G.722 and comfort noise; the VLA header extension with its simulcast and spatial layer allocations; RTCP application feedback; stats; _internal_test_exports (now cfg(test) helpers)
  • every crypto backend but aws-lc-rs, keeping str0m's CryptoProvider trait for moq-webrtc on rind
  • dimpl: dtls13/, auto.rs, the RustCrypto backend, and str0m's DtlsVersion knob
  • the cfg branches flattening left behind, two files upstream never compiled, and their tests
at copy now
str0m, str0m-proto, is, str0m-aws-lc-rs, netem 115,193 81,223
dimpl 59,193 24,403
sctp-proto 26,575 25,252

(Rust lines, tests included.)

Kept: dimpl's typed TimeoutError::Handshake now reaches moq-webrtc as RtcError::Dtls(DtlsError::CryptoError(CryptoError::DtlsImpl(_))) instead of str0m's CryptoError::Other(String), with the same message text. The typed DTLS timeout has not landed, so the ICE module has no text match to replace; that quest now says to match the variant.

Fix found on the way (4a8dd48595): dimpl 0.9 arms no timer on a passive DTLS side before its ClientHello, so an answerer whose offer carried no candidates never checked one trickled in later, and the p2p server-reflexive test timed out. A remote candidate now asks str0m for an immediate first timeout.

Packaging and docs: str0m's pcap captures are excluded from the published crate, its 4.4 MB H.265 capture is trimmed to the first 27 frames (475 KiB, under sh/large-files.sh's cap; the test still checks the keyframe and 23 delta frames), signature goes from the workspace, and the workspace-hack is regenerated. doc/bin/rtc.md, the OSS scanner's threat model, and the quests citing str0m or dimpl source now point at the vendored files.

Impact

Public API: none. The vendored modules are private, and the pub fns taking str0m types live in private modules.

Wire:

  • DTLS: unchanged. moq-webrtc always ran DTLS 1.2, and the same suites and SRTP profiles are offered. Headless Chromium and Firefox both negotiate DTLS 1.2 (FEFD), TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, and SRTP_AEAD_AES_256_GCM against this branch (see Validation).
  • RTCP: unchanged. RTCP XR stays (see Choices), so receiver reports still carry an RRTR block, a remote RRTR is still answered with DLRR, and the receive side keeps its measured RTT. Application-specific feedback (PSFB FMT=15) was never consumed and is now ignored on receipt.
  • RTP: unchanged. BWE was never enabled, so sends always went through the null pacer with no padding or probes; outgoing packets still carry transport-wide sequence numbers, and receive-side TWCC feedback, REMB, and SSRC 0 probe handling stay. RED was never negotiated. The removed codecs were never enabled, so remote offers carrying them still parse and are still declined; static payload types without an rtpmap are still accepted.

Choices made without asking

  • "VLA and simulcast layers" read as the VLA extension plus its simulcast and spatial layer allocation structs. SDP simulcast and RIDs stay: moq-webrtc reads per-layer REMB through rids_rx, and WHIP publishers send simulcast.
  • RTCP XR stays, against the plan's removal list. str0m's XR is only the RRTR/DLRR pair, and DLRR is the receive side's only RTT source (set_dlrr_item in streams/receive.rs). Removing it moved NACK retries to the 100 ms default and the video recovery deadline (recovery_deadline, 3x RTT, gating buffer_rx.rs's timeout_allows_progress) to a fixed 300 ms: too long on a 20 ms link, too short past 100 ms RTT. It also changed the wire, which the plan says stays unchanged. The epic README now says why XR stays. Re-dropping it means taking that regression and stating it in Impact; not recommended.
  • AMR-WB stays: it is not on the removal list, although moq-webrtc never enables it. Its negotiation test (tests/amr-wb.rs) is restored with it.
  • dimpl's PSK suites stay (about ten files, plus the ccm crate they alone use): not on the removal list, and certificate mode already refuses them, so they never reach the wire.
  • Dead upstream API stays: about 120 items moq-webrtc never calls (DirectApi, candidate builders, TURN STUN methods, VP8 descriptor patching, and so on) are upstream's public API, mostly with their own tests, and the plan keeps upstream tests for what remains.
  • The tests' L_CRYPTO/R_CRYPTO per-peer provider switch stays, trimmed to aws-lc-rs, so the rind quest can pit its provider against aws-lc-rs.
  • SCTP still compiles in every build. The epic's "only with the data-channel feature" is epic-level work no child owns, so it stays in the epic README.

Validation

  • cargo nextest run -p moq-webrtc --features p2p: 1683 passed, 3 skipped (upstream's #[ignore]d measurements). Without p2p: 1661 passed, 3 skipped.
  • cargo clippy --locked --all-targets -- -D warnings on moq-webrtc with default features, --features p2p, --no-default-features, and --no-default-features --features p2p, and on moq-cli.
  • just ci passes locally on c6f49f0463. That commit fixes the PR's own Check failures on 3f4cb05a71: it replaces em dashes in 39 vendored files with - (as moq-dev/moq#7501 did elsewhere) and biome-formats str0m/docs/chrome-sdp.json, which sdp/data.rs reads as a test fixture. The test js failure on that run (job) is in js/net/src/connection/connect.test.ts, which this PR does not touch, and it passed in the local run. A hedge timer from the previous test fired under the clock guard during "an http:// fingerprint longer than a SHA-256 is refused".
  • cargo fmt --all --check, cargo doc with -D warnings on moq-webrtc, cargo shear (moq-webrtc clean; its kio warnings are pre-existing), cargo sort --check, cargo hakari generate --diff, sh/rs/hakari.py, cargo deny check, sh/large-files.sh, sh/markdown.sh check, quest check --base origin/main, and cargo package -p moq-webrtc --list (no pcaps).
  • Browser smoke test on b17dd3ca15 (not rerun after restoring XR, which the str0m suites above cover), local relay: a headless page publishes a canvas plus oscillator over WHIP to moq import rtc --listen, and a second page plays the broadcast back over WHEP from moq export rtc --listen.
    • Chromium: both legs on DTLS 1.2, ECDHE-ECDSA AES-128-GCM, SRTP AEAD AES-256-GCM; WHEP decoded 158 VP8 frames and 53 Opus packets.
    • Firefox: the same negotiation; WHEP decoded 70 VP8 frames and 52 Opus packets.

Suggested follow-ups

  • SCTP behind the data-channel feature (from the epic): WHIP/WHEP builds still compile sctp_proto and str0m's SCTP glue.

  • Drop dimpl's PSK suites and the ccm dependency, if MoQ will never use PSK DTLS.

  • Trim dead upstream API that moq-webrtc never calls, once the rind and clock quests have settled which seams they need.

  • Flaky connect.test.ts hedge timer: hedgeWebTransport's 500 ms timer can outlive its test and trip the host-clock guard in the next one (seen on this run).

Review

mechanical fix by quest land watch: merged main at ce4b849a1c00f2650e2b688c164d2c00d406d7de with the quest merge driver (head ad48043)

Round 1 of a new session (quest review --base origin/main): Codex, gpt-6.1-sol, medium effort, on head c6f49f046362ace9202a26294cda8367937ebbfd against base a46d23f897. No findings.

Earlier: round 2 on 3f4cb05a71 had no findings, and pullfrog's review of b17dd3ca15 was addressed in 3f4cb05a71 (RTCP XR kept, which the maintainer confirmed; tests/amr-wb.rs restored).

🤖 Generated with Claude Code

(Written by Claude Opus 5.5)

kixelated and others added 21 commits November 7, 2026 08:14
Quest-Claim: e2997f6b1410b6c9
Verbatim upstream sources, not yet compiled, so later commits show only
our changes:
- str0m dc317173b16fc6ed86633e6b08b229c9195deb87 (src, tests),
  with str0m-proto 0.7.0, is 0.11.1, str0m-aws-lc-rs 0.6.0, and the
  test-only str0m-netem 0.4.0 from the same revision
- dimpl 0.9.0 (src, tests)
- sctp-proto 0.10.7 (src, tests)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
str0m's tests of GCC, VLA, RED, DTMF, G.722, comfort noise, AMR-WB,
stats, app feedback, RTCP XR, PII redaction, and drv go with that code.
dimpl's DTLS 1.3, version auto-selection, and OpenSSL/wolfSSL interop
suites go too: the interop suites would build OpenSSL and wolfSSL from
source for moq-webrtc's tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each upstream crate becomes a private module under moq-webrtc's
`vendor`, keeping its file layout:
- crate-root paths point at the module (`crate::vendor::str0m::`), and
  sibling crates at theirs;
- upstream cargo features resolve to `all()` or `any()` for this build,
  with `_internal_test_exports` becoming `cfg(test)`;
- dimpl and sctp-proto log through tracing like the rest of the crate,
  rather than through `log`, which nothing here bridged;
- sctp-proto drops `no_std`, and doctests become `ignore`d examples.

The upstream test suites run as unit tests of the module. Their
OpenSSL-generated certificates come from rcgen instead, `is`'s HMAC-SHA1
and str0m's reference SHA-1 from aws-lc-rs, and sctp-proto's harness no
longer mirrors its in-memory packets onto real UDP ports, which
collided between parallel test processes.

The SDP origin keeps `o=str0m-0.24.1`. The gateway's log-leak test uses
a canary token, since DTLS now logs "master secret" under the crate.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
str0m's ICE agent has no clock until its first timeout, and asks for none
before it, so Rtc only drove it on some other component's timer. dimpl
0.9 arms no timer on a passive DTLS side before its ClientHello, so an
answerer whose offer carried no candidates never checked one trickled in
later, and the p2p server-reflexive test timed out. A remote candidate
now asks for an immediate first timeout.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
rustfmt only: tabs and a 120-column width, as for the other vendored code.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Drop dimpl's DTLS 1.3 engine, its auto-sense handshake, the RustCrypto
backend, and str0m's DtlsVersion knob. moq-webrtc always ran DTLS 1.2,
so the wire is unchanged; the upstream tests for the removed paths go with
them and the DTLS 1.2 halves of the version-parameterized tests stay.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
str0m flattened every dimpl error into CryptoError::Other(String). Carry
it as CryptoError::DtlsImpl instead, so a handshake timeout stays
TimeoutError::Handshake for whoever matches it next. The message text is
unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The vendored str0m no longer computes peer or media stats, sends or parses
RTCP extended reports, or handles application feedback. Its internal test
exports become plain test helpers.

Without XR's RRTR and DLRR blocks the receive side has no RTT measurement,
so NACK retries fall back to the default 100 ms RTT.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
moq-webrtc never enabled str0m's BWE, so its sends always went through
the null pacer, which never asks for padding. Remove the GCC estimator,
the leaky-bucket pacer and its controller, send-side probes and padding,
and the TWCC send register that only fed the estimator. Outgoing packets
still carry transport-wide sequence numbers, receive-side TWCC feedback
and SSRC 0 probe handling stay, and REMB keeps its BweKind::Remb event.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The vendored str0m keeps the codecs MoQ bridges (Opus, H.264, H.265,
VP8, VP9, AV1) plus AMR-WB. Remote offers still parse: rtpmap lines for
the removed formats become unknown codecs, which the answer already
declined since none were enabled, and static payload types without an
rtpmap stay accepted. RED, telephone-event, and H.266 fmtp parsing go
with their codecs, as do the RED send sink, RED receive recovery, the
telephone-event writer, and the payload queue's send deadlines.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The VLA header extension and its simulcast and spatial layer allocation
structs were never registered by moq-webrtc. The LEB128 encoder it hosted
moves into the AV1 packetizer, its only other user. SDP simulcast and RIDs
stay because moq-webrtc reads per-layer REMB through them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Flattening upstream's feature flags left `cfg(any())` items, `cfg(all())`
markers, and single-backend dispatch for crypto providers that no longer
exist. Remove them, along with two files upstream never compiled (str0m's
`crypto/srtp.rs` and an empty dimpl `message/config.rs`), the no-op
`log_stat!` macro, and docs describing feature flags the copy lacks. The
tests' per-peer `L_CRYPTO`/`R_CRYPTO` switch stays for a second backend.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
str0m's 5.7 MB of pcap captures are read only by its #[cfg(test)]
modules, so the published crate does not need them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
str0m, dimpl, and sctp-proto now live in moq-webrtc's source, so a flaw in
them is in scope for the threat model rather than upstream's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Delete the quest and its links, and point the quests that cite str0m or
dimpl source at the vendored files. The typed DTLS timeout quest no longer
needs a text match: the vendored dtls.rs keeps dimpl's variant.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The 4.4 MB capture was 240 frames, but its keyframe test reads only the
first 5 s and the one keyframe is the first frame. Keep the first 27 frames
(0.87 s, 475 KiB) and the matching rows of h265.txt; the test still checks
the keyframe and 23 delta frames.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The import rewrite slid `use crate::vendor::str0m` under
`#[cfg(feature = "server")]`, which then gated it instead of axum, so a
build without the server feature failed to compile.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e workspace-hack

Trimming dimpl's other crypto backends left `signature` unused, and an empty
`message/config.rs` that an earlier commit meant to delete was still tracked.
The vendored stack's dependencies also shift the unified features, so the
workspace-hack is regenerated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated
kixelated marked this pull request as ready for review November 7, 2026 17:56

@kixelated kixelated left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review by review (OpenAI)

Reviewed head b17dd3c.

No actionable findings in the inspected adaptation and removal paths. Vendoring behind private modules is consistent with the planned provider replacement; keeping the provider seam and upstream tests is the right direction. The initial ICE timeout now starts passive-answerer checks without relying on a DTLS timer. The retained null-pacer/RTX, receive-TWCC/REMB, simulcast/RID and DTLS 1.2 paths appear preserved, with the XR/NACK fallback change explicitly documented.

Verification limits: GitHub-only static review using paginated file listings, the post-copy commits and selected full source/caller paths. This was not an exhaustive audit of all 132k imported lines or a byte-for-byte upstream provenance check. I did not run builds, tests, browser interop, package verification or inspect binary captures. The reported runtime and interoperability results remain author-provided.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ No critical issues — two things worth a look before merging.

Reviewed changes

Reviewed the full import of the WebRTC stack into rs/moq-webrtc/src/vendor and each trim against the upstream sources at the recorded revisions.

  • Vendoring is faithful. str0m (str0m@dc317173, still 0.24.1 in its own Cargo.toml), str0m-proto 0.7.0, is 0.11.1, str0m-aws-lc-rs 0.6.0, netem 0.4.0, dimpl 0.9.0 (c17b3b8), and sctp-proto 0.10.7 match upstream's workspace deps. Diffing the checkout against the upstream tarball (ignoring whitespace) shows only formatting and crate::vendor::… path rewrites in kept code.
  • Trim matches the plan. BWE/GCC, the leaky pacer, send probes/padding and the TWCC send register, RTCP XR/app-feedback, stats, H.266/RED/DTMF/G.7xx/CN, VLA, internal test exports, DTLS 1.3/auto.rs, the RustCrypto and non-aws-lc backends, and dead cfg branches are gone; AMR-WB and the PSK suites stay. The static-payload acceptance rule is preserved exactly (matches!(pt, 0 | 8 | 9 | 13) replaces CodecSpec::from_static_pt), outgoing packets still carry a TWCC sequence, and RtpHeader::unpad_payload still strips received padding.
  • The ICE timer fix is bounded. Rtc::poll_timeout only substitutes last_now while is::Agent::poll_timeout is None, which the is code returns only before the first handle_timeout, so the extra immediate timeout cannot spin. add_remote_candidate calls wake_all, so the recompute is reached.
  • Typed DTLS errors and packaging. CryptoError::DtlsImpl is only constructed in str0m/dtls.rs, so the new "DTLS error: " prefix is not doubled, and the test pins the unchanged message text. Ports, licenses (str0m ships only LICENSE-MIT.txt, whose repo covers is/str0m-proto/str0m-aws-lc-rs/netem; the packet/ Apache notice is kept), the H.265 capture trim (475 KiB < the 500 KiB cap), and the quest edits (retargeted section lines and Rtc::init_dtls all exist) check out. No public API is exposed and the private session/vendor modules keep the surface unchanged.

ℹ️ Removing RTCP XR also raises the video frame recovery deadline to 300 ms

The XR deletion removes the only production writer of StreamRxStats::rtt, and that field feeds recovery_deadline (3×RTT) as well as the NACK retry interval. So besides the retry interval moving to 105 ms, an incomplete video frame from a publisher is now held for 300 ms (3× the 100 ms default) before it is emitted without the missing packet, rather than 3×RTT (about 60 ms at 20 ms RTT). The Impact section only mentions the NACK interval.

Technical details
# RTCP XR removal widens the receive-side recovery deadline

## Affected sites
- `rs/moq-webrtc/src/vendor/str0m/streams/receive.rs:619-626` — `recovery_deadline` falls back to `DEFAULT_RTT * 3` when `stats.rtt` is `None`.
- `rs/moq-webrtc/src/vendor/str0m/streams/receive.rs:663` — `nack_report(now, self.stats.rtt)` uses `DEFAULT_RTT + 5 ms` when `None` (`streams/register_nack.rs:208`).
- `rs/moq-webrtc/src/vendor/str0m/streams/receive.rs:867` — the only remaining `stats.rtt = Some(..)` is inside a test.
- `rs/moq-webrtc/src/vendor/str0m/packet/buffer_rx.rs:499` — `timeout_allows_progress` gates emitting a frame on that deadline; `session.rs:738` (`update_receive_recovery`) recomputes it per video buffer.
- Baseline `31cff5a09:rs/moq-webrtc/src/vendor/str0m/streams/receive.rs` — `set_dlrr_item` was what set `stats.rtt` from the peer's DLRR.

## Required outcome
- Either state the full effect in Impact (recovery deadline, not just the retry interval), or keep the small RRTR/DLRR subset of XR so the receiver keeps a measured RTT while the rest of XR stays removed.

ℹ️ AMR-WB keeps its code but loses its only negotiation test

0b4a3fd4c deleted vendor/str0m/tests/amr-wb.rs, whose only purpose was the AMR-WB SDP negotiation (a=rtpmap:122 AMR-WB/16000/1, octet-align/mode-set) plus a round-trip over every frame type and SID. AMR-WB is explicitly kept (“AMR-WB stays”), and the quest plan says to keep upstream's tests for what remains, but vendor/str0m/tests/mod.rs has no mod amr_wb and nothing else in the harness or sdp-negotiation.rs mentions AMR-WB.

Technical details
# Restore the AMR-WB negotiation test, or remove AMR-WB too

## Affected sites
- `rs/moq-webrtc/src/vendor/str0m/tests/mod.rs` — no `mod amr_wb;` entry, so the ported test is gone.
- Deleted in `0b4a3fd4c`: `rs/moq-webrtc/src/vendor/str0m/tests/amr-wb.rs` (273 lines).
- `rs/moq-webrtc/src/vendor/str0m/packet/amr_wb.rs:191+` — unit tests cover packetize/depacketize in both layouts, but not SDP negotiation or the `octet-align`/`mode-set` fmtp path in `sdp/data.rs`.

## Required outcome
- Keep the test with the retained codec (add `#[path = "amr-wb.rs"] mod amr_wb;` to `tests/mod.rs`), or delete AMR-WB as well so the tree has no untested retained codec.

Pullfrog  | Fix it ➔ | View workflow run | Using deepseek-v4.1-flash-1017 (free via Pullfrog for OSS) | 𝕏

RTCP XR in str0m is only the RRTR/DLRR pair, the receive side's one RTT
measurement. Without it NACK retries and the video recovery deadline fell
back to the 100 ms default, and str0m stopped answering a remote RRTR with
DLRR. Restore it with its tests, and restore upstream's AMR-WB negotiation
test, since AMR-WB stays.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@kixelated kixelated left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review by review (OpenAI)

Reviewed head 3f4cb05, focusing on the restoration since b17dd3c.

No actionable findings in this update. Retaining RRTR/DLRR is the better direction: it restores measured receive-side RTT for both NACK retries and frame recovery deadlines, rather than accepting the fixed fallback discussed in the prior reviews. Serialization, session replies, local-SSRC routing and receive-stream updates are connected consistently. The restored DLRR and AMR-WB tests are registered, and the NACK regression covers measured RTT in both RTP and frame modes.

Verification limits: GitHub-only static review, including comparison of restored XR/DLRR and AMR-WB code with the original import. No builds, tests or browser interoperability run; the reported browser smoke test predates this restoration. This incremental review does not expand the earlier review into an exhaustive audit of the vendored stack.

@kixelated

Copy link
Copy Markdown
Collaborator Author

Maintainer decision (2026-11-07, /quest-complete):

  • ✅ Keep RTCP XR (RRTR/DLRR), as 3f4cb05 does: the receive side keeps a measured RTT for NACK and the recovery deadline, and the wire stays unchanged. Application feedback stays removed.
  • Drop XR as the quest plan listed

(Written by Claude Opus 5.5 with high)

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes

Reviewed the delta since the prior pullfrog review (b17dd3ca1 → 3f4cb05a7): the restored RTCP XR path and its tests, plus the epic plan update.

  • Restored upstream's RTCP XR (RRTR/DLRR) end to end — xr.rs, the Rtcp::ExtendedReport variant and parsing, RtcpFb::Rrtr/DlrrItem flattening, session-level pending_rrtrs with DLRR piggybacked on Sender Reports, handle_dlrr, and set_dlrr_item setting StreamRxStats::rtt. The restored code is byte-for-byte upstream dc317173 modulo path rewrites and formatting, and the receive-side RTT feeds both recovery_deadline and the NACK retry interval again.
  • Restored tests/dlrr.rs, the dlrr_for_local_ssrc_updates_receive_streams unit test, and nack_retries_follow_measured_rtt_in_both_receive_modes, which assert the DLRR round trip, the local-SSRC filter, and RTT-following retry spacing.
  • Restored tests/amr-wb.rs verbatim and re-registered it in tests/mod.rs, so the retained AMR-WB codec keeps its SDP negotiation coverage.
  • Updated the epic README so its trim list drops RTCP XR and states why XR stays.

Verified locally against the head: cargo test -p moq-webrtc --features p2p --no-run compiles, and the dlrr, amr_wb, and nack_retries_follow tests pass.

Pullfrog  | View workflow run | Using deepseek-v4.1-flash-1017 (free via Pullfrog for OSS) | 𝕏

…red stack

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated
kixelated added this pull request to the merge queue Nov 7, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Nov 7, 2026
@moq-bot

moq-bot Bot commented Nov 7, 2026

Copy link
Copy Markdown
Contributor

quest land watch: the merge queue removed this pull request at c6f49f0 because it conflicts with main (merge_conflict).

The land fixer works on it in the background, and the watcher re-enqueues it at the back of the queue once it is fixed or judged flaky, or hands it back here with what it needs.

(written by quest land watch)

@moq-bot
moq-bot Bot enabled auto-merge November 7, 2026 21:59
@moq-bot

moq-bot Bot commented Nov 7, 2026

Copy link
Copy Markdown
Contributor

quest land watch: armed auto-merge on this pull request at ad48043, so it joins the back of the merge queue once its required checks pass, with main at ce4b849 merged in by the quest merge driver.

(written by quest land watch)

@moq-bot
moq-bot Bot added this pull request to the merge queue Nov 7, 2026
Merged via the queue into main with commit 76bb38f Nov 7, 2026
8 of 10 checks passed
@moq-bot
moq-bot Bot deleted the quest/m1/webrtc-vendor branch November 7, 2026 22:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant