SCReAM v2 Implementation Differences

Date: June 9, 2026
Commit: f48df12def0d531a66a3dffcea021fbe0f99dcde
Note: This document was automatically generated by an AI assistant (Gemini) comparing the WebRTC source code with the IETF specification.

This document describes the differences between the WebRTC implementation of SCReAM v2 and the IETF draft draft-johansson-ccwg-rfc8298bis-screamv2-07.

The WebRTC implementation is currently in development and some features are not yet fully implemented.

4. Detailed Description of SCReAMv2 Sender Algorithm

4.1. Sender Side State

4.1.1. Status Update When Sending Data

4.1.2. Status Update on Receiving Feedback

  • The WebRTC implementation defines the feedback structure in scream_feedback.h.
  • Instead of tracking bytes_newly_acked and bytes_newly_acked_ce separately and resetting them after window updates as described in the spec (Section 4.1.2), the WebRTC ScreamFeedback struct directly provides acked_not_marked_size (sum of sizes of packets in the feedback that are NOT ECN CE-marked) and num_ce_marked_packets. This simplifies the window update logic in scream_v2.cc.
  • Feedback Hold Time Tracking:
    • The WebRTC implementation explicitly tracks feedback_hold_time_ (the average time feedback is delayed at the receiver before being sent) in scream_v2.cc:L311.
    • This hold time is integrated into multiple RTT-based calculations (initial window, window increase scaling, and target rate calculation) to prevent underestimating the true round-trip loop time.

4.2. Network Congestion Control

4.2.1. Congestion Detection: Delay, Data Unit Loss and ECN-CE

4.2.1.1. Detecting Lost Data Units
  • Different Loss Detection Mechanism:
    • The spec describes a RACK-like loss detection mechanism based on a reordering window and a “lost” flag in the list of transmitted data units (Section 4.2.1.1).
    • The WebRTC implementation uses a custom LossEstimator (loss_estimator.cc) which implements a biased asymmetric step filter (leaky bucket) to estimate a short-term congestion_level_ (between 0.0 and 1.0).
      • Filter Mechanics: If one or more packets are lost during an RTT, the filter steps up the congestion level by 1.0 / rtts_with_loss_before_backoff (default +1/3). If an RTT is lossless, it steps down by 1.0 / lossless_rtts_before_clear (default -1/2).
      • Spurious Loss Filtering: This asymmetric design ensures that spurious random losses (e.g., 1% uniform loss on wireless links, which results in ~40% of RTTs having at least one loss) result in a net-negative drift, keeping the congestion level near 0.0 and preventing unnecessary backoffs. It requires 3 consecutive RTTs with loss to reach the 1.0 threshold.
    • Impact on Backoff: Instead of reacting to individual loss events immediately, the WebRTC implementation only triggers a loss-based backoff when the LossEstimator reports that the connection is congested() (congestion level >= 0.99) OR if queue delay is also detected. See scream_v2.cc:L134-L139.
    • Impact on Window Increase: When the congestion level is elevated ($\ge 0.01$), the reference window increase is blocked, even if the current feedback report contains zero packet loss. Because the congestion level decays by 0.5 per lossless RTT, it takes 2 full lossless RTTs for the increase blocker to clear after congestion ends. This prevents the window from immediately expanding again after a congestion event. See scream_v2.cc:L199 and loss_estimator.cc:L77.
4.2.1.2. Receiving ECN-CE with classic ECN
  • Classic ECN Not Supported:
    • The spec defines a classic ECN mode where the reference window is scaled by a fixed BETA_ECN (default 0.8) (Section 4.2.1.2).
    • The WebRTC implementation does not support classic ECN. It only implements L4S-style ECN marking reaction. There is no BETA_ECN parameter or classic ECN backoff path in scream_v2.cc.
4.2.1.3. Receiving ECN-CE for L4S
  • L4S Alpha Update Frequency:
    • The spec recommends accumulating delivered and marked packets and updating l4s_alpha at most once per min(10ms, s_rtt) (Section 4.2.1.3).
    • The WebRTC implementation updates l4s_alpha_ on every feedback message based on the fraction of marked packets in that specific feedback, without the time interval constraint. See scream_v2.cc:L109-L125.
