Internet Protocols · Real-Time Media
Reading Loss and Round-Trip Time from RTCP Sender and Receiver Reports
How the fraction-lost, jitter, and LSR/DLSR fields are computed, why the arithmetic is fixed-point, and where the round-trip estimate breaks down.
RTP carries no acknowledgements, so a sender learns nothing about network conditions from the data path. The information arrives on a second, slower channel: RTCP reports sent by every participant at a bounded rate. A sender report describes what the sender has transmitted; a receiver report describes what one receiver observed. Between them they encode loss counts, an interarrival jitter estimate, and enough timestamps to compute round-trip time without any additional probe traffic.
The design constraint is bandwidth. RTCP is allocated a fixed fraction of the session bandwidth, five percent by RFC 3550, split between senders and receivers. On a 64 kbit/s audio call that is 3.2 kbit/s for all control traffic combined, shared among all participants. Every field in a report had to earn its space, which explains the fixed-point encodings and the 24-bit counters.
What each report actually contains
A sender report carries the sender’s SSRC, a 64-bit NTP timestamp, the corresponding RTP timestamp, the total number of RTP packets sent, and the total number of payload octets sent excluding headers and padding. The NTP and RTP timestamps describe the same instant in two clocks, which is what makes lip sync possible across streams; that correspondence is the subject of mapping RTP clocks to wall time.
A receiver report block carries the source SSRC being reported on, then five fields of interest:
- Fraction lost, eight bits, the loss rate since the previous report, expressed in units of 1/256. A value of 64 means 25 percent.
- Cumulative packets lost, 24 bits, signed, the total loss since the start of reception.
- Extended highest sequence number received, 32 bits: the high 16 bits count sequence number cycles, the low 16 bits hold the highest sequence number seen.
- Interarrival jitter, 32 bits, in timestamp units, an estimate rather than a measurement.
- Last SR timestamp (LSR), 32 bits, the middle 32 bits of the NTP timestamp from the most recent sender report received from that source.
- Delay since last SR (DLSR), 32 bits, the time elapsed between receiving that sender report and sending this receiver report, in units of 1/65536 second.
The LSR and DLSR pair exists for one purpose. When the sender receives a report containing them, it subtracts both from its current time, and the difference is the round-trip time. The middle 32 bits of an NTP timestamp are the seconds’ low 16 bits and the fraction’s high 16 bits, giving roughly 15 microseconds of resolution and a wrap period of about 18 hours, which is long enough for any plausible round trip.
The loss arithmetic and why it needs a base
Fraction lost cannot be computed from cumulative loss alone, because cumulative loss says nothing about the recent past. The receiver keeps, per source, the extended highest sequence number at the time of the previous report and a count of packets expected. For each new report it computes the number expected in the interval as the difference between the current and previous extended sequence numbers, the number actually received as the difference of cumulative received counts, and the loss as the difference. Then:
expected_interval = extended_max - extended_max_prev
received_interval = received - received_prev
lost_interval = expected_interval - received_interval
fraction = lost_interval * 256 / expected_interval /* clamp to 0..255 */
Two details break naive implementations. First, the arithmetic must be done on modular differences of the extended sequence number, because the 16-bit field wraps and because a large jump in sequence numbers can mean either loss or a sender restart. Second, a negative interval loss is possible when packets arrive out of order across the report boundary: a packet counted as lost in one interval can be received during the next. RFC 3550 says the fraction must be clamped to zero rather than reported as a negative value, since the field is unsigned. The cumulative count, being signed, is allowed to decrease in exactly this situation, and it is clamped at the extremes of its 24-bit range so that a long outage does not overflow into a positive value.
The 24-bit cumulative counter is worth pausing on. Its positive maximum is 8,388,607, so at 50 packets per second it takes about 47 hours of complete loss to reach it; but a stream that runs for days and loses a small percentage will accumulate real loss and eventually saturate. When the counter sits at its maximum, the sender sees loss that never improves, because further loss cannot be represented. Long-lived sessions need to interpret saturation as “at least this much” rather than as a precise count.
Jitter is a smoothed first difference, not a standard deviation
The jitter field is computed from arrival times and RTP timestamps, not from sequence numbers. For each packet, the receiver measures the transit time in timestamp units, D(i,j) = (Rj - Ri) - (Sj - Si), where R is arrival time converted to the same clock and S is the RTP timestamp. That difference is the change in transit time between two packets; if the network delay were constant, it would be zero. The running estimate is updated as:
J = J + (|D(i-1,i)| - J) / 16
This is an exponential moving average with a gain of 1/16, chosen so the estimate responds within a few dozen packets while remaining stable against single-packet spikes. It is not a variance and not a percentile; it is a mean absolute deviation of the transit-time derivative, which is the quantity a playout buffer needs, because buffer sizing depends on how much the delay varies rather than on how large it is.
The conversion between arrival time and timestamp units is where implementations go wrong. The RTP timestamp advances at the codec clock rate, so a difference in RTP timestamps must be converted to seconds using that rate before comparison with an arrival-time difference measured in seconds. A receiver that compares raw RTP timestamp deltas against wall-clock microseconds produces a jitter figure that is wrong by the ratio of the clock rate to one million. The result is still monotonic with real jitter, which is why the bug survives testing, but the absolute value is meaningless and any buffer sizing that uses it is wrong.
Where the round-trip estimate fails
The RTT computed from LSR and DLSR measures a specific path: from the sender to one receiver and back, at the moment of a report exchange. It excludes the receiver’s own processing delay before it sends the report only if that delay is reported in DLSR, which is exactly what DLSR is for. A receiver that computes DLSR from the wrong timestamp, or omits it, inflates the sender’s RTT estimate by the reporting delay, which on a lightly loaded host is milliseconds and on a busy one can be hundreds.
Several conditions make the estimate unavailable or misleading. If the receiver has not yet received a sender report, LSR is zero and the sender must ignore the block for RTT purposes. If reports are sparse, the estimate is stale. In a session with many receivers, the sender gets one RTT estimate per receiver per report interval, and the report interval grows with the participant count because of the bandwidth fraction, so a large conference yields infrequent, and increasingly stale, measurements from each participant.
Reduced-size RTCP, defined in RFC 5506, changes the calculus. It allows receiver reports without the sender-report and SDES portions that RFC 3550 requires in a compound packet, which cuts the size of each report substantially. The loss and jitter fields are unaffected; what shrinks is the fixed overhead around them. Sessions that negotiate reduced-size RTCP can therefore report more often within the same bandwidth allocation, at the cost of losing the SDES canonical name that identifies participants.
Feedback that RTCP alone cannot provide
Everything above is periodic and statistical. A receiver that has just lost a packet needed for a video frame cannot express that through a fraction-lost field, which describes the past five seconds. That gap is filled by the early RTCP feedback profiles, where a receiver sends a negative acknowledgement or a picture-loss indication within a few milliseconds of detecting the problem, rather than waiting for the report timer. Those mechanisms, and the timing rules that keep them from flooding the session, are covered in RTCP feedback messages and retransmission.
The trade-off throughout is between freshness and bandwidth. Reports sent every second would give a sender a responsive view of the network but would consume the entire control allocation in a modest session. The five-second nominal interval in RFC 3550 is a compromise, randomized between roughly half and one and a half times the nominal value so that all participants in a large session do not report simultaneously. Implementations that need faster feedback use the early-feedback mechanisms rather than shortening the interval, because the interval is a shared resource and the feedback messages are individually small.
References
- RFC 3550: RTP: A Transport Protocol for Real-Time Applications — IETF
- RFC 5506: Support for Reduced-Size Real-Time Transport Control Protocol (RTCP) — IETF
- RTP: Audio and Video for the Internet — Colin Perkins, Addison-Wesley, 2003