<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE rfc [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">
]>
<?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>
<!-- generated by https://github.com/cabo/kramdown-rfc version 1.7.43 (Ruby 3.4.9) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-ageneau-ccwg-ndtc-03" category="info" consensus="true" submissionType="IETF" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.34.1 -->
  <front>
    <title abbrev="NDTC">Network Delivery Time Control</title>
    <seriesInfo name="Internet-Draft" value="draft-ageneau-ccwg-ndtc-03"/>
    <author fullname="Paul-Louis Ageneau">
      <organization>Netflix</organization>
      <address>
        <email>pageneau@netflix.com</email>
      </address>
    </author>
    <author fullname="Grenville Armitage">
      <organization>Independent</organization>
      <address>
        <email>gja.ietf@gmail.com</email>
      </address>
    </author>
    <author fullname="Scott Danahy">
      <organization>Netflix</organization>
      <address>
        <email>sdanahy@netflix.com</email>
      </address>
    </author>
    <date year="2026" month="November" day="02"/>
    <area>Web and Internet Transport</area>
    <workgroup>Congestion Control Working Group</workgroup>
    <keyword>rate adaptation</keyword>
    <keyword>real-time</keyword>
    <keyword>low-latency video</keyword>
    <abstract>
      <?line 85?>

<t>This document describes Network Delivery Time Control (NDTC), a rate
adaptation algorithm for real-time video streaming suited for
interactive applications like cloud gaming. NDTC leverages the Frame
Dithering Available Capacity Estimation (FDACE) heuristic, which
estimates available path capacity without inducing congestion.
The algorithm dynamically adjusts frame sizes and transmission
times to ensure timely delivery, while also responding to
conventional congestion signals.</t>
    </abstract>
    <note removeInRFC="true">
      <name>About This Document</name>
      <t>
        The latest revision of this draft can be found at <eref target="https://paullouisageneau.github.io/draft-ageneau-ccwg-ndtc/draft-ageneau-ccwg-ndtc.html"/>.
        Status information for this document may be found at <eref target="https://datatracker.ietf.org/doc/draft-ageneau-ccwg-ndtc/"/>.
      </t>
      <t>
        Discussion of this document takes place on the
        Congestion Control Working Group Working Group mailing list (<eref target="mailto:ccwg@ietf.org"/>),
        which is archived at <eref target="https://mailarchive.ietf.org/arch/browse/ccwg/"/>.
        Subscribe at <eref target="https://www.ietf.org/mailman/listinfo/ccwg/"/>.
      </t>
      <t>Source for this draft and an issue tracker can be found at
        <eref target="https://github.com/paullouisageneau/draft-ageneau-ccwg-ndtc"/>.</t>
    </note>
  </front>
  <middle>
    <?line 96?>

<section anchor="introduction">
      <name>Introduction</name>
      <t>This document specifies implementation details and considerations for
Network Delivery Time Control (NDTC) <xref target="NDTC-LCN"/>, a rate
adaptation and congestion control algorithm for real-time, interactive video flows
which adapts the target frame size to fit within the available
path capacity, proactively minimizing self-induced congestion.
NDTC also reacts to traditional packet loss signals and is compatible
with networks that implement the Low Latency, Low Loss, and Scalable Throughput (L4S)
Internet Service.</t>
      <t>NDTC's characteristics make it ideal for high-bitrate, real-time,
interactive applications:</t>
      <ul spacing="normal">
        <li>
          <t>It does not self-induce congestion, keeping queueing delays and
packet loss to a minimum,</t>
        </li>
        <li>
          <t>Ramp up is fast with no risk of overshoot, even at high bitrates,</t>
        </li>
        <li>
          <t>The encoded video is not required to closely follow the target bitrate,
and there is no need to send filler data.</t>
        </li>
      </ul>
      <t>These properties make it particularly suited for interactive
cloud gaming applications, and (potentially) for bitrate ladder rung
selection in low-latency video applications.</t>
      <t>At a very high level, when NDTC is applied to cloud gaming it continuously
runs the following loop:</t>
      <ul spacing="normal">
        <li>
          <t>Pace each video frame's packets at a rate between 1x and 2x (on average)
our current estimate of available path capacity, in order to probe the
network path for additional capacity while minimizing burst load on network
bottlenecks.</t>
        </li>
        <li>
          <t>Set the target frame size of the video encoder to a fraction of the
available capacity estimate, thus keeping frame delivery latencies low.</t>
        </li>
      </ul>
      <t>Each frame's paced packet train is a probe to test and update our
estimate of available capacity, and thus continuously update our
upper bound on the next encoded video frame's size.</t>
    </section>
    <section anchor="conventions-and-definitions">
      <name>Conventions and Definitions</name>
      <t>The key words "<bcp14>MUST</bcp14>", "<bcp14>MUST NOT</bcp14>", "<bcp14>REQUIRED</bcp14>", "<bcp14>SHALL</bcp14>", "<bcp14>SHALL
NOT</bcp14>", "<bcp14>SHOULD</bcp14>", "<bcp14>SHOULD NOT</bcp14>", "<bcp14>RECOMMENDED</bcp14>", "<bcp14>NOT RECOMMENDED</bcp14>",
"<bcp14>MAY</bcp14>", and "<bcp14>OPTIONAL</bcp14>" in this document are to be interpreted as
described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/> when, and only when, they
appear in all capitals, as shown here.</t>
      <?line -18?>

</section>
    <section anchor="general-principle">
      <name>General Principle</name>
      <t>A key requirement for real-time video is ensuring
each frame arrives on time to be presented. Consequently,
NDTC focuses on timely frame delivery rather than attempting to maximize throughput.
NDTC aims to ensure each frame reception duration is shorter than a frame period,
providing sufficient headroom to ensure high probability of each frame arriving in time.
In practice, the control loop of the algorithm stabilizes the frame reception
duration by dynamically setting the target frame size to a fraction of the
estimated path capacity.</t>
      <t>NDTC introduces and relies on Frame Dithering Available Capacity Estimation (FDACE),
a heuristic that paces packetized frames over a dithered send duration and
estimates available path capacity from the relationship between send
durations and observed receive durations. Importantly, capacity estimation is performed
without injecting additional traffic (beyond the video stream we wish to deliver)
or filling the path bottleneck to capacity. We then ensure that the flow uses only a
fraction of the measured capacity to prevent risks of self-induced congestion.</t>
      <t>This process is combined with an
AIMD (Additive Increase Multiplicative Decrease) congestion control process
for compatibility with both packet loss congestion signals and ECN (Explicit
Congestion Notification) <xref target="RFC9331"/> for the L4S (Low Latency, Low Loss, and
Scalable Throughput) Internet Service <xref target="RFC9330"/>.</t>
      <t>For the rest of this document we describe NDTC based on the following mental model:</t>
      <ul spacing="normal">
        <li>
          <t>The server is encoding video on-the-fly at a frame rate <tt>1/TFRAME</tt> (where <tt>TFRAME</tt>
is the frame period), while capping each frame to a video frame size target <tt>TARGET</tt>.</t>
        </li>
        <li>
          <t>The server forms a path capacity probe by pacing the frame's constituent packets
out over target send duration <tt>TSEND</tt>.</t>
        </li>
        <li>
          <t>The path's estimated available capacity <tt>AVAILABLE</tt> is continuously updated using
each frame's actual send and receive durations (<tt>SEND</tt> and <tt>RECV</tt> respectively).</t>
        </li>
        <li>
          <t><tt>TARGET</tt> is recalculated whenever <tt>AVAILABLE</tt> changes to ensure the next <tt>RECV</tt> is
stabilized around target reception duration <tt>TRECV</tt>.</t>
        </li>
        <li>
          <t>Additionally, <tt>TARGET</tt> is capped by a combined AIMD process reacting to congestion
signals like packet loss and ECN.</t>
        </li>
      </ul>
      <t>To properly probe the path, <tt>TSEND</tt> <bcp14>MUST</bcp14> be a fraction of <tt>TRECV</tt>, and to minimize on-path
congestion, <tt>TRECV</tt> <bcp14>MUST</bcp14> be a fraction of <tt>TFRAME</tt>.
We RECOMMEND that <tt>TRECV = 0.6 * TFRAME</tt> and <tt>TSEND = 0.5 * TRECV</tt>.
(For example, sending at 30fps would result in <tt>TFRAME = 33ms</tt>, <tt>TRECV = 20ms</tt>
and <tt>TSEND = 10ms</tt>.)</t>
      <t>Note: NDTC focuses on uncovering <em>enough</em> available capacity to meet the application's
needs, it is not trying to instantly discover <em>all</em> the available
capacity on a path. Specifically, choosing <tt>TSEND = 0.5 * TRECV</tt> limits FDACE to
probing up to <tt>2.0 * AVAILABLE</tt> in any single iteration of the FDACE heuristic.</t>
      <t>NDTC initializes <tt>TARGET</tt> to <tt>INIT_TARGET</tt>, and whenever <tt>TARGET</tt> is recalculated