4.2.1.4. Detecting Increased Queue Delay
  • Jitter Reduction and Delay Variation Scaling:
  • Queue Delay Average Update Frequency:
4.2.1.4.1. Competing Flows Compensation
  • Not Implemented:
    • The spec describes a dynamic target delay adjustment (adjust_qdelay_target) to allow SCReAM v2 to compete with aggressive loss-based flows (like TCP Reno/Cubic) by increasing qdelay_target when competing traffic is detected (Section 4.2.1.4.1).
    • The WebRTC implementation does not implement this feature. The queue_delay_target remains static (default 60ms). This is explicitly marked as a TODO in scream_v2_parameters.h:L107.

4.2.2. Reference Window Update

4.2.2.1. Reference Window Reduction
  • Inflection Point Scaling Factor:
    • The spec uses a factor of 8 in the calculation of scl_t (scaling factor close to inflection point ref_wnd_i) (Section 4.2.2.1).
    • The WebRTC implementation defaults to a lower factor of 2.0 (backoff_scale_factor_close_to_ref_window_i in scream_v2_parameters.cc:L38), meaning the increase/decrease around the inflection point is slower (more cautious) than in the spec.
  • Backoff Scaling Condition:
    • The spec scales down L4S backoff if qdelay < qdelay_target * 0.25 (Section 4.2.2.1).
    • The WebRTC implementation scales it down if !delay_based_congestion_control_.IsQueueDelayDetected(), which translates to queue_delay_avg_ <= queue_delay_target / 2 (default 30ms) (scream_v2.cc:L158).
  • L4S Alpha Bump:
    • When resetting the reference window after a long period of inactivity (> 100 RTTs), the WebRTC implementation also bumps l4s_alpha_ to 0.25 to ensure a rapid reaction if congestion re-occurs (scream_v2.cc:L187). This is not explicitly specified in the spec.
  • Inflection Point (ref_window_i) Update Logic:
    • Spec: ref_wnd_i is updated to ref_wnd immediately when any congestion event is detected, protected by a simple time-based guard: it cannot be updated more than once every 10 RTTs (Section 4.2.2.1).
    • WebRTC: Implements a state-based guard using allow_ref_window_i_update_. It only updates ref_window_i_ when a net decrease in ref_window_ occurs, and then blocks further updates (allow_ref_window_i_update_ = false) until a net increase in ref_window_ has been observed. This ensures ref_window_i_ captures the true peak before a congestion episode and is not dragged down by consecutive back-to-back reductions. See scream_v2.cc:L259-L271.
4.2.2.2. Reference Window Increase
  • RTT Scaling for Small RTTs:
    • The spec scales down the window increase linearly using s_rtt / VIRTUAL_RTT (Section 4.2.2.2).
    • The WebRTC implementation scales it down using the square of the RTT ratio (rtt_ratio * rtt_ratio) and also includes feedback_hold_time_ in the RTT calculation: (rtt + feedback_hold) / virtual_rtt. This results in a more aggressive reduction of the increase rate for very small RTTs. See scream_v2.cc:L209-L215.
  • Application Limited State (ALR) Tracking:
    • Spec: The spec discusses limiting the reference window growth when the amount of data in flight is small to avoid window inflation (“Increase ref_wnd only if bytes in flight is large enough”) and recommends stopping the increase if target_bitrate reaches TARGET_BITRATE_MAX (Section 4.2.2.2).
    • WebRTC: Implements a formal, explicit Application Limited State (ALR) tracking mechanism (enabled by default via EnableAlr field trial). The sender enters ALR when the maximum data in flight during the last RTTs is insufficient to fill the reference window (max_allowed_ref_window() < ref_window_). See scream_v2.cc:L68-L70.
    • ALR Effects in WebRTC: Entering ALR has three major impacts to ensure stability during sparse traffic periods:
      1. Halts Window Growth: The reference window ref_window_ is strictly prevented from increasing. See scream_v2.cc:L253.
      2. Slows RTT Smoothing: The EWMA gain used for smoothing the RTT is drastically reduced from 1/8 to 1/128 (smoothed_rtt_avg_in_alr_g). This prevents RTT estimates from being corrupted by sparse, potentially delayed feedback samples when traffic is low. See delay_based_congestion_control.cc:L101.
      3. Freezes Feedback Hold Time Updates: The running average of the receiver's feedback hold time is not updated during ALR, preventing stale or atypical delay samples from affecting the average. See scream_v2.cc:L74.

