medea_client_api_proto/stats.rs
1//! Contains DTOs for [RTCPeerConnection] metrics according to the
2//! [Identifiers for WebRTC's Statistics API][0] specification.
3//!
4//! [RTCPeerConnection]: https://w3.org/TR/webrtc#dom-rtcpeerconnection
5//! [0]: https://w3.org/TR/webrtc-stats
6
7use std::{
8 collections::BTreeMap,
9 hash::{Hash, Hasher},
10 time::{Duration, SystemTime, SystemTimeError},
11};
12
13use derive_more::with_trait::{Display, From};
14use serde::{Deserialize, Serialize};
15
16/// Deserialization helper for enums, allowing to store unknown data as a
17/// [`String`] in the [`Unknown`] variant.
18///
19/// [`Unknown`]: NonExhaustive::Unknown
20#[derive(
21 Clone,
22 Debug,
23 Deserialize,
24 Display,
25 Eq,
26 Hash,
27 Ord,
28 PartialEq,
29 PartialOrd,
30 Serialize,
31)]
32#[serde(untagged)]
33pub enum NonExhaustive<T> {
34 /// Known enum variant if it successfully deserialized.
35 Known(T),
36
37 /// Unknown enum variant with its data as [`String`].
38 #[display("Unknown: {_0}")]
39 Unknown(String),
40}
41
42/// Unique ID that is associated with the object that was inspected to produce
43/// an [`RtcStat`] object.
44///
45/// Two [`RtcStat`]s objects, extracted from two different [RTCStatsReport]
46/// objects, MUST have the same ID if they were produced by inspecting the same
47/// underlying object.
48///
49/// [RTCStatsReport]: https://w3.org/TR/webrtc#dom-rtcstatsreport
50#[derive(
51 Clone, Debug, Deserialize, Display, Eq, From, Hash, PartialEq, Serialize,
52)]
53#[from(forward)]
54pub struct StatId(pub String);
55
56/// [Stats object] constructed by inspecting a specific [monitored object].
57///
58/// [Full doc on W3C][spec].
59///
60/// [monitored object]: https://w3.org/TR/webrtc-stats#dfn-monitored-object
61/// [spec]: https://w3.org/TR/webrtc-stats#dom-rtcstats
62/// [Stats object]: https://w3.org/TR/webrtc-stats#dfn-stats-object
63#[derive(Clone, Debug, Deserialize, Hash, PartialEq, Serialize)]
64pub struct RtcStat {
65 /// Unique ID that is associated with the object that was inspected to
66 /// produce this [`RtcStat`] object.
67 pub id: StatId,
68
69 /// Timestamp associated with this [`RtcStat`] object.
70 ///
71 /// The time is relative to the UNIX epoch (Jan 1, 1970, UTC).
72 ///
73 /// For statistics that came from a remote source (e.g. from received [RTCP]
74 /// packets), timestamp represents the time at which the information arrived
75 /// at the local endpoint. The remote timestamp can be found in an
76 /// additional field in an [`RtcStat`]-derived dictionary, if applicable.
77 ///
78 /// [RTCP]: https://webrtcglossary.com/rtcp
79 pub timestamp: HighResTimeStamp,
80
81 /// Actual stats of this [`RtcStat`].
82 ///
83 /// All possible stats are described in the [`RtcStatsType`] enum.
84 #[serde(flatten)]
85 pub stats: RtcStatsType,
86}
87
88/// Possible types of [`RtcStat`]s.
89///
90/// [Full doc on W3C][spec].
91///
92/// [spec]: https://w3.org/TR/webrtc-stats#dom-rtcstatstype
93#[derive(Clone, Debug, Deserialize, Hash, PartialEq, Serialize)]
94#[serde(tag = "type", rename_all = "kebab-case")]
95pub enum RtcStatsType {
96 /// Statistics for a codec that is currently used by [RTP stream]s being
97 /// sent or received by [RTCPeerConnection] object.
98 ///
99 /// [RTCPeerConnection]: https://w3.org/TR/webrtc#dom-rtcpeerconnection
100 /// [RTP stream]: https://w3.org/TR/webrtc-stats#dfn-rtp-stream
101 Codec(Box<RtcCodecStats>),
102
103 /// Statistics for an inbound [RTP stream] that is currently received with
104 /// this [RTCPeerConnection] object.
105 ///
106 /// RTX streams do not show up as separate [`RtcInboundRtpStreamStats`]
107 /// objects but affect the [`RtcReceivedRtpStreamStats::packets_received`],
108 /// [`RtcInboundRtpStreamStats::bytes_received`],
109 /// [`RtcInboundRtpStreamStats::retransmitted_packets_received`] and
110 /// [`RtcInboundRtpStreamStats::retransmitted_bytes_received`] counters of
111 /// the relevant [`RtcInboundRtpStreamStats`] objects.
112 ///
113 /// FEC streams do not show up as separate [`RtcInboundRtpStreamStats`]
114 /// objects but affect the [`RtcReceivedRtpStreamStats::packets_received`],
115 /// [`RtcInboundRtpStreamStats::bytes_received`],
116 /// [`RtcInboundRtpStreamStats::fec_packets_received`] and
117 /// [`RtcInboundRtpStreamStats::fec_bytes_received`] counters of the
118 /// relevant [`RtcInboundRtpStreamStats`] objects.
119 ///
120 /// [RTCPeerConnection]: https://w3.org/TR/webrtc#dom-rtcpeerconnection
121 /// [RTP stream]: https://w3.org/TR/webrtc-stats#dfn-rtp-stream
122 InboundRtp(Box<RtcInboundRtpStreamStats>),
123
124 /// Statistics for an outbound [RTP stream] that is currently sent with this
125 /// [RTCPeerConnection] object.
126 ///
127 /// When there are multiple [RTP stream]s connected to the same sender due
128 /// to using simulcast, there will be one [`RtcOutboundRtpStreamStats`]
129 /// per [RTP stream], with distinct values of the [SSRC] member. RTX streams
130 /// do not show up as separate [`RtcOutboundRtpStreamStats`] objects but
131 /// affect the [`RtcSentRtpStreamStats::packets_sent`],
132 /// [`RtcSentRtpStreamStats::bytes_sent`],
133 /// [`RtcOutboundRtpStreamStats::retransmitted_packets_sent`] and
134 /// [`RtcOutboundRtpStreamStats::retransmitted_bytes_sent`] counters of the
135 /// relevant [`RtcOutboundRtpStreamStats`] objects.
136 ///
137 /// [RTCPeerConnection]: https://w3.org/TR/webrtc#dom-rtcpeerconnection
138 /// [RTP stream]: https://w3.org/TR/webrtc-stats#dfn-rtp-stream
139 /// [SSRC]: https://w3.org/TR/webrtc-stats#dfn-ssrc
140 OutboundRtp(Box<RtcOutboundRtpStreamStats>),
141
142 /// Statistics for the remote endpoint's inbound [RTP stream] corresponding
143 /// to an outbound stream that is currently sent with this
144 /// [RTCPeerConnection] object.
145 ///
146 /// It is measured at the remote endpoint and reported in an
147 /// [RTCP Receiver Report][1] (RR) or [RTCP Extended Report][2] (XR).
148 ///
149 /// [RTCPeerConnection]: https://w3.org/TR/webrtc#dom-rtcpeerconnection
150 /// [RTP stream]: https://w3.org/TR/webrtc-stats#dfn-rtp-stream
151 /// [1]: https://w3.org/TR/webrtc-stats#dfn-receiver-report
152 /// [2]: https://w3.org/TR/webrtc-stats#dfn-extended-report
153 RemoteInboundRtp(Box<RtcRemoteInboundRtpStreamStats>),
154
155 /// Statistics for the remote endpoint's outbound [RTP stream] corresponding
156 /// to an inbound stream that is currently received with this
157 /// [RTCPeerConnection] object.
158 ///
159 /// It is measured at the remote endpoint and reported in an
160 /// [RTCP Sender Report][1] (SR).
161 ///
162 /// [RTCPeerConnection]: https://w3.org/TR/webrtc#dom-rtcpeerconnection
163 /// [RTP stream]: https://w3.org/TR/webrtc-stats#dfn-rtp-stream
164 /// [1]: https://w3.org/TR/webrtc-stats#dfn-sender-report
165 RemoteOutboundRtp(Box<RtcRemoteOutboundRtpStreamStats>),
166
167 /// Statistics for the media produced by a [MediaStreamTrack][1] that is
168 /// currently attached to an [RTCRtpSender].
169 ///
170 /// This reflects the media that is fed to the encoder; after
171 /// [getUserMedia()][2] constraints have been applied (i.e. not the raw
172 /// media produced by the camera).
173 ///
174 /// [RTCRtpSender]: https://w3.org/TR/webrtc#dom-rtcrtpsender
175 /// [1]: https://w3.org/TR/mediacapture-streams#dom-mediastreamtrack
176 /// [2]: https://tinyurl.com/w3-streams#dom-mediadevices-getusermedia
177 MediaSource(Box<RtcMediaSourceStats>),
178
179 /// Statistics related to audio playout.
180 MediaPlayout(Box<RtcAudioPlayoutStats>),
181
182 /// Statistics related to an [RTCPeerConnection] object.
183 ///
184 /// [RTCPeerConnection]: https://w3.org/TR/webrtc#dom-rtcpeerconnection
185 PeerConnection(Box<RtcPeerConnectionStats>),
186
187 /// Statistics related to each [RTCDataChannel] ID.
188 ///
189 /// [RTCDataChannel]: https://w3.org/TR/webrtc#dom-rtcdatachannel
190 DataChannel(Box<RtcDataChannelStats>),
191
192 /// Transport statistics related to an [RTCPeerConnection] object.
193 ///
194 /// It is accessed by the [`RtcTransportStats`].
195 ///
196 /// [RTCPeerConnection]: https://w3.org/TR/webrtc#dom-rtcpeerconnection
197 Transport(Box<RtcTransportStats>),
198
199 /// [ICE] candidate pair statistics related to [RTCIceTransport] objects.
200 ///
201 /// A candidate pair that is not the current pair for a transport is
202 /// [deleted][1] when the [RTCIceTransport] does an [ICE] restart, at the
203 /// time the state changes to `new`. The candidate pair that is the current
204 /// pair for a transport is deleted after an [ICE] restart when the
205 /// [RTCIceTransport] switches to using a candidate pair generated from the
206 /// new candidates; this time doesn't correspond to any other externally
207 /// observable event.
208 ///
209 /// [ICE]: https://datatracker.ietf.org/doc/html/rfc8445
210 /// [RTCIceTransport]: https://w3.org/TR/webrtc#dom-rtcicetransport
211 /// [1]: https://w3.org/TR/webrtc-stats#dfn-deleted
212 CandidatePair(Box<RtcIceCandidatePairStats>),
213
214 /// [ICE] local candidate statistics related to the [RTCIceTransport]
215 /// objects.
216 ///
217 /// A local candidate is [deleted][1] when the [RTCIceTransport] does an
218 /// [ICE] restart, and the candidate is no longer a member of any
219 /// non-deleted candidate pair.
220 ///
221 /// [ICE]: https://datatracker.ietf.org/doc/html/rfc8445
222 /// [RTCIceTransport]: https://w3.org/TR/webrtc#dom-rtcicetransport
223 /// [1]: https://w3.org/TR/webrtc-stats#dfn-deleted
224 LocalCandidate(Box<RtcIceCandidateStats>),
225
226 /// [ICE] remote candidate statistics related to the [RTCIceTransport]
227 /// objects.
228 ///
229 /// A remote candidate is [deleted][1] when the [RTCIceTransport] does an
230 /// [ICE] restart, and the candidate is no longer a member of any
231 /// non-deleted candidate pair.
232 ///
233 /// [ICE]: https://datatracker.ietf.org/doc/html/rfc8445
234 /// [RTCIceTransport]: https://w3.org/TR/webrtc#dom-rtcicetransport
235 /// [1]: https://w3.org/TR/webrtc-stats#dfn-deleted
236 RemoteCandidate(Box<RtcIceCandidateStats>),
237
238 /// Information about a certificate used by the [RTCIceTransport].
239 ///
240 /// It is accessed by [`RtcCertificateStats`].
241 ///
242 /// [RTCIceTransport]: https://w3.org/TR/webrtc#dom-rtcicetransport
243 Certificate(Box<RtcCertificateStats>),
244
245 /// Disabled or unknown variants of stats will be deserialized as [`Other`].
246 ///
247 /// [`Other`]: RtcStatsType::Other
248 #[serde(other)]
249 Other,
250}
251
252/// Statistics that apply to any end of any [RTP stream].
253///
254/// [Full doc on W3C][spec].
255///
256/// [RTP stream]: https://w3.org/TR/webrtc-stats#dfn-rtp-stream
257/// [spec]: https://w3.org/TR/webrtc-stats#dom-rtcrtpstreamstats
258#[expect(clippy::module_name_repetitions, reason = "spec compliance")]
259#[serde_with::skip_serializing_none]
260#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
261#[serde(rename_all = "camelCase")]
262pub struct RtcRtpStreamStats {
263 /// Synchronization source ([SSRC]) identifier is an unsigned integer value
264 /// per [RFC3550] used to identify the stream of [RTP] packets that this
265 /// stats object is describing.
266 ///
267 /// For outbound and inbound local, [SSRC] describes the stats for the [RTP]
268 /// stream that were sent and received, respectively by those endpoints.
269 ///
270 /// For the remote inbound and remote outbound, [SSRC] describes the stats
271 /// for the [RTP] stream that were received by and sent to the remote
272 /// endpoint.
273 ///
274 /// [RFC3550]: https://rfc-editor.org/rfc/rfc3550
275 /// [RTP]: https://webrtcglossary.com/rtp
276 /// [SSRC]: https://w3.org/TR/webrtc-stats#dfn-ssrc
277 pub ssrc: Option<u32>,
278
279 /// Either `audio` or `video`.
280 ///
281 /// This MUST match the [`kind` attribute][1] of the related
282 /// [MediaStreamTrack][0].
283 ///
284 /// [0]: https://w3.org/TR/mediacapture-streams#dom-mediastreamtrack
285 /// [1]: https://w3.org/TR/mediacapture-streams#dom-mediastreamtrack-kind
286 pub kind: String,
287
288 /// Unique identifier that is associated to the object that was inspected to
289 /// produce the [`RtcTransportStats`] associated with this [RTP stream].
290 ///
291 /// [RTP stream]: https://w3.org/TR/webrtc-stats#dfn-rtp-stream
292 pub transport_id: Option<String>,
293
294 /// Unique identifier that is associated to the object that was inspected to
295 /// produce the [`RtcCodecStats`] associated with this [RTP stream].
296 ///
297 /// [RTP stream]: https://w3.org/TR/webrtc-stats#dfn-rtp-stream
298 pub codec_id: Option<String>,
299}
300
301/// Statistics measured at the receiving end of an [RTP stream], known either
302/// because they're measured locally or transmitted via an
303/// [RTCP Receiver Report] (RR) or [Extended Report] (XR) block.
304///
305/// [Full doc on W3C][spec].
306///
307/// [Extended Report]: https://w3.org/TR/webrtc-stats#dfn-extended-report
308/// [RTP stream]: https://w3.org/TR/webrtc-stats#dfn-rtp-stream
309/// [RTCP Receiver Report]: https://w3.org/TR/webrtc-stats#dfn-receiver-report
310/// [spec]: https://w3.org/TR/webrtc-stats#dom-rtcreceivedrtpstreamstats
311#[expect(clippy::module_name_repetitions, reason = "spec compliance")]
312#[serde_with::skip_serializing_none]
313#[derive(Clone, Debug, Deserialize, Serialize, Hash, PartialEq)]
314#[serde(rename_all = "camelCase")]
315pub struct RtcReceivedRtpStreamStats {
316 /// Generic [RTP stream] data.
317 ///
318 /// [RTP stream]: https://w3.org/TR/webrtc-stats#dfn-rtp-stream
319 #[serde(flatten)]
320 pub stream: RtcRtpStreamStats,
321
322 /// Total number of [RTP] packets received for this [SSRC].
323 ///
324 /// This includes retransmissions.
325 ///
326 /// At the receiving endpoint, this is calculated as defined in
327 /// [RFC3550 Section 6.4.1][1].
328 ///
329 /// At the sending endpoint the [`packets_received`][0] is estimated by
330 /// subtracting the Cumulative Number of Packets Lost from the Extended
331 /// Highest Sequence Number Received, both reported in the
332 /// [RTCP Receiver Report][2], and then subtracting the initial
333 /// Extended Sequence Number that was sent to this [SSRC] in an
334 /// [RTCP Sender Report] and then adding one, to mirror what is discussed in
335 /// [Appendix A.3 in RFC3550][3], but for the sender side.
336 ///
337 /// If no [RTCP Receiver Report][0] has been received yet, then is `0`.
338 ///
339 /// [RTCP Sender Report]: https://w3.org/TR/webrtc-stats#dfn-sender-report
340 /// [RTP]: https://webrtcglossary.com/rtp
341 /// [SSRC]: https://w3.org/TR/webrtc-stats#dfn-ssrc
342 /// [0]: RtcReceivedRtpStreamStats::packets_received
343 /// [1]: https://rfc-editor.org/rfc/rfc3550#section-6.4.1
344 /// [2]: https://w3.org/TR/webrtc-stats#dfn-receiver-report
345 /// [3]: https://rfc-editor.org/rfc/rfc3550#appendix-A.3
346 pub packets_received: Option<u64>,
347
348 /// Total number of [RTP] packets received for this [SSRC] marked with the
349 /// [ECT(1) marking][1].
350 ///
351 /// [RTP]: https://webrtcglossary.com/rtp
352 /// [SSRC]: https://w3.org/TR/webrtc-stats#dfn-ssrc
353 /// [1]: https://rfc-editor.org/rfc/rfc3168#section-3
354 pub packets_received_with_ect1: Option<u64>,
355
356 /// Total number of [RTP] packets received for this [SSRC] marked with the
357 /// [CE marking][1].
358 ///
359 /// [RTP]: https://webrtcglossary.com/rtp
360 /// [SSRC]: https://w3.org/TR/webrtc-stats#dfn-ssrc
361 /// [1]: https://rfc-editor.org/rfc/rfc3168#section-4
362 pub packets_received_with_ce: Option<u64>,
363
364 /// Total number of [RTP] packets for which an [RFC8888 Section 3.1][1]
365 /// report has been sent with a zero `R` bit.
366 ///
367 /// Only exists if support for the `ccfb` feedback mechanism has been
368 /// negotiated.
369 ///
370 /// [RTP]: https://webrtcglossary.com/rtp
371 /// [1]: https://rfc-editor.org/rfc/rfc8888#section-3.1
372 pub packets_reported_as_lost: Option<u64>,
373
374 /// Total number of [RTP] packets for which an [RFC8888 Section 3.1][1]
375 /// report has been sent with a zero `R` bit, but a later report for the
376 /// same packet has the `R` bit set to `1`.
377 ///
378 /// Only exists if support for the `ccfb` feedback mechanism has been
379 /// negotiated.
380 ///
381 /// [RTP]: https://webrtcglossary.com/rtp
382 /// [1]: https://rfc-editor.org/rfc/rfc8888#section-3.1
383 pub packets_reported_as_lost_but_recovered: Option<u64>,
384
385 /// Total number of [RTP] packets lost for this [SSRC].
386 ///
387 /// Calculated as defined in [RFC3550 Section 6.4.1][1].
388 ///
389 /// Note that because of how this is estimated, it can be negative if more
390 /// packets are received than sent.
391 ///
392 /// [RTP]: https://webrtcglossary.com/rtp
393 /// [SSRC]: https://w3.org/TR/webrtc-stats#dfn-ssrc
394 /// [1]: https://rfc-editor.org/rfc/rfc3550#section-6.4.1
395 pub packets_lost: Option<i64>,
396
397 /// Packet jitter measured in seconds for this [SSRC].
398 ///
399 /// Calculated as defined in [Section 6.4.1 of RFC3550][1].
400 ///
401 /// [SSRC]: https://w3.org/TR/webrtc-stats#dfn-ssrc
402 /// [1]: https://rfc-editor.org/rfc/rfc3550#section-6.4.1
403 pub jitter: Option<Double>,
404}
405
406/// Statistics measured at the sending end of an [RTP stream], known either
407/// because they're measured locally or because they're received via [RTCP],
408/// usually in an [RTCP Sender Report] (SR).
409///
410/// [Full doc on W3C][spec].
411///
412/// [RTP stream]: https://w3.org/TR/webrtc-stats#dfn-rtp-stream
413/// [RTCP]: https://webrtcglossary.com/rtcp
414/// [RTCP Sender Report]: https://w3.org/TR/webrtc-stats#dfn-sender-report
415/// [spec]: https://w3.org/TR/webrtc-stats#dom-rtcsentrtpstreamstats
416#[expect(clippy::module_name_repetitions, reason = "spec compliance")]
417#[serde_with::skip_serializing_none]
418#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, Hash)]
419#[serde(rename_all = "camelCase")]
420pub struct RtcSentRtpStreamStats {
421 /// Generic [RTP stream] data.
422 ///
423 /// [RTP stream]: https://w3.org/TR/webrtc-stats#dfn-rtp-stream
424 #[serde(flatten)]
425 pub stream: RtcRtpStreamStats,
426
427 /// Total number of [RTP] packets sent for this [SSRC].
428 ///
429 /// This includes retransmissions.
430 ///
431 /// Calculated as defined in [RFC3550 Section 6.4.1][1].
432 ///
433 /// [RTP]: https://webrtcglossary.com/rtp
434 /// [SSRC]: https://w3.org/TR/webrtc-stats#dfn-ssrc
435 /// [1]: https://rfc-editor.org/rfc/rfc3550#section-6.4.1
436 pub packets_sent: Option<u64>,
437
438 /// Total number of bytes sent for this [SSRC].
439 ///
440 /// This includes retransmissions.
441 ///
442 /// Calculated as defined in [RFC3550 Section 6.4.1][1].
443 ///
444 /// [SSRC]: https://w3.org/TR/webrtc-stats#dfn-ssrc
445 /// [1]: https://rfc-editor.org/rfc/rfc3550#section-6.4.1
446 pub bytes_sent: Option<u64>,
447}
448
449/// Codecs are created when registered for an [RTP] transport, but only the
450/// subset of codecs that are in use (referenced by an [RTP stream]) are exposed
451/// in [getStats()].
452///
453/// The [`RtcCodecStats`] object is created when one or more
454/// [`RtcRtpStreamStats::codec_id`] references the codec. When there no longer
455/// exists any reference to the [`RtcCodecStats`], the stats object is deleted.
456/// If the same codec is used again in the future, the [`RtcCodecStats`] object
457/// is revived with the same [`StatId`] as before.
458///
459/// Codec objects may be referenced by multiple [RTP stream]s in media sections
460/// using the same transport, but similar codecs in different transports have
461/// different [`RtcCodecStats`] objects.
462///
463/// [Full doc on W3C][spec].
464///
465/// [getStats()]: https://tinyurl.com/webrtc-rfc-get-stats
466/// [RTP]: https://webrtcglossary.com/rtp
467/// [RTP stream]: https://w3.org/TR/webrtc-stats#dfn-rtp-stream
468/// [spec]: https://w3.org/TR/webrtc-stats#dom-rtccodecstats
469#[expect(clippy::module_name_repetitions, reason = "spec compliance")]
470#[serde_with::skip_serializing_none]
471#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
472#[serde(rename_all = "camelCase")]
473pub struct RtcCodecStats {
474 /// Payload type as used in [RTP] encoding or decoding.
475 ///
476 /// [RTP]: https://webrtcglossary.com/rtp
477 pub payload_type: u32,
478
479 /// Unique identifier of the transport on which this codec is being used,
480 /// which can be used to look up the corresponding [`RtcTransportStats`]
481 /// object.
482 pub transport_id: String,
483
484 /// Codec MIME media type/subtype defined in the IANA media types registry
485 /// [IANA-MEDIA-TYPES][0], e.g. `video/VP8`.
486 ///
487 /// [0]: https://iana.org/assignments/media-types/media-types.xhtml
488 pub mime_type: String,
489
490 /// Media sampling rate.
491 pub clock_rate: Option<u32>,
492
493 /// Number of channels (mono=1, stereo=2).
494 pub channels: Option<u32>,
495
496 /// The "format specific parameters" field from the `a=fmtp` line in the
497 /// SDP corresponding to the codec, if one exists, as
498 /// [defined by RFC8829][1].
499 ///
500 /// [1]: https://rfc-editor.org/rfc/rfc8829#section-5.8
501 pub sdp_fmtp_line: Option<String>,
502}
503
504/// Measurement metrics for an incoming media [RTP stream].
505///
506/// The timestamp reported in the statistics object is the time at which the
507/// data was sampled.
508///
509/// [Full doc on W3C][spec].
510///
511/// [RTP stream]: https://w3.org/TR/webrtc-stats#dfn-rtp-stream
512/// [spec]: https://w3.org/TR/webrtc-stats#dom-rtcoutboundrtpstreamstats
513#[expect(clippy::module_name_repetitions, reason = "spec compliance")]
514#[serde_with::skip_serializing_none]
515#[derive(Clone, Debug, Deserialize, Hash, PartialEq, Serialize)]
516#[serde(rename_all = "camelCase")]
517pub struct RtcInboundRtpStreamStats {
518 /// Generic ingress [RTP stream] data.
519 ///
520 /// [RTP stream]: https://w3.org/TR/webrtc-stats#dfn-rtp-stream
521 #[serde(flatten)]
522 pub received_stream: RtcReceivedRtpStreamStats,
523
524 /// Media kind specific part of these [`RtcInboundRtpStreamStats`].
525 #[serde(flatten)]
526 pub media_specific: InboundRtpMediaType,
527
528 /// [`id` attribute][2] value of the [MediaStreamTrack][1].
529 ///
530 /// [1]: https://w3.org/TR/mediacapture-streams#mediastreamtrack
531 /// [2]: https://w3.org/TR/mediacapture-streams#dom-mediastreamtrack-id
532 pub track_identifier: Option<String>,
533
534 /// [mid] value of the [RTCRtpTransceiver][0] owning this stream.
535 ///
536 /// If the [RTCRtpTransceiver][0] owning this stream has a [mid] value that
537 /// is not `null`, this is that value, otherwise this member MUST NOT be
538 /// present.
539 ///
540 /// [mid]: https://w3.org/TR/webrtc#dom-rtptransceiver-mid
541 /// [0]: https://w3.org/TR/webrtc#rtcrtptransceiver-interface
542 pub mid: Option<String>,
543
544 /// Identifier for looking up the remote [`RtcRemoteOutboundRtpStreamStats`]
545 /// object for the same [SSRC].
546 ///
547 /// [SSRC]: https://w3.org/TR/webrtc-stats#dfn-ssrc
548 pub remote_id: Option<String>,
549
550 /// Total number of bytes received for this [SSRC].
551 ///
552 /// This includes retransmissions.
553 ///
554 /// Calculated as defined in [RFC3550 Section 6.4.1][1].
555 ///
556 /// [SSRC]: https://w3.org/TR/webrtc-stats#dfn-ssrc
557 /// [1]: https://rfc-editor.org/rfc/rfc3550#section-6.4.1
558 pub bytes_received: Option<u64>,
559
560 /// Total number of audio samples or video frames that have come out of the
561 /// jitter buffer (increasing the [`jitter_buffer_delay`][1]).
562 ///
563 /// [1]: RtcInboundRtpStreamStats::jitter_buffer_delay
564 pub jitter_buffer_emitted_count: Option<u64>,
565
566 /// Sum of the time, in seconds, each [audio sample] or a video frame takes
567 /// from the time the first packet is received by the jitter buffer (ingest
568 /// timestamp) to the time it exits the jitter buffer (emit timestamp).
569 ///
570 /// The purpose of the jitter buffer is to recombine [RTP] packets into
571 /// frames (in the case of video) and have smooth playout. The model
572 /// described here assumes that the samples or frames are still compressed
573 /// and have not yet been decoded.
574 ///
575 /// In the case of audio, several samples belong to the same [RTP] packet,
576 /// hence they will have the same ingest timestamp but different jitter
577 /// buffer emit timestamps.
578 ///
579 /// In the case of video, the frame may be received over several [RTP]
580 /// packets, hence the ingest timestamp is the earliest packet of the frame
581 /// that entered the jitter buffer and the emit timestamp is when the whole
582 /// frame exits the jitter buffer.
583 ///
584 /// This metric increases upon samples or frames exiting, having completed
585 /// their time in the buffer (and incrementing the
586 /// [`jitter_buffer_emitted_count`][1]).
587 ///
588 /// The average jitter buffer delay can be calculated by dividing the
589 /// [`jitter_buffer_delay`][2] with the [`jitter_buffer_emitted_count`][1].
590 ///
591 /// [audio sample]: https://w3.org/TR/webrtc-stats#dfn-audio-sample
592 /// [RTP]: https://webrtcglossary.com/rtp
593 /// [1]: RtcInboundRtpStreamStats::jitter_buffer_emitted_count
594 /// [2]: RtcInboundRtpStreamStats::jitter_buffer_delay
595 pub jitter_buffer_delay: Option<Double>,
596
597 /// Cumulative time of delays, in seconds, at the time that a sample is
598 /// emitted from the jitter buffer.
599 ///
600 /// This value is increased by the target jitter buffer delay every time a
601 /// sample is emitted by the jitter buffer. The added target is the target
602 /// delay, in seconds, at the time that the sample was emitted from the
603 /// jitter buffer.
604 ///
605 /// To get the average target delay, divide by
606 /// [`jitter_buffer_emitted_count`][1].
607 ///
608 /// [1]: RtcInboundRtpStreamStats::jitter_buffer_emitted_count
609 pub jitter_buffer_target_delay: Option<Double>,
610
611 /// Minimum jitter buffer delay, in seconds.
612 ///
613 /// There are various reasons why the jitter buffer delay might be increased
614 /// to a higher value, such as to achieve A/V synchronization or because a
615 /// [jitterBufferTarget][0] was set on an [RTCRtpReceiver]. When using
616 /// one of these mechanisms, it can be useful to keep track of the minimal
617 /// jitter buffer delay that could have been achieved, so clients can track
618 /// the amount of additional delay that is being added.
619 ///
620 /// This metric works the same way as the [`jitter_buffer_target_delay`][1],
621 /// except that it is not affected by external mechanisms that increase the
622 /// jitter buffer target delay, such as [jitterBufferTarget][0], A/V sync,
623 /// or any other mechanisms. This metric is purely based on the network
624 /// characteristics such as jitter and packet loss, and can be seen as the
625 /// minimum obtainable jitter buffer delay if no external factors would
626 /// affect it.
627 ///
628 /// This metric is updated every time the [`jitter_buffer_emitted_count`][2]
629 /// is updated.
630 ///
631 /// [RTCRtpReceiver]: https://w3.org/TR/webrtc#rtcrtpreceiver-interface
632 /// [0]: https://w3.org/TR/webrtc#dom-rtcrtpreceiver-jitterbuffertarget
633 /// [1]: RtcInboundRtpStreamStats::jitter_buffer_target_delay
634 /// [2]: RtcInboundRtpStreamStats::jitter_buffer_emitted_count
635 pub jitter_buffer_minimum_delay: Option<Double>,
636
637 /// Total number of [RTP] header and padding bytes received for this [SSRC].
638 ///
639 /// This includes retransmissions. Does not include transport headers
640 /// (IP/UDP). [`header_bytes_received`][1] + [`bytes_received`][2] equals
641 /// the total number of bytes received as payload over the transport.
642 ///
643 /// [RTP]: https://webrtcglossary.com/rtp
644 /// [SSRC]: https://w3.org/TR/webrtc-stats#dfn-ssrc
645 /// [1]: RtcInboundRtpStreamStats::header_bytes_received
646 /// [2]: RtcInboundRtpStreamStats::bytes_received
647 pub header_bytes_received: Option<u64>,
648
649 /// Cumulative number of [RTP] packets discarded by the jitter buffer due to
650 /// late or early-arrival, i.e. these packets are not played out.
651 ///
652 /// [RTP] packets discarded due to packet duplication are not reported in
653 /// this metric [XRBLOCK-STATS].
654 ///
655 /// Calculated as defined in [RFC7002 Section 3.2][1] and [Appendix A.a][2].
656 ///
657 /// [RTP]: https://webrtcglossary.com/rtp
658 /// [XRBLOCK-STATS]: https://tinyurl.com/xr-report
659 /// [1]: https://rfc-editor.org/rfc/rfc7002#section-3.2
660 /// [2]: https://rfc-editor.org/rfc/rfc7002#appendix-A
661 pub packets_discarded: Option<u64>,
662
663 /// Timestamp at which the last [RTP] packet was received for this [SSRC].
664 ///
665 /// This differs from the [`RtcStat::timestamp`], which represents the time
666 /// at which the statistics were generated or received by the local
667 /// endpoint.
668 ///
669 /// [RTP]: https://webrtcglossary.com/rtp
670 /// [SSRC]: https://w3.org/TR/webrtc-stats#dfn-ssrc
671 pub last_packet_received_timestamp: Option<HighResTimeStamp>,
672
673 /// Estimated playout time of this receiver's track in sender [NTP] time.
674 ///
675 /// Can be used to estimate A/V sync across tracks from the same source.
676 ///
677 /// [NTP]: https://en.wikipedia.org/wiki/Network_Time_Protocol
678 pub estimated_playout_timestamp: Option<HighResTimeStamp>,
679
680 /// Total number of [RTP] FEC bytes received for this [SSRC], only including
681 /// payload bytes.
682 ///
683 /// This is a subset of the [`bytes_received`][1].
684 ///
685 /// If FEC uses a different [SSRC], packets are still accounted for here.
686 ///
687 /// [RTP]: https://webrtcglossary.com/rtp
688 /// [SSRC]: https://w3.org/TR/webrtc-stats#dfn-ssrc
689 /// [1]: RtcInboundRtpStreamStats::bytes_received
690 pub fec_bytes_received: Option<u64>,
691
692 /// Total number of [RTP] FEC packets received for this [SSRC].
693 ///
694 /// If FEC uses a different [SSRC], packets are still accounted for here.
695 ///
696 /// Can also increment when receiving in-band FEC (for example, [Opus]).
697 ///
698 /// [Opus]: https://en.wikipedia.org/wiki/Opus_(audio_format)
699 /// [RTP]: https://webrtcglossary.com/rtp
700 /// [SSRC]: https://w3.org/TR/webrtc-stats#dfn-ssrc
701 pub fec_packets_received: Option<u64>,
702
703 /// Total number of [RTP] FEC packets received for this [SSRC] where the
704 /// error correction payload was discarded (for example, sources already
705 /// recovered or FEC arrived late).
706 ///
707 /// This is a subset of the [`fec_bytes_received`][1].
708 ///
709 /// [RTP]: https://webrtcglossary.com/rtp
710 /// [SSRC]: https://w3.org/TR/webrtc-stats#dfn-ssrc
711 /// [1]: RtcInboundRtpStreamStats::fec_bytes_received
712 pub fec_packets_discarded: Option<u64>,
713
714 /// Sum of the time, in seconds, each [audio sample] or video frame takes
715 /// from the time the first [RTP] packet is received (reception timestamp)
716 /// and to the time the corresponding sample or frame is decoded (decoded
717 /// timestamp).
718 ///
719 /// At this point the audio sample or video frame is ready for playout by
720 /// the [MediaStreamTrack][1]. Typically ready for playout here means after
721 /// the audio sample or video frame is fully decoded by the decoder.
722 ///
723 /// [audio sample]: https://w3.org/TR/webrtc-stats#dfn-audio-sample
724 /// [RTP]: https://webrtcglossary.com/rtp
725 /// [1]: https://w3.org/TR/mediacapture-streams#mediastreamtrack
726 pub total_processing_delay: Option<Double>,
727
728 /// Total number of [Negative ACKnowledgement (NACK)][1] [RTCP] feedback
729 /// packets sent by this receiver for this [SSRC], as defined in
730 /// [RFC4585 Section 6.2.1][0].
731 ///
732 /// [RTCP]: https://webrtcglossary.com/rtcp
733 /// [SSRC]: https://w3.org/TR/webrtc-stats#dfn-ssrc
734 /// [0]: https://rfc-editor.org/rfc/rfc4585#section-6.2.1
735 /// [1]: https://bloggeek.me/webrtcglossary/nack
736 pub nack_count: Option<u32>,
737
738 /// Total number of retransmitted packets that were received for this
739 /// [SSRC].
740 ///
741 /// This is a subset of the [`RtcReceivedRtpStreamStats::packets_received`].
742 ///
743 /// If RTX is not negotiated, retransmitted packets can not be identified
744 /// and this member MUST NOT exist.
745 ///
746 /// [SSRC]: https://w3.org/TR/webrtc-stats#dfn-ssrc
747 pub retransmitted_packets_received: Option<u64>,
748
749 /// Total number of retransmitted bytes that were received for this [SSRC],
750 /// only including payload bytes.
751 ///
752 /// This is a subset of the [`bytes_received`][1].
753 ///
754 /// If RTX is not negotiated, retransmitted packets can not be identified
755 /// and this member MUST NOT exist.
756 ///
757 /// [SSRC]: https://w3.org/TR/webrtc-stats#dfn-ssrc
758 /// [1]: RtcInboundRtpStreamStats::bytes_received
759 pub retransmitted_bytes_received: Option<u64>,
760
761 /// [SSRC] of the RTX stream that is associated with this stream's [SSRC].
762 ///
763 /// If RTX is negotiated for retransmissions on a separate [RTP stream],
764 /// this is the [SSRC] of the RTX stream that is associated with this
765 /// stream's [SSRC].
766 ///
767 /// If RTX is not negotiated, this value MUST NOT be present.
768 ///
769 /// [RTP stream]: https://w3.org/TR/webrtc-stats#dfn-rtp-stream
770 /// [SSRC]: https://w3.org/TR/webrtc-stats#dfn-ssrc
771 pub rtx_ssrc: Option<u32>,
772
773 /// [SSRC] of the FEC stream that is associated with this stream's [SSRC].
774 ///
775 /// If a FEC mechanism that uses a separate [RTP stream] is negotiated, this
776 /// is the [SSRC] of the FEC stream that is associated with this stream's
777 /// [SSRC].
778 ///
779 /// If FEC is not negotiated or uses the same [RTP stream], this value MUST
780 /// NOT be present.
781 ///
782 /// [RTP stream]: https://w3.org/TR/webrtc-stats#dfn-rtp-stream
783 /// [SSRC]: https://w3.org/TR/webrtc-stats#dfn-ssrc
784 pub fec_ssrc: Option<u32>,
785}
786
787/// Measurement metrics for the outgoing [RTP stream].
788///
789/// The timestamp reported in the statistics object is the time at which the
790/// data was sampled.
791///
792/// [Full doc on W3C][spec].
793///
794/// [RTP stream]: https://w3.org/TR/webrtc-stats#dfn-rtp-stream
795/// [spec]: https://w3.org/TR/webrtc-stats#dom-rtcoutboundrtpstreamstats
796#[expect(clippy::module_name_repetitions, reason = "spec compliance")]
797#[serde_with::skip_serializing_none]
798#[derive(Clone, Debug, Deserialize, Hash, PartialEq, Serialize)]
799#[serde(rename_all = "camelCase")]
800pub struct RtcOutboundRtpStreamStats {
801 /// Generic egress [RTP stream] data.
802 ///
803 /// [RTP stream]: https://w3.org/TR/webrtc-stats#dfn-rtp-stream
804 #[serde(flatten)]
805 pub sent_stream: RtcSentRtpStreamStats,
806
807 /// Media kind specific part of these [`RtcOutboundRtpStreamStats`].
808 #[serde(flatten)]
809 pub media_specific: OutboundRtpMediaType,
810
811 /// [mid] value of the [RTCRtpTransceiver][0] owning this stream.
812 ///
813 /// If the [RTCRtpTransceiver][0] owning this stream has a [mid] value that
814 /// is not `null`, this is that value, otherwise this member MUST NOT be
815 /// present.
816 ///
817 /// [mid]: https://w3.org/TR/webrtc#dom-rtptransceiver-mid
818 /// [0]: https://w3.org/TR/webrtc#rtcrtptransceiver-interface
819 pub mid: Option<String>,
820
821 /// Identifier of the stats object representing the track currently attached
822 /// to the sender of this stream, an [`RtcMediaSourceStats`].
823 pub media_source_id: Option<String>,
824
825 /// Identifier for looking up the remote [`RtcRemoteInboundRtpStreamStats`]
826 /// object for the same [SSRC].
827 ///
828 /// [SSRC]: https://w3.org/TR/webrtc-stats#dfn-ssrc
829 pub remote_id: Option<String>,
830
831 /// Total number of [RTP] header and padding bytes sent for this [SSRC].
832 ///
833 /// This does not include the size of transport layer headers such as IP or
834 /// UDP.
835 ///
836 /// [`header_bytes_sent`] + [`RtcSentRtpStreamStats::bytes_sent`] equals the
837 /// number of bytes sent as payload over the transport.
838 ///
839 /// [`header_bytes_sent`]: RtcOutboundRtpStreamStats::header_bytes_sent
840 /// [RTP]: https://webrtcglossary.com/rtp
841 /// [SSRC]: https://w3.org/TR/webrtc-stats#dfn-ssrc
842 pub header_bytes_sent: Option<u64>,
843
844 /// Total number of packets that were retransmitted for this [SSRC].
845 ///
846 /// This is a subset of the [`RtcSentRtpStreamStats::packets_sent`].
847 ///
848 /// If RTX is not negotiated, retransmitted packets are sent over this
849 /// [SSRC].
850 ///
851 /// If RTX was negotiated, retransmitted packets are sent over a separate
852 /// [SSRC] but is still accounted for here.
853 ///
854 /// [SSRC]: https://w3.org/TR/webrtc-stats#dfn-ssrc
855 pub retransmitted_packets_sent: Option<u64>,
856
857 /// Total number of bytes that were retransmitted for this [SSRC], only
858 /// including payload bytes.
859 ///
860 /// This is a subset of [`RtcSentRtpStreamStats::bytes_sent`].
861 ///
862 /// If RTX is not negotiated, retransmitted bytes are sent over this [SSRC].
863 ///
864 /// If RTX was negotiated, retransmitted bytes are sent over a separate
865 /// [SSRC] but is still accounted for here.
866 ///
867 /// [SSRC]: https://w3.org/TR/webrtc-stats#dfn-ssrc
868 pub retransmitted_bytes_sent: Option<u64>,
869
870 /// [SSRC] of the RTX stream that is associated with this stream's [SSRC].
871 ///
872 /// If RTX is negotiated for retransmissions on a separate [RTP stream],
873 /// this is the [SSRC] of the RTX stream that is associated with this
874 /// stream's [SSRC].
875 ///
876 /// If RTX is not negotiated, this value MUST NOT be present.
877 ///
878 /// [RTP stream]: https://w3.org/TR/webrtc-stats#dfn-rtp-stream
879 /// [SSRC]: https://w3.org/TR/webrtc-stats#dfn-ssrc
880 pub rtx_ssrc: Option<u32>,
881
882 /// Current encoder target in bits per second.
883 ///
884 /// The target is an instantaneous value reflecting the encoder's settings,
885 /// but the resulting payload bytes sent per second, excluding
886 /// retransmissions, SHOULD closely correlate to the target.
887 ///
888 /// See also the [`RtcSentRtpStreamStats::bytes_sent`] and the
889 /// [`retransmitted_bytes_sent`][1].
890 ///
891 /// This is defined in the same way as the ["TIAS" bitrate RFC3890][0].
892 ///
893 /// [0]: https://rfc-editor.org/rfc/rfc3890#section-6.2
894 /// [1]: RtcOutboundRtpStreamStats::retransmitted_bytes_sent
895 pub target_bitrate: Option<Double>,
896
897 /// Total number of seconds that packets have spent buffered locally before
898 /// being transmitted onto the network.
899 ///
900 /// The time is measured from when a packet is emitted from the [RTP]
901 /// packetizer until it is handed over to the OS network socket. This
902 /// measurement is added to [`total_packet_send_delay`][1] when
903 /// [`RtcSentRtpStreamStats::packets_sent`] is incremented.
904 ///
905 /// [RTP]: https://webrtcglossary.com/rtp
906 /// [1]: RtcOutboundRtpStreamStats::total_packet_send_delay
907 pub total_packet_send_delay: Option<Double>,
908
909 /// Total number of [Negative ACKnowledgement (NACK)][1] packets, as defined
910 /// in [RFC4585 Section 6.2.1][0], received by this sender.
911 ///
912 /// [0]: https://rfc-editor.org/rfc/rfc4585#section-6.2.1
913 /// [1]: https://bloggeek.me/webrtcglossary/nack
914 pub nack_count: Option<u32>,
915
916 /// Indicates whether this [RTP stream] is configured to be sent or
917 /// disabled.
918 ///
919 /// Note that an active stream can still not be sending, e.g. when being
920 /// limited by network conditions.
921 ///
922 /// [RTP stream]: https://w3.org/TR/webrtc-stats#dfn-rtp-stream
923 pub active: Option<bool>,
924
925 /// Total number of [RTP] packets sent for this [SSRC] with the [ECT(1)][1]
926 /// marking defined in [RFC3168 Section 5][2] and used by the L4S protocol
927 /// described in [RFC9331].
928 ///
929 /// [RFC9331]: https://rfc-editor.org/rfc/rfc9331
930 /// [RTP]: https://webrtcglossary.com/rtp
931 /// [SSRC]: https://w3.org/TR/webrtc-stats#dfn-ssrc
932 /// [1]: https://rfc-editor.org/rfc/rfc3168#section-3
933 /// [2]: https://rfc-editor.org/rfc/rfc3168#section-5
934 pub packets_sent_with_ect1: Option<u64>,
935}
936
937/// Remote endpoint's measurement metrics for a particular incoming [RTP stream]
938/// (corresponding to an outgoing [RTP stream] at the sending endpoint).
939///
940/// The timestamp reported in the statistics object is the time at which the
941/// corresponding [RTCP RR] was received.
942///
943/// [Full doc on W3C][spec].
944///
945/// [RTP stream]: https://w3.org/TR/webrtc-stats#dfn-rtp-stream
946/// [RTCP RR]: https://w3.org/TR/webrtc-stats#dfn-receiver-report
947/// [spec]: https://w3.org/TR/webrtc-stats#dom-rtcremoteinboundrtpstreamstats
948#[expect(clippy::module_name_repetitions, reason = "spec compliance")]
949#[serde_with::skip_serializing_none]
950#[derive(Clone, Debug, Deserialize, Hash, PartialEq, Serialize)]
951#[serde(rename_all = "camelCase")]
952pub struct RtcRemoteInboundRtpStreamStats {
953 /// Generic ingress [RTP stream] data.
954 ///
955 /// [RTP stream]: https://w3.org/TR/webrtc-stats#dfn-rtp-stream
956 #[serde(flatten)]
957 pub received_stream: RtcReceivedRtpStreamStats,
958
959 /// Identifier of the local [`RtcOutboundRtpStreamStats`] object for the
960 /// same [SSRC].
961 ///
962 /// [SSRC]: https://w3.org/TR/webrtc-stats#dfn-ssrc
963 pub local_id: Option<String>,
964
965 /// Estimated round trip time for this [SSRC] based on the [RTCP] timestamps
966 /// in the [RTCP Receiver Report][0] (RR) and measured in seconds.
967 ///
968 /// Calculated as defined in [Section 6.4.1 of RFC3550][1].
969 ///
970 /// MUST NOT exist until a [RTCP Receiver Report][0] is received with a
971 /// DLSR value other than `0` has been received.
972 ///
973 /// [RTCP]: https://webrtcglossary.com/rtcp
974 /// [SSRC]: https://w3.org/TR/webrtc-stats#dfn-ssrc
975 /// [0]: https://w3.org/TR/webrtc-stats#dfn-receiver-report
976 /// [1]: https://rfc-editor.org/rfc/rfc3550#section-6.4.1
977 pub round_trip_time: Option<Double>,
978
979 /// Cumulative sum of all round trip time measurements in seconds since the
980 /// beginning of the session.
981 ///
982 /// The individual round trip time is calculated based on the [RTCP]
983 /// timestamps in the [RTCP Receiver Report][0] (RR) [RFC3550], hence
984 /// requires a DLSR value other than `0`.
985 ///
986 /// The average round trip time can be computed from the
987 /// [`total_round_trip_time`][1] by dividing it by
988 /// [`round_trip_time_measurements`][2].
989 ///
990 /// [RFC3550]: https://rfc-editor.org/rfc/rfc3550
991 /// [RTCP]: https://webrtcglossary.com/rtcp
992 /// [0]: https://w3.org/TR/webrtc-stats#dfn-receiver-report
993 /// [1]: RtcRemoteInboundRtpStreamStats::total_round_trip_time
994 /// [2]: RtcRemoteInboundRtpStreamStats::round_trip_time_measurements
995 pub total_round_trip_time: Option<Double>,
996
997 /// Fraction packet loss reported for this [SSRC].
998 ///
999 /// Calculated as defined in [RFC3550 Section 6.4.1][1] and
1000 /// [Appendix A.3][2].
1001 ///
1002 /// [SSRC]: https://w3.org/TR/webrtc-stats#dfn-ssrc
1003 /// [1]: https://rfc-editor.org/rfc/rfc3550#section-6.4.1
1004 /// [2]: https://rfc-editor.org/rfc/rfc3550#appendix-A.3
1005 pub fraction_lost: Option<Double>,
1006
1007 /// Total number of [RTCP RR] blocks received for this [SSRC] that contain a
1008 /// valid round trip time.
1009 ///
1010 /// This counter will not increment if the [`round_trip_time`][1] can not be
1011 /// calculated because no [RTCP Receiver Report][0] with a DLSR value other
1012 /// than `0` has been received.
1013 ///
1014 /// [RTCP RR]: https://w3.org/TR/webrtc-stats#dfn-receiver-report
1015 /// [SSRC]: https://w3.org/TR/webrtc-stats#dfn-ssrc
1016 /// [0]: https://w3.org/TR/webrtc-stats#dfn-receiver-report
1017 /// [1]: RtcRemoteInboundRtpStreamStats::round_trip_time
1018 pub round_trip_time_measurements: Option<u64>,
1019
1020 /// Number of packets that were sent with [ECT(1)][2] markings per
1021 /// [RFC3168 Section 3][1], but where an [RFC8888] report gave information
1022 /// that the packet was received with a marking of "not-ECT".
1023 ///
1024 /// [RFC8888]: https://rfc-editor.org/rfc/rfc8888
1025 /// [1]: https://rfc-editor.org/rfc/rfc3168#section-3
1026 /// [2]: https://rfc-editor.org/rfc/rfc3168#section-5
1027 pub packets_with_bleached_ect1_marking: Option<u64>,
1028}
1029
1030/// Remote endpoint's measurement metrics for its outgoing [RTP stream]
1031/// (corresponding to an outgoing [RTP stream] at the sending endpoint).
1032///
1033/// The timestamp reported in this statistics object is the time at which the
1034/// corresponding [RTCP SR] was received.
1035///
1036/// [Full doc on W3C][spec].
1037///
1038/// [RTP stream]: https://w3.org/TR/webrtc-stats#dfn-rtp-stream
1039/// [RTCP SR]: https://w3.org/TR/webrtc-stats#dfn-sender-report
1040/// [spec]: https://w3.org/TR/webrtc-stats#dom-rtcremoteoutboundrtpstreamstats
1041#[expect(clippy::module_name_repetitions, reason = "spec compliance")]
1042#[serde_with::skip_serializing_none]
1043#[derive(Clone, Debug, Deserialize, Hash, PartialEq, Serialize)]
1044#[serde(rename_all = "camelCase")]
1045pub struct RtcRemoteOutboundRtpStreamStats {
1046 /// Generic egress [RTP stream] data.
1047 ///
1048 /// [RTP stream]: https://w3.org/TR/webrtc-stats#dfn-rtp-stream
1049 #[serde(flatten)]
1050 pub sent_stream: RtcSentRtpStreamStats,
1051
1052 /// Identifier of the local [`RtcInboundRtpStreamStats`] object for the same
1053 /// [SSRC].
1054 ///
1055 /// [SSRC]: https://w3.org/TR/webrtc-stats#dfn-ssrc
1056 pub local_id: Option<String>,
1057
1058 /// Remote timestamp at which these statistics were sent by the remote
1059 /// endpoint.
1060 ///
1061 /// This differs from the [`RtcStat::timestamp`], which represents the time
1062 /// at which the statistics were generated or received by the local
1063 /// endpoint.
1064 ///
1065 /// The remote timestamp, if present, is derived from the [NTP] timestamp in
1066 /// an [RTCP Sender Report] (SR) block, which reflects the remote endpoint's
1067 /// clock. That clock may not be synchronized with the local clock.
1068 ///
1069 /// [NTP]: https://en.wikipedia.org/wiki/Network_Time_Protocol
1070 /// [RTCP Sender Report]: https://w3.org/TR/webrtc-stats#dfn-sender-report
1071 pub remote_timestamp: Option<HighResTimeStamp>,
1072
1073 /// Total number of [RTCP Sender Report] (SR) blocks sent for this [SSRC].
1074 ///
1075 /// [RTCP Sender Report]: https://w3.org/TR/webrtc-stats#dfn-sender-report
1076 /// [SSRC]: https://w3.org/TR/webrtc-stats#dfn-ssrc
1077 pub reports_sent: Option<u64>,
1078
1079 /// Estimated round trip time for this [SSRC] based on the latest
1080 /// [RTCP Sender Report] (SR) that contains a [DLRR report block][1] as
1081 /// defined in [RFC3611].
1082 ///
1083 /// The calculation of the round trip time is defined in
1084 /// [Section 4.5 of RFC3611][1].
1085 ///
1086 /// MUST NOT exist if the latest SR does not contain the
1087 /// [DLRR report block][1], or if the last RR timestamp in the
1088 /// [DLRR report block][1] is zero, or if the delay since last RR value in
1089 /// the [DLRR report block][1] is zero.
1090 ///
1091 /// [SSRC]: https://w3.org/TR/webrtc-stats#dfn-ssrc
1092 /// [RFC3611]: https://rfc-editor.org/rfc/rfc3611
1093 /// [RTCP Sender Report]: https://w3.org/TR/webrtc-stats#dfn-sender-report
1094 /// [1]: https://www.rfc-editor.org/rfc/rfc3611#section-4.5
1095 pub round_trip_time: Option<Double>,
1096
1097 /// Cumulative sum of all round trip time measurements in seconds since the
1098 /// beginning of the session.
1099 ///
1100 /// The individual round trip time is calculated based on the
1101 /// [DLRR report block][1] in the [RTCP Sender Report] (SR) [RFC3611].
1102 ///
1103 /// This counter will not increment if the [`round_trip_time`][2] can not be
1104 /// calculated. The average round trip time can be computed from the
1105 /// [`total_round_trip_time`][3] by dividing it by
1106 /// [`round_trip_time_measurements`][4].
1107 ///
1108 /// [RFC3611]: https://rfc-editor.org/rfc/rfc3611
1109 /// [RTCP Sender Report]: https://w3.org/TR/webrtc-stats#dfn-sender-report
1110 /// [1]: https://www.rfc-editor.org/rfc/rfc3611#section-4.5
1111 /// [2]: RtcRemoteOutboundRtpStreamStats::round_trip_time
1112 /// [3]: RtcRemoteOutboundRtpStreamStats::total_round_trip_time
1113 /// [4]: RtcRemoteOutboundRtpStreamStats::round_trip_time_measurements
1114 pub total_round_trip_time: Option<Double>,
1115
1116 /// Total number of [RTCP Sender Report] (SR) blocks received for this
1117 /// [SSRC] that contain a [DLRR report block][1] that can derive a valid
1118 /// round trip time according to [RFC3611].
1119 ///
1120 /// This counter will not increment if the [`round_trip_time`][2] can not be
1121 /// calculated.
1122 ///
1123 /// [RFC3611]: https://rfc-editor.org/rfc/rfc3611
1124 /// [RTCP Sender Report]: https://w3.org/TR/webrtc-stats#dfn-sender-report
1125 /// [SSRC]: https://w3.org/TR/webrtc-stats#dfn-ssrc
1126 /// [1]: https://www.rfc-editor.org/rfc/rfc3611#section-4.5
1127 /// [2]: RtcRemoteOutboundRtpStreamStats::round_trip_time
1128 pub round_trip_time_measurements: Option<u64>,
1129}
1130
1131/// Statistics of a track that is currently attached to one or more senders.
1132///
1133/// It contains information about media sources such as frame rate and
1134/// resolution prior to encoding. This is the media passed from the
1135/// [MediaStreamTrack][1] to the [RTCRtpSender]s. This is in contrast to
1136/// [`RtcOutboundRtpStreamStats`] whose members describe metrics as measured
1137/// after the encoding step. For example, a track may be captured from a
1138/// high-resolution camera, its frames downscaled due to track constraints and
1139/// then further downscaled by the encoders due to CPU and network conditions.
1140/// This dictionary reflects the video frames or [audio sample]s passed out from
1141/// the track - after track constraints have been applied but before any
1142/// encoding or further downsampling occurs.
1143///
1144/// [Full doc on W3C][spec].
1145///
1146/// [audio sample]: https://w3.org/TR/webrtc-stats#dfn-audio-sample
1147/// [RTCRtpSender]: https://w3.org/TR/webrtc#dom-rtcrtpsender
1148/// [spec]: https://w3.org/TR/webrtc-stats#dom-rtcmediasourcestats
1149/// [1]: https://w3.org/TR/mediacapture-streams#mediastreamtrack
1150#[expect(clippy::module_name_repetitions, reason = "spec compliance")]
1151#[serde_with::skip_serializing_none]
1152#[derive(Clone, Debug, Deserialize, Hash, PartialEq, Serialize)]
1153#[serde(rename_all = "camelCase")]
1154pub struct RtcMediaSourceStats {
1155 /// [`id` attribute][2] value of the [MediaStreamTrack][1].
1156 ///
1157 /// [1]: https://w3.org/TR/mediacapture-streams#mediastreamtrack
1158 /// [2]: https://w3.org/TR/mediacapture-streams#dom-mediastreamtrack-id
1159 pub track_identifier: Option<String>,
1160
1161 /// Fields which should be in the [`RtcStat`] based on its `kind`.
1162 #[serde(flatten)]
1163 pub kind: MediaSourceKind,
1164}
1165
1166/// Statistics of one playout path.
1167///
1168/// If the same playout statistics object is referenced by multiple
1169/// [`RtcInboundRtpStreamStats`] this is an indication that audio mixing is
1170/// happening in which case sample counters in this statistics object refer to
1171/// the samples after mixing.
1172///
1173/// [Full doc on W3C][spec].
1174///
1175/// [spec]: https://w3.org/TR/webrtc-stats#dom-rtcaudioplayoutstats
1176#[expect(clippy::module_name_repetitions, reason = "spec compliance")]
1177#[serde_with::skip_serializing_none]
1178#[derive(Clone, Debug, Hash, Deserialize, Serialize, PartialEq)]
1179#[serde(rename_all = "camelCase")]
1180pub struct RtcAudioPlayoutStats {
1181 /// For audio playout, this has the value `audio`.
1182 ///
1183 /// This reflects the [`kind` attribute][1] of the [MediaStreamTrack][0]
1184 /// being played out.
1185 ///
1186 /// [0]: https://w3.org/TR/mediacapture-streams#mediastreamtrack
1187 /// [1]: https://w3.org/TR/mediacapture-streams#dom-mediastreamtrack-kind
1188 pub kind: Option<String>,
1189
1190 /// Total duration, in seconds, of synthesized audio samples that have been
1191 /// played out.
1192 ///
1193 /// If the playout path is unable to produce audio samples on time for
1194 /// device playout, samples are synthesized to be playout out instead.
1195 /// [`synthesized_samples_duration`][1] is measured in seconds and is
1196 /// incremented each time an audio sample is synthesized by this playout
1197 /// path.
1198 ///
1199 /// This metric can be used together with [`total_samples_duration`][2] to
1200 /// calculate the percentage of played out media being synthesized.
1201 ///
1202 /// Synthesization typically only happens if the pipeline is
1203 /// underperforming. Samples synthesized by the [`RtcInboundRtpStreamStats`]
1204 /// are not counted for here, but in
1205 /// [`InboundRtpMediaType::Audio::concealed_samples`].
1206 ///
1207 /// [1]: RtcAudioPlayoutStats::synthesized_samples_duration
1208 /// [2]: RtcAudioPlayoutStats::total_samples_duration
1209 pub synthesized_samples_duration: Option<Double>,
1210
1211 /// Number of synthesized samples events.
1212 ///
1213 /// This counter increases every time a sample is synthesized after a
1214 /// non-synthesized sample. That is, multiple consecutive synthesized
1215 /// samples will increase the [`synthesized_samples_duration`][1] multiple
1216 /// times but is a single synthesization samples event.
1217 ///
1218 /// [1]: RtcAudioPlayoutStats::synthesized_samples_duration
1219 pub synthesized_samples_events: Option<u32>,
1220
1221 /// Total duration, in seconds, of all audio samples that have been played
1222 /// out.
1223 ///
1224 /// Includes both synthesized and non-synthesized samples.
1225 pub total_samples_duration: Option<Double>,
1226
1227 /// Total estimated delay of the playout path for all audio samples.
1228 ///
1229 /// When audio samples are pulled by the playout device, this counter is
1230 /// incremented with the estimated delay of the playout path for that audio
1231 /// sample. The playout delay includes the delay from being emitted to the
1232 /// actual time of playout on the device.
1233 ///
1234 /// This metric can be used together with [`total_samples_count`][1] to
1235 /// calculate the average playout delay per sample.
1236 ///
1237 /// [1]: RtcAudioPlayoutStats::total_samples_count
1238 pub total_playout_delay: Option<Double>,
1239
1240 /// Total number of samples emitted for playout.
1241 ///
1242 /// When audio samples are pulled by the playout device, this counter is
1243 /// incremented with the number of samples emitted for playout.
1244 pub total_samples_count: Option<u64>,
1245}
1246
1247/// Statistics for an [RTCPeerConnection] object.
1248///
1249/// [Full doc on W3C][spec].
1250///
1251/// [RTCPeerConnection]: https://w3.org/TR/webrtc#dom-rtcpeerconnection
1252/// [spec]: https://w3.org/TR/webrtc-stats#dom-rtcpeerconnectionstats
1253#[expect(clippy::module_name_repetitions, reason = "spec compliance")]
1254#[serde_with::skip_serializing_none]
1255#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
1256#[serde(rename_all = "camelCase")]
1257pub struct RtcPeerConnectionStats {
1258 /// Number of unique [RTCDataChannel]s that have entered the
1259 /// [`open` state][1] during their lifetime.
1260 ///
1261 /// [RTCDataChannel]: https://w3.org/TR/webrtc#dom-rtcdatachannel
1262 /// [1]: https://w3.org/TR/webrtc#dom-rtcdatachannelstate-open
1263 pub data_channels_opened: Option<u32>,
1264
1265 /// Number of unique [RTCDataChannel]s that have left the [`open` state][1]
1266 /// during their lifetime (due to being closed by either end or the
1267 /// underlying transport being closed).
1268 ///
1269 /// [RTCDataChannel]s that transition from [`connecting`][2] to
1270 /// [`closing`][3] or [`closed`][4] state without ever being [`open`][1] are
1271 /// not counted in this number.
1272 ///
1273 /// [RTCDataChannel]: https://w3.org/TR/webrtc#dom-rtcdatachannel
1274 /// [1]: https://w3.org/TR/webrtc#dom-rtcdatachannelstate-open
1275 /// [2]: https://w3.org/TR/webrtc#dom-rtcdatachannelstate-connecting
1276 /// [3]: https://w3.org/TR/webrtc#dom-rtcdatachannelstate-closing
1277 /// [4]: https://w3.org/TR/webrtc#dom-rtcdatachannelstate-closed
1278 pub data_channels_closed: Option<u32>,
1279}
1280
1281/// Non-exhaustive version of a [`KnownRtcDataChannelState`].
1282pub type RtcDataChannelState = NonExhaustive<KnownRtcDataChannelState>;
1283
1284/// Possible states of [RTCDataChannel]'s underlying data connection.
1285///
1286/// [RTCDataChannel]: https://w3.org/TR/webrtc#dom-rtcdatachannel
1287#[derive(
1288 Clone, Copy, Debug, Deserialize, Display, Eq, Hash, PartialEq, Serialize,
1289)]
1290#[serde(rename_all = "kebab-case")]
1291pub enum KnownRtcDataChannelState {
1292 /// User agent is attempting to establish the underlying data transport.
1293 ///
1294 /// This is the initial state of an [RTCDataChannel] object, whether created
1295 /// with [createDataChannel()][1], or dispatched as a part of an
1296 /// [RTCDataChannelEvent].
1297 ///
1298 /// [RTCDataChannel]: https://w3.org/TR/webrtc#dom-rtcdatachannel
1299 /// [RTCDataChannelEvent]: https://w3.org/TR/webrtc#dom-rtcdatachannelevent
1300 /// [1]: https://w3.org/TR/webrtc#dom-peerconnection-createdatachannel
1301 #[display("connecting")]
1302 Connecting,
1303
1304 /// [Underlying data transport][1] is established and communication is
1305 /// possible.
1306 ///
1307 /// [1]: https://w3.org/TR/webrtc#dfn-data-transport
1308 #[display("open")]
1309 Open,
1310
1311 /// [Procedure][2] to close down the [underlying data transport][1] has
1312 /// started.
1313 ///
1314 /// [1]: https://w3.org/TR/webrtc#dfn-data-transport
1315 /// [2]: https://w3.org/TR/webrtc#data-transport-closing-procedure
1316 #[display("closing")]
1317 Closing,
1318
1319 /// [Underlying data transport][1] has been [`closed`][2] or could not be
1320 /// established.
1321 ///
1322 /// [1]: https://w3.org/TR/webrtc#dfn-data-transport
1323 /// [2]: https://w3.org/TR/webrtc#dom-rtcdatachannelstate-closed
1324 #[display("closed")]
1325 Closed,
1326}
1327
1328/// Statistics related to each [RTCDataChannel] ID.
1329///
1330/// [Full doc on W3C][spec].
1331///
1332/// [RTCDataChannel]: https://w3.org/TR/webrtc#dom-rtcdatachannel
1333/// [spec]: https://w3.org/TR/webrtc-stats#dom-rtcdatachannelstats
1334#[expect(clippy::module_name_repetitions, reason = "spec compliance")]
1335#[serde_with::skip_serializing_none]
1336#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
1337#[serde(rename_all = "camelCase")]
1338pub struct RtcDataChannelStats {
1339 /// [`label`] value of the [RTCDataChannel] object.
1340 ///
1341 /// [RTCDataChannel]: https://w3.org/TR/webrtc#dom-rtcdatachannel
1342 /// [`label`]: https://w3.org/TR/webrtc#dom-datachannel-label
1343 pub label: Option<String>,
1344
1345 /// [`protocol`][1] value of the [RTCDataChannel] object.
1346 ///
1347 /// [RTCDataChannel]: https://w3.org/TR/webrtc#dom-rtcdatachannel
1348 /// [1]: https://w3.org/TR/webrtc#dom-datachannel-protocol
1349 pub protocol: Option<String>,
1350
1351 /// [`id`][1] attribute of the [RTCDataChannel] object.
1352 ///
1353 /// [RTCDataChannel]: https://w3.org/TR/webrtc#dom-rtcdatachannel
1354 /// [1]: https://w3.org/TR/webrtc#dom-rtcdatachannel-id
1355 pub data_channel_identifier: Option<u16>,
1356
1357 /// [`readyState`][1] value of the [RTCDataChannel] object.
1358 ///
1359 /// [RTCDataChannel]: https://w3.org/TR/webrtc#dom-rtcdatachannel
1360 /// [1]: https://w3.org/TR/webrtc#dom-datachannel-readystate
1361 pub state: Option<RtcDataChannelState>,
1362
1363 /// Total number of API `message` events sent.
1364 pub messages_sent: Option<u32>,
1365
1366 /// Total number of payload bytes sent on the [RTCDataChannel].
1367 ///
1368 /// [RTCDataChannel]: https://w3.org/TR/webrtc#dom-rtcdatachannel
1369 pub bytes_sent: Option<u64>,
1370
1371 /// Total number of API `message` events received.
1372 pub messages_received: Option<u32>,
1373
1374 /// Total number of bytes received on the [RTCDataChannel].
1375 ///
1376 /// [RTCDataChannel]: https://w3.org/TR/webrtc#dom-rtcdatachannel
1377 pub bytes_received: Option<u64>,
1378}
1379
1380/// Statistics corresponding to an [RTCDtlsTransport] and its underlying
1381/// [RTCIceTransport].
1382///
1383/// When bundling is used, a single transport will be used for all
1384/// [MediaStreamTrack][0]s in the bundle group. If bundling is not used,
1385/// different [MediaStreamTrack][0]s will use different transports. Bundling is
1386/// described in [WebRTC].
1387///
1388/// [Full doc on W3C][spec].
1389///
1390/// [RTCDtlsTransport]: https://w3.org/TR/webrtc#dom-rtcdtlstransport
1391/// [RTCIceTransport]: https://w3.org/TR/webrtc#dom-rtcicetransport
1392/// [WebRTC]: https://w3.org/TR/webrtc
1393/// [spec]: https://w3.org/TR/webrtc-stats#dom-rtctransportstats
1394/// [0]: https://w3.org/TR/mediacapture-streams#mediastreamtrack
1395#[expect(clippy::module_name_repetitions, reason = "spec compliance")]
1396#[serde_with::skip_serializing_none]
1397#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
1398#[serde(rename_all = "camelCase")]
1399pub struct RtcTransportStats {
1400 /// Total number of packets sent over the transport.
1401 pub packets_sent: Option<u64>,
1402
1403 /// Total number of packets received on the transport.
1404 pub packets_received: Option<u64>,
1405
1406 /// Total number of payload bytes sent on the underlying [RTCIceTransport],
1407 /// i.e. not including headers, padding or [ICE] connectivity checks.
1408 ///
1409 /// [ICE]: https://datatracker.ietf.org/doc/html/rfc8445
1410 /// [RTCIceTransport]: https://w3.org/TR/webrtc#dom-rtcicetransport
1411 pub bytes_sent: Option<u64>,
1412
1413 /// Total number of payload bytes received on the underlying
1414 /// [RTCIceTransport], i.e. not including headers, padding or [ICE]
1415 /// connectivity checks.
1416 ///
1417 /// [ICE]: https://datatracker.ietf.org/doc/html/rfc8445
1418 /// [RTCIceTransport]: https://w3.org/TR/webrtc#dom-rtcicetransport
1419 pub bytes_received: Option<u64>,
1420
1421 /// Current value of the [`role` attribute][1] of the underlying
1422 /// [RTCIceTransport].
1423 ///
1424 /// [RTCIceTransport]: https://w3.org/TR/webrtc#dom-rtcicetransport
1425 /// [1]: https://w3.org/TR/webrtc#dom-icetransport-role
1426 pub ice_role: Option<RtcIceRole>,
1427
1428 /// Current value of the local username fragment used in message validation
1429 /// procedures [RFC5245] for the underlying [RTCIceTransport].
1430 ///
1431 /// It may be updated on [setLocalDescription()][0] and on [ICE] restart.
1432 ///
1433 /// [ICE]: https://datatracker.ietf.org/doc/html/rfc8445
1434 /// [RFC5245]: https://rfc-editor.org/rfc/rfc5245
1435 /// [RTCIceTransport]: https://w3.org/TR/webrtc#dom-rtcicetransport
1436 /// [0]: https://w3.org/TR/webrtc#dom-peerconnection-setlocaldescription
1437 pub ice_local_username_fragment: Option<String>,
1438
1439 /// Current value of the [`state` attribute][1] of the underlying
1440 /// [RTCIceTransport].
1441 ///
1442 /// [RTCIceTransport]: https://w3.org/TR/webrtc#dom-rtcicetransport
1443 /// [1]: https://w3.org/TR/webrtc#dom-icetransport-state
1444 pub ice_state: Option<RtcIceTransportState>,
1445
1446 /// Current value of the [`state` attribute][1] of the [RTCDtlsTransport].
1447 ///
1448 /// [RTCDtlsTransport]: https://w3.org/TR/webrtc#dom-rtcdtlstransport
1449 /// [1]: https://w3.org/TR/webrtc#dom-rtcdtlstransport-state
1450 pub dtls_state: Option<RtcDtlsTransportState>,
1451
1452 /// Unique identifier that is associated to the object that was inspected to
1453 /// produce the [`RtcIceCandidatePairStats`] associated with the transport.
1454 pub selected_candidate_pair_id: Option<String>,
1455
1456 /// Identified of the local certificate for components where [DTLS] is
1457 /// negotiated.
1458 ///
1459 /// [DTLS]: https://webrtcglossary.com/dtls
1460 pub local_certificate_id: Option<String>,
1461
1462 /// Identified of the remote certificate for components where [DTLS] is
1463 /// negotiated.
1464 ///
1465 /// [DTLS]: https://webrtcglossary.com/dtls
1466 pub remote_certificate_id: Option<String>,
1467
1468 /// Agreed [TLS] version for components where [DTLS] is negotiated.
1469 ///
1470 /// It's represented as four upper case hexadecimal digits representing the
1471 /// two bytes of the version.
1472 ///
1473 /// Only present after [DTLS] negotiation is complete.
1474 ///
1475 /// [DTLS]: https://webrtcglossary.com/dtls
1476 /// [TLS]: https://webrtcglossary.com/tls
1477 pub tls_version: Option<String>,
1478
1479 /// Descriptive name of the cipher suite used for the [DTLS] transport, as
1480 /// defined in the
1481 /// ["Description" column of the IANA cipher suite registry][0].
1482 ///
1483 /// [DTLS]: https://webrtcglossary.com/dtls
1484 /// [0]: https://w3.org/TR/webrtc-stats#bib-iana-tls-ciphers
1485 pub dtls_cipher: Option<String>,
1486
1487 /// [`Client`] or [`Server`] depending on the [DTLS] role.
1488 ///
1489 /// [`Unknown`] before the [DTLS] negotiation starts.
1490 ///
1491 /// [`Client`]: KnownRtcDtlsRole::Client
1492 /// [`Server`]: KnownRtcDtlsRole::Server
1493 /// [`Unknown`]: KnownRtcDtlsRole::Unknown
1494 /// [DTLS]: https://webrtcglossary.com/dtls
1495 pub dtls_role: Option<RtcDtlsRole>,
1496
1497 /// Descriptive name of the protection profile used for the [SRTP]
1498 /// transport, as defined in the
1499 /// ["Profile" column of the IANA DTLS-SRTP protection profile registry][0]
1500 /// and described further in [RFC5764].
1501 ///
1502 /// [RFC5764]: https://rfc-editor.org/rfc/rfc5764
1503 /// [SRTP]: https://webrtcglossary.com/srtp
1504 /// [0]: https://iana.org/assignments/srtp-protection/srtp-protection.xhtml
1505 pub srtp_cipher: Option<String>,
1506
1507 /// Number of Transport-Layer Feedback Messages of type
1508 /// `CongestionControl Feedback Packet`, as described in
1509 /// [RFC8888 Section 3.1][0], sent on the transport.
1510 ///
1511 /// [0]: https://rfc-editor.org/rfc/rfc8888#section-3.1
1512 pub ccfb_messages_sent: Option<u32>,
1513
1514 /// Number of Transport-Layer Feedback Messages of type
1515 /// `CongestionControl Feedback Packet`, as described in
1516 /// [RFC8888 Section 3.1][0], received on the transport.
1517 ///
1518 /// [0]: https://rfc-editor.org/rfc/rfc8888#section-3.1
1519 pub ccfb_messages_received: Option<u32>,
1520
1521 /// Number of times that the selected candidate pair of the transport has
1522 /// changed.
1523 ///
1524 /// Going from not having a selected candidate pair to having a selected
1525 /// candidate pair, or the other way around, also increases this counter.
1526 /// It is initially zero and becomes one when an initial candidate pair is
1527 /// selected.
1528 pub selected_candidate_pair_changes: Option<u32>,
1529}
1530
1531/// [ICE] candidate pair statistics related to [RTCIceTransport] objects.
1532///
1533/// The candidate pair that is not the current pair for transport is
1534/// [deleted][1] when the [RTCIceTransport] does an [ICE] restart, at the time
1535/// the state changes to [`KnownRtcIceTransportState::New`].
1536///
1537/// The candidate pair that is the current pair for transport is [deleted][1]
1538/// after an [ICE] restart when the [RTCIceTransport] switches to using a
1539/// candidate pair generated from the new candidates; this time doesn't
1540/// correspond to any other externally observable event.
1541///
1542/// [`RtcStatsType::CandidatePair`] variant.
1543///
1544/// [Full doc on W3C][spec].
1545///
1546/// [ICE]: https://datatracker.ietf.org/doc/html/rfc8445
1547/// [RTCIceTransport]: https://w3.org/TR/webrtc#dom-rtcicetransport
1548/// [spec]: https://w3.org/TR/webrtc-stats#dom-rtcicecandidatepairstats
1549/// [1]: https://w3.org/TR/webrtc-stats#dfn-deleted
1550#[expect(clippy::module_name_repetitions, reason = "spec compliance")]
1551#[serde_with::skip_serializing_none]
1552#[derive(Clone, Debug, Deserialize, Hash, PartialEq, Serialize)]
1553#[serde(rename_all = "camelCase")]
1554pub struct RtcIceCandidatePairStats {
1555 /// Unique identifier associated to the object that was inspected to produce
1556 /// the [`RtcTransportStats`] associated with this candidates pair.
1557 pub transport_id: Option<String>,
1558
1559 /// Unique identifier associated to the object that was inspected to produce
1560 /// the [`RtcIceCandidateStats`] for the local candidate associated with
1561 /// this candidates pair.
1562 pub local_candidate_id: Option<String>,
1563
1564 /// Unique identifier associated to the object that was inspected to produce
1565 /// the [`RtcIceCandidateStats`] for the remote candidate associated with
1566 /// this candidates pair.
1567 pub remote_candidate_id: Option<String>,
1568
1569 /// State of the checklist for the local and remote candidates in a pair.
1570 pub state: RtcStatsIceCandidatePairState,
1571
1572 /// Related to updating the nominated flag described in
1573 /// [Section 7.1.3.2.4 of RFC 5245][1].
1574 ///
1575 /// [1]: https://tools.ietf.org/html/rfc5245#section-7.1.3.2.4
1576 pub nominated: Option<bool>,
1577
1578 /// Priority calculated as defined in [Section 15.1 of RFC 5245][1].
1579 ///
1580 /// [1]: https://tools.ietf.org/html/rfc5245#section-15.1
1581 pub priority: Option<u64>,
1582
1583 /// Total number of packets sent on this candidate pair.
1584 pub packets_sent: Option<u64>,
1585
1586 /// Total number of packets received on this candidate pair.
1587 pub packets_received: Option<u64>,
1588
1589 /// Total number of payload bytes sent on this candidate pair, i.e. not
1590 /// including headers, padding or [ICE] connectivity checks.
1591 ///
1592 /// [ICE]: https://datatracker.ietf.org/doc/html/rfc8445
1593 pub bytes_sent: Option<u64>,
1594
1595 /// Total number of payload bytes received on this candidate pair, i.e. not
1596 /// including headers, padding or [ICE] connectivity checks.
1597 ///
1598 /// [ICE]: https://datatracker.ietf.org/doc/html/rfc8445
1599 pub bytes_received: Option<u64>,
1600
1601 /// Timestamp at which the last packet was sent on this particular candidate
1602 /// pair, excluding [STUN] packets.
1603 ///
1604 /// [STUN]: https://webrtcglossary.com/stun
1605 pub last_packet_sent_timestamp: Option<HighResTimeStamp>,
1606
1607 /// Timestamp at which the last packet was received on this particular
1608 /// candidate pair, excluding [STUN] packets.
1609 ///
1610 /// [STUN]: https://webrtcglossary.com/stun
1611 pub last_packet_received_timestamp: Option<HighResTimeStamp>,
1612
1613 /// Sum of all round trip time measurements in seconds since the beginning
1614 /// of the session, based on [STUN] connectivity check [STUN-PATH-CHAR]
1615 /// responses (`responsesReceived`), including those that reply to requests
1616 /// that are sent in order to verify consent [RFC7675].
1617 ///
1618 /// The average round trip time can be computed from
1619 /// [`total_round_trip_time`][1] by dividing it by
1620 /// [`responses_received`][2].
1621 ///
1622 /// [RFC7675]: https://tools.ietf.org/html/rfc7675
1623 /// [STUN]: https://webrtcglossary.com/stun
1624 /// [STUN-PATH-CHAR]: https://w3.org/TR/webrtc-stats#bib-stun-path-char
1625 /// [1]: RtcIceCandidatePairStats::total_round_trip_time
1626 /// [2]: RtcIceCandidatePairStats::responses_received
1627 pub total_round_trip_time: Option<Double>,
1628
1629 /// Latest round trip time measured in seconds, computed from both [STUN]
1630 /// connectivity checks [STUN-PATH-CHAR], including those that are sent for
1631 /// consent verification [RFC7675].
1632 ///
1633 /// [RFC7675]: https://tools.ietf.org/html/rfc7675
1634 /// [STUN]: https://webrtcglossary.com/stun
1635 /// [STUN-PATH-CHAR]: https://w3.org/TR/webrtc-stats#bib-stun-path-char
1636 pub current_round_trip_time: Option<Double>,
1637
1638 /// Bitrate calculated by the underlying congestion control by combining the
1639 /// available bitrate for all the outgoing [RTP stream]s using this
1640 /// candidate pair.
1641 ///
1642 /// The bitrate measurement doesn't count the size of the IP or other
1643 /// transport layers like TCP or UDP. It's similar to the TIAS defined in
1644 /// [RFC3890], i.e. it's measured in bits per second and the bitrate is
1645 /// calculated over a 1-second window. For candidate pairs in use, the
1646 /// estimate is normally no lower than the bitrate for the packets sent at
1647 /// [`last_packet_sent_timestamp`][1], but might be higher.
1648 ///
1649 /// [RTP stream]: https://w3.org/TR/webrtc-stats#dfn-rtp-stream
1650 /// [RFC3890]: https://rfc-editor.org/rfc/rfc3890
1651 /// [1]: RtcIceCandidatePairStats::last_packet_sent_timestamp
1652 pub available_outgoing_bitrate: Option<Double>,
1653
1654 /// Bitrate calculated by the underlying congestion control by combining the
1655 /// available bitrate for all the incoming [RTP stream]s using this
1656 /// candidate pair.
1657 ///
1658 /// The bitrate measurement doesn't count the size of the IP or other
1659 /// transport layers like TCP or UDP. It's similar to the TIAS defined in
1660 /// [RFC3890], i.e. it's measured in bits per second and the bitrate is
1661 /// calculated over a 1-second window. For candidate pairs in use, the
1662 /// estimate is normally no lower than the bitrate for the packets sent at
1663 /// [`last_packet_received_timestamp`][1], but might be higher.
1664 ///
1665 /// [RTP stream]: https://w3.org/TR/webrtc-stats#dfn-rtp-stream
1666 /// [RFC3890]: https://rfc-editor.org/rfc/rfc3890
1667 /// [1]: RtcIceCandidatePairStats::last_packet_received_timestamp
1668 pub available_incoming_bitrate: Option<Double>,
1669
1670 /// Total number of connectivity check requests received (including
1671 /// retransmissions).
1672 ///
1673 /// It's impossible for the receiver to tell whether the request was sent in
1674 /// order to check connectivity or check consent, so all connectivity checks
1675 /// requests are counted here.
1676 pub requests_received: Option<u64>,
1677
1678 /// Total number of connectivity check requests sent (not including
1679 /// retransmissions).
1680 pub requests_sent: Option<u64>,
1681
1682 /// Total number of connectivity check responses received.
1683 pub responses_received: Option<u64>,
1684
1685 /// Total number of connectivity check responses sent.
1686 ///
1687 /// Since we cannot distinguish connectivity check requests and consent
1688 /// requests, all responses are counted.
1689 pub responses_sent: Option<u64>,
1690
1691 /// Total number of consent requests sent.
1692 pub consent_requests_sent: Option<u64>,
1693
1694 /// Total number of packets for this candidate pair that have been discarded
1695 /// due to socket errors, i.e. a socket error occurred when
1696 /// handing the packets to the socket.
1697 ///
1698 /// This might happen due to various reasons, including full buffer or no
1699 /// available memory.
1700 pub packets_discarded_on_send: Option<u32>,
1701
1702 /// Total number of bytes for this candidate pair that have been discarded
1703 /// due to socket errors, i.e. a socket error occurred when handing the
1704 /// packets containing the bytes to the socket.
1705 ///
1706 /// This might happen due to various reasons, including full buffer or no
1707 /// available memory.
1708 ///
1709 /// Calculated as defined in [RFC3550 section 6.4.1][1].
1710 ///
1711 /// [1]: https://rfc-editor.org/rfc/rfc3550#section-6.4.1
1712 pub bytes_discarded_on_send: Option<u64>,
1713}
1714
1715/// Properties of a `candidate` in [Section 15.1 of RFC5245][1].
1716///
1717/// It corresponds to a [RTCIceCandidate] object.
1718///
1719/// [Full doc on W3C][spec].
1720///
1721/// [RTCIceCandidate]: https://w3.org/TR/webrtc#dom-rtcicecandidate
1722/// [spec]: https://w3.org/TR/webrtc-stats#dom-rtcicecandidatestats
1723/// [1]: https://rfc-editor.org/rfc/rfc5245#section-15.1
1724#[expect(clippy::module_name_repetitions, reason = "spec compliance")]
1725#[serde_with::skip_serializing_none]
1726#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
1727#[serde(rename_all = "camelCase")]
1728pub struct RtcIceCandidateStats {
1729 /// Unique ID that is associated to the object that was inspected to produce
1730 /// the [`RtcTransportStats`] associated with the candidate.
1731 pub transport_id: Option<String>,
1732
1733 /// Address of the candidate, allowing for IPv4 addresses, IPv6 addresses,
1734 /// and fully qualified domain names (FQDNs).
1735 ///
1736 /// See [RFC5245 Section 15.1][1] for details.
1737 ///
1738 /// [1]: https://rfc-editor.org/rfc/rfc5245#section-15.1
1739 pub address: Option<String>,
1740
1741 /// Port number of the candidate.
1742 pub port: Option<i32>,
1743
1744 /// Valid values for transport is one of `udp` and `tcp`.
1745 ///
1746 /// Based on the `transport` defined in [RFC5245 Section 15.1][1].
1747 ///
1748 /// [1]: https://rfc-editor.org/rfc/rfc5245#section-15.1
1749 pub protocol: Option<String>,
1750
1751 /// Type of the [ICE] candidate.
1752 ///
1753 /// [ICE]: https://datatracker.ietf.org/doc/html/rfc8445
1754 pub candidate_type: RtcIceCandidateType,
1755
1756 /// Priority calculated as defined in [RFC5245 Section 15.1][1].
1757 ///
1758 /// [1]: https://rfc-editor.org/rfc/rfc5245#section-15.1
1759 pub priority: Option<i32>,
1760
1761 /// For local candidates of type [`KnownRtcIceCandidateType::Srflx`] or type
1762 /// [`KnownRtcIceCandidateType::Relay`] this is the URL of the [ICE] server
1763 /// from which the candidate was obtained and defined in [WebRTC].
1764 ///
1765 /// For remote candidates, this property MUST NOT be present.
1766 ///
1767 /// [ICE]: https://datatracker.ietf.org/doc/html/rfc8445
1768 /// [WebRTC]: https://w3.org/TR/webrtc
1769 pub url: Option<String>,
1770
1771 /// Protocol used by the endpoint to communicate with the [TURN] server.
1772 ///
1773 /// This is only present for local relay candidates and defined in [WebRTC].
1774 ///
1775 /// For remote candidates, this property MUST NOT be present.
1776 ///
1777 /// [TURN]: https://webrtcglossary.com/turn
1778 /// [WebRTC]: https://w3.org/TR/webrtc
1779 pub relay_protocol: Option<IceServerTransportProtocol>,
1780
1781 /// [ICE] foundation as defined in [RFC5245 Section 15.1][1].
1782 ///
1783 /// [ICE]: https://datatracker.ietf.org/doc/html/rfc8445
1784 /// [1]: https://rfc-editor.org/rfc/rfc5245#section-15.1
1785 pub foundation: Option<String>,
1786
1787 /// [ICE] `rel-addr` as defined in [RFC5245 Section 15.1][1].
1788 ///
1789 /// Only set for [`KnownRtcIceCandidateType::Srflx`],
1790 /// [`KnownRtcIceCandidateType::Prflx`] and
1791 /// [`KnownRtcIceCandidateType::Relay`] candidates.
1792 ///
1793 /// [ICE]: https://datatracker.ietf.org/doc/html/rfc8445
1794 /// [1]: https://rfc-editor.org/rfc/rfc5245#section-15.1
1795 pub related_address: Option<String>,
1796
1797 /// [ICE] `rel-port` as defined in [RFC5245 Section 15.1][1].
1798 ///
1799 /// Only set for [`KnownRtcIceCandidateType::Srflx`],
1800 /// [`KnownRtcIceCandidateType::Prflx`] and
1801 /// [`KnownRtcIceCandidateType::Relay`] candidates.
1802 ///
1803 /// [ICE]: https://datatracker.ietf.org/doc/html/rfc8445
1804 /// [1]: https://rfc-editor.org/rfc/rfc5245#section-15.1
1805 pub related_port: Option<i32>,
1806
1807 /// [ICE] username fragment as defined in [RFC5245 section 7.1.2.3][1].
1808 ///
1809 /// For [`KnownRtcIceCandidateType::Prflx`] remote candidates this is not
1810 /// set unless the [ICE] username fragment has been previously signaled.
1811 ///
1812 /// [ICE]: https://datatracker.ietf.org/doc/html/rfc8445
1813 /// [1]: https://rfc-editor.org/rfc/rfc5245#section-7.1.2.3
1814 pub username_fragment: Option<String>,
1815
1816 /// [ICE] candidate TCP type, as defined іn [`RtcIceTcpCandidateType`] and
1817 /// used in [RTCIceCandidate].
1818 ///
1819 /// [ICE]: https://datatracker.ietf.org/doc/html/rfc8445
1820 /// [RTCIceCandidate]: https://w3.org/TR/webrtc#dom-rtcicecandidate
1821 pub tcp_type: Option<RtcIceTcpCandidateType>,
1822
1823 /// Type of network used by a local [ICE] candidate.
1824 ///
1825 /// **Not spec compliant**, but provided by most user agents.
1826 ///
1827 /// [ICE]: https://datatracker.ietf.org/doc/html/rfc8445
1828 pub network_type: Option<String>,
1829}
1830
1831/// Non-exhaustive version of a [`KnownIceServerTransportProtocol`].
1832pub type IceServerTransportProtocol =
1833 NonExhaustive<KnownIceServerTransportProtocol>;
1834
1835/// Possible types of the transport protocol used between the client and the
1836/// server, as defined in [RFC8656 Section 3.1][1].
1837///
1838/// [1]: https://rfc-editor.org/rfc/rfc8656#section-3.1
1839#[derive(
1840 Clone, Copy, Debug, Deserialize, Display, Eq, Hash, PartialEq, Serialize,
1841)]
1842#[serde(rename_all = "lowercase")]
1843pub enum KnownIceServerTransportProtocol {
1844 /// UDP as transport to the server.
1845 #[display("udp")]
1846 Udp,
1847
1848 /// TCP as transport to the server.
1849 #[display("tcp")]
1850 Tcp,
1851
1852 /// TLS as transport to the server.
1853 #[display("tls")]
1854 Tls,
1855}
1856
1857/// Non-exhaustive version of a [`KnownRtcIceTcpCandidateType`].
1858pub type RtcIceTcpCandidateType = NonExhaustive<KnownRtcIceTcpCandidateType>;
1859
1860/// Possible types of an [ICE] TCP candidate, as defined in [RFC6544].
1861///
1862/// [ICE]: https://datatracker.ietf.org/doc/html/rfc8445
1863/// [RFC6544]: https://rfc-editor.org/rfc/rfc6544
1864#[derive(
1865 Clone, Copy, Debug, Deserialize, Display, Eq, Hash, PartialEq, Serialize,
1866)]
1867#[serde(rename_all = "kebab-case")]
1868pub enum KnownRtcIceTcpCandidateType {
1869 /// Candidate for which the transport will attempt to open an outbound
1870 /// connection but will not receive incoming connection requests.
1871 #[display("active")]
1872 Active,
1873
1874 /// Candidate for which the transport will receive incoming connection
1875 /// attempts, but not attempt a connection.
1876 #[display("passive")]
1877 Passive,
1878
1879 /// Candidate for which the transport will attempt to open a connection
1880 /// simultaneously with its peer.
1881 #[display("so")]
1882 So,
1883}
1884
1885/// Information about a certificate used by an [RTCIceTransport].
1886///
1887/// [Full doc on W3C][spec].
1888///
1889/// [RTCIceTransport]: https://w3.org/TR/webrtc#dom-rtcicetransport
1890/// [spec]: https://w3.org/TR/webrtc-stats#dom-rtccertificatestats
1891#[expect(clippy::module_name_repetitions, reason = "spec compliance")]
1892#[serde_with::skip_serializing_none]
1893#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
1894#[serde(rename_all = "camelCase")]
1895pub struct RtcCertificateStats {
1896 /// Fingerprint of the certificate.
1897 ///
1898 /// Only use the fingerprint value as defined in
1899 /// [Section 5 of RFC4572][1].
1900 ///
1901 /// [1]: https://tools.ietf.org/html/rfc4572#section-5
1902 pub fingerprint: String,
1903
1904 /// Hash function used to compute the certificate fingerprint.
1905 ///
1906 /// For instance, `sha-256`.
1907 pub fingerprint_algorithm: String,
1908
1909 /// The DER-encoded [Base64] representation of the certificate.
1910 ///
1911 /// [Base64]: https://en.wikipedia.org/wiki/Base64
1912 /// [DER]: https://en.wikipedia.org/wiki/X.690#DER_encoding
1913 pub base64_certificate: String,
1914
1915 /// Identifier referring to the stats object that contains the next
1916 /// certificate in the certificate chain.
1917 ///
1918 /// If the current certificate is at the end of the chain (i.e. a
1919 /// self-signed certificate), this will not be set.
1920 pub issuer_certificate_id: Option<String>,
1921}
1922
1923/// Non-exhaustive version of a [`KnownRtcIceRole`].
1924pub type RtcIceRole = NonExhaustive<KnownRtcIceRole>;
1925
1926/// Variants of [ICE roles][1].
1927///
1928/// More info in the [RFC5245].
1929///
1930/// [RFC5245]: https://tools.ietf.org/html/rfc5245
1931/// [1]: https://w3.org/TR/webrtc#dom-icetransport-role
1932#[derive(
1933 Clone, Copy, Debug, Deserialize, Display, Eq, Hash, PartialEq, Serialize,
1934)]
1935#[serde(rename_all = "camelCase")]
1936pub enum KnownRtcIceRole {
1937 /// Agent whose role as defined by [Section 3 in RFC 5245][1], has not yet
1938 /// been determined.
1939 ///
1940 /// [1]: https://tools.ietf.org/html/rfc5245#section-3
1941 #[display("unknown")]
1942 Unknown,
1943
1944 /// Controlling agent as defined by [Section 3 in RFC 5245][1].
1945 ///
1946 /// [1]: https://tools.ietf.org/html/rfc5245#section-3
1947 #[display("controlling")]
1948 Controlling,
1949
1950 /// Controlled agent as defined by [Section 3 in RFC 5245][1].
1951 ///
1952 /// [1]: https://tools.ietf.org/html/rfc5245#section-3
1953 #[display("controlled")]
1954 Controlled,
1955}
1956
1957/// Non-exhaustive version of a [`KnownRtcDtlsTransportState`].
1958pub type RtcDtlsTransportState = NonExhaustive<KnownRtcDtlsTransportState>;
1959
1960/// Possible states of a [DTLS] transport.
1961///
1962/// [DTLS]: https://webrtcglossary.com/dtls
1963#[derive(
1964 Clone, Copy, Debug, Deserialize, Display, Eq, Hash, PartialEq, Serialize,
1965)]
1966#[serde(rename_all = "camelCase")]
1967pub enum KnownRtcDtlsTransportState {
1968 /// [DTLS] has not started negotiating yet.
1969 ///
1970 /// [DTLS]: https://webrtcglossary.com/dtls
1971 #[display("new")]
1972 New,
1973
1974 /// [DTLS] is in the process of negotiating a secure connection and
1975 /// verifying the remote fingerprint.
1976 ///
1977 /// [DTLS]: https://webrtcglossary.com/dtls
1978 #[display("connecting")]
1979 Connecting,
1980
1981 /// [DTLS] has completed negotiation of a secure connection and verified the
1982 /// remote fingerprint.
1983 ///
1984 /// [DTLS]: https://webrtcglossary.com/dtls
1985 #[display("connected")]
1986 Connected,
1987
1988 /// [DTLS] transport has been closed intentionally as the result of receipt
1989 /// of a `close_notify` alert, or calling [close()].
1990 ///
1991 /// [close()]: https://w3.org/TR/webrtc#dom-rtcpeerconnection-close
1992 /// [DTLS]: https://webrtcglossary.com/dtls
1993 #[display("closed")]
1994 Closed,
1995
1996 /// [DTLS] transport has failed as the result of an error (such as receipt
1997 /// of an error alert or failure to validate the remote fingerprint).
1998 ///
1999 /// [DTLS]: https://webrtcglossary.com/dtls
2000 #[display("failed")]
2001 Failed,
2002}
2003
2004/// Non-exhaustive version of a [`KnownRtcIceTransportState`].
2005pub type RtcIceTransportState = NonExhaustive<KnownRtcIceTransportState>;
2006
2007/// Possible states of the underlying [ICE] transport used by a
2008/// [RTCPeerConnection].
2009///
2010/// [ICE]: https://datatracker.ietf.org/doc/html/rfc8445
2011/// [RTCPeerConnection]: https://w3.org/TR/webrtc#dom-rtcpeerconnection
2012#[derive(
2013 Clone, Copy, Debug, Deserialize, Display, Eq, Hash, PartialEq, Serialize,
2014)]
2015#[serde(rename_all = "camelCase")]
2016pub enum KnownRtcIceTransportState {
2017 /// [RTCIceTransport] has shut down and is no longer responding to [STUN]
2018 /// requests.
2019 ///
2020 /// [RTCIceTransport]: https://w3.org/TR/webrtc#dom-rtcicetransport
2021 /// [STUN]: https://webrtcglossary.com/stun
2022 #[display("closed")]
2023 Closed,
2024
2025 /// [RTCIceTransport] has finished gathering, received an indication that
2026 /// there are no more remote candidates, finished checking all candidate
2027 /// pairs, and all pairs have either failed connectivity checks or lost
2028 /// consent, and either zero local candidates were gathered or the PAC timer
2029 /// has expired (see [RFC8863]).
2030 ///
2031 /// This is a terminal state until [ICE] is restarted. Since an [ICE]
2032 /// restart may cause connectivity to resume, entering the [`Failed`] state
2033 /// doesn't cause [DTLS] transports, [SCTP] associations or the data
2034 /// channels that run over them to close, or tracks to mute.
2035 ///
2036 /// [`Failed`]: KnownRtcIceTransportState::Failed
2037 /// [DTLS]: https://webrtcglossary.com/dtls
2038 /// [ICE]: https://datatracker.ietf.org/doc/html/rfc8445
2039 /// [RTCIceTransport]: https://w3.org/TR/webrtc#dom-rtcicetransport
2040 /// [RFC8863]: https://rfc-editor.org/rfc/rfc8863
2041 /// [SCTP]: https://webrtcglossary.com/sctp
2042 #[display("failed")]
2043 Failed,
2044
2045 /// [ICE Agent] has determined that connectivity is currently lost for thw
2046 /// [RTCIceTransport].
2047 ///
2048 /// This is a transient state that may trigger intermittently (and resolve
2049 /// itself without action) on a flaky network. The way this state is
2050 /// determined is implementation dependent. Examples include:
2051 /// - Losing the network interface for the connection in use.
2052 /// - Repeatedly failing to receive a response to STUN requests.
2053 ///
2054 /// Alternatively, the [RTCIceTransport] has finished checking all existing
2055 /// candidates pairs and not found a connection (or consent checks [RFC7675]
2056 /// once successful, have now failed), but it is still gathering and/or
2057 /// waiting for additional remote candidates.
2058 ///
2059 /// [ICE Agent]: https://w3.org/TR/webrtc#dfn-ice-agent
2060 /// [RTCIceTransport]: https://w3.org/TR/webrtc#dom-rtcicetransport
2061 /// [RFC7675]: https://rfc-editor.org/rfc/rfc7675
2062 /// [STUN]: https://webrtcglossary.com/stun
2063 #[display("disconnected")]
2064 Disconnected,
2065
2066 /// [RTCIceTransport] is gathering candidates and/or waiting for remote
2067 /// candidates to be supplied, and has not yet started checking.
2068 ///
2069 /// [RTCIceTransport]: https://w3.org/TR/webrtc#dom-rtcicetransport
2070 #[display("new")]
2071 New,
2072
2073 /// [RTCIceTransport] has received at least one remote candidate (by means
2074 /// of [addIceCandidate()][0] or discovered as a peer-reflexive
2075 /// candidate when receiving a [STUN] binding request) and is checking
2076 /// candidate pairs and has either not yet found a connection or consent
2077 /// checks [RFC7675] have failed on all previously successful candidate
2078 /// pairs.
2079 ///
2080 /// In addition to checking, it may also still be gathering.
2081 ///
2082 /// [RTCIceTransport]: https://w3.org/TR/webrtc#dom-rtcicetransport
2083 /// [RFC7675]: https://rfc-editor.org/rfc/rfc7675
2084 /// [STUN]: https://webrtcglossary.com/stun
2085 /// [0]: https://w3.org/TR/webrtc#dom-peerconnection-addicecandidate
2086 #[display("checking")]
2087 Checking,
2088
2089 /// [RTCIceTransport] has finished gathering, received an indication
2090 /// that there are no more remote candidates, finished checking all
2091 /// candidate pairs and found a connection.
2092 ///
2093 /// If consent checks [RFC7675] subsequently fail on all successful
2094 /// candidate pairs, the state transitions to [`Failed`].
2095 ///
2096 /// [`Failed`]: KnownRtcIceTransportState::Failed
2097 /// [RTCIceTransport]: https://w3.org/TR/webrtc#dom-rtcicetransport
2098 /// [RFC7675]: https://rfc-editor.org/rfc/rfc7675
2099 #[display("completed")]
2100 Completed,
2101
2102 /// [RTCIceTransport] has found a usable connection, but is still checking
2103 /// other candidate pairs to see if there is a better connection.
2104 ///
2105 /// It may also still be gathering and/or waiting for additional remote
2106 /// candidates. If consent checks [RFC7675] fail on the connection in use,
2107 /// and there are no other successful candidate pairs available, then the
2108 /// state transitions to [`Checking`] (if there are candidate pairs
2109 /// remaining to be checked) or [`Disconnected`] (if there are no candidate
2110 /// pairs to check, but the peer is still gathering and/or waiting for
2111 /// additional remote candidates).
2112 ///
2113 /// [`Checking`]: KnownRtcIceTransportState::Checking
2114 /// [`Disconnected`]: KnownRtcIceTransportState::Disconnected
2115 /// [RTCIceTransport]: https://w3.org/TR/webrtc#dom-rtcicetransport
2116 /// [RFC7675]: https://rfc-editor.org/rfc/rfc7675
2117 #[display("connected")]
2118 Connected,
2119}
2120
2121/// Non-exhaustive version of a [`KnownRtcDtlsRole`].
2122pub type RtcDtlsRole = NonExhaustive<KnownRtcDtlsRole>;
2123
2124/// Possible roles in the DTLS handshake for transport.
2125///
2126/// [DTLS]: https://webrtcglossary.com/dtls
2127#[derive(
2128 Clone, Copy, Debug, Deserialize, Display, Eq, Hash, PartialEq, Serialize,
2129)]
2130#[serde(rename_all = "camelCase")]
2131pub enum KnownRtcDtlsRole {
2132 /// [RTCPeerConnection] is acting as a [DTLS] client as defined in
2133 /// [RFC6347].
2134 ///
2135 /// [DTLS]: https://webrtcglossary.com/dtls
2136 /// [RTCPeerConnection]: https://w3.org/TR/webrtc#dom-rtcpeerconnection
2137 /// [RFC6347]: https://rfc-editor.org/rfc/rfc6347
2138 #[display("client")]
2139 Client,
2140
2141 /// [RTCPeerConnection] is acting as a [DTLS] server as defined in
2142 /// [RFC6347].
2143 ///
2144 /// [DTLS]: https://webrtcglossary.com/dtls
2145 /// [RTCPeerConnection]: https://w3.org/TR/webrtc#dom-rtcpeerconnection
2146 /// [RFC6347]: https://rfc-editor.org/rfc/rfc6347
2147 #[display("server")]
2148 Server,
2149
2150 /// [DTLS] role of the [RTCPeerConnection] hasn't been determined yet.
2151 ///
2152 /// [DTLS]: https://webrtcglossary.com/dtls
2153 /// [RTCPeerConnection]: https://w3.org/TR/webrtc#dom-rtcpeerconnection
2154 #[display("unknown")]
2155 Unknown,
2156}
2157
2158/// Non-exhaustive version of a [`KnownRtcStatsIceCandidatePairState`].
2159pub type RtcStatsIceCandidatePairState =
2160 NonExhaustive<KnownRtcStatsIceCandidatePairState>;
2161
2162/// Possible states of a candidate pair.
2163#[derive(
2164 Clone, Copy, Debug, Deserialize, Display, Eq, Hash, PartialEq, Serialize,
2165)]
2166#[serde(rename_all = "kebab-case")]
2167pub enum KnownRtcStatsIceCandidatePairState {
2168 /// Check for this pair hasn't been performed, and it can't yet be performed
2169 /// until some other check succeeds, allowing this pair to unfreeze and move
2170 /// into the [`Waiting`] state.
2171 ///
2172 /// [`Waiting`]: KnownRtcStatsIceCandidatePairState::Waiting
2173 #[display("frozen")]
2174 Frozen,
2175
2176 /// Check has not been performed for this pair, and can be performed as soon
2177 /// as it's the highest-priority waiting pair on the check list.
2178 #[display("waiting")]
2179 Waiting,
2180
2181 /// Check has been sent for this pair, but the transaction is in progress.
2182 #[display("in-progress")]
2183 InProgress,
2184
2185 /// Check for this pair was already done and failed, either never producing
2186 /// any response or producing an unrecoverable failure response.
2187 #[display("failed")]
2188 Failed,
2189
2190 /// Check for this pair was already done and produced a successful result.
2191 #[display("succeeded")]
2192 Succeeded,
2193
2194 /// Other candidate pair was nominated.
2195 ///
2196 /// This state is **obsolete and not spec compliant**, however, it still
2197 /// may be emitted by some implementations.
2198 #[display("cancelled")]
2199 Cancelled,
2200}
2201
2202/// Non-exhaustive version of a [`KnownRtcIceCandidateType`].
2203pub type RtcIceCandidateType = NonExhaustive<KnownRtcIceCandidateType>;
2204
2205/// [RTCIceCandidateType] represents the type of the ICE candidate, as defined
2206/// in [Section 15.1 of RFC 5245][1].
2207///
2208/// [RTCIceCandidateType]: https://w3.org/TR/webrtc#rtcicecandidatetype-enum
2209/// [1]: https://tools.ietf.org/html/rfc5245#section-15.1
2210#[derive(
2211 Clone, Copy, Debug, Deserialize, Display, Eq, Hash, PartialEq, Serialize,
2212)]
2213#[serde(rename_all = "lowercase")]
2214pub enum KnownRtcIceCandidateType {
2215 /// Host candidate, as defined in [Section 4.1.1.1 of RFC 5245][1].
2216 ///
2217 /// [1]: https://tools.ietf.org/html/rfc5245#section-4.1.1.1
2218 #[display("host")]
2219 Host,
2220
2221 /// Server reflexive candidate, as defined in
2222 /// [Section 4.1.1.2 of RFC 5245][1].
2223 ///
2224 /// [1]: https://tools.ietf.org/html/rfc5245#section-4.1.1.2
2225 #[display("srflx")]
2226 Srflx,
2227
2228 /// Peer reflexive candidate, as defined in
2229 /// [Section 4.1.1.2 of RFC 5245][1].
2230 ///
2231 /// [1]: https://tools.ietf.org/html/rfc5245#section-4.1.1.2
2232 #[display("prflx")]
2233 Prflx,
2234
2235 /// Relay candidate, as defined in [Section 7.1.3.2.1 of RFC 5245][1].
2236 ///
2237 /// [1]: https://tools.ietf.org/html/rfc5245#section-7.1.3.2.1
2238 #[display("relay")]
2239 Relay,
2240}
2241
2242/// [`RtcStat`] fields of [`RtcStatsType::InboundRtp`] type based on its `kind`.
2243///
2244/// [Full doc on W3C][spec].
2245///
2246/// [spec]: https://w3.org/TR/webrtc-stats#dom-rtcinboundrtpstreamstats
2247#[serde_with::skip_serializing_none]
2248#[derive(Clone, Debug, Deserialize, Hash, PartialEq, Serialize)]
2249#[serde(tag = "mediaType", rename_all = "camelCase")]
2250pub enum InboundRtpMediaType {
2251 /// Fields when the `kind` is `audio`.
2252 ///
2253 /// [Full doc on W3C][spec].
2254 ///
2255 /// [spec]: https://w3.org/TR/webrtc-stats#dom-rtcinboundrtpstreamstats
2256 #[serde(rename_all = "camelCase")]
2257 Audio {
2258 /// Total number of samples that have been received on the [RTP stream].
2259 ///
2260 /// This includes [`InboundRtpMediaType::Audio::concealed_samples`].
2261 ///
2262 /// [RTP stream]: https://w3.org/TR/webrtc-stats#dfn-rtp-stream
2263 total_samples_received: Option<u64>,
2264
2265 /// Total number of samples that are concealed samples.
2266 ///
2267 /// A concealed sample is a sample that was replaced with synthesized
2268 /// samples generated locally before being played out. Examples of
2269 /// samples that have to be concealed are samples from lost packets
2270 /// (reported in [`RtcReceivedRtpStreamStats::packets_lost`]) or samples
2271 /// from packets that arrive too late to be played out (reported in
2272 /// [`RtcInboundRtpStreamStats::packets_discarded`]).
2273 concealed_samples: Option<u64>,
2274
2275 /// Total number of concealed samples inserted that are "silent".
2276 ///
2277 /// Playing out silent samples results in silence or comfort noise.
2278 ///
2279 /// This is a subset of
2280 /// [`InboundRtpMediaType::Audio::concealed_samples`].
2281 silent_concealed_samples: Option<u64>,
2282
2283 /// Number of concealment events.
2284 ///
2285 /// This counter increases every time a concealed sample is synthesized
2286 /// after a non-concealed sample. That is, multiple consecutive
2287 /// concealed samples will increase the
2288 /// [`InboundRtpMediaType::Audio::concealed_samples`] count multiple
2289 /// times, but is a single concealment event.
2290 concealment_events: Option<u64>,
2291
2292 /// Number of inserted deceleration samples.
2293 ///
2294 /// When playout is slowed down, this counter is increased by the
2295 /// difference between the number of samples received and the number of
2296 /// samples played out. If playout is slowed down by inserting samples,
2297 /// this will be the number of inserted samples.
2298 inserted_samples_for_deceleration: Option<u64>,
2299
2300 /// Number of removed acceleration samples.
2301 ///
2302 /// When playout is sped up, this counter is increased by the difference
2303 /// between the number of samples received and the number of samples
2304 /// played out. If speedup is achieved by removing samples, this will be
2305 /// the count of samples removed.
2306 removed_samples_for_acceleration: Option<u64>,
2307
2308 /// Audio level of the receiving track.
2309 ///
2310 /// For audio levels of tracks attached locally, see the
2311 /// [`MediaSourceKind::Audio`] instead.
2312 ///
2313 /// The value is between `0..1` (linear), where `1.0` represents
2314 /// `0 dBov`, `0` represents silence, and `0.5` represents approximately
2315 /// `6 dBSPL` change in the sound pressure level from `0 dBov`.
2316 ///
2317 /// The audio level is averaged over some small interval, using the
2318 /// algorithm described under [totalAudioEnergy][1]. The interval used
2319 /// is implementation-defined.
2320 ///
2321 /// [1]: https://tinyurl.com/webrtc-stats-totalaudioenergy
2322 audio_level: Option<Double>,
2323
2324 /// Audio energy of the receiving track.
2325 ///
2326 /// For audio energy of tracks attached locally, see the
2327 /// [`MediaSourceKind::Audio`] instead.
2328 total_audio_energy: Option<Double>,
2329
2330 /// Audio duration of the receiving track.
2331 ///
2332 /// For audio durations of tracks attached locally, see the
2333 /// [`MediaSourceKind::Audio`] instead.
2334 total_samples_duration: Option<Double>,
2335
2336 /// Indicator whether audio playout is happening.
2337 ///
2338 /// This is used to look up the corresponding [`RtcAudioPlayoutStats`].
2339 playout_id: Option<String>,
2340 },
2341
2342 /// Fields when the `kind` is `video`.
2343 ///
2344 /// [Full doc on W3C][spec].
2345 ///
2346 /// [spec]: https://w3.org/TR/webrtc-stats#dom-rtcinboundrtpstreamstats
2347 #[serde(rename_all = "camelCase")]
2348 Video {
2349 /// Total number of frames correctly decoded for the [RTP stream], i.e.
2350 /// frames that would be displayed if no frames are dropped.
2351 ///
2352 /// [RTP stream]: https://w3.org/TR/webrtc-stats#dfn-rtp-stream
2353 frames_decoded: Option<u32>,
2354
2355 /// Total number of key frames, such as key frames in VP8 [RFC6386] or
2356 /// IDR-frames in H.264 [RFC6184], successfully decoded for the media
2357 /// [RTP stream].
2358 ///
2359 /// This is a subset of [`InboundRtpMediaType::Video::frames_decoded`].
2360 /// [`InboundRtpMediaType::Video::frames_decoded`] -
2361 /// [`InboundRtpMediaType::Video::key_frames_decoded`] gives the number
2362 /// of delta frames decoded.
2363 ///
2364 /// [RFC6386]: https://w3.org/TR/webrtc-stats#bib-rfc6386
2365 /// [RFC6184]: https://w3.org/TR/webrtc-stats#bib-rfc6184
2366 /// [RTP stream]: https://w3.org/TR/webrtc-stats#dfn-rtp-stream
2367 key_frames_decoded: Option<u32>,
2368
2369 /// Total number of frames that have been rendered.
2370 ///
2371 /// It's incremented just after a frame has been rendered.
2372 frames_rendered: Option<u32>,
2373
2374 /// Total number of frames dropped prior to decode or dropped because
2375 /// the frame missed its display deadline for the receiver's track.
2376 ///
2377 /// The measurement begins when the receiver is created and is a
2378 /// cumulative metric as defined in Appendix A (g) of [RFC7004].
2379 ///
2380 /// [RFC7004]: https://rfc-editor.org/rfc/rfc7004
2381 frames_dropped: Option<u32>,
2382
2383 /// Width of the last decoded frame.
2384 ///
2385 /// Before the first frame is decoded this attribute is missing.
2386 frame_width: Option<u32>,
2387
2388 /// Height of the last decoded frame.
2389 ///
2390 /// Before the first frame is decoded this attribute is missing.
2391 frame_height: Option<u32>,
2392
2393 /// Number of decoded frames in the last second.
2394 frames_per_second: Option<Double>,
2395
2396 /// Sum of the QP values of frames decoded by the receiver.
2397 ///
2398 /// The count of frames is in
2399 /// [`InboundRtpMediaType::Video::frames_decoded`].
2400 ///
2401 /// The definition of QP value depends on the codec; for VP8, the QP
2402 /// value is the value carried in the frame header as the syntax element
2403 /// `y_ac_qi`, and defined in [RFC6386] section 19.2. Its range is
2404 /// `0..127`.
2405 ///
2406 /// Note, that the QP value is only an indication of quantizer values
2407 /// used; many formats have ways to vary the quantizer value within the
2408 /// frame.
2409 ///
2410 /// [RFC6386]: https://rfc-editor.org/rfc/rfc6386
2411 qp_sum: Option<u64>,
2412
2413 /// Total number of seconds that have been spent decoding the
2414 /// [`InboundRtpMediaType::Video::frames_decoded`] frames of
2415 /// the [RTP stream].
2416 ///
2417 /// The average decode time can be calculated by dividing this value
2418 /// with the [`InboundRtpMediaType::Video::frames_decoded`]. The time
2419 /// it takes to decode one frame is the time passed between feeding the
2420 /// decoder a frame and the decoder returning decoded data for that
2421 /// frame.
2422 ///
2423 /// [RTP stream]: https://w3.org/TR/webrtc-stats#dfn-rtp-stream
2424 total_decode_time: Option<Double>,
2425
2426 /// Sum of the interframe delays in seconds between consecutively
2427 /// rendered frames, recorded just after a frame has been rendered.
2428 ///
2429 /// The interframe delay variance be calculated from
2430 /// [`InboundRtpMediaType::Video::total_inter_frame_delay`],
2431 /// [`InboundRtpMediaType::Video::total_squared_inter_frame_delay`],
2432 /// and [`InboundRtpMediaType::Video::frames_rendered`] according to the
2433 /// formula:
2434 /// `(total_squared_inter_frame_delay - total_inter_frame_delay^2 /
2435 /// frames_rendered) / frames_rendered`.
2436 total_inter_frame_delay: Option<Double>,
2437
2438 /// Sum of the squared interframe delays in seconds between
2439 /// consecutively rendered frames, recorded just after a frame has been
2440 /// rendered.
2441 ///
2442 /// See the [`InboundRtpMediaType::Video::total_inter_frame_delay`] for
2443 /// details on how to calculate the interframe delay variance.
2444 total_squared_inter_frame_delay: Option<Double>,
2445
2446 /// Total number of video pauses experienced by the receiver.
2447 ///
2448 /// Video is considered to be paused if time passed since last rendered
2449 /// frame exceeds 5 seconds. It's incremented when a frame is rendered
2450 /// after such a pause.
2451 pause_count: Option<u32>,
2452
2453 /// Total duration of pauses, in seconds.
2454 ///
2455 /// For definition of pause see the
2456 /// [`InboundRtpMediaType::Video::pause_count`].
2457 ///
2458 /// This value is updated when a frame is rendered.
2459 total_pauses_duration: Option<Double>,
2460
2461 /// Total number of video freezes experienced by the receiver.
2462 ///
2463 /// It's a freeze if frame duration, which is time interval between two
2464 /// consecutively rendered frames, is equal or exceeds
2465 /// `Max(3 * avg_frame_duration_ms, avg_frame_duration_ms + 150)`,
2466 /// where `avg_frame_duration_ms` is linear average of durations of last
2467 /// 30 rendered frames.
2468 freeze_count: Option<u32>,
2469
2470 /// Total duration of rendered frames which are considered as frozen, in
2471 /// seconds.
2472 ///
2473 /// For definition of freeze see the
2474 /// [`InboundRtpMediaType::Video::freeze_count`].
2475 ///
2476 /// This value is updated when a frame is rendered.
2477 total_freezes_duration: Option<Double>,
2478
2479 /// Total number of Full Intra Request (FIR) packets, as defined in
2480 /// [RFC5104] section 4.3.1, sent by the receiver.
2481 ///
2482 /// Doesn't count the RTCP FIR indicated in [RFC2032] which was
2483 /// deprecated by [RFC4587].
2484 ///
2485 /// [RFC5104]: https://rfc-editor.org/rfc/rfc5104
2486 /// [RFC2032]: https://rfc-editor.org/rfc/rfc2032
2487 /// [RFC4587]: https://rfc-editor.org/rfc/rfc4587
2488 fir_count: Option<u32>,
2489
2490 /// Total number of Picture Loss Indication (PLI) packets, as defined in
2491 /// [RFC4585] section 6.3.1, sent by the receiver.
2492 ///
2493 /// [RFC4585]: https://rfc-editor.org/rfc/rfc4585
2494 pli_count: Option<u32>,
2495
2496 /// Total number of complete frames received on the [RTP stream].
2497 ///
2498 /// This metric is incremented when the complete frame is received.
2499 ///
2500 /// [RTP stream]: https://w3.org/TR/webrtc-stats#dfn-rtp-stream
2501 frames_received: Option<u32>,
2502
2503 /// Identification of the used the decoder implementation.
2504 ///
2505 /// This is useful for diagnosing interoperability issues.
2506 decoder_implementation: Option<String>,
2507
2508 /// Indicator whether the decoder currently used is considered power
2509 /// efficient by the user agent.
2510 ///
2511 /// This SHOULD reflect if the configuration results in hardware
2512 /// acceleration, but the user agent MAY take other information into
2513 /// account when deciding if the configuration is considered power
2514 /// efficient.
2515 power_efficient_decoder: Option<bool>,
2516
2517 /// Total number of frames correctly decoded for the [RTP stream] that
2518 /// consist of more than one RTP packet.
2519 ///
2520 /// For such frames the [`total_assembly_time`][1] is incremented. The
2521 /// average frame assembly time can be calculated by dividing the
2522 /// [`total_assembly_time`][1] with this value.
2523 ///
2524 /// [RTP stream]: https://w3.org/TR/webrtc-stats#dfn-rtp-stream
2525 /// [1]: InboundRtpMediaType::Video::total_assembly_time
2526 frames_assembled_from_multiple_packets: Option<u32>,
2527
2528 /// Sum of the time, in seconds, each video frame takes from the time
2529 /// the first RTP packet is received (reception timestamp) and to the
2530 /// time the last RTP packet of a frame is received.
2531 ///
2532 /// Only incremented for frames consisting of more than one RTP packet.
2533 ///
2534 /// Given the complexities involved, the time of arrival or the
2535 /// reception timestamp is measured as close to the network layer as
2536 /// possible. This metric is not incremented for frames that are not
2537 /// decoded, i.e., [`InboundRtpMediaType::Video::frames_dropped`] or
2538 /// frames that fail decoding for other reasons (if any).
2539 total_assembly_time: Option<Double>,
2540
2541 /// Cumulative sum of all corruption probability measurements that have
2542 /// been made for this SSRC.
2543 ///
2544 /// See the [`InboundRtpMediaType::Video::corruption_measurements`]
2545 /// regarding when this attribute SHOULD be present.
2546 ///
2547 /// Each measurement added to
2548 /// [`InboundRtpMediaType::Video::total_corruption_probability`] MUST be
2549 /// in the range `[0.0, 1.0]`, where a value of `0.0` indicates the
2550 /// system has estimated there is no or negligible corruption present in
2551 /// the processed frame. Similarly, a value of `1.0` indicates there is
2552 /// almost certainly a corruption visible in the processed frame. A
2553 /// value in between those two, indicates there is likely some
2554 /// corruption visible, but it could for instance have a low magnitude
2555 /// or be present only in a small portion of the frame.
2556 total_corruption_probability: Option<Double>,
2557
2558 /// Cumulative sum of all corruption probability measurements squared
2559 /// that have been made for this SSRC.
2560 ///
2561 /// See the [`InboundRtpMediaType::Video::corruption_measurements`]
2562 /// regarding when this attribute SHOULD be present.
2563 total_squared_corruption_probability: Option<Double>,
2564
2565 /// Number of corruption probability measurements.
2566 ///
2567 /// When the user agent is able to make a corruption probability
2568 /// measurement, this counter is incremented for each such measurement
2569 /// and the [`total_corruption_probability`][2] and the
2570 /// [`total_squared_corruption_probability`][1] are aggregated with this
2571 /// measurement and measurement squared respectively. If the
2572 /// [corruption-detection][0] header extension is present in the RTP
2573 /// packets, corruption probability measurements MUST be present.
2574 ///
2575 /// [0]: https://tinyurl.com/goog-corruption-detection
2576 /// [1]:InboundRtpMediaType::Video::total_squared_corruption_probability
2577 /// [2]: InboundRtpMediaType::Video::total_corruption_probability
2578 corruption_measurements: Option<u64>,
2579 },
2580}
2581
2582/// [`RtcStat`] fields of [`RtcStatsType::OutboundRtp`] type based on its
2583/// `kind`.
2584#[serde_with::skip_serializing_none]
2585#[derive(Clone, Debug, Deserialize, Hash, PartialEq, Serialize)]
2586#[serde(tag = "mediaType", rename_all = "camelCase")]
2587pub enum OutboundRtpMediaType {
2588 /// Fields when the `kind` is `audio`.
2589 #[serde(rename_all = "camelCase")]
2590 Audio {
2591 /// Total number of samples that have been sent over the [RTP stream].
2592 ///
2593 /// [RTP stream]: https://w3.org/TR/webrtc-stats#dfn-rtp-stream
2594 total_samples_sent: Option<u64>,
2595
2596 /// Indicator whether the last [RTP] packet sent contained voice
2597 /// activity or not, based on the presence of the `V` bit in the
2598 /// extension header.
2599 ///
2600 /// [RTP]: https://webrtcglossary.com/rtp
2601 voice_activity_flag: Option<bool>,
2602 },
2603
2604 /// Fields when the `kind` is `video`.
2605 ///
2606 /// [Full doc on W3C][spec].
2607 ///
2608 /// [spec]: https://w3.org/TR/webrtc-stats#dom-rtcoutboundrtpstreamstats
2609 #[serde(rename_all = "camelCase")]
2610 Video(Box<RtcOutboundRtpStreamVideo>),
2611}
2612
2613/// Video-specific [`RtcOutboundRtpStreamStats`] part.
2614///
2615/// [Full doc on W3C][spec].
2616///
2617/// [spec]: https://w3.org/TR/webrtc-stats#dom-rtcoutboundrtpstreamstats
2618#[serde_with::skip_serializing_none]
2619#[derive(Clone, Debug, Deserialize, Hash, PartialEq, Serialize)]
2620#[serde(rename_all = "camelCase")]
2621pub struct RtcOutboundRtpStreamVideo {
2622 /// Only exists if a [rid] has been set for the [RTP stream].
2623 ///
2624 /// If [rid] is set, this value will be present regardless if the
2625 /// [RID RTP header extension][1] has been negotiated.
2626 ///
2627 /// [rid]: https://w3.org/TR/webrtc#dom-rtcrtpcodingparameters-rid
2628 /// [RTP stream]: https://w3.org/TR/webrtc-stats#dfn-rtp-stream
2629 /// [1]: https://www.rfc-editor.org/rfc/rfc9429#section-5.2.1-13.11
2630 pub rid: Option<String>,
2631
2632 /// Index of the encoding that represents the [RTP stream] in the RTP
2633 /// sender's list of [encodings][0].
2634 ///
2635 /// [0]: https://w3.org/TR/webrtc#dom-rtcrtpsendparameters-encodings
2636 pub encoding_index: Option<u32>,
2637
2638 /// Value, increased by the target frame size in bytes every time a frame
2639 /// has been encoded.
2640 ///
2641 /// The actual frame size may be bigger or smaller than this number.
2642 ///
2643 /// This value goes up every time the
2644 /// [`RtcOutboundRtpStreamVideo::frames_encoded`] goes up.
2645 pub total_encoded_bytes_target: Option<u64>,
2646
2647 /// Width of the last encoded frame.
2648 ///
2649 /// The resolution of the encoded frame may be lower than the media source
2650 /// (see [RTCVideoSourceStats.width][1]).
2651 ///
2652 /// Before the first frame is encoded this attribute is missing.
2653 ///
2654 /// [1]: https://w3.org/TR/webrtc-stats#dom-rtcvideosourcestats-width
2655 pub frame_width: Option<u32>,
2656
2657 /// Height of the last encoded frame.
2658 ///
2659 /// The resolution of the encoded frame may be lower than the media source
2660 /// (see [RTCVideoSourceStats.height][1]).
2661 ///
2662 /// Before the first frame is encoded this attribute is missing.
2663 ///
2664 /// [1]: https://w3.org/TR/webrtc-stats#dom-rtcvideosourcestats-height
2665 pub frame_height: Option<u32>,
2666
2667 /// Number of encoded frames during the last second.
2668 ///
2669 /// This may be lower than the media source frame rate (see
2670 /// [RTCVideoSourceStats.framesPerSecond][1]).
2671 ///
2672 /// [1]: https://tinyurl.com/rrmkrfk
2673 pub frames_per_second: Option<Double>,
2674
2675 /// Total number of frames sent on the [RTP stream].
2676 ///
2677 /// [RTP stream]: https://w3.org/TR/webrtc-stats#dfn-rtp-stream
2678 pub frames_sent: Option<u32>,
2679
2680 /// Total number of huge frames sent by the [RTP stream].
2681 ///
2682 /// Huge frames, by definition, are frames that have an encoded size at
2683 /// least 2.5 times the average size of the frames. The average size of the
2684 /// frames is defined as the target bitrate per second divided by the target
2685 /// FPS at the time the frame was encoded. These are usually complex to
2686 /// encode frames with a lot of changes in the picture. This can be used to
2687 /// estimate slide changes in the streamed presentation.
2688 ///
2689 /// The multiplier of 2.5 is chosen from analyzing encoded frame sizes for a
2690 /// sample presentation using [WebRTC] standalone implementation. 2.5 is a
2691 /// reasonably large multiplier which still caused all slide change events
2692 /// to be identified as a huge frames. It, however, produced 1.4% of false
2693 /// positive slide change detections which is deemed reasonable.
2694 ///
2695 /// [RTP stream]: https://w3.org/TR/webrtc-stats#dfn-rtp-stream
2696 /// [WebRTC]: https://w3.org/TR/webrtc
2697 pub huge_frames_sent: Option<u32>,
2698
2699 /// Total number of frames successfully encoded for the media [RTP stream].
2700 ///
2701 /// [RTP stream]: https://w3.org/TR/webrtc-stats#dfn-rtp-stream
2702 pub frames_encoded: Option<u32>,
2703
2704 /// Total number of key frames, such as key frames in VP8 [RFC6386] or
2705 /// IDR-frames in H.264 [RFC6184], successfully encoded for the media
2706 /// [RTP stream].
2707 ///
2708 /// This is a subset of
2709 /// [`RtcOutboundRtpStreamVideo::frames_encoded`].
2710 /// [`RtcOutboundRtpStreamVideo::frames_encoded`] -
2711 /// [`RtcOutboundRtpStreamVideo::key_frames_encoded`] gives the number of
2712 /// delta frames encoded.
2713 ///
2714 /// [RFC6386]: https://rfc-editor.org/rfc/rfc6386
2715 /// [RFC6184]: https://rfc-editor.org/rfc/rfc6184
2716 /// [RTP stream]: https://w3.org/TR/webrtc-stats#dfn-rtp-stream
2717 pub key_frames_encoded: Option<u32>,
2718
2719 /// Sum of the QP values of frames encoded by the sender.
2720 ///
2721 /// The count of frames is in [`RtcOutboundRtpStreamVideo::frames_encoded`].
2722 ///
2723 /// The definition of QP value depends on the codec; for VP8, the QP value
2724 /// is the value carried in the frame header as the syntax element
2725 /// `y_ac_qi`, and defined in [RFC6386] section 19.2. Its range is `0..127`.
2726 ///
2727 /// Note, that the QP value is only an indication of quantizer values used;
2728 /// many formats have ways to vary the quantizer value within the frame.
2729 ///
2730 /// [RFC6386]: https://rfc-editor.org/rfc/rfc6386
2731 pub qp_sum: Option<u64>,
2732
2733 /// Cumulative sum of the PSNR values of frames encoded by the sender.
2734 ///
2735 /// The record includes values for the `y`, `u` and `v` components.
2736 ///
2737 /// The count of measurements is in [`Self::psnr_measurements`].
2738 pub psnr_sum: Option<BTreeMap<String, Double>>,
2739
2740 /// Number of times PSNR was measured.
2741 ///
2742 /// The components of [`Self::psnr_sum`] are aggregated with this
2743 /// measurement.
2744 pub psnr_measurements: Option<u64>,
2745
2746 /// Total number of seconds that has been spent encoding the
2747 /// [`RtcOutboundRtpStreamVideo::frames_encoded`] frames of the
2748 /// [RTP stream].
2749 ///
2750 /// The average encode time can be calculated by dividing this value with
2751 /// [`RtcOutboundRtpStreamVideo::frames_encoded`]. The time it takes to
2752 /// encode one frame is the time passed between feeding the encoder a frame
2753 /// and the encoder returning encoded data for that frame. This doesn't
2754 /// include any additional time it may take to packetize the resulting data.
2755 ///
2756 /// [RTP stream]: https://w3.org/TR/webrtc-stats#dfn-rtp-stream
2757 pub total_encode_time: Option<Double>,
2758
2759 /// Total number of Full Intra Request (FIR) packets, as defined in
2760 /// [RFC5104] section 4.3.1, received by the sender.
2761 ///
2762 /// Doesn't count the RTCP FIR indicated in [RFC2032] which was deprecated
2763 /// by [RFC4587].
2764 ///
2765 /// [RFC5104]: https://rfc-editor.org/rfc/rfc5104
2766 /// [RFC2032]: https://rfc-editor.org/rfc/rfc2032
2767 /// [RFC4587]: https://rfc-editor.org/rfc/rfc4587
2768 pub fir_count: Option<u32>,
2769
2770 /// Total number of Picture Loss Indication (PLI) packets, as defined in
2771 /// [RFC4585] section 6.3.1, received by the sender.
2772 ///
2773 /// [RFC4585]: https://rfc-editor.org/rfc/rfc4585
2774 pub pli_count: Option<u32>,
2775
2776 /// Identification of the used encoder implementation.
2777 ///
2778 /// This is useful for diagnosing interoperability issues.
2779 pub encoder_implementation: Option<String>,
2780
2781 /// Indicator whether the encoder currently used is considered power
2782 /// efficient by the user agent.
2783 ///
2784 /// This SHOULD reflect if the configuration results in hardware
2785 /// acceleration, but the user agent MAY take other information into account
2786 /// when deciding if the configuration is considered power efficient.
2787 pub power_efficient_encoder: Option<bool>,
2788
2789 /// Current reason for limiting the resolution and/or framerate.
2790 ///
2791 /// The implementation reports the most limiting factor. If the
2792 /// implementation is not able to determine the most limiting factor because
2793 /// multiple may exist, the reasons MUST be reported in the following order
2794 /// of priority: `bandwidth`, `cpu`, `other`.
2795 pub quality_limitation_reason: Option<RtcQualityLimitationReason>,
2796
2797 /// Record of the total time, in seconds, that the [RTP stream] has spent in
2798 /// each quality limitation state.
2799 ///
2800 /// The record includes a mapping for all [`RtcQualityLimitationReason`]
2801 /// types, including [`KnownRtcQualityLimitationReason::None`].
2802 ///
2803 /// The sum of all entries minus [`KnownRtcQualityLimitationReason::None`]
2804 /// gives the total time that the stream has been limited.
2805 ///
2806 /// [RTP stream]: https://w3.org/TR/webrtc-stats#dfn-rtp-stream
2807 pub quality_limitation_durations:
2808 Option<BTreeMap<RtcQualityLimitationReason, Double>>,
2809
2810 /// Number of times that the resolution has changed because of the quality
2811 /// limit (`quality_limitation_reason` has a value other than
2812 /// [`KnownRtcQualityLimitationReason::None`]).
2813 ///
2814 /// The counter is initially zero and increases when the resolution goes up
2815 /// or down. For example, if a `720p` track is sent as `480p` for some time
2816 /// and then recovers to `720p`, this will have the value `2`.
2817 pub quality_limitation_resolution_changes: Option<u32>,
2818
2819 /// Currently configured [scalability mode][0] the [RTP stream], if any.
2820 ///
2821 /// [0]: https://w3c.github.io/webrtc-svc#scalabilitymodes*
2822 /// [RTP stream]: https://w3.org/TR/webrtc-stats#dfn-rtp-stream
2823 pub scalability_mode: Option<String>,
2824}
2825
2826/// Non-exhaustive version of a [`KnownRtcQualityLimitationReason`].
2827pub type RtcQualityLimitationReason =
2828 NonExhaustive<KnownRtcQualityLimitationReason>;
2829
2830/// Reason of why media quality in a stream is being reduced by a codec during
2831/// encoding.
2832#[derive(
2833 Clone,
2834 Copy,
2835 Debug,
2836 Deserialize,
2837 Display,
2838 Eq,
2839 Hash,
2840 Ord,
2841 PartialEq,
2842 PartialOrd,
2843 Serialize,
2844)]
2845#[serde(rename_all = "kebab-case")]
2846pub enum KnownRtcQualityLimitationReason {
2847 /// Resolution and/or framerate is not limited.
2848 #[display("none")]
2849 None,
2850
2851 /// Resolution and/or framerate is primarily limited due to CPU load.
2852 #[display("cpu")]
2853 Cpu,
2854
2855 /// Resolution and/or framerate is primarily limited due to congestion cues
2856 /// during bandwidth estimation.
2857 ///
2858 /// Typical, congestion control algorithms use inter-arrival time,
2859 /// round-trip time, packet or other congestion cues to perform bandwidth
2860 /// estimation.
2861 #[display("bandwidth")]
2862 Bandwidth,
2863
2864 /// Resolution and/or framerate is primarily limited for a reason other than
2865 /// the above.
2866 #[display("other")]
2867 Other,
2868}
2869
2870/// [`RtcStat`] fields of an [`RtcStatsType::MediaSource`], based on its `kind`.
2871#[serde_with::skip_serializing_none]
2872#[derive(Clone, Copy, Debug, Deserialize, Hash, PartialEq, Serialize)]
2873#[serde(tag = "kind", rename_all = "camelCase")]
2874pub enum MediaSourceKind {
2875 /// Representation of a video track that is attached to one or more senders.
2876 ///
2877 /// It's [`RtcMediaSourceStats`] whose kind is `video`.
2878 ///
2879 /// [Full doc on W3C][spec].
2880 ///
2881 /// [spec]: https://w3.org/TR/webrtc-stats#dom-rtcvideosourcestats
2882 #[serde(rename_all = "camelCase")]
2883 Video {
2884 /// Width (in pixels) of the last frame originating from the source.
2885 ///
2886 /// Before a frame has been produced this attribute is missing.
2887 width: Option<u32>,
2888
2889 /// Height (in pixels) of the last frame originating from the source.
2890 ///
2891 /// Before a frame has been produced this attribute is missing.
2892 height: Option<u32>,
2893
2894 /// Total number of frames originating from the source.
2895 frames: Option<u32>,
2896
2897 /// Number of frames originating from the source, measured during the
2898 /// last second.
2899 ///
2900 /// For the first second of this object's lifetime this attribute is
2901 /// missing.
2902 frames_per_second: Option<Double>,
2903 },
2904
2905 /// Representation of an audio track that is attached to one or more
2906 /// senders.
2907 ///
2908 /// It's [`RtcMediaSourceStats`] whose kind is `audio`.
2909 ///
2910 /// [Full doc on W3C][spec].
2911 ///
2912 /// [spec]: https://w3.org/TR/webrtc-stats#dom-rtcaudiosourcestats
2913 #[serde(rename_all = "camelCase")]
2914 Audio {
2915 /// Audio level of the media source.
2916 ///
2917 /// For audio levels of remotely sourced tracks, see
2918 /// [`RtcInboundRtpStreamStats`] instead.
2919 ///
2920 /// The value is between `0..1` (linear), where `1.0` represents `0`
2921 /// dBov, `0` represents silence, and `0.5` represents approximately
2922 /// `6` dBSPL change in the sound pressure level from `0` dBov.
2923 ///
2924 /// The audio level is averaged over some small interval, using the
2925 /// algorithm described under
2926 /// [`MediaSourceKind::Audio::total_audio_energy`]. The interval used
2927 /// is implementation-defined.
2928 audio_level: Option<Double>,
2929
2930 /// Audio energy of the media source.
2931 ///
2932 /// For audio energy of remotely sourced tracks, see
2933 /// [`RtcInboundRtpStreamStats`] instead.
2934 total_audio_energy: Option<Double>,
2935
2936 /// Audio duration of the media source.
2937 ///
2938 /// For audio durations of remotely sourced tracks, see
2939 /// [`RtcInboundRtpStreamStats`] instead.
2940 ///
2941 /// Represents the total duration in seconds of all samples that have
2942 /// been produced by this source for the lifetime of this stats object.
2943 /// Can be used with [`MediaSourceKind::Audio::total_audio_energy`]
2944 /// to compute an average audio level over different intervals.
2945 total_samples_duration: Option<Double>,
2946
2947 /// Only exists when the [MediaStreamTrack][0] is sourced from a
2948 /// microphone where echo cancellation is applied.
2949 ///
2950 /// Calculated in decibels, as defined in [ECHO] (2012) section 3.14.
2951 ///
2952 /// If multiple audio channels are used, the channel of the least audio
2953 /// energy is considered for any sample.
2954 ///
2955 /// [0]: https://w3.org/TR/mediacapture-streams#dom-mediastreamtrack
2956 /// [ECHO]: https://w3.org/TR/webrtc-stats#bib-echo
2957 echo_return_loss: Option<Double>,
2958
2959 /// Only exists when the [MediaStreamTrack][0] is sourced from a
2960 /// microphone where echo cancellation is applied.
2961 ///
2962 /// Calculated in decibels, as defined in [ECHO] (2012) section 3.15.
2963 ///
2964 /// If multiple audio channels are used, the channel of the least audio
2965 /// energy is considered for any sample.
2966 ///
2967 /// [0]: https://w3.org/TR/mediacapture-streams#dom-mediastreamtrack
2968 /// [ECHO]: https://w3.org/TR/webrtc-stats#bib-echo
2969 echo_return_loss_enhancement: Option<Double>,
2970 },
2971}
2972
2973/// Representation of [DOMHighResTimeStamp][1].
2974///
2975/// Can be converted to the [`SystemTime`] with millisecond-wise accuracy.
2976///
2977/// [`HighResTimeStamp`] type is a [`f64`] and is used to store a time value
2978/// in milliseconds. This type can be used to describe a discrete point in time
2979/// or a time interval (the difference in time between two discrete points in
2980/// time).
2981///
2982/// The time, given in milliseconds, should be accurate to 5 µs (microseconds),
2983/// with the fractional part of the number indicating fractions of a
2984/// millisecond. However, if the browser is unable to provide a time value
2985/// accurate to 5 µs (due, for example, to hardware or software constraints),
2986/// the browser can represent the value as a time in milliseconds accurate to a
2987/// millisecond. Also note the section below on reduced time precision
2988/// controlled by browser preferences to avoid timing attacks and
2989/// fingerprinting.
2990///
2991/// Further, if the device or operating system the user agent is running on
2992/// doesn't have a clock accurate to the microsecond level, they may only be
2993/// accurate to the millisecond.
2994///
2995/// [1]: https://developer.mozilla.org/docs/Web/API/DOMHighResTimeStamp
2996#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
2997pub struct HighResTimeStamp(pub f64);
2998
2999impl From<HighResTimeStamp> for SystemTime {
3000 fn from(timestamp: HighResTimeStamp) -> Self {
3001 Self::UNIX_EPOCH + Duration::from_secs_f64(timestamp.0 / 1000.0)
3002 }
3003}
3004
3005impl TryFrom<SystemTime> for HighResTimeStamp {
3006 type Error = SystemTimeError;
3007
3008 fn try_from(time: SystemTime) -> Result<Self, Self::Error> {
3009 Ok(Self(
3010 time.duration_since(SystemTime::UNIX_EPOCH)?.as_secs_f64() * 1000.0,
3011 ))
3012 }
3013}
3014
3015/// Hashing string representation.
3016///
3017/// Some people believe that such behavior is incorrect (but in some programming
3018/// languages this is a default behavior) due to `NaN`, `Inf` or `-Inf` (they
3019/// all will have the same hashes).
3020/// But in the case of [`RtcStat`] received from the client, there should be no
3021/// such situations, and the hash will always be correct.
3022impl Hash for HighResTimeStamp {
3023 fn hash<H: Hasher>(&self, state: &mut H) {
3024 self.0.to_string().hash(state);
3025 }
3026}
3027
3028/// Comparison string representations.
3029///
3030/// Such implementation is required, so that the results of comparing values and
3031/// comparing hashes match.
3032impl PartialEq for HighResTimeStamp {
3033 fn eq(&self, other: &Self) -> bool {
3034 self.0.to_string().eq(&other.0.to_string())
3035 }
3036}
3037
3038/// Floating point numeric type that corresponds to the set of *finite*
3039/// double-precision 64-bit [IEEE 754] floating point numbers.
3040///
3041/// Web IDL [double] type.
3042///
3043/// [double]: https://webidl.spec.whatwg.org#idl-double
3044/// [IEEE 754]: https://ieeexplore.ieee.org/document/8766229
3045#[derive(Copy, Clone, Debug, Deserialize, Serialize)]
3046pub struct Double(pub f64);
3047
3048/// Hashing string representation.
3049///
3050/// Some people believe that such behavior is incorrect (but in some programming
3051/// languages this is a default behavior) due to `NaN`, `Inf` or `-Inf` (they
3052/// all will have the same hashes).
3053/// But in the case of [`RtcStat`] received from the client, there should be no
3054/// such situations, and the hash will always be correct.
3055impl Hash for Double {
3056 fn hash<H: Hasher>(&self, state: &mut H) {
3057 self.0.to_string().hash(state);
3058 }
3059}
3060
3061/// Comparison string representations.
3062///
3063/// Such implementation is required, so that the results of comparing values and
3064/// comparing hashes match.
3065impl PartialEq for Double {
3066 fn eq(&self, other: &Self) -> bool {
3067 self.0.to_string().eq(&other.0.to_string())
3068 }
3069}