the result is constrained to <tt>MIN_TARGET &lt;= TARGET &lt;= MAX_TARGET</tt>. Actual values
for the <tt>INIT_TARGET</tt>, <tt>MIN_TARGET</tt> and <tt>MAX_TARGET</tt> parameters are application-specific.</t>
    </section>
    <section anchor="algorithm-overview">
      <name>Algorithm Overview</name>
      <t>This section details implementation of the whole NDTC feedback loop
using variable and parameter names summarized
in section <xref target="variables-and-parameters"/> (rather than the more
mathematically-oriented names used in NDTC's conference paper <xref target="NDTC-LCN"/>).</t>
      <section anchor="illustrating-using-rtprtcp">
        <name>Illustrating using RTP/RTCP</name>
        <t>Although NDTC can be implemented for various real-time video transport
protocols, this document illustrates the use of NDTC to support
applications using RTP/RTCP <xref target="RFC3550"/>.</t>
        <t>In particular, NDTC operates on a single video stream and it is frame-oriented.
References to a "frame" in the rest of this document mean a sequence of
consecutive RTP packets having the same SSRC and RTP timestamp and ending
with a packet whose RTP marker bit is set.</t>
        <t>Defining a frame when NDTC is used for non-RTP flows
is currently outside the scope of this document.</t>
        <t>NDTC can be generalized to transports with multiple video streams by running
an instance of the algorithm for each video stream. This is currently outside
the scope of this document.</t>
      </section>
      <section anchor="architecture-considerations">
        <name>Architecture Considerations</name>
        <t>NDTC can be implemented either sender-side or receiver-side depending on the
application's needs.</t>
        <t>In the following discussion, the "agent" refers to the entity running the NDTC algorithm.
A core requirement to execute FDACE is that, for every frame, the agent
learns the precise durations over which a given frame was sent (<tt>SEND</tt>)
and received (<tt>RECV</tt>). Recommendations for transmitting this timing information between
senders and receivers are discussed in subsequent sections.</t>
        <t>If the agent is the sender, the algorithm runs on every frame feedback. If the
agent is the receiver, the algorithm runs as soon as a frame is received and
sends the updated target frame size (<tt>TARGET</tt>) to the server.</t>
        <section anchor="sender-side-agent">
          <name>Sender-side Agent</name>
          <t>Sender-side NDTC can be instantiated by having receivers
pass <tt>RECV</tt> back to the sender inside existing
RTCP-based Feedback for Congestion Control <xref target="RFC8888"/> or
Transport-wide Congestion Control (TWCC) <xref target="draft-holmer-rmcat-transport-wide-cc-extensions"/>
reports. Alternatively, an implementor might introduce application-specific
RTCP feedback to make messages smaller and achieve better precision.</t>
          <t>The receiver is also required to report which packets have not been received
(as described in <xref target="loss"/>) and <bcp14>SHOULD</bcp14> also reflect Explicit Congestion Notification (ECN)
markings of received packets (if support for L4S is desired).</t>
          <t>In this scenario, the agent has local control of the underlying
packet pacer and video encoder.</t>
        </section>
        <section anchor="receiver-side-agent">
          <name>Receiver-side Agent</name>
          <t>Receiver-side NDTC requires the receiver to regularly pass back updates
to <tt>TARGET</tt> (to properly control the video encoder) and <tt>SLOPE</tt>
(section <xref target="fdace"/>) to properly control the packet pacer. This may
be achieved with e.g. RTCP messages like Receiver Estimated Maximum Bitrate (REMB)
<xref target="draft-alvestrand-rmcat-remb"/>.</t>
          <t>Note: if the receiver agent cannot pass back <tt>SLOPE</tt> information, the sender's
pacing heuristic <bcp14>SHOULD</bcp14> assume <tt>SLOPE = 1</tt>.</t>
        </section>
        <section anchor="timing-and-timestamping">
          <name>Timing and Timestamping</name>
          <t>The precision with which <tt>SEND</tt> and <tt>RECV</tt> are measured and reported
<bcp14>MUST</bcp14> be 1ms or better, because the durations are typically around a few
milliseconds only, and a lower precision would not be sufficient to obtain a
consistent estimate, even by averaging multiple samples.
We RECOMMEND a precision of 0.1ms.</t>
          <t>If the agent is implemented sender-side, we assume the agent derives <tt>SEND</tt>
from local knowledge (e.g. timestamps generated low in the networking stack),
and learns <tt>RECV</tt> from reports passed back by the receiver.</t>
          <t>If the agent is implemented receiver-side, we assume the agent derives <tt>RECV</tt>
from local knowledge (e.g. kernel timestamps from the underlying network
interface) and learns <tt>SEND</tt> via in-band messages from the sender. For instance,
the sender can write the effective send time on each packet just before it goes
out using the <xref target="abs-send-time"/> RTP extension.</t>
        </section>
      </section>
      <section anchor="fdace">
        <name>Frame Dithering Available Capacity Estimation (FDACE)</name>
        <t>FDACE calculates an estimated available capacity <tt>AVAILABLE</tt> and a slope <tt>SLOPE</tt>
given send and receive durations for a frame.</t>
        <t>Frame size <tt>LENGTH</tt> is calculated by summing up packet payload sizes for the frame
according to <xref target="framesize"/>.
Therefore <tt>AVAILABLE</tt> will actually refer to application-layer
capacity expressed in terms of video bitrate.</t>
        <t>If the frame consists of a single packet, if <tt>LENGTH</tt> is strictly less than
<tt>MIN_LENGTH</tt>, or if the frame suffered packet loss in the sense of <xref target="loss"/>,
the agent does not run FDACE.
Instead, it retains the <tt>TARGET</tt> and <tt>SLOPE</tt> values from the most recent frame
for which FDACE ran and immediately jumps to the AIMD congestion control
described in <xref target="congestion"/>.</t>
        <t>If the frame was packetized as 2 packets or more and suffered no packet loss,
the agent first calculates the normalized send duration <tt>NSEND</tt> and the
normalized reception duration <tt>NRECV</tt> for the frame by respectively dividing
frame send duration <tt>SEND</tt> and frame receive duration <tt>RECV</tt> by frame size
<tt>LENGTH</tt>.</t>
        <artwork><![CDATA[
NSEND = SEND / LENGTH
NRECV = RECV / LENGTH
]]></artwork>
        <t>Send duration <tt>SEND</tt> corresponds to the elapsed time between sending the first
packet and sending the last packet of the frame (i.e. the one with the RTP marker).
<tt>SEND</tt> <bcp14>MUST</bcp14> be the actual duration over which the pacer sent the frame,
not the calculated target duration from <xref target="pacer"/>.
Packet send times <bcp14>SHOULD</bcp14> be measured as close to socket send calls as possible.</t>
        <t>Receive duration <tt>RECV</tt> corresponds to the elapsed time between reception of
the first packet and reception of the last packet of the frame (i.e. the one
with the RTP marker). Note there is no need for sender and receiver clock
synchronization.
In practice, packet reception times <bcp14>SHOULD</bcp14> be measured using kernel timestamps
for enhanced precision, as the application might take significant time to
receive packets in userspace.
The agent <bcp14>SHOULD</bcp14> cap <tt>RECV</tt> to a small multiple of the frame period in order to
mitigate outliers caused by transient adverse network events while still
allowing the value to grow large enough to capture bursts of cross-traffic
and reflect sudden path capacity reductions.
The <bcp14>RECOMMENDED</bcp14> maximum value for <tt>RECV</tt> is <tt>3*TFRAME</tt>.</t>
        <t>A dual-variable EWMA process is updated with the new sample <tt>(NSEND, NRECV)</tt>.
The process calculates the averages <tt>AVG_NSEND</tt>, <tt>AVG_NRECV</tt>, the variances
<tt>VAR_NSEND</tt> and <tt>VAR_NRECV</tt>, and the covariance <tt>COVAR</tt>.
The <bcp14>RECOMMENDED</bcp14> weight is <tt>LAMBDA = 0.04</tt>.
A suitable implementation of the dual-variable EWMA process is detailed
in <xref target="ewma-implementation"/>.</t>
        <t>The agent now derives the linear regression parameters from the output of the
EWMA process. The slope <tt>SLOPE</tt> and y-intercept <tt>INTERCEPT</tt> of the linear
equation <tt>NRECV = SLOPE * NSEND + INTERCEPT</tt> are calculated as follows:</t>
        <artwork><![CDATA[
if (VAR_NSEND > 0.0 && COVAR > 0.0) {
    SLOPE = min(COVAR / VAR_NSEND, 1.0)
} else {
    SLOPE = 0.0
}
INTERCEPT = max(AVG_NRECV - SLOPE * AVG_NSEND, 0.0)
]]></artwork>
        <t><tt>SLOPE</tt> reflects how pacing frames changes their reception as they go through
the path bottleneck and intercept more or less cross-traffic. The relationship
is locally linear because we observe normalized times and not rates, and network
path components behave linearly in terms of processing time per byte to a good
approximation.</t>
        <t>If the path is not constraining, for instance during ramp-up, receive duration
is always equal to send duration, and <tt>SLOPE = 1</tt>, which can be interpreted as
the path capacity looking infinite.</t>
        <t>If there is no visible cross-traffic and the flow is alone at
bottleneck, the slope <tt>SLOPE</tt> is 0, the send rate does not matter as we always
receive at bottleneck rate.
If cross-traffic takes most of the bottleneck capacity, <tt>SLOPE</tt> is close to 1.
More generally, we can calculate that in a single FIFO bottleneck scenario
with constant-rate cross traffic, <tt>SLOPE</tt> is the fraction of the bottleneck
capacity occupied by cross-traffic. However, this statement does not hold
true in all scenarios. FDACE does not require such a simple scenario and
performs correctly in more complex network setups, for instance with more
advanced AQM (Active Queue Management) disciplines (see <xref target="aqm"/>).</t>
        <t>The y-intercept <tt>INTERCEPT</tt> reflects the normalized receive duration that we
would measure if the frame was sent as an unpaced burst, reflecting total path
capacity.</t>
        <t>The agent extrapolates <tt>ESTIMATE</tt>, the normalized reception duration that we
would measure if the frame was sent at receive rate, reflecting available
capacity on the path. It corresponds to the ordinate of intersection with
the identity line <tt>NRECV = NSEND</tt>.</t>
        <t>In order to be robust when <tt>SLOPE</tt> is close or equal to 1, <tt>ESTIMATE</tt> is
approximated with successive iterations from <tt>AVG_NRECV</tt> and converging to the
intersection.
The <bcp14>RECOMMENDED</bcp14> number of iterations is <tt>ITERATIONS = 3</tt>. If <tt>ITERATIONS</tt> is
too low, NDTC will overestimate the available capacity in the presence of
cross-traffic. If <tt>ITERATIONS</tt> is higher, NDTC yields more easily against
elastic cross-traffic.</t>
        <artwork><![CDATA[
ESTIMATE = AVG_NRECV
for (i = 0; i < ITERATIONS; i++) {
    ESTIMATE = SLOPE * ESTIMATE + INTERCEPT
}
]]></artwork>
        <t>This means that when the flow is not constrained and <tt>SLOPE = 1</tt>,
<tt>ESTIMATE = AVG_NRECV</tt>, which is a conservative estimate for the capacity.</t>
        <t>For increased simplicity and performance in CPU-constrained environments,
the loop <bcp14>MAY</bcp14> be unrolled as noted in <xref target="estimate-implementation"/>.</t>
        <t>The agent <bcp14>SHOULD</bcp14> add a conservative margin <tt>MARGIN</tt> to <tt>ESTIMATE</tt>, increasing
with the linear regression error. The idea is that when the model fits poorly,
the agent should add a higher margin as a safety buffer.
The <bcp14>RECOMMENDED</bcp14> formula to calculate <tt>MARGIN</tt> is to multiply a constant
<tt>KMARGIN</tt> by the standard deviation of <tt>NRECV</tt> and <tt>1-R2</tt> where <tt>R2</tt> is the
coefficient of determination representing the proportion of variation in
<tt>NRECV</tt> explained by the linear regression. The <bcp14>RECOMMENDED</bcp14> value for <tt>KMARGIN</tt>
is 0.25. A value too close to 0 makes the algorithm react slower to abrupt
changes. A value too high for <tt>KMARGIN</tt> makes the algorithm significantly underestimate
the capacity in the presence of bursty cross traffic.</t>
        <artwork><![CDATA[
if (VAR_NSEND > 0.0 && VAR_NRECV > 0.0) {
    R2 = COVAR^2 / (VAR_NSEND * VAR_NRECV)
    MARGIN = KMARGIN * sqrt(VAR_NRECV) * (1-R2)
} else {
    MARGIN = 0.0
}
]]></artwork>
        <t>Available capacity <tt>AVAILABLE</tt> is calculated by taking the reciprocal of
the sum <tt>ESTIMATE + MARGIN</tt>:</t>
        <artwork><![CDATA[
AVAILABLE = 1.0 / (ESTIMATE + MARGIN)
]]></artwork>
      </section>
      <section anchor="target">
        <name>Target Frame Size from Available Capacity</name>
        <t>Before FDACE and the combined congestion control run for the first time,
<tt>TARGET</tt> is initialized to <tt>INIT_TARGET</tt> and <tt>SLOPE</tt> is initialized to 1.0.</t>
        <t>Each time FDACE runs and updates the available capacity, the agent now derives
the new target frame size <tt>TARGET</tt> from <tt>TRECV</tt> and <tt>AVAILABLE</tt> and caps it to
<tt>MAX_TARGET</tt>.</t>
        <artwork><![CDATA[
TARGET = min(TRECV * AVAILABLE, MAX_TARGET)
]]></artwork>
        <t>The agent <bcp14>MUST</bcp14> cap <tt>TARGET</tt> to <tt>MAX_TARGET</tt> even if the encoder has its own internal
maximum frame size to prevent a runaway feedback loop in case the path capacity
is very large. Without capping, NDTC would continue increasing the target frame
size until it matches the available path capacity even if the encoded video can't
follow it, pacing over shorter and shorter durations in the process.
Frames would be sent as very short bursts, increasing the risk of packet loss.
<tt>MAX_TARGET</tt> <bcp14>SHOULD</bcp14> be a sensible frame size that the video content can
realistically reach.</t>
      </section>
      <section anchor="congestion">
        <name>Combined AIMD Congestion Control</name>
        <t>Even if FDACE can successfully run on its own most of the time, it doesn't react
to conventional indications of network congestion, in particular packet loss,
whereas reacting to packet loss is essential in the presence of a policer on the
path. Therefore, NDTC combines an AIMD (Additive Increase Multiplicative
Decrease) process with FDACE to also adjust the frame size and send duration in
response to conventional congestion feedback. It allows the algorithm to
seamlessly transition between capacity estimation and congestion signals,
following the path evolution.</t>
        <t>The AIMD process computes a congestion target frame size <tt>CTARGET</tt> and a
pseudo-slope <tt>CSLOPE</tt> to respectively cap <tt>TARGET</tt> and <tt>SLOPE</tt>, in order to limit
the effective pacer rate. See <xref target="pacer"/> for details about how the pacer adapts
the sending duration according to the slope.</t>
        <ul spacing="normal">
          <li>
            <t>When <tt>CTARGET &lt; TARGET</tt>, the flow is congestion-limited, therefore <tt>TARGET</tt>
is set to <tt>CTARGET</tt> and <tt>CSLOPE</tt> is set to 0.0 so the pacer sends at rate
<tt>CTARGET / TRECV</tt>.</t>
          </li>
          <li>
            <t>When <tt>CTARGET &gt;= TARGET</tt>, the flow is not congestion limited, therefore
<tt>TARGET</tt> is unchanged and <tt>CSLOPE</tt> is set so that the pacer send duration
results in a send rate around <tt>CTARGET / TRECV</tt>.</t>
          </li>
          <li>
            <t>When <tt>CTARGET</tt> reaches <tt>TARGET * TRECV / TSEND</tt>, <tt>CSLOPE</tt> reaches 1.0 and
the pacer reaches its minimum send duration and maximum send rate around
<tt>TARGET/TRECV</tt>.</t>
          </li>
        </ul>
        <t>Therefore, the maximum congestion frame size for the AIMD logic is defined to
correspond to the maximum send rate:</t>
        <artwork><![CDATA[
CMAX = TARGET * TRECV / TSEND
]]></artwork>
        <t>For each transmitted frame, the agent identifies whether packets of the frame were
lost as described in <xref target="loss"/>, and runs the AIMD logic to update a congestion
frame size <tt>CSIZE</tt>. <tt>CSIZE</tt> <bcp14>SHOULD</bcp14> be initialized to <tt>MAX_TARGET</tt> as in most
cases FDACE should be self-sufficient.</t>
        <t>If one or more packets were lost, the agent performs a decrease by capping
<tt>CSIZE</tt> to <tt>CMAX</tt> and multiplying it by <tt>BETA</tt>. If no packets were lost
and <tt>CSIZE</tt> is less than <tt>CMAX</tt>, the agent increases <tt>CSIZE</tt> by adding
<tt>ALPHA</tt>, then caps the result to <tt>CMAX</tt>.
The <bcp14>RECOMMENDED</bcp14> values are <tt>ALPHA=40 bytes</tt> and <tt>BETA=0.7</tt> to make increase
and decrease relatively conservative and minimize QoE reduction.</t>
        <t>The AIMD logic <bcp14>SHOULD NOT</bcp14> feature a slow start phase and both decrease and
increase <bcp14>SHOULD</bcp14> be suppressed for one round-trip after a loss event.
In order to support L4S <xref target="RFC9330"/>, the agent <bcp14>SHOULD</bcp14> also react similarly
to Prague congestion control <xref target="draft-briscoe-iccrg-prague-congestion-control"/>,
which requires supporting ECN <xref target="RFC9331"/>, and if the agent is the sender, it also
requires compatible feedback like <xref target="RFC8888"/>. If the last ECN decrease is
more recent than the last packet loss event, the increase <bcp14>SHOULD</bcp14> be performed
by adding a larger <tt>EALPHA</tt> instead of <tt>ALPHA</tt> for the flow to compete more
fairly with other flows. The <bcp14>RECOMMENDED</bcp14> value is <tt>EALPHA=400 bytes</tt>.</t>
        <t>The <bcp14>RECOMMENDED</bcp14> algorithm is described in <xref target="aimd-implementation"/>.</t>
        <t>If the agent is the sender, it <bcp14>SHOULD</bcp14> also perform the decrease in case it
does not get any feedback for a significant duration after sending a frame.
In any case, the sender <bcp14>SHOULD</bcp14> implement a circuit breaker to stop sending
after it stops receiving feedback for a significant duration, following the
recommendations in <xref target="RFC8083"/>.</t>
        <t>The congestion frame size <tt>CTARGET</tt> is calculated as the minimum of
<tt>CSIZE</tt> and <tt>CMAX</tt>:</t>
        <artwork><![CDATA[
CTARGET = min(CSIZE, CMAX)
]]></artwork>
        <t>Then, <tt>CSLOPE</tt> is calculated such that the average pacing rate is
<tt>CTARGET/TRECV</tt>. This is obtained by solving for <tt>CSLOPE</tt> in the pacer
equation in <xref target="pacer"/> such that when <tt>LENGTH = TARGET</tt>, the send
duration results in an effective send rate of <tt>CTARGET/TRECV</tt>:</t>
        <artwork><![CDATA[
CSLOPE = max(1 - (TSEND/TRECV) * (CMAX/CTARGET), 0) / (1 - TSEND/TRECV)
]]></artwork>
      </section>
      <section anchor="encoder">
        <name>Encoder Target Frame Size</name>
        <t>The agent caps the target frame size <tt>TARGET</tt> and the slope <tt>SLOPE</tt>
with <tt>CTARGET</tt> and <tt>CSLOPE</tt> respectively to take into account the most
conservative estimate:</t>
        <artwork><![CDATA[
TARGET = min(TARGET, CTARGET)
SLOPE = min(SLOPE, CSLOPE)
]]></artwork>
        <t>The agent <bcp14>MUST</bcp14> then floor <tt>TARGET</tt> to <tt>MIN_TARGET</tt>:</t>
        <artwork><![CDATA[
TARGET = max(TARGET, MIN_TARGET)
]]></artwork>
        <t>Flooring to <tt>MIN_TARGET</tt> is required to ensure that the whole feedback loop
does not get stuck producing 1-packet frames, which do not allow the agent
to run FDACE and update <tt>TARGET</tt>.
The <bcp14>RECOMMENDED</bcp14> value for <tt>MIN_TARGET</tt> is 2000 bytes as a frame of such a size
will be packetized into 2 packets of significant size given a typical path MTU.</t>
        <t>Note that the flow becomes unresponsive to congestion when the target frame size
is at <tt>MIN_TARGET</tt> (at 30fps, 2000 bytes correspond to 480Kbps), therefore,
care should be taken not to set this value too high as it could harm other flows.
This is particularly a concern in an L4S context, where the consideration is
similar to the fractional window tradeoff for a Prague congestion controller
<xref target="draft-briscoe-iccrg-prague-congestion-control"/>.</t>
        <t>The sender <bcp14>SHOULD</bcp14> set the encoder target frame size to <tt>TARGET</tt> as soon as possible
(i.e. the encoder target bitrate is set to <tt>TARGET/TFRAME</tt>).</t>
      </section>
      <section anchor="pacer">
        <name>Adaptive Frame Pacer</name>
        <t>When a new video frame is generated at the sender, it is first packetized
into RTP packets.
The exact packetization process depends on video codec. The sender
<bcp14>SHOULD</bcp14> first pad the frame to <tt>MIN_TARGET</tt> with codec-specific bitstream filler
data if it is smaller. A frame of size <tt>MIN_TARGET</tt> or larger <bcp14>MUST</bcp14> be packetized
in at least 2 packets. The sender <bcp14>SHOULD</bcp14> also attempt to packetize the frame
into packets of similar sizes. The sender <bcp14>MAY</bcp14> add RTP padding as specified
in <xref target="RFC3550"/> to help make packet sizes similar.</t>
        <t>The sender now calculates the desired send duration <tt>SEND</tt> for the frame.</t>
        <t>When not at bottleneck, the send duration is around target send duration <tt>TSEND</tt>.
To ensure a positive feedback loop, <tt>TSEND</tt> <bcp14>MUST</bcp14> be strictly less than
<tt>TRECV</tt>, the <bcp14>RECOMMENDED</bcp14> value is <tt>TSEND = 0.5 * TRECV = 0.3 * TFRAME</tt>.</t>
        <t>The sender first calculates the base pacing duration <tt>PACE</tt> by adding dithering of
amplitude <tt>DELTA</tt> to <tt>TSEND</tt> and interpolating with <tt>TRECV</tt> according to
<tt>SLOPE</tt>. The <bcp14>RECOMMENDED</bcp14> value for <tt>DELTA</tt> is <tt>0.5*TSEND</tt>.
With <tt>rand()</tt> a pseudo-random value in <tt>\[-1, 1\]</tt>, <tt>PACE</tt> is calculated as:</t>
        <artwork><![CDATA[
PACE = SLOPE * (TSEND + rand() * DELTA) + (1 - SLOPE) * TRECV
]]></artwork>
        <t>Adapting the duration according to <tt>SLOPE</tt> reduces how aggressively NDTC paces
packets as the flow gets closer to filling the entire bottleneck.
It makes the feedback loop run closer to the desired operating point and
minimizes transient queueing for each frame.
It also helps FDACE by probing locally in non-linear scenarios and
stabilizes competition with other NDTC flows.</t>
        <t>The sender then scales the pacing duration proportionally to <tt>LENGTH/TARGET</tt>,
where the frame size <tt>LENGTH</tt> is calculated according to <xref target="framesize"/>.
This helps sustain the send rate when the encoder produces frames that don't
match the target frame size. For instance, the encoder may chronically
underproduce because the video is not dynamic or complex enough, and
it may temporarily overproduce on scene change.
Eventually, <tt>SEND</tt> is capped at the frame period <tt>TFRAME</tt>.</t>
        <artwork><![CDATA[
SEND = min(PACE * LENGTH/TARGET, TFRAME)
]]></artwork>
        <t>The sender also calculates a frame alignment delay as follows to reduce frame
jitter. The delay is calculated to compensate the send duration variation so
the last packets of frames are received at regular frame period intervals:</t>
        <artwork><![CDATA[
DELAY = SLOPE * max(PACE + SLOPE * DELTA - SEND, 0)
]]></artwork>
        <t>The packets of the frame are sent after <tt>DELAY</tt> over the duration <tt>SEND</tt>,
meaning that if the frame is available at <tt>t</tt>, the first packet is sent at
<tt>t + DELAY</tt> and the last packet (i.e. the one with the RTP marker) should be
sent at <tt>t + DELAY + SEND</tt>. Other packets are spread evenly over the interval.</t>
        <t>To achieve this, the sender <bcp14>SHOULD</bcp14> wait for duration <tt>DELAY</tt>, then for each packet
<tt>p</tt>, send it, then wait for an interval <tt>SEND * SIZE(p) / LENGTH</tt> where
<tt>SIZE(p)</tt> is the payload size for packet p.
The pacer <bcp14>SHOULD</bcp14> match send times with an absolute precision of at least 1ms.
It <bcp14>MUST</bcp14> prevent cumulative errors from actual wait durations being different
from expected durations.</t>
        <t>If ECN is not supported, the pacer does not need to precisely pace packets
besides the first and last one, and it <bcp14>MAY</bcp14> instead group packets in small
bursts to prevent waking up too often.</t>
        <t>In any case, the agent <bcp14>MUST</bcp14> use the actually achieved send duration, not the
calculated pacing duration, when running FDACE for the frame.</t>
        <t>If FEC is enabled, the sender <bcp14>SHOULD NOT</bcp14> send FEC packets during duration <tt>SEND</tt>
and <bcp14>SHOULD</bcp14> instead pace FEC packets after it, spreading them so that the
interval between packets is calculated similarly to the interval for video
packets.</t>
        <t>If the sender supports retransmissions, the sender <bcp14>SHOULD</bcp14> handle retransmitted
packets separately. They <bcp14>SHOULD</bcp14> be paced and sent in parallel to video frames.
If the application features an audio stream, the sender <bcp14>SHOULD</bcp14> handle audio
packets separately. They <bcp14>SHOULD</bcp14> be sent immediately after they are generated,
without adding a delay.
This means retransmissions and audio packets can be sent between two video
packets. From the point of view of FDACE, they will be accounted for as
cross-traffic sharing the same path.</t>
        <t>The pacer <bcp14>MUST</bcp14> handle the corner case where packets from the previous frame are
still waiting to be sent when the new frame is available, for instance because
the new frame is early. In this case, it is crucial to ensure that the previous
frame is fully sent before the new frame is sent. Therefore if packets from the
previous frame were to be sent after the first packet of the new frame, the
sender <bcp14>MUST</bcp14> reschedule the leftover packets to send them before the first packet
of the new frame.</t>
      </section>
    </section>
    <section anchor="implementation-details">
      <name>Implementation Details</name>
      <section anchor="variables-and-parameters">
        <name>Variables and Parameters</name>
        <t>The following table summarizes parameters used by the algorithm:</t>
        <table>
          <thead>
            <tr>
              <th align="left">Parameter</th>
              <th align="left">Description</th>
              <th align="left">Unit</th>
              <th align="left">Recommended</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="left">
                <tt>MIN_TARGET</tt></td>
              <td align="left">minimum target frame size</td>
              <td align="left">bytes</td>
              <td align="left">2000</td>
            </tr>
            <tr>
              <td align="left">
                <tt>MAX_TARGET</tt></td>
              <td align="left">maximum target frame size</td>
              <td align="left">bytes</td>
              <td align="left">-</td>
            </tr>
            <tr>
              <td align="left">
                <tt>INIT_TARGET</tt></td>
              <td align="left">initial target frame size</td>
              <td align="left">bytes</td>
              <td align="left">
                <tt>&lt;= MAX_TARGET/2</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>MIN_LENGTH</tt></td>
              <td align="left">minimum frame length to run FDACE</td>
              <td align="left">bytes</td>
              <td align="left">
                <tt>MIN_TARGET/2</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>TRECV</tt></td>
              <td align="left">target receive duration</td>
              <td align="left">seconds</td>
              <td align="left">
                <tt>0.6 * TFRAME</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>TSEND</tt></td>
              <td align="left">target send duration</td>
              <td align="left">seconds</td>
              <td align="left">
                <tt>0.5 * TRECV</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>ITERATIONS</tt></td>
              <td align="left">extrapolation iterations</td>
              <td align="left">-</td>
              <td align="left">3</td>
            </tr>
            <tr>
              <td align="left">
                <tt>ALPHA</tt></td>
              <td align="left">congestion additive increase</td>
              <td align="left">bytes</td>
              <td align="left">40</td>
            </tr>
            <tr>
              <td align="left">
                <tt>EALPHA</tt></td>
              <td align="left">congestion additive increase for ECN</td>
              <td align="left">bytes</td>
              <td align="left">400</td>
            </tr>
            <tr>
              <td align="left">
                <tt>BETA</tt></td>
              <td align="left">congestion multiplicative decrease</td>
              <td align="left">-</td>
              <td align="left">0.7</td>
            </tr>
            <tr>
              <td align="left">
                <tt>DELTA</tt></td>
              <td align="left">send dithering amplitude</td>
              <td align="left">seconds</td>
              <td align="left">
                <tt>0.5 * TSEND</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>LAMBDA</tt></td>
              <td align="left">regression EWMA weight</td>
              <td align="left">-</td>
              <td align="left">0.04</td>
            </tr>
            <tr>
              <td align="left">
                <tt>KMARGIN</tt></td>
              <td align="left">estimation margin constant</td>
              <td align="left">-</td>
              <td align="left">0.25</td>
            </tr>
            <tr>
              <td align="left">
                <tt>TFRAME</tt></td>
              <td align="left">video frame period</td>
              <td align="left">seconds</td>
              <td align="left">application-specific</td>
            </tr>
          </tbody>
        </table>
        <t>The following table summarizes variables used by the algorithm:</t>
        <table>
          <thead>
            <tr>
              <th align="left">Variable</th>
              <th align="left">Description</th>
              <th align="left">Unit</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="left">
                <tt>AVAILABLE</tt></td>
              <td align="left">estimated available capacity</td>
              <td align="left">bytes/second</td>
            </tr>
            <tr>
              <td align="left">
                <tt>DELAY</tt></td>
              <td align="left">pacing alignment delay</td>
              <td align="left">seconds</td>
            </tr>
            <tr>
              <td align="left">
                <tt>TARGET</tt></td>
              <td align="left">target frame size from FDACE</td>
              <td align="left">bytes</td>
            </tr>
            <tr>
              <td align="left">
                <tt>CTARGET</tt></td>
              <td align="left">target frame size from AIMD</td>
              <td align="left">bytes</td>
            </tr>
            <tr>
              <td align="left">
                <tt>LENGTH</tt></td>
              <td align="left">actual frame size</td>
              <td align="left">bytes</td>
            </tr>
            <tr>
              <td align="left">
                <tt>CMAX</tt></td>
              <td align="left">AIMD maximum frame size</td>
              <td align="left">bytes</td>
            </tr>
            <tr>
              <td align="left">
                <tt>CSIZE</tt></td>
              <td align="left">AIMD frame size</td>
              <td align="left">bytes</td>
            </tr>
            <tr>
              <td align="left">
                <tt>PACE</tt></td>
              <td align="left">base pacing duration</td>
              <td align="left">seconds</td>
            </tr>
            <tr>
              <td align="left">
                <tt>SEND</tt></td>
              <td align="left">send duration for the frame</td>
              <td align="left">seconds</td>
            </tr>
            <tr>
              <td align="left">
                <tt>RECV</tt></td>
              <td align="left">receive duration for the frame</td>
              <td align="left">seconds</td>
            </tr>
            <tr>
              <td align="left">
                <tt>SLOPE</tt></td>
              <td align="left">linear regression slope (a)</td>
              <td align="left">-</td>
            </tr>
            <tr>
              <td align="left">
                <tt>INTERCEPT</tt></td>
              <td align="left">linear regression y-intercept (b)</td>
              <td align="left">seconds/byte</td>
            </tr>
            <tr>
              <td align="left">
                <tt>ESTIMATE</tt></td>
              <td align="left">extrapolated estimate</td>
              <td align="left">seconds/byte</td>
            </tr>
            <tr>
              <td align="left">
                <tt>MARGIN</tt></td>
              <td align="left">estimation margin</td>
              <td align="left">seconds/byte</td>
            </tr>
            <tr>
              <td align="left">
                <tt>CSLOPE</tt></td>
              <td align="left">pseudo-slope from AIMD</td>
              <td align="left">-</td>
            </tr>
            <tr>
              <td align="left">
                <tt>NSEND</tt></td>
              <td align="left">normalized send duration</td>
              <td align="left">seconds/byte</td>
            </tr>
            <tr>
              <td align="left">
                <tt>NRECV</tt></td>
              <td align="left">normalized receive duration</td>
              <td align="left">seconds/byte</td>
            </tr>
            <tr>
              <td align="left">
                <tt>AVG_NSEND</tt></td>
              <td align="left">average of norm. send duration</td>
              <td align="left">seconds/byte</td>
            </tr>
            <tr>
              <td align="left">
                <tt>AVG_NRECV</tt></td>
              <td align="left">average of norm. receive duration</td>
              <td align="left">seconds/byte</td>
            </tr>
            <tr>
              <td align="left">
                <tt>VAR_NSEND</tt></td>
              <td align="left">variance of norm. send duration</td>
              <td align="left">(seconds/byte)^2</td>
            </tr>
            <tr>
              <td align="left">
                <tt>VAR_NRECV</tt></td>
              <td align="left">variance of norm. receive duration</td>
              <td align="left">(seconds/byte)^2</td>
            </tr>
            <tr>
              <td align="left">
                <tt>COVAR</tt></td>
              <td align="left">covariance of norm. send and receive durations</td>
              <td align="left">(seconds/byte)^2</td>
            </tr>
          </tbody>
        </table>
      </section>
      <section anchor="framesize">
        <name>Frame Size Calculation</name>
        <t>The frame size <tt>LENGTH</tt> is used for normalizing the send and receive durations in FDACE
and calculating the pacing duration. <tt>LENGTH</tt> is calculated as the sum of RTP payloads
corresponding to the frame (i.e. sharing the same timestamp). FEC and retransmitted
packets <bcp14>MUST NOT</bcp14> be counted in <tt>LENGTH</tt>.</t>
        <t>Since frame size is calculated from payload sizes only, FDACE will estimate an
application-layer capacity, and <tt>TARGET</tt> can be set directly as encoder target.
Implementors <bcp14>MAY</bcp14> choose to take into account RTP headers, and optionally UDP/IP headers.
In that case, capacity will more closely reflect network capacity, however target frame
size <bcp14>SHOULD</bcp14> be decreased by the typical header overhead before being set as encoder target.</t>
        <t>If the frame consists of two packets or more, send and receive durations do not
account for one of the extreme packets.
When sending, since the pacer waits after sending each packet, the sender <bcp14>SHOULD</bcp14>
sum up payload sizes except the last one.
When running FDACE, the agent does not know how the path exactly handles packets,
so it can't know for sure which payload to exclude at reception.
Therefore, in the context of FDACE, the agent <bcp14>SHOULD</bcp14> calculate <tt>LENGTH</tt> as the sum
of all payloads of the frame minus the average size of the first and last one.
It means that if the frame consists in two packets, <tt>LENGTH</tt> is half the sum of
the two payloads, i.e. the average packet size. This is why <tt>MIN_LENGTH</tt> should
be set to <tt>MIN_TARGET/2</tt>.
If the frame consists of a single packet, <tt>LENGTH</tt> is the size of the packet.</t>
        <t>Note that if the frame is packetized into packets of similar sizes as
recommended, which packet to exclude does not matter since the payload
sizes are the same.</t>
      </section>
      <section anchor="loss">
        <name>Loss Detection</name>
        <t>Packet loss is taken into account to decide if FDACE should be run for a frame
and to trigger AIMD decrease. Lost packets are detected by tracking
discontinuities in received sequence numbers.</t>
        <t>The receiver <bcp14>SHOULD</bcp14> reorder packets for the currently received frame (i.e.
timestamp) to avoid misclassifying reordered packets as lost. As soon as the
first packet of the next frame (i.e. timestamp) is received, missing packets for
the previous frame <bcp14>MUST</bcp14> be reported as lost. The receiver <bcp14>MUST</bcp14> consider a packet
as lost in the context of this algorithm even if it can be recovered with
Forward Error Correction or retransmission. Therefore, a frame triggering
packet loss reaction may still be successfully transmitted.</t>
      </section>
    </section>
    <section anchor="fairness">
      <name>Fairness Considerations</name>
      <t>As NDTC does not attempt to maximize throughput, it also does not attempt to
achieve throughput fairness in general. Targeting a reception duration means
that NDTC tends to yield to capacity seeking-flows, but it does not get starved.</t>
      <t>Thanks to its design, NDTC never takes more capacity than the combined AIMD
congestion control logic allows, so it is guaranteed not to starve traditional
capacity-seeking flows.</t>
    </section>
    <section anchor="aqm">
      <name>Active Queue Management Considerations</name>
      <t>As with interactive flows in general, NDTC flows greatly benefit
from AQM (Active Queue Management) disciplines.</t>
      <t>In the case of NDTC, flow queueing, for instance in FQ-CoDel <xref target="RFC8290"/>
or Cake <xref target="CAKE"/>, particularly helps FDACE as cross-traffic packets are
interleaved in each frame, providing stability in addition to fairness.
As NDTC adapts the send duration to pace close to available capacity,
Cake's DRR++ scheme additionally allows NDTC to have priority over bulk traffic.</t>
      <t>NDTC can also take advantage of L4S bottlenecks if the AIMD logic
behaves as a Prague congestion controller like suggested in <xref target="aimd-implementation"/>,
providing fairness with TCP Prague and traditional TCP flows.
An essential aspect is that NDTC can seamlessly transition between L4S and
standard bottlenecks as the network path evolves.</t>
    </section>
    <section anchor="security">
      <name>Security Considerations</name>
      <t>An attacker who could insert, edit, or drop messages from the connection could
cause NDTC to underutilize the path capacity or overshoot it, causing network
congestion. The RTP flow and RTCP feedback should be protected from message
injection and modification using SRTP.</t>
      <t>In a more sophisticated attack, an attacker could selectively delay video
packets in order to manipulate timings and make NDTC incorrectly estimate
available path capacity. However, the combined congestion control should prevent
NDTC from causing network congestion in that scenario.</t>
      <t>When using L4S, this draft inherits the security considerations discussed in
<xref target="RFC9330"/>. In particular, network operators might choose to restrict or police
L4S flows. Additionally, <tt>MIN_TARGET</tt> should be set low enough to ensure NDTC
flows are responsive enough not to cause a queue to build up.</t>
    </section>
    <section anchor="iana-considerations">
      <name>IANA Considerations</name>
      <t>This document has no IANA actions.</t>
    </section>
  </middle>
  <back>
    <references anchor="sec-normative-references">
      <name>Normative References</name>
      <reference anchor="draft-alvestrand-rmcat-remb" target="https://datatracker.ietf.org/doc/html/draft-alvestrand-rmcat-remb-03">
        <front>
          <title>RTCP message for Receiver Estimated Maximum Bitrate</title>
          <author initials="H." surname="Alvestrand" fullname="H. Alvestrand">
            <organization/>
          </author>
          <date year="2013" month="October" day="21"/>
        </front>
      </reference>
      <reference anchor="draft-holmer-rmcat-transport-wide-cc-extensions" target="https://datatracker.ietf.org/doc/html/draft-holmer-rmcat-transport-wide-cc-extensions-01">
        <front>
          <title>RTP Extensions for Transport-wide Congestion Control</title>
          <author initials="S." surname="Holmer" fullname="S. Holmer">
            <organization/>
          </author>
          <author initials="M." surname="Flodman" fullname="M. Flodman">
            <organization/>
          </author>
          <author initials="E." surname="Sprang" fullname="E. Sprang">
            <organization/>
          </author>
          <date year="2015" month="October" day="19"/>
        </front>
      </reference>
      <reference anchor="draft-briscoe-iccrg-prague-congestion-control" target="https://datatracker.ietf.org/doc/html/draft-briscoe-iccrg-prague-congestion-control-04">
        <front>
          <title>Prague Congestion Control</title>
          <author initials="K. D." surname="Schepper" fullname="K. De Schepper">
            <organization/>
          </author>
          <author initials="O." surname="Tilmans" fullname="O. Tilmans">
            <organization/>
          </author>
          <author initials="B." surname="Briscoe" fullname="B. Briscoe">
            <organization/>
          </author>
          <author initials="V." surname="Goel" fullname="V. Goel">
            <organization/>
          </author>
          <date>n.d.</date>
        </front>
      </reference>
      <reference anchor="abs-send-time" target="http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time">
        <front>
          <title>RTP Header Extension for Absolute Sender Time</title>
          <author>
            <organization/>
          </author>
          <date>n.d.</date>
        </front>
      </reference>
      <reference anchor="NDTC-LCN" target="https://ieeexplore.ieee.org/document/11146354">
        <front>
          <title>Network Delivery Time Control: a Novel Approach to Rate Adaptation for Low-Latency Video Flows</title>
          <author initials="P.-L." surname="Ageneau" fullname="Paul-Louis Ageneau">
            <organization/>
          </author>
          <author initials="G." surname="Armitage" fullname="Grenville Armitage">
            <organization/>
          </author>
          <date year="2025" month="October" day="13"/>
        </front>
        <seriesInfo name="IEEE 50th Conference on Local Computer Networks (LCN)" value=""/>
      </reference>
      <reference anchor="CAKE" target="https://www.bufferbloat.net/projects/codel/wiki/Cake">
        <front>
          <title>Cake - Common Applications Kept Enhanced</title>
          <author>
            <organization/>
          </author>
          <date>n.d.</date>
        </front>
      </reference>
      <reference anchor="RFC2119">
        <front>
          <title>Key words for use in RFCs to Indicate Requirement Levels</title>
          <author fullname="S. Bradner" initials="S." surname="Bradner"/>
          <date month="March" year="1997"/>
          <abstract>
            <t>In many standards track documents several words are used to signify the requirements in the specification. These words are often capitalized. This document defines these words as they should be interpreted in IETF documents. This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements.</t>
          </abstract>
        </front>
        <seriesInfo name="BCP" value="14"/>
        <seriesInfo name="RFC" value="2119"/>
        <seriesInfo name="DOI" value="10.17487/RFC2119"/>
      </reference>
      <reference anchor="RFC8174">
        <front>
          <title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
          <author fullname="B. Leiba" initials="B." surname="Leiba"/>
          <date month="May" year="2017"/>
          <abstract>
            <t>RFC 2119 specifies common key words that may be used in protocol specifications. This document aims to reduce the ambiguity by clarifying that only UPPERCASE usage of the key words have the defined special meanings.</t>
          </abstract>
        </front>
        <seriesInfo name="BCP" value="14"/>
        <seriesInfo name="RFC" value="8174"/>
        <seriesInfo name="DOI" value="10.17487/RFC8174"/>
      </reference>
      <reference anchor="RFC9331">
        <front>
          <title>The Explicit Congestion Notification (ECN) Protocol for Low Latency, Low Loss, and Scalable Throughput (L4S)</title>
          <author fullname="K. De Schepper" initials="K." surname="De Schepper"/>
          <author fullname="B. Briscoe" initials="B." role="editor" surname="Briscoe"/>
          <date month="January" year="2023"/>
          <abstract>
            <t>This specification defines the protocol to be used for a new network service called Low Latency, Low Loss, and Scalable throughput (L4S). L4S uses an Explicit Congestion Notification (ECN) scheme at the IP layer that is similar to the original (or 'Classic') ECN approach, except as specified within. L4S uses 'Scalable' congestion control, which induces much more frequent control signals from the network, and it responds to them with much more fine-grained adjustments so that very low (typically sub-millisecond on average) and consistently low queuing delay becomes possible for L4S traffic without compromising link utilization. Thus, even capacity-seeking (TCP-like) traffic can have high bandwidth and very low delay at the same time, even during periods of high traffic load.</t>
            <t>The L4S identifier defined in this document distinguishes L4S from 'Classic' (e.g., TCP-Reno-friendly) traffic. Then, network bottlenecks can be incrementally modified to distinguish and isolate existing traffic that still follows the Classic behaviour, to prevent it from degrading the low queuing delay and low loss of L4S traffic. This Experimental specification defines the rules that L4S transports and network elements need to follow, with the intention that L4S flows neither harm each other's performance nor that of Classic traffic. It also suggests open questions to be investigated during experimentation. Examples of new Active Queue Management (AQM) marking algorithms and new transports (whether TCP-like or real time) are specified separately.</t>
          </abstract>
        </front>
        <seriesInfo name="RFC" value="9331"/>
        <seriesInfo name="DOI" value="10.17487/RFC9331"/>
      </reference>
      <reference anchor="RFC9330">
        <front>
          <title>Low Latency, Low Loss, and Scalable Throughput (L4S) Internet Service: Architecture</title>
          <author fullname="B. Briscoe" initials="B." role="editor" surname="Briscoe"/>
          <author fullname="K. De Schepper" initials="K." surname="De Schepper"/>
          <author fullname="M. Bagnulo" initials="M." surname="Bagnulo"/>
          <author fullname="G. White" initials="G." surname="White"/>
          <date month="January" year="2023"/>
          <abstract>
            <t>This document describes the L4S architecture, which enables Internet applications to achieve low queuing latency, low congestion loss, and scalable throughput control. L4S is based on the insight that the root cause of queuing delay is in the capacity-seeking congestion controllers of senders, not in the queue itself. With the L4S architecture, all Internet applications could (but do not have to) transition away from congestion control algorithms that cause substantial queuing delay and instead adopt a new class of congestion controls that can seek capacity with very little queuing. These are aided by a modified form of Explicit Congestion Notification (ECN) from the network. With this new architecture, applications can have both low latency and high throughput.</t>
            <t>The architecture primarily concerns incremental deployment. It defines mechanisms that allow the new class of L4S congestion controls to coexist with 'Classic' congestion controls in a shared network. The aim is for L4S latency and throughput to be usually much better (and rarely worse) while typically not impacting Classic performance.</t>
          </abstract>
        </front>
        <seriesInfo name="RFC" value="9330"/>
        <seriesInfo name="DOI" value="10.17487/RFC9330"/>
      </reference>
      <reference anchor="RFC3550">
        <front>
          <title>RTP: A Transport Protocol for Real-Time Applications</title>
          <author fullname="H. Schulzrinne" initials="H." surname="Schulzrinne"/>
          <author fullname="S. Casner" initials="S." surname="Casner"/>
          <author fullname="R. Frederick" initials="R." surname="Frederick"/>
          <author fullname="V. Jacobson" initials="V." surname="Jacobson"/>
          <date month="July" year="2003"/>
          <abstract>
            <t>This memorandum describes RTP, the real-time transport protocol. RTP provides end-to-end network transport functions suitable for applications transmitting real-time data, such as audio, video or simulation data, over multicast or unicast network services. RTP does not address resource reservation and does not guarantee quality-of- service for real-time services. The data transport is augmented by a control protocol (RTCP) to allow monitoring of the data delivery in a manner scalable to large multicast networks, and to provide minimal control and identification functionality. RTP and RTCP are designed to be independent of the underlying transport and network layers. The protocol supports the use of RTP-level translators and mixers. Most of the text in this memorandum is identical to RFC 1889 which it obsoletes. There are no changes in the packet formats on the wire, only changes to the rules and algorithms governing how the protocol is used. The biggest change is an enhancement to the scalable timer algorithm for calculating when to send RTCP packets in order to minimize transmission in excess of the intended rate when many participants join a session simultaneously. [STANDARDS-TRACK]</t>
          </abstract>
        </front>
        <seriesInfo name="STD" value="64"/>
        <seriesInfo name="RFC" value="3550"/>
        <seriesInfo name="DOI" value="10.17487/RFC3550"/>
      </reference>
      <reference anchor="RFC8888">
        <front>
          <title>RTP Control Protocol (RTCP) Feedback for Congestion Control</title>
          <author fullname="Z. Sarker" initials="Z." surname="Sarker"/>
          <author fullname="C. Perkins" initials="C." surname="Perkins"/>
          <author fullname="V. Singh" initials="V." surname="Singh"/>
          <author fullname="M. Ramalho" initials="M." surname="Ramalho"/>
          <date month="January" year="2021"/>
          <abstract>
            <t>An effective RTP congestion control algorithm requires more fine-grained feedback on packet loss, timing, and Explicit Congestion Notification (ECN) marks than is provided by the standard RTP Control Protocol (RTCP) Sender Report (SR) and Receiver Report (RR) packets. This document describes an RTCP feedback message intended to enable congestion control for interactive real-time traffic using RTP. The feedback message is designed for use with a sender-based congestion control algorithm, in which the receiver of an RTP flow sends back to the sender RTCP feedback packets containing the information the sender needs to perform congestion control.</t>
          </abstract>
        </front>
        <seriesInfo name="RFC" value="8888"/>
        <seriesInfo name="DOI" value="10.17487/RFC8888"/>
      </reference>
      <reference anchor="RFC8083">
        <front>
          <title>Multimedia Congestion Control: Circuit Breakers for Unicast RTP Sessions</title>
          <author fullname="C. Perkins" initials="C." surname="Perkins"/>
          <author fullname="V. Singh" initials="V." surname="Singh"/>
          <date month="March" year="2017"/>
          <abstract>
            <t>The Real-time Transport Protocol (RTP) is widely used in telephony, video conferencing, and telepresence applications. Such applications are often run on best-effort UDP/IP networks. If congestion control is not implemented in these applications, then network congestion can lead to uncontrolled packet loss and a resulting deterioration of the user's multimedia experience. The congestion control algorithm acts as a safety measure by stopping RTP flows from using excessive resources and protecting the network from overload. At the time of this writing, however, while there are several proprietary solutions, there is no standard algorithm for congestion control of interactive RTP flows.</t>
            <t>This document does not propose a congestion control algorithm. It instead defines a minimal set of RTP circuit breakers: conditions under which an RTP sender needs to stop transmitting media data to protect the network from excessive congestion. It is expected that, in the absence of long-lived excessive congestion, RTP applications running on best-effort IP networks will be able to operate without triggering these circuit breakers. To avoid triggering the RTP circuit breaker, any Standards Track congestion control algorithms defined for RTP will need to operate within the envelope set by these RTP circuit breaker algorithms.</t>
          </abstract>
        </front>
        <seriesInfo name="RFC" value="8083"/>
        <seriesInfo name="DOI" value="10.17487/RFC8083"/>
      </reference>
      <reference anchor="RFC8290">
        <front>
          <title>The Flow Queue CoDel Packet Scheduler and Active Queue Management Algorithm</title>
          <author fullname="T. Hoeiland-Joergensen" initials="T." surname="Hoeiland-Joergensen"/>
          <author fullname="P. McKenney" initials="P." surname="McKenney"/>
          <author fullname="D. Taht" initials="D." surname="Taht"/>
          <author fullname="J. Gettys" initials="J." surname="Gettys"/>
          <author fullname="E. Dumazet" initials="E." surname="Dumazet"/>
          <date month="January" year="2018"/>
          <abstract>
            <t>This memo presents the FQ-CoDel hybrid packet scheduler and Active Queue Management (AQM) algorithm, a powerful tool for fighting bufferbloat and reducing latency.</t>
            <t>FQ-CoDel mixes packets from multiple flows and reduces the impact of head-of-line blocking from bursty traffic. It provides isolation for low-rate traffic such as DNS, web, and videoconferencing traffic. It improves utilisation across the networking fabric, especially for bidirectional traffic, by keeping queue lengths short, and it can be implemented in a memory- and CPU-efficient fashion across a wide range of hardware.</t>
          </abstract>
        </front>
        <seriesInfo name="RFC" value="8290"/>
        <seriesInfo name="DOI" value="10.17487/RFC8290"/>
      </reference>
    </references>
    <?line 819?>

<section anchor="ewma-implementation">
      <name>Dual-variable EWMA Process Implementation</name>
      <t>All variables are initialized at zero. When receiving a new sample
<tt>(NSEND, NRECV)</tt>, the EWMA process <bcp14>SHOULD</bcp14> be updated as follows:</t>
      <artwork><![CDATA[
COUNT = COUNT + 1
WEIGHT = max(LAMBDA, 1.0/COUNT)
DELTA_NSEND = NSEND - AVG_NSEND
DELTA_NRECV = NRECV - AVG_NRECV
AVG_NSEND += WEIGHT * DELTA_NSEND
AVG_NRECV += WEIGHT * DELTA_NRECV
VAR_NSEND = (1 - WEIGHT) * (VAR_NSEND + WEIGHT * DELTA_NSEND^2)
VAR_NRECV = (1 - WEIGHT) * (VAR_NRECV + WEIGHT * DELTA_NRECV^2)
COVAR = (1 - WEIGHT) * (COVAR + WEIGHT * DELTA_NSEND * DELTA_NRECV)
]]></artwork>
      <t><tt>COUNT</tt> is also initialized at zero and the weight <tt>1.0/COUNT</tt> is used
at the beginning to ensure initial values get equal weights and prevent
the very first value from having an unreasonably large effect on the average.</t>
    </section>
    <section anchor="estimate-implementation">
      <name>Estimate Implementation</name>
      <t><tt>ESTIMATE</tt> is calculated step-by-step with <tt>ITERATIONS</tt> iterations, and the
<bcp14>RECOMMENDED</bcp14> value for <tt>ITERATIONS</tt> is 3. In a CPU-constrained environment,
for instance if NDTC runs for a very large number of parallel sessions,
the loop <bcp14>MAY</bcp14> therefore be unrolled, making <tt>ESTIMATE</tt> linear according to
<tt>AVG_NRECV</tt>:</t>
      <artwork><![CDATA[
ESTIMATE = SLOPE^3 * AVG_NRECV + (SLOPE^2 + SLOPE + 1) * INTERCEPT
]]></artwork>
    </section>
    <section anchor="aimd-implementation">
      <name>AIMD Logic Implementation</name>
      <t>On frame feedback, the agent <bcp14>SHOULD</bcp14> run the following AIMD logic to update
the congestion frame size <tt>CSIZE</tt>:</t>
      <artwork><![CDATA[
ecn_gain = 1.0 / 16.0
ecn_fraction = float(ecn_marking_count) / float(packet_count)
ecn_average += ecn_gain * (ecn_fraction - ecn_average)

// Multiplicative decrease
if (last_decrease_time > first_packet_send_time) {
    // Suppress decrease for one round-trip
} else if (packet_lost_count > 0) {
    // Loss decrease
    CSIZE = min(CSIZE, CMAX) * BETA
    last_decrease_time = now()
} else if (last_ecn_decrease_time > first_packet_send_time) {
    // Suppress ECN decrease for one round-trip
} else if (ecn_marking_count > 0) {
    // ECN decrease
    CSIZE = min(CSIZE, CMAX) * (1.0 - ecn_average * (1.0 - BETA))
    last_ecn_decrease_time = now()
}

// Additive increase (suppressed after loss but not ECN decrease)
if (last_decrease_time <= first_packet_send_time && CSIZE < CMAX) {
    if (last_ecn_decrease_time <= last_decrease_time) {
        CSIZE = min(CSIZE + ALPHA, CMAX)
    } else {
        CSIZE = min(CSIZE + EALPHA * (1.0 - ecn_fraction), CMAX)
    }
}
]]></artwork>
      <t>This algorithm uses logic close to a Prague congestion controller
<xref target="draft-briscoe-iccrg-prague-congestion-control"/>, it also uses
the recommended ECN gain 1/16. For a new flow, <tt>ecn_average</tt>
        <bcp14>SHOULD</bcp14> be initialized to 1.0.</t>
      <t>If ECN is not supported, the AIMD logic <bcp14>MAY</bcp14> be simplified to only the
multiplicative decrease on packet loss (suppressed for one round-trip)
and the additive increase otherwise.</t>
    </section>
  </back>
  <!-- ##markdown-source:
H4sIAAAAAAAAA61963YbyZHm/3yKXOmcMdkNgKSkHttat2fQFNXNY90sst07
67GFApAgyiqg4KoCKVqSn2WfZZ9s44uIvAFFttpn/cMtFqryEhn3Ww6HQ9OV
XeWe2gevXHdTN+/tM1eV1665tZflytnTet01dfXAFNNp467x3rPL0wdmVnTu
qm5un9pyvaiNmdezdbGiceZNseiGxZVbu2I7nM1urobreTcbHj827Xa6Ktu2
pCFvN/Tq+dnlc2sf2qJqaxq4XM/dxtH/rbsHA/vAzcuubsqiwh/n4+/oP3VD
/3p7+fyBWW9XU9c8NXNaxlMzq9etW7fb9qntmq0ztMzHpmhcQaP+5Ka2WM/t
+bpzzdp19rIp1u2mbroHBvu9aurtht6jjV65tqPF+T3bn+jncn1lv8crD8x7
d0sfzJ8aO7QNzWuLebHpCnzCj1xRDTuCGf6o6pthRe+sZ7f2upy72ly79ZaW
au2XT2itwOnB3vNVUVb0HND9z9J1i1HdXOF50cyW9HzZdZv26dERXsMjOs+R
f+0ID46mTX3TuiMMcIQPr8puuZ3Sp5tiW1X1tmz1BI/uOE98hA22XTLf7scj
GXZU1ncNc9fz0bJbEdKZYtst6wYgp/msXdD4gmYP3tBcwxeYzI7l6wf8Cm2x
WJf/4GN5agmpF1X5gX9xCrWNzvafa/lxNKtXNNX+FN83bn1dVpWz42ZVdvRZ
3xTnEW2zaa7+VjDQ//MKD+6c5GJWd519VqyL5e2X7qCd8+s7G1jXzYo+umYs
U7hW13RChPDzYbMikh02bjV9ymN1RXPl6PD82RElFfTm7L1rIq4QVR/hJI7u
GQ6UzQMKH3l7efrGrlwLHLALoti3bubAUOwZITst0M3ty+JDudqu7HdlB0Li
z8NJ0/+GVoDzw8iOw5T8C9O7fXR88nh4cjx8dBJ2uqyrlWt0WZ0n8eEN0R5h
1dB9IFoE52n/9d1/8RTD45McIm/sWfiRYXKZfW33WcGdILkY2R94HdnTlyP7
vKrnq2KdPT4b2YsNTXWVw+4bwO7ktwF206ZsZ7UblrNZczWkD662tKOwJvwT
a/rXIfeFEwyPn6Rwe8Pv/RLg/GFE0stezJZus9mB0OsRybOKANRmj78b2e9k
cdnjP43s97XDRMW0HZJsmTNn34cAAeDm5mZ046YNMS1s3X2gqendddceNd1m
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
pr9mDPnf9DY87oGpKOrNctRLrwoyf9aiv79woDG9TswvRjIBYbhL095ouqNF
DnJWgUPSsMCAVrT2bOeiyTQclRawdnxPQmyMq/FMAMeIKJGkqFBLoK+q1BNc
L0QocDxyW1aopJAI4PjVeO+mq8vs/rIlt6uSN4twV9JwOOS7F/gS7mf7bWDf
aFb4Tojx48O+NrC4W65KggLYUFr2S8f7D9fUI6kIjwVlRdJu1+y22xV0y3rS
Rn+F79u716j19PWPry65yxD++7U9MT+dnX//g6+gkfgLt2E94lcODcd03vn2
5fLfYeyx6n/3PfC0F2tsqhbetF9/a3UyTUjTEWIP1543eIzYCOlbybuVt7jm
Kv72de/wf310aGK/pTu+l9l7J8f30qh2/1t53j9vPorvQstAnYSbj3qwICS9
acRrEs4iuD6Nhvqn7qrUO9EC3fiIqxY9Q1WV/oIynHA6z4E45ZOv+GJLShOu
wZH0RixuAQnTskam0K3vYs1Vc76XoroOmN78DTw9dHFHGzhjspaHWZpP5zbD
KSmv9F/NH886AYbAaWgIbe5IH99pIPiYeV1xX3+7gcl1S72nkav/xRqPbYSS
zokhz6d1mlaUt8nrQoZF0jBvAMnDF6VGSGjcJk+Uj3GFp3tdDDmW8tfHvv2x
IrQU2/31UUgFJYoH5sYmhVKMKErcCzY19o6uTy8z5rUvRvXSv8dbBt9Fl4VK
+7omGFViemtcOWqn23Wz9Tv0dgy9w07+fXTMT0Nn2W8hfYruAA/1Eq937GRB
wqT8JBqBPuWvvfOL2E+Ygqg7G3hokzcPjTk62r383DthuOkbnHjv/JN33Pfr
90Jl73R+qPz8g+/+RiNeaDV/DLDvF/X7dm6YRYeCi0H2g35yyXjskgrrwkOG
Z0+9L+0XYX9+p2ft36LG5uAwnZvfAkz+9V1mBfb373TvPHd2mg71cxs9APJk
5xkfAgiHhxEM+xsMoGAcGO8lVhwkLRnEmc6eFvgQoLKkCz28C1V+9+0dUOSm
6ryz3+l2BAL3HAiNtT+D/64XUsQkOIfEl4LjpayH4F1fSepJDmFPQIfZaFlv
1OgF4/uthTtE2/f/a+Fj9DRhLr3ROeZb4XSY/E+OiLdwRYUoYQtubjtJcGZi
7uzhIh3/7s1XTvigtk+VVqwoh+Pb0ZCBDol2V+ZN7ZNjBb0O7m0EIheSMnve
w1cupLkpWwjw/wcH3ZQeFJsAAA==

-->

</rfc>
