Table of Contents

RTCP quality metrics

The SDK measures call quality from RTCP and surfaces it as snapshots you can log, chart or alert on. Values are measured, not estimated placeholders.

Consuming snapshots

call.QualitySnapshotChanged += (_, e) =>
{
    var s = e.Snapshot;
    // marshal off the media/RTCP thread before doing real work
    logger.LogInformation("jitter={Jitter} loss={Loss} rtt={Rtt} mos={Mos}",
        s.Jitter, s.PacketLoss, s.RoundTripTime, s.PeerMos);
};

client.QualityManager also exposes the current quality state for polling scenarios.

What is measured

Metric Source
Jitter (local + remote) RTCP SR/RR interarrival jitter
Packet loss RTCP SR/RR loss fraction / cumulative loss
Round-trip time Derived from SR/RR LSR/DLSR timestamps
Peer MOS RTCP-XR VoIP Metrics (RFC 3611 §4.7) when the peer sends XR

RTT feeds the adaptive jitter buffer, so the playout delay tracks real network conditions.

Known limitation: on a low-loss/loopback path, packets that arrive too late for playout can currently be counted as unrecoverable loss, so the loss figure may read higher than the true network loss. Treat loss as directional/trend data rather than an exact network-loss percentage until this is fixed (issue tracker).

Raw RTP counters

Where the quality snapshot gives derived values (ms / %), call.RtpStatistics exposes the underlying RFC 3550 counters for diagnostics and billing — SSRC identifiers, packet/octet counts, cumulative and fraction loss, and interarrival jitter in RTP units. It is null until the first RTCP reporting interval has produced counters.

var rtp = call.RtpStatistics;
if (rtp is { } s)
    logger.LogInformation("ssrc={Ssrc} sent={Sent} recv={Recv} lost={Lost}",
        s.LocalSsrc, s.PacketsSent, s.PacketsReceived, s.CumulativePacketsLost);

Compound-packet tolerance

RTCP compound decoding tolerates unknown packet types (e.g. RFC 3611 XR blocks from peers that send more than SR/RR), so a richer-than-expected report does not break parsing.

What the SDK speaks

The support matrix below is what the wire codec actually implements — not what RTCP as a whole defines. A peer may send anything in this list and be understood; anything outside it is skipped without disturbing the rest of the compound.

Packet PT / FMT Receive Send
Sender Report (SR) 200
Receiver Report (RR) 201
Source Description (SDES) 202 ✅ CNAME only
Goodbye (BYE) 203
Application-defined (APP) 204
Extended Report (XR) 207 ✅ VoIP Metrics only
Picture Loss Indication (PLI) 206 / 1
Full Intra Request (FIR) 206 / 4
Generic NACK 205 / 1
Transport-wide CC feedback 205 / 15

Gaps worth knowing before you integrate

  • XR is receive-only, and only VoIP Metrics (BT=7). RFC 3611 defines seven other block types (loss/duplicate RLE, packet receipt times, receiver reference time, DLRR, statistics summary); those are skipped over. The SDK never emits an XR, so a peer relying on our MOS or DLRR will not get one.
  • Transport-wide congestion control is the draft format, not RFC 8888. What we speak is draft-holmer-rmcat-transport-wide-cc-extensions-01, RTPFB FMT=15 — the format Chrome and libwebrtc use and what nearly every WebRTC endpoint negotiates. RFC 8888 CCFB is RTPFB FMT=11 with a different body and is not implemented; a peer expecting CCFB receives nothing it can parse.
  • No REMB (PSFB FMT=15) and no TMMBR/TMMBN (RFC 5104). Bitrate signalling is receive-side transport-cc plus the SDK's own estimate, surfaced as a recommended send bitrate. A peer that only signals bandwidth via REMB or TMMBR will not be heard.
  • No SLI or RPSI (PSFB FMT=2/3). Key-frame recovery is PLI and FIR.
  • SDES carries CNAME only. Other items (NAME, EMAIL, TOOL, …) are parsed on receive but never sent.

None of these is a defect against a promise — they are listed here so the promise is explicit.

Threading

QualitySnapshotChanged fires on the media/RTCP thread. Keep the handler non-blocking — copy the values and hand off (see Events and Threading).

Note on MOS

Peer MOS is only present when the remote endpoint emits RTCP-XR VoIP Metrics. Against peers that send only plain SR/RR, jitter/loss/RTT are available but peer MOS may be absent — treat it as optional.