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}