4.3. Sender Transmission Control

4.3.1. Send Window Calculation

  • The WebRTC implementation calculates the maximum allowed data in flight (send window) in ScreamV2::max_data_in_flight() (scream_v2.cc:L286-L297) using the same formula as the spec: ref_window * ref_wnd_overhead (Section 4.3.1).
  • However, it uses ref_window_scale_factor_due_to_avg_min_delay(true) instead of qdelay_dev_norm to dynamically adjust ref_wnd_overhead between REF_WND_OVERHEAD_MIN (1.5) and REF_WND_OVERHEAD_MAX (3.0).

4.3.2. Packet Pacing

  • No Relaxed Pacing Logic:
    • The spec describes a complex “relaxed pacing” mechanism that increases the pacing rate (effectively allowing larger bursts) when the target bitrate is close to the maximum, to reduce application-layer latency (Section 4.3.2).
    • The WebRTC implementation does not implement relaxed pacing in the SCReAM module. Instead, it calculates a simple pacing_rate as target_rate_ * pacing_factor (default factor 1.1) in scream_v2.h:L50 and delegates the actual pacing to the standard WebRTC pacer via ScreamNetworkController::MaybeCreatePacerConfig.
  • Bandwidth Probing and Periodic Padding (WebRTC Addition):
    • Spec: The spec does not define any mechanism for bandwidth probing or background padding.
    • WebRTC: Adds a comprehensive probing and periodic padding mechanism to quickly discover and maintain link capacity estimates, especially during inactivity or at call start. This is implemented in scream_network_controller.cc:L224 and controlled by WebRTC-specific parameters (e.g., initial_probing_duration, time_between_periodic_padding, periodic_padding_duration, allow_padding_after_last_congestion_time) defined in scream_v2_parameters.h.

4.4. Media Rate Control

  • Simplified Target Rate Calculation (Missing Compensations):
    • The spec describes a complex media rate control that adjusts the target rate using rate_adjust_factor (to compensate for media queue buildup) and frame_size_dev (to compensate for varying frame sizes) (Section 4.4).
    • The WebRTC implementation does not implement these compensations. This is marked as a TODO in scream_v2.cc:L359.
    • Instead, it uses a simplified formula: target_rate = scale_target_rate * (ref_window_ / (smoothed_rtt + feedback_hold_time_)) (where scale_target_rate scales down the rate slightly if the window is very small). See scream_v2.cc:L321-L335.
  • Queue Draining Logic:
    • The WebRTC implementation adds a custom “drain queue” logic. If the minimum queue delay remains above a threshold (queue_delay_drain_threshold, default 5ms) for a prolonged period (queue_delay_drain_period, default 20s), it temporarily halves the target rate for a few RTTs to attempt to drain the queue. If this fails, it resets the queue delay estimate. See scream_v2.cc:L336-L357. This is not explicitly part of Section 4.4 in the spec, but serves as a robust guard against persistent queue build-up.

4.5. Clock drift issues and remedies

  • Implementation Details:
    • The spec describes a clock drift remedy that tracks qdelay_min over an RTT, averages it, and triggers a reset and 50% rate reduction if qdelay_min_avg > qdelay_target / 4 (Section 4.5).
    • The WebRTC implementation uses a sliding window minimum filter (base_delay_history_ with window length 10) in DelayBasedCongestionControl to track the base delay and compensate for clock drift. The history is updated every 1 minute (base_delay_history_update_interval).
    • The “drain queue” logic in UpdateTargetRate (described in Section 4.4 above) acts as the practical trigger for resetting the queue delay estimate if clock drift (or other non-congestion factors) causes the one-way delay to increase permanently.