github.com/pion/webrtc/v3@v3.2.24/stats.go (about)

     1  // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
     2  // SPDX-License-Identifier: MIT
     3  
     4  package webrtc
     5  
     6  import (
     7  	"encoding/json"
     8  	"fmt"
     9  	"sync"
    10  	"time"
    11  
    12  	"github.com/pion/ice/v2"
    13  )
    14  
    15  // A Stats object contains a set of statistics copies out of a monitored component
    16  // of the WebRTC stack at a specific time.
    17  type Stats interface {
    18  	statsMarker()
    19  }
    20  
    21  // UnmarshalStatsJSON unmarshals a Stats object from JSON
    22  func UnmarshalStatsJSON(b []byte) (Stats, error) {
    23  	type typeJSON struct {
    24  		Type StatsType `json:"type"`
    25  	}
    26  	typeHolder := typeJSON{}
    27  
    28  	err := json.Unmarshal(b, &typeHolder)
    29  	if err != nil {
    30  		return nil, fmt.Errorf("unmarshal json type: %w", err)
    31  	}
    32  
    33  	switch typeHolder.Type {
    34  	case StatsTypeCodec:
    35  		return unmarshalCodecStats(b)
    36  	case StatsTypeInboundRTP:
    37  		return unmarshalInboundRTPStreamStats(b)
    38  	case StatsTypeOutboundRTP:
    39  		return unmarshalOutboundRTPStreamStats(b)
    40  	case StatsTypeRemoteInboundRTP:
    41  		return unmarshalRemoteInboundRTPStreamStats(b)
    42  	case StatsTypeRemoteOutboundRTP:
    43  		return unmarshalRemoteOutboundRTPStreamStats(b)
    44  	case StatsTypeCSRC:
    45  		return unmarshalCSRCStats(b)
    46  	case StatsTypeMediaSource:
    47  		return unmarshalMediaSourceStats(b)
    48  	case StatsTypeMediaPlayout:
    49  		return unmarshalMediaPlayoutStats(b)
    50  	case StatsTypePeerConnection:
    51  		return unmarshalPeerConnectionStats(b)
    52  	case StatsTypeDataChannel:
    53  		return unmarshalDataChannelStats(b)
    54  	case StatsTypeStream:
    55  		return unmarshalStreamStats(b)
    56  	case StatsTypeTrack:
    57  		return unmarshalTrackStats(b)
    58  	case StatsTypeSender:
    59  		return unmarshalSenderStats(b)
    60  	case StatsTypeReceiver:
    61  		return unmarshalReceiverStats(b)
    62  	case StatsTypeTransport:
    63  		return unmarshalTransportStats(b)
    64  	case StatsTypeCandidatePair:
    65  		return unmarshalICECandidatePairStats(b)
    66  	case StatsTypeLocalCandidate, StatsTypeRemoteCandidate:
    67  		return unmarshalICECandidateStats(b)
    68  	case StatsTypeCertificate:
    69  		return unmarshalCertificateStats(b)
    70  	case StatsTypeSCTPTransport:
    71  		return unmarshalSCTPTransportStats(b)
    72  	default:
    73  		return nil, fmt.Errorf("type: %w", ErrUnknownType)
    74  	}
    75  }
    76  
    77  // StatsType indicates the type of the object that a Stats object represents.
    78  type StatsType string
    79  
    80  const (
    81  	// StatsTypeCodec is used by CodecStats.
    82  	StatsTypeCodec StatsType = "codec"
    83  
    84  	// StatsTypeInboundRTP is used by InboundRTPStreamStats.
    85  	StatsTypeInboundRTP StatsType = "inbound-rtp"
    86  
    87  	// StatsTypeOutboundRTP is used by OutboundRTPStreamStats.
    88  	StatsTypeOutboundRTP StatsType = "outbound-rtp"
    89  
    90  	// StatsTypeRemoteInboundRTP is used by RemoteInboundRTPStreamStats.
    91  	StatsTypeRemoteInboundRTP StatsType = "remote-inbound-rtp"
    92  
    93  	// StatsTypeRemoteOutboundRTP is used by RemoteOutboundRTPStreamStats.
    94  	StatsTypeRemoteOutboundRTP StatsType = "remote-outbound-rtp"
    95  
    96  	// StatsTypeCSRC is used by RTPContributingSourceStats.
    97  	StatsTypeCSRC StatsType = "csrc"
    98  
    99  	// StatsTypeMediaSource is used by AudioSourceStats or VideoSourceStats depending on kind.
   100  	StatsTypeMediaSource = "media-source"
   101  
   102  	// StatsTypeMediaPlayout is used by AudioPlayoutStats.
   103  	StatsTypeMediaPlayout StatsType = "media-playout"
   104  
   105  	// StatsTypePeerConnection used by PeerConnectionStats.
   106  	StatsTypePeerConnection StatsType = "peer-connection"
   107  
   108  	// StatsTypeDataChannel is used by DataChannelStats.
   109  	StatsTypeDataChannel StatsType = "data-channel"
   110  
   111  	// StatsTypeStream is used by MediaStreamStats.
   112  	StatsTypeStream StatsType = "stream"
   113  
   114  	// StatsTypeTrack is used by SenderVideoTrackAttachmentStats and SenderAudioTrackAttachmentStats depending on kind.
   115  	StatsTypeTrack StatsType = "track"
   116  
   117  	// StatsTypeSender is used by the AudioSenderStats or VideoSenderStats depending on kind.
   118  	StatsTypeSender StatsType = "sender"
   119  
   120  	// StatsTypeReceiver is used by the AudioReceiverStats or VideoReceiverStats depending on kind.
   121  	StatsTypeReceiver StatsType = "receiver"
   122  
   123  	// StatsTypeTransport is used by TransportStats.
   124  	StatsTypeTransport StatsType = "transport"
   125  
   126  	// StatsTypeCandidatePair is used by ICECandidatePairStats.
   127  	StatsTypeCandidatePair StatsType = "candidate-pair"
   128  
   129  	// StatsTypeLocalCandidate is used by ICECandidateStats for the local candidate.
   130  	StatsTypeLocalCandidate StatsType = "local-candidate"
   131  
   132  	// StatsTypeRemoteCandidate is used by ICECandidateStats for the remote candidate.
   133  	StatsTypeRemoteCandidate StatsType = "remote-candidate"
   134  
   135  	// StatsTypeCertificate is used by CertificateStats.
   136  	StatsTypeCertificate StatsType = "certificate"
   137  
   138  	// StatsTypeSCTPTransport is used by SCTPTransportStats
   139  	StatsTypeSCTPTransport StatsType = "sctp-transport"
   140  )
   141  
   142  // MediaKind indicates the kind of media (audio or video)
   143  type MediaKind string
   144  
   145  const (
   146  	// MediaKindAudio indicates this is audio stats
   147  	MediaKindAudio MediaKind = "audio"
   148  	// MediaKindVideo indicates this is video stats
   149  	MediaKindVideo MediaKind = "video"
   150  )
   151  
   152  // StatsTimestamp is a timestamp represented by the floating point number of
   153  // milliseconds since the epoch.
   154  type StatsTimestamp float64
   155  
   156  // Time returns the time.Time represented by this timestamp.
   157  func (s StatsTimestamp) Time() time.Time {
   158  	millis := float64(s)
   159  	nanos := int64(millis * float64(time.Millisecond))
   160  
   161  	return time.Unix(0, nanos).UTC()
   162  }
   163  
   164  func statsTimestampFrom(t time.Time) StatsTimestamp {
   165  	return StatsTimestamp(t.UnixNano() / int64(time.Millisecond))
   166  }
   167  
   168  func statsTimestampNow() StatsTimestamp {
   169  	return statsTimestampFrom(time.Now())
   170  }
   171  
   172  // StatsReport collects Stats objects indexed by their ID.
   173  type StatsReport map[string]Stats
   174  
   175  type statsReportCollector struct {
   176  	collectingGroup sync.WaitGroup
   177  	report          StatsReport
   178  	mux             sync.Mutex
   179  }
   180  
   181  func newStatsReportCollector() *statsReportCollector {
   182  	return &statsReportCollector{report: make(StatsReport)}
   183  }
   184  
   185  func (src *statsReportCollector) Collecting() {
   186  	src.collectingGroup.Add(1)
   187  }
   188  
   189  func (src *statsReportCollector) Collect(id string, stats Stats) {
   190  	src.mux.Lock()
   191  	defer src.mux.Unlock()
   192  
   193  	src.report[id] = stats
   194  	src.collectingGroup.Done()
   195  }
   196  
   197  func (src *statsReportCollector) Done() {
   198  	src.collectingGroup.Done()
   199  }
   200  
   201  func (src *statsReportCollector) Ready() StatsReport {
   202  	src.collectingGroup.Wait()
   203  	src.mux.Lock()
   204  	defer src.mux.Unlock()
   205  	return src.report
   206  }
   207  
   208  // CodecType specifies whether a CodecStats objects represents a media format
   209  // that is being encoded or decoded
   210  type CodecType string
   211  
   212  const (
   213  	// CodecTypeEncode means the attached CodecStats represents a media format that
   214  	// is being encoded, or that the implementation is prepared to encode.
   215  	CodecTypeEncode CodecType = "encode"
   216  
   217  	// CodecTypeDecode means the attached CodecStats represents a media format
   218  	// that the implementation is prepared to decode.
   219  	CodecTypeDecode CodecType = "decode"
   220  )
   221  
   222  // CodecStats contains statistics for a codec that is currently being used by RTP streams
   223  // being sent or received by this PeerConnection object.
   224  type CodecStats struct {
   225  	// Timestamp is the timestamp associated with this object.
   226  	Timestamp StatsTimestamp `json:"timestamp"`
   227  
   228  	// Type is the object's StatsType
   229  	Type StatsType `json:"type"`
   230  
   231  	// ID is a unique id that is associated with the component inspected to produce
   232  	// this Stats object. Two Stats objects will have the same ID if they were produced
   233  	// by inspecting the same underlying object.
   234  	ID string `json:"id"`
   235  
   236  	// PayloadType as used in RTP encoding or decoding
   237  	PayloadType PayloadType `json:"payloadType"`
   238  
   239  	// CodecType of this CodecStats
   240  	CodecType CodecType `json:"codecType"`
   241  
   242  	// TransportID is the unique identifier of the transport on which this codec is
   243  	// being used, which can be used to look up the corresponding TransportStats object.
   244  	TransportID string `json:"transportId"`
   245  
   246  	// MimeType is the codec MIME media type/subtype. e.g., video/vp8 or equivalent.
   247  	MimeType string `json:"mimeType"`
   248  
   249  	// ClockRate represents the media sampling rate.
   250  	ClockRate uint32 `json:"clockRate"`
   251  
   252  	// Channels is 2 for stereo, missing for most other cases.
   253  	Channels uint8 `json:"channels"`
   254  
   255  	// SDPFmtpLine is the a=fmtp line in the SDP corresponding to the codec,
   256  	// i.e., after the colon following the PT.
   257  	SDPFmtpLine string `json:"sdpFmtpLine"`
   258  
   259  	// Implementation identifies the implementation used. This is useful for diagnosing
   260  	// interoperability issues.
   261  	Implementation string `json:"implementation"`
   262  }
   263  
   264  func (s CodecStats) statsMarker() {}
   265  
   266  func unmarshalCodecStats(b []byte) (CodecStats, error) {
   267  	var codecStats CodecStats
   268  	err := json.Unmarshal(b, &codecStats)
   269  	if err != nil {
   270  		return CodecStats{}, fmt.Errorf("unmarshal codec stats: %w", err)
   271  	}
   272  	return codecStats, nil
   273  }
   274  
   275  // InboundRTPStreamStats contains statistics for an inbound RTP stream that is
   276  // currently received with this PeerConnection object.
   277  type InboundRTPStreamStats struct {
   278  	// Timestamp is the timestamp associated with this object.
   279  	Timestamp StatsTimestamp `json:"timestamp"`
   280  
   281  	// Type is the object's StatsType
   282  	Type StatsType `json:"type"`
   283  
   284  	// ID is a unique id that is associated with the component inspected to produce
   285  	// this Stats object. Two Stats objects will have the same ID if they were produced
   286  	// by inspecting the same underlying object.
   287  	ID string `json:"id"`
   288  
   289  	// SSRC is the 32-bit unsigned integer value used to identify the source of the
   290  	// stream of RTP packets that this stats object concerns.
   291  	SSRC SSRC `json:"ssrc"`
   292  
   293  	// Kind is either "audio" or "video"
   294  	Kind string `json:"kind"`
   295  
   296  	// It is a unique identifier that is associated to the object that was inspected
   297  	// to produce the TransportStats associated with this RTP stream.
   298  	TransportID string `json:"transportId"`
   299  
   300  	// CodecID is a unique identifier that is associated to the object that was inspected
   301  	// to produce the CodecStats associated with this RTP stream.
   302  	CodecID string `json:"codecId"`
   303  
   304  	// FIRCount counts the total number of Full Intra Request (FIR) packets received
   305  	// by the sender. This metric is only valid for video and is sent by receiver.
   306  	FIRCount uint32 `json:"firCount"`
   307  
   308  	// PLICount counts the total number of Picture Loss Indication (PLI) packets
   309  	// received by the sender. This metric is only valid for video and is sent by receiver.
   310  	PLICount uint32 `json:"pliCount"`
   311  
   312  	// NACKCount counts the total number of Negative ACKnowledgement (NACK) packets
   313  	// received by the sender and is sent by receiver.
   314  	NACKCount uint32 `json:"nackCount"`
   315  
   316  	// SLICount counts the total number of Slice Loss Indication (SLI) packets received
   317  	// by the sender. This metric is only valid for video and is sent by receiver.
   318  	SLICount uint32 `json:"sliCount"`
   319  
   320  	// QPSum is the sum of the QP values of frames passed. The count of frames is
   321  	// in FramesDecoded for inbound stream stats, and in FramesEncoded for outbound stream stats.
   322  	QPSum uint64 `json:"qpSum"`
   323  
   324  	// PacketsReceived is the total number of RTP packets received for this SSRC.
   325  	PacketsReceived uint32 `json:"packetsReceived"`
   326  
   327  	// PacketsLost is the total number of RTP packets lost for this SSRC. Note that
   328  	// because of how this is estimated, it can be negative if more packets are received than sent.
   329  	PacketsLost int32 `json:"packetsLost"`
   330  
   331  	// Jitter is the packet jitter measured in seconds for this SSRC
   332  	Jitter float64 `json:"jitter"`
   333  
   334  	// PacketsDiscarded is the cumulative number of RTP packets discarded by the jitter
   335  	// buffer due to late or early-arrival, i.e., these packets are not played out.
   336  	// RTP packets discarded due to packet duplication are not reported in this metric.
   337  	PacketsDiscarded uint32 `json:"packetsDiscarded"`
   338  
   339  	// PacketsRepaired is the cumulative number of lost RTP packets repaired after applying
   340  	// an error-resilience mechanism. It is measured for the primary source RTP packets
   341  	// and only counted for RTP packets that have no further chance of repair.
   342  	PacketsRepaired uint32 `json:"packetsRepaired"`
   343  
   344  	// BurstPacketsLost is the cumulative number of RTP packets lost during loss bursts.
   345  	BurstPacketsLost uint32 `json:"burstPacketsLost"`
   346  
   347  	// BurstPacketsDiscarded is the cumulative number of RTP packets discarded during discard bursts.
   348  	BurstPacketsDiscarded uint32 `json:"burstPacketsDiscarded"`
   349  
   350  	// BurstLossCount is the cumulative number of bursts of lost RTP packets.
   351  	BurstLossCount uint32 `json:"burstLossCount"`
   352  
   353  	// BurstDiscardCount is the cumulative number of bursts of discarded RTP packets.
   354  	BurstDiscardCount uint32 `json:"burstDiscardCount"`
   355  
   356  	// BurstLossRate is the fraction of RTP packets lost during bursts to the
   357  	// total number of RTP packets expected in the bursts.
   358  	BurstLossRate float64 `json:"burstLossRate"`
   359  
   360  	// BurstDiscardRate is the fraction of RTP packets discarded during bursts to
   361  	// the total number of RTP packets expected in bursts.
   362  	BurstDiscardRate float64 `json:"burstDiscardRate"`
   363  
   364  	// GapLossRate is the fraction of RTP packets lost during the gap periods.
   365  	GapLossRate float64 `json:"gapLossRate"`
   366  
   367  	// GapDiscardRate is the fraction of RTP packets discarded during the gap periods.
   368  	GapDiscardRate float64 `json:"gapDiscardRate"`
   369  
   370  	// TrackID is the identifier of the stats object representing the receiving track,
   371  	// a ReceiverAudioTrackAttachmentStats or ReceiverVideoTrackAttachmentStats.
   372  	TrackID string `json:"trackId"`
   373  
   374  	// ReceiverID is the stats ID used to look up the AudioReceiverStats or VideoReceiverStats
   375  	// object receiving this stream.
   376  	ReceiverID string `json:"receiverId"`
   377  
   378  	// RemoteID is used for looking up the remote RemoteOutboundRTPStreamStats object
   379  	// for the same SSRC.
   380  	RemoteID string `json:"remoteId"`
   381  
   382  	// FramesDecoded represents the total number of frames correctly decoded for this SSRC,
   383  	// i.e., frames that would be displayed if no frames are dropped. Only valid for video.
   384  	FramesDecoded uint32 `json:"framesDecoded"`
   385  
   386  	// LastPacketReceivedTimestamp represents the timestamp at which the last packet was
   387  	// received for this SSRC. This differs from Timestamp, which represents the time
   388  	// at which the statistics were generated by the local endpoint.
   389  	LastPacketReceivedTimestamp StatsTimestamp `json:"lastPacketReceivedTimestamp"`
   390  
   391  	// AverageRTCPInterval is the average RTCP interval between two consecutive compound RTCP packets.
   392  	// This is calculated by the sending endpoint when sending compound RTCP reports.
   393  	// Compound packets must contain at least a RTCP RR or SR packet and an SDES packet
   394  	// with the CNAME item.
   395  	AverageRTCPInterval float64 `json:"averageRtcpInterval"`
   396  
   397  	// FECPacketsReceived is the total number of RTP FEC packets received for this SSRC.
   398  	// This counter can also be incremented when receiving FEC packets in-band with media packets (e.g., with Opus).
   399  	FECPacketsReceived uint32 `json:"fecPacketsReceived"`
   400  
   401  	// BytesReceived is the total number of bytes received for this SSRC.
   402  	BytesReceived uint64 `json:"bytesReceived"`
   403  
   404  	// PacketsFailedDecryption is the cumulative number of RTP packets that failed
   405  	// to be decrypted. These packets are not counted by PacketsDiscarded.
   406  	PacketsFailedDecryption uint32 `json:"packetsFailedDecryption"`
   407  
   408  	// PacketsDuplicated is the cumulative number of packets discarded because they
   409  	// are duplicated. Duplicate packets are not counted in PacketsDiscarded.
   410  	//
   411  	// Duplicated packets have the same RTP sequence number and content as a previously
   412  	// received packet. If multiple duplicates of a packet are received, all of them are counted.
   413  	// An improved estimate of lost packets can be calculated by adding PacketsDuplicated to PacketsLost.
   414  	PacketsDuplicated uint32 `json:"packetsDuplicated"`
   415  
   416  	// PerDSCPPacketsReceived is the total number of packets received for this SSRC,
   417  	// per Differentiated Services code point (DSCP) [RFC2474]. DSCPs are identified
   418  	// as decimal integers in string form. Note that due to network remapping and bleaching,
   419  	// these numbers are not expected to match the numbers seen on sending. Not all
   420  	// OSes make this information available.
   421  	PerDSCPPacketsReceived map[string]uint32 `json:"perDscpPacketsReceived"`
   422  }
   423  
   424  func (s InboundRTPStreamStats) statsMarker() {}
   425  
   426  func unmarshalInboundRTPStreamStats(b []byte) (InboundRTPStreamStats, error) {
   427  	var inboundRTPStreamStats InboundRTPStreamStats
   428  	err := json.Unmarshal(b, &inboundRTPStreamStats)
   429  	if err != nil {
   430  		return InboundRTPStreamStats{}, fmt.Errorf("unmarshal inbound rtp stream stats: %w", err)
   431  	}
   432  	return inboundRTPStreamStats, nil
   433  }
   434  
   435  // QualityLimitationReason lists the reason for limiting the resolution and/or framerate.
   436  // Only valid for video.
   437  type QualityLimitationReason string
   438  
   439  const (
   440  	// QualityLimitationReasonNone means the resolution and/or framerate is not limited.
   441  	QualityLimitationReasonNone QualityLimitationReason = "none"
   442  
   443  	// QualityLimitationReasonCPU means the resolution and/or framerate is primarily limited due to CPU load.
   444  	QualityLimitationReasonCPU QualityLimitationReason = "cpu"
   445  
   446  	// QualityLimitationReasonBandwidth means the resolution and/or framerate is primarily limited due to congestion cues during bandwidth estimation. Typical, congestion control algorithms use inter-arrival time, round-trip time, packet or other congestion cues to perform bandwidth estimation.
   447  	QualityLimitationReasonBandwidth QualityLimitationReason = "bandwidth"
   448  
   449  	// QualityLimitationReasonOther means the resolution and/or framerate is primarily limited for a reason other than the above.
   450  	QualityLimitationReasonOther QualityLimitationReason = "other"
   451  )
   452  
   453  // OutboundRTPStreamStats contains statistics for an outbound RTP stream that is
   454  // currently sent with this PeerConnection object.
   455  type OutboundRTPStreamStats struct {
   456  	// Timestamp is the timestamp associated with this object.
   457  	Timestamp StatsTimestamp `json:"timestamp"`
   458  
   459  	// Type is the object's StatsType
   460  	Type StatsType `json:"type"`
   461  
   462  	// ID is a unique id that is associated with the component inspected to produce
   463  	// this Stats object. Two Stats objects will have the same ID if they were produced
   464  	// by inspecting the same underlying object.
   465  	ID string `json:"id"`
   466  
   467  	// SSRC is the 32-bit unsigned integer value used to identify the source of the
   468  	// stream of RTP packets that this stats object concerns.
   469  	SSRC SSRC `json:"ssrc"`
   470  
   471  	// Kind is either "audio" or "video"
   472  	Kind string `json:"kind"`
   473  
   474  	// It is a unique identifier that is associated to the object that was inspected
   475  	// to produce the TransportStats associated with this RTP stream.
   476  	TransportID string `json:"transportId"`
   477  
   478  	// CodecID is a unique identifier that is associated to the object that was inspected
   479  	// to produce the CodecStats associated with this RTP stream.
   480  	CodecID string `json:"codecId"`
   481  
   482  	// FIRCount counts the total number of Full Intra Request (FIR) packets received
   483  	// by the sender. This metric is only valid for video and is sent by receiver.
   484  	FIRCount uint32 `json:"firCount"`
   485  
   486  	// PLICount counts the total number of Picture Loss Indication (PLI) packets
   487  	// received by the sender. This metric is only valid for video and is sent by receiver.
   488  	PLICount uint32 `json:"pliCount"`
   489  
   490  	// NACKCount counts the total number of Negative ACKnowledgement (NACK) packets
   491  	// received by the sender and is sent by receiver.
   492  	NACKCount uint32 `json:"nackCount"`
   493  
   494  	// SLICount counts the total number of Slice Loss Indication (SLI) packets received
   495  	// by the sender. This metric is only valid for video and is sent by receiver.
   496  	SLICount uint32 `json:"sliCount"`
   497  
   498  	// QPSum is the sum of the QP values of frames passed. The count of frames is
   499  	// in FramesDecoded for inbound stream stats, and in FramesEncoded for outbound stream stats.
   500  	QPSum uint64 `json:"qpSum"`
   501  
   502  	// PacketsSent is the total number of RTP packets sent for this SSRC.
   503  	PacketsSent uint32 `json:"packetsSent"`
   504  
   505  	// PacketsDiscardedOnSend is the total number of RTP packets for this SSRC that
   506  	// have been discarded due to socket errors, i.e. a socket error occurred when handing
   507  	// the packets to the socket. This might happen due to various reasons, including
   508  	// full buffer or no available memory.
   509  	PacketsDiscardedOnSend uint32 `json:"packetsDiscardedOnSend"`
   510  
   511  	// FECPacketsSent is the total number of RTP FEC packets sent for this SSRC.
   512  	// This counter can also be incremented when sending FEC packets in-band with
   513  	// media packets (e.g., with Opus).
   514  	FECPacketsSent uint32 `json:"fecPacketsSent"`
   515  
   516  	// BytesSent is the total number of bytes sent for this SSRC.
   517  	BytesSent uint64 `json:"bytesSent"`
   518  
   519  	// BytesDiscardedOnSend is the total number of bytes for this SSRC that have
   520  	// been discarded due to socket errors, i.e. a socket error occurred when handing
   521  	// the packets containing the bytes to the socket. This might happen due to various
   522  	// reasons, including full buffer or no available memory.
   523  	BytesDiscardedOnSend uint64 `json:"bytesDiscardedOnSend"`
   524  
   525  	// TrackID is the identifier of the stats object representing the current track
   526  	// attachment to the sender of this stream, a SenderAudioTrackAttachmentStats
   527  	// or SenderVideoTrackAttachmentStats.
   528  	TrackID string `json:"trackId"`
   529  
   530  	// SenderID is the stats ID used to look up the AudioSenderStats or VideoSenderStats
   531  	// object sending this stream.
   532  	SenderID string `json:"senderId"`
   533  
   534  	// RemoteID is used for looking up the remote RemoteInboundRTPStreamStats object
   535  	// for the same SSRC.
   536  	RemoteID string `json:"remoteId"`
   537  
   538  	// LastPacketSentTimestamp represents the timestamp at which the last packet was
   539  	// sent for this SSRC. This differs from timestamp, which represents the time at
   540  	// which the statistics were generated by the local endpoint.
   541  	LastPacketSentTimestamp StatsTimestamp `json:"lastPacketSentTimestamp"`
   542  
   543  	// TargetBitrate is the current target bitrate configured for this particular SSRC
   544  	// and is the Transport Independent Application Specific (TIAS) bitrate [RFC3890].
   545  	// Typically, the target bitrate is a configuration parameter provided to the codec's
   546  	// encoder and does not count the size of the IP or other transport layers like TCP or UDP.
   547  	// It is measured in bits per second and the bitrate is calculated over a 1 second window.
   548  	TargetBitrate float64 `json:"targetBitrate"`
   549  
   550  	// FramesEncoded represents the total number of frames successfully encoded for this RTP media stream.
   551  	// Only valid for video.
   552  	FramesEncoded uint32 `json:"framesEncoded"`
   553  
   554  	// TotalEncodeTime is the total number of seconds that has been spent encoding the
   555  	// framesEncoded frames of this stream. The average encode time can be calculated by
   556  	// dividing this value with FramesEncoded. The time it takes to encode one frame is the
   557  	// time passed between feeding the encoder a frame and the encoder returning encoded data
   558  	// for that frame. This does not include any additional time it may take to packetize the resulting data.
   559  	TotalEncodeTime float64 `json:"totalEncodeTime"`
   560  
   561  	// AverageRTCPInterval is the average RTCP interval between two consecutive compound RTCP
   562  	// packets. This is calculated by the sending endpoint when sending compound RTCP reports.
   563  	// Compound packets must contain at least a RTCP RR or SR packet and an SDES packet with the CNAME item.
   564  	AverageRTCPInterval float64 `json:"averageRtcpInterval"`
   565  
   566  	// QualityLimitationReason is the current reason for limiting the resolution and/or framerate,
   567  	// or "none" if not limited. Only valid for video.
   568  	QualityLimitationReason QualityLimitationReason `json:"qualityLimitationReason"`
   569  
   570  	// QualityLimitationDurations is record of the total time, in seconds, that this
   571  	// stream has spent in each quality limitation state. The record includes a mapping
   572  	// for all QualityLimitationReason types, including "none". Only valid for video.
   573  	QualityLimitationDurations map[string]float64 `json:"qualityLimitationDurations"`
   574  
   575  	// PerDSCPPacketsSent is the total number of packets sent for this SSRC, per DSCP.
   576  	// DSCPs are identified as decimal integers in string form.
   577  	PerDSCPPacketsSent map[string]uint32 `json:"perDscpPacketsSent"`
   578  }
   579  
   580  func (s OutboundRTPStreamStats) statsMarker() {}
   581  
   582  func unmarshalOutboundRTPStreamStats(b []byte) (OutboundRTPStreamStats, error) {
   583  	var outboundRTPStreamStats OutboundRTPStreamStats
   584  	err := json.Unmarshal(b, &outboundRTPStreamStats)
   585  	if err != nil {
   586  		return OutboundRTPStreamStats{}, fmt.Errorf("unmarshal outbound rtp stream stats: %w", err)
   587  	}
   588  	return outboundRTPStreamStats, nil
   589  }
   590  
   591  // RemoteInboundRTPStreamStats contains statistics for the remote endpoint's inbound
   592  // RTP stream corresponding to an outbound stream that is currently sent with this
   593  // PeerConnection object. It is measured at the remote endpoint and reported in an RTCP
   594  // Receiver Report (RR) or RTCP Extended Report (XR).
   595  type RemoteInboundRTPStreamStats struct {
   596  	// Timestamp is the timestamp associated with this object.
   597  	Timestamp StatsTimestamp `json:"timestamp"`
   598  
   599  	// Type is the object's StatsType
   600  	Type StatsType `json:"type"`
   601  
   602  	// ID is a unique id that is associated with the component inspected to produce
   603  	// this Stats object. Two Stats objects will have the same ID if they were produced
   604  	// by inspecting the same underlying object.
   605  	ID string `json:"id"`
   606  
   607  	// SSRC is the 32-bit unsigned integer value used to identify the source of the
   608  	// stream of RTP packets that this stats object concerns.
   609  	SSRC SSRC `json:"ssrc"`
   610  
   611  	// Kind is either "audio" or "video"
   612  	Kind string `json:"kind"`
   613  
   614  	// It is a unique identifier that is associated to the object that was inspected
   615  	// to produce the TransportStats associated with this RTP stream.
   616  	TransportID string `json:"transportId"`
   617  
   618  	// CodecID is a unique identifier that is associated to the object that was inspected
   619  	// to produce the CodecStats associated with this RTP stream.
   620  	CodecID string `json:"codecId"`
   621  
   622  	// FIRCount counts the total number of Full Intra Request (FIR) packets received
   623  	// by the sender. This metric is only valid for video and is sent by receiver.
   624  	FIRCount uint32 `json:"firCount"`
   625  
   626  	// PLICount counts the total number of Picture Loss Indication (PLI) packets
   627  	// received by the sender. This metric is only valid for video and is sent by receiver.
   628  	PLICount uint32 `json:"pliCount"`
   629  
   630  	// NACKCount counts the total number of Negative ACKnowledgement (NACK) packets
   631  	// received by the sender and is sent by receiver.
   632  	NACKCount uint32 `json:"nackCount"`
   633  
   634  	// SLICount counts the total number of Slice Loss Indication (SLI) packets received
   635  	// by the sender. This metric is only valid for video and is sent by receiver.
   636  	SLICount uint32 `json:"sliCount"`
   637  
   638  	// QPSum is the sum of the QP values of frames passed. The count of frames is
   639  	// in FramesDecoded for inbound stream stats, and in FramesEncoded for outbound stream stats.
   640  	QPSum uint64 `json:"qpSum"`
   641  
   642  	// PacketsReceived is the total number of RTP packets received for this SSRC.
   643  	PacketsReceived uint32 `json:"packetsReceived"`
   644  
   645  	// PacketsLost is the total number of RTP packets lost for this SSRC. Note that
   646  	// because of how this is estimated, it can be negative if more packets are received than sent.
   647  	PacketsLost int32 `json:"packetsLost"`
   648  
   649  	// Jitter is the packet jitter measured in seconds for this SSRC
   650  	Jitter float64 `json:"jitter"`
   651  
   652  	// PacketsDiscarded is the cumulative number of RTP packets discarded by the jitter
   653  	// buffer due to late or early-arrival, i.e., these packets are not played out.
   654  	// RTP packets discarded due to packet duplication are not reported in this metric.
   655  	PacketsDiscarded uint32 `json:"packetsDiscarded"`
   656  
   657  	// PacketsRepaired is the cumulative number of lost RTP packets repaired after applying
   658  	// an error-resilience mechanism. It is measured for the primary source RTP packets
   659  	// and only counted for RTP packets that have no further chance of repair.
   660  	PacketsRepaired uint32 `json:"packetsRepaired"`
   661  
   662  	// BurstPacketsLost is the cumulative number of RTP packets lost during loss bursts.
   663  	BurstPacketsLost uint32 `json:"burstPacketsLost"`
   664  
   665  	// BurstPacketsDiscarded is the cumulative number of RTP packets discarded during discard bursts.
   666  	BurstPacketsDiscarded uint32 `json:"burstPacketsDiscarded"`
   667  
   668  	// BurstLossCount is the cumulative number of bursts of lost RTP packets.
   669  	BurstLossCount uint32 `json:"burstLossCount"`
   670  
   671  	// BurstDiscardCount is the cumulative number of bursts of discarded RTP packets.
   672  	BurstDiscardCount uint32 `json:"burstDiscardCount"`
   673  
   674  	// BurstLossRate is the fraction of RTP packets lost during bursts to the
   675  	// total number of RTP packets expected in the bursts.
   676  	BurstLossRate float64 `json:"burstLossRate"`
   677  
   678  	// BurstDiscardRate is the fraction of RTP packets discarded during bursts to
   679  	// the total number of RTP packets expected in bursts.
   680  	BurstDiscardRate float64 `json:"burstDiscardRate"`
   681  
   682  	// GapLossRate is the fraction of RTP packets lost during the gap periods.
   683  	GapLossRate float64 `json:"gapLossRate"`
   684  
   685  	// GapDiscardRate is the fraction of RTP packets discarded during the gap periods.
   686  	GapDiscardRate float64 `json:"gapDiscardRate"`
   687  
   688  	// LocalID is used for looking up the local OutboundRTPStreamStats object for the same SSRC.
   689  	LocalID string `json:"localId"`
   690  
   691  	// RoundTripTime is the estimated round trip time for this SSRC based on the
   692  	// RTCP timestamps in the RTCP Receiver Report (RR) and measured in seconds.
   693  	RoundTripTime float64 `json:"roundTripTime"`
   694  
   695  	// FractionLost is the fraction packet loss reported for this SSRC.
   696  	FractionLost float64 `json:"fractionLost"`
   697  }
   698  
   699  func (s RemoteInboundRTPStreamStats) statsMarker() {}
   700  
   701  func unmarshalRemoteInboundRTPStreamStats(b []byte) (RemoteInboundRTPStreamStats, error) {
   702  	var remoteInboundRTPStreamStats RemoteInboundRTPStreamStats
   703  	err := json.Unmarshal(b, &remoteInboundRTPStreamStats)
   704  	if err != nil {
   705  		return RemoteInboundRTPStreamStats{}, fmt.Errorf("unmarshal remote inbound rtp stream stats: %w", err)
   706  	}
   707  	return remoteInboundRTPStreamStats, nil
   708  }
   709  
   710  // RemoteOutboundRTPStreamStats contains statistics for the remote endpoint's outbound
   711  // RTP stream corresponding to an inbound stream that is currently received with this
   712  // PeerConnection object. It is measured at the remote endpoint and reported in an
   713  // RTCP Sender Report (SR).
   714  type RemoteOutboundRTPStreamStats struct {
   715  	// Timestamp is the timestamp associated with this object.
   716  	Timestamp StatsTimestamp `json:"timestamp"`
   717  
   718  	// Type is the object's StatsType
   719  	Type StatsType `json:"type"`
   720  
   721  	// ID is a unique id that is associated with the component inspected to produce
   722  	// this Stats object. Two Stats objects will have the same ID if they were produced
   723  	// by inspecting the same underlying object.
   724  	ID string `json:"id"`
   725  
   726  	// SSRC is the 32-bit unsigned integer value used to identify the source of the
   727  	// stream of RTP packets that this stats object concerns.
   728  	SSRC SSRC `json:"ssrc"`
   729  
   730  	// Kind is either "audio" or "video"
   731  	Kind string `json:"kind"`
   732  
   733  	// It is a unique identifier that is associated to the object that was inspected
   734  	// to produce the TransportStats associated with this RTP stream.
   735  	TransportID string `json:"transportId"`
   736  
   737  	// CodecID is a unique identifier that is associated to the object that was inspected
   738  	// to produce the CodecStats associated with this RTP stream.
   739  	CodecID string `json:"codecId"`
   740  
   741  	// FIRCount counts the total number of Full Intra Request (FIR) packets received
   742  	// by the sender. This metric is only valid for video and is sent by receiver.
   743  	FIRCount uint32 `json:"firCount"`
   744  
   745  	// PLICount counts the total number of Picture Loss Indication (PLI) packets
   746  	// received by the sender. This metric is only valid for video and is sent by receiver.
   747  	PLICount uint32 `json:"pliCount"`
   748  
   749  	// NACKCount counts the total number of Negative ACKnowledgement (NACK) packets
   750  	// received by the sender and is sent by receiver.
   751  	NACKCount uint32 `json:"nackCount"`
   752  
   753  	// SLICount counts the total number of Slice Loss Indication (SLI) packets received
   754  	// by the sender. This metric is only valid for video and is sent by receiver.
   755  	SLICount uint32 `json:"sliCount"`
   756  
   757  	// QPSum is the sum of the QP values of frames passed. The count of frames is
   758  	// in FramesDecoded for inbound stream stats, and in FramesEncoded for outbound stream stats.
   759  	QPSum uint64 `json:"qpSum"`
   760  
   761  	// PacketsSent is the total number of RTP packets sent for this SSRC.
   762  	PacketsSent uint32 `json:"packetsSent"`
   763  
   764  	// PacketsDiscardedOnSend is the total number of RTP packets for this SSRC that
   765  	// have been discarded due to socket errors, i.e. a socket error occurred when handing
   766  	// the packets to the socket. This might happen due to various reasons, including
   767  	// full buffer or no available memory.
   768  	PacketsDiscardedOnSend uint32 `json:"packetsDiscardedOnSend"`
   769  
   770  	// FECPacketsSent is the total number of RTP FEC packets sent for this SSRC.
   771  	// This counter can also be incremented when sending FEC packets in-band with
   772  	// media packets (e.g., with Opus).
   773  	FECPacketsSent uint32 `json:"fecPacketsSent"`
   774  
   775  	// BytesSent is the total number of bytes sent for this SSRC.
   776  	BytesSent uint64 `json:"bytesSent"`
   777  
   778  	// BytesDiscardedOnSend is the total number of bytes for this SSRC that have
   779  	// been discarded due to socket errors, i.e. a socket error occurred when handing
   780  	// the packets containing the bytes to the socket. This might happen due to various
   781  	// reasons, including full buffer or no available memory.
   782  	BytesDiscardedOnSend uint64 `json:"bytesDiscardedOnSend"`
   783  
   784  	// LocalID is used for looking up the local InboundRTPStreamStats object for the same SSRC.
   785  	LocalID string `json:"localId"`
   786  
   787  	// RemoteTimestamp represents the remote timestamp at which these statistics were
   788  	// sent by the remote endpoint. This differs from timestamp, which represents the
   789  	// time at which the statistics were generated or received by the local endpoint.
   790  	// The RemoteTimestamp, if present, is derived from the NTP timestamp in an RTCP
   791  	// Sender Report (SR) packet, which reflects the remote endpoint's clock.
   792  	// That clock may not be synchronized with the local clock.
   793  	RemoteTimestamp StatsTimestamp `json:"remoteTimestamp"`
   794  }
   795  
   796  func (s RemoteOutboundRTPStreamStats) statsMarker() {}
   797  
   798  func unmarshalRemoteOutboundRTPStreamStats(b []byte) (RemoteOutboundRTPStreamStats, error) {
   799  	var remoteOutboundRTPStreamStats RemoteOutboundRTPStreamStats
   800  	err := json.Unmarshal(b, &remoteOutboundRTPStreamStats)
   801  	if err != nil {
   802  		return RemoteOutboundRTPStreamStats{}, fmt.Errorf("unmarshal remote outbound rtp stream stats: %w", err)
   803  	}
   804  	return remoteOutboundRTPStreamStats, nil
   805  }
   806  
   807  // RTPContributingSourceStats contains statistics for a contributing source (CSRC) that contributed
   808  // to an inbound RTP stream.
   809  type RTPContributingSourceStats struct {
   810  	// Timestamp is the timestamp associated with this object.
   811  	Timestamp StatsTimestamp `json:"timestamp"`
   812  
   813  	// Type is the object's StatsType
   814  	Type StatsType `json:"type"`
   815  
   816  	// ID is a unique id that is associated with the component inspected to produce
   817  	// this Stats object. Two Stats objects will have the same ID if they were produced
   818  	// by inspecting the same underlying object.
   819  	ID string `json:"id"`
   820  
   821  	// ContributorSSRC is the SSRC identifier of the contributing source represented
   822  	// by this stats object. It is a 32-bit unsigned integer that appears in the CSRC
   823  	// list of any packets the relevant source contributed to.
   824  	ContributorSSRC SSRC `json:"contributorSsrc"`
   825  
   826  	// InboundRTPStreamID is the ID of the InboundRTPStreamStats object representing
   827  	// the inbound RTP stream that this contributing source is contributing to.
   828  	InboundRTPStreamID string `json:"inboundRtpStreamId"`
   829  
   830  	// PacketsContributedTo is the total number of RTP packets that this contributing
   831  	// source contributed to. This value is incremented each time a packet is counted
   832  	// by InboundRTPStreamStats.packetsReceived, and the packet's CSRC list contains
   833  	// the SSRC identifier of this contributing source, ContributorSSRC.
   834  	PacketsContributedTo uint32 `json:"packetsContributedTo"`
   835  
   836  	// AudioLevel is present if the last received RTP packet that this source contributed
   837  	// to contained an [RFC6465] mixer-to-client audio level header extension. The value
   838  	// of audioLevel is between 0..1 (linear), where 1.0 represents 0 dBov, 0 represents
   839  	// silence, and 0.5 represents approximately 6 dBSPL change in the sound pressure level from 0 dBov.
   840  	AudioLevel float64 `json:"audioLevel"`
   841  }
   842  
   843  func (s RTPContributingSourceStats) statsMarker() {}
   844  
   845  func unmarshalCSRCStats(b []byte) (RTPContributingSourceStats, error) {
   846  	var csrcStats RTPContributingSourceStats
   847  	err := json.Unmarshal(b, &csrcStats)
   848  	if err != nil {
   849  		return RTPContributingSourceStats{}, fmt.Errorf("unmarshal csrc stats: %w", err)
   850  	}
   851  	return csrcStats, nil
   852  }
   853  
   854  // AudioSourceStats represents an audio track that is attached to one or more senders.
   855  type AudioSourceStats struct {
   856  	// Timestamp is the timestamp associated with this object.
   857  	Timestamp StatsTimestamp `json:"timestamp"`
   858  
   859  	// Type is the object's StatsType
   860  	Type StatsType `json:"type"`
   861  
   862  	// ID is a unique id that is associated with the component inspected to produce
   863  	// this Stats object. Two Stats objects will have the same ID if they were produced
   864  	// by inspecting the same underlying object.
   865  	ID string `json:"id"`
   866  
   867  	// TrackIdentifier represents the id property of the track.
   868  	TrackIdentifier string `json:"trackIdentifier"`
   869  
   870  	// Kind is "audio"
   871  	Kind string `json:"kind"`
   872  
   873  	// AudioLevel represents the output audio level of the track.
   874  	//
   875  	// The value is a value between 0..1 (linear), where 1.0 represents 0 dBov,
   876  	// 0 represents silence, and 0.5 represents approximately 6 dBSPL change in
   877  	// the sound pressure level from 0 dBov.
   878  	//
   879  	// If the track is sourced from an Receiver, does no audio processing, has a
   880  	// constant level, and has a volume setting of 1.0, the audio level is expected
   881  	// to be the same as the audio level of the source SSRC, while if the volume setting
   882  	// is 0.5, the AudioLevel is expected to be half that value.
   883  	AudioLevel float64 `json:"audioLevel"`
   884  
   885  	// TotalAudioEnergy is the total energy of all the audio samples sent/received
   886  	// for this object, calculated by duration * Math.pow(energy/maxEnergy, 2) for
   887  	// each audio sample seen.
   888  	TotalAudioEnergy float64 `json:"totalAudioEnergy"`
   889  
   890  	// TotalSamplesDuration represents the total duration in seconds of all samples
   891  	// that have sent or received (and thus counted by TotalSamplesSent or TotalSamplesReceived).
   892  	// Can be used with TotalAudioEnergy to compute an average audio level over different intervals.
   893  	TotalSamplesDuration float64 `json:"totalSamplesDuration"`
   894  
   895  	// EchoReturnLoss is only present while the sender is sending a track sourced from
   896  	// a microphone where echo cancellation is applied. Calculated in decibels.
   897  	EchoReturnLoss float64 `json:"echoReturnLoss"`
   898  
   899  	// EchoReturnLossEnhancement is only present while the sender is sending a track
   900  	// sourced from a microphone where echo cancellation is applied. Calculated in decibels.
   901  	EchoReturnLossEnhancement float64 `json:"echoReturnLossEnhancement"`
   902  
   903  	// DroppedSamplesDuration represents the total duration, in seconds, of samples produced by the device that got
   904  	// dropped before reaching the media source. Only applicable if this media source is backed by an audio capture device.
   905  	DroppedSamplesDuration float64 `json:"droppedSamplesDuration"`
   906  
   907  	// DroppedSamplesEvents is the number of dropped samples events. This counter increases every time a sample is
   908  	// dropped after a non-dropped sample. That is, multiple consecutive dropped samples will increase
   909  	// droppedSamplesDuration multiple times but is a single dropped samples event.
   910  	DroppedSamplesEvents uint64 `json:"droppedSamplesEvents"`
   911  
   912  	// TotalCaptureDelay is the total delay, in seconds, for each audio sample between the time the sample was emitted
   913  	// by the capture device and the sample reaching the source. This can be used together with totalSamplesCaptured to
   914  	// calculate the average capture delay per sample. Only applicable if the audio source represents an audio capture device.
   915  	TotalCaptureDelay float64 `json:"totalCaptureDelay"`
   916  
   917  	// TotalSamplesCaptured is the total number of captured samples reaching the audio source, i.e. that were not dropped
   918  	// by the capture pipeline. The frequency of the media source is not necessarily the same as the frequency of encoders
   919  	// later in the pipeline. Only applicable if the audio source represents an audio capture device.
   920  	TotalSamplesCaptured uint64 `json:"totalSamplesCaptured"`
   921  }
   922  
   923  func (s AudioSourceStats) statsMarker() {}
   924  
   925  // VideoSourceStats represents a video track that is attached to one or more senders.
   926  type VideoSourceStats struct {
   927  	// Timestamp is the timestamp associated with this object.
   928  	Timestamp StatsTimestamp `json:"timestamp"`
   929  
   930  	// Type is the object's StatsType
   931  	Type StatsType `json:"type"`
   932  
   933  	// ID is a unique id that is associated with the component inspected to produce
   934  	// this Stats object. Two Stats objects will have the same ID if they were produced
   935  	// by inspecting the same underlying object.
   936  	ID string `json:"id"`
   937  
   938  	// TrackIdentifier represents the id property of the track.
   939  	TrackIdentifier string `json:"trackIdentifier"`
   940  
   941  	// Kind is "video"
   942  	Kind string `json:"kind"`
   943  
   944  	// Width is width of the last frame originating from this source in pixels.
   945  	Width uint32 `json:"width"`
   946  
   947  	// Height is height of the last frame originating from this source in pixels.
   948  	Height uint32 `json:"height"`
   949  
   950  	// Frames is the total number of frames originating from this source.
   951  	Frames uint32 `json:"frames"`
   952  
   953  	// FramesPerSecond is the number of frames originating from this source, measured during the last second.
   954  	FramesPerSecond float64 `json:"framesPerSecond"`
   955  }
   956  
   957  func (s VideoSourceStats) statsMarker() {}
   958  
   959  func unmarshalMediaSourceStats(b []byte) (Stats, error) {
   960  	type kindJSON struct {
   961  		Kind string `json:"kind"`
   962  	}
   963  	kindHolder := kindJSON{}
   964  
   965  	err := json.Unmarshal(b, &kindHolder)
   966  	if err != nil {
   967  		return nil, fmt.Errorf("unmarshal json kind: %w", err)
   968  	}
   969  
   970  	switch MediaKind(kindHolder.Kind) {
   971  	case MediaKindAudio:
   972  		var mediaSourceStats AudioSourceStats
   973  		err := json.Unmarshal(b, &mediaSourceStats)
   974  		if err != nil {
   975  			return nil, fmt.Errorf("unmarshal audio source stats: %w", err)
   976  		}
   977  		return mediaSourceStats, nil
   978  	case MediaKindVideo:
   979  		var mediaSourceStats VideoSourceStats
   980  		err := json.Unmarshal(b, &mediaSourceStats)
   981  		if err != nil {
   982  			return nil, fmt.Errorf("unmarshal video source stats: %w", err)
   983  		}
   984  		return mediaSourceStats, nil
   985  	default:
   986  		return nil, fmt.Errorf("kind: %w", ErrUnknownType)
   987  	}
   988  }
   989  
   990  // AudioPlayoutStats represents one playout path - if the same playout stats object is referenced by multiple
   991  // RTCInboundRtpStreamStats this is an indication that audio mixing is happening in which case sample counters in this
   992  // stats object refer to the samples after mixing. Only applicable if the playout path represents an audio device.
   993  type AudioPlayoutStats struct {
   994  	// Timestamp is the timestamp associated with this object.
   995  	Timestamp StatsTimestamp `json:"timestamp"`
   996  
   997  	// Type is the object's StatsType
   998  	Type StatsType `json:"type"`
   999  
  1000  	// ID is a unique id that is associated with the component inspected to produce
  1001  	// this Stats object. Two Stats objects will have the same ID if they were produced
  1002  	// by inspecting the same underlying object.
  1003  	ID string `json:"id"`
  1004  
  1005  	// Kind is "audio"
  1006  	Kind string `json:"kind"`
  1007  
  1008  	// SynthesizedSamplesDuration is measured in seconds and is incremented each time an audio sample is synthesized by
  1009  	// this playout path. This metric can be used together with totalSamplesDuration to calculate the percentage of played
  1010  	// out media being synthesized. If the playout path is unable to produce audio samples on time for device playout,
  1011  	// samples are synthesized to be playout out instead. Synthesization typically only happens if the pipeline is
  1012  	// underperforming. Samples synthesized by the RTCInboundRtpStreamStats are not counted for here, but in
  1013  	// InboundRtpStreamStats.concealedSamples.
  1014  	SynthesizedSamplesDuration float64 `json:"synthesizedSamplesDuration"`
  1015  
  1016  	// SynthesizedSamplesEvents is the number of synthesized samples events. This counter increases every time a sample
  1017  	// is synthesized after a non-synthesized sample. That is, multiple consecutive synthesized samples will increase
  1018  	// synthesizedSamplesDuration multiple times but is a single synthesization samples event.
  1019  	SynthesizedSamplesEvents uint64 `json:"synthesizedSamplesEvents"`
  1020  
  1021  	// TotalSamplesDuration represents the total duration in seconds of all samples
  1022  	// that have sent or received (and thus counted by TotalSamplesSent or TotalSamplesReceived).
  1023  	// Can be used with TotalAudioEnergy to compute an average audio level over different intervals.
  1024  	TotalSamplesDuration float64 `json:"totalSamplesDuration"`
  1025  
  1026  	// When audio samples are pulled by the playout device, this counter is incremented with the estimated delay of the
  1027  	// playout path for that audio sample. The playout delay includes the delay from being emitted to the actual time of
  1028  	// playout on the device. This metric can be used together with totalSamplesCount to calculate the average
  1029  	// playout delay per sample.
  1030  	TotalPlayoutDelay float64 `json:"totalPlayoutDelay"`
  1031  
  1032  	// When audio samples are pulled by the playout device, this counter is incremented with the number of samples
  1033  	// emitted for playout.
  1034  	TotalSamplesCount uint64 `json:"totalSamplesCount"`
  1035  }
  1036  
  1037  func (s AudioPlayoutStats) statsMarker() {}
  1038  
  1039  func unmarshalMediaPlayoutStats(b []byte) (Stats, error) {
  1040  	var audioPlayoutStats AudioPlayoutStats
  1041  	err := json.Unmarshal(b, &audioPlayoutStats)
  1042  	if err != nil {
  1043  		return nil, fmt.Errorf("unmarshal audio playout stats: %w", err)
  1044  	}
  1045  	return audioPlayoutStats, nil
  1046  }
  1047  
  1048  // PeerConnectionStats contains statistics related to the PeerConnection object.
  1049  type PeerConnectionStats struct {
  1050  	// Timestamp is the timestamp associated with this object.
  1051  	Timestamp StatsTimestamp `json:"timestamp"`
  1052  
  1053  	// Type is the object's StatsType
  1054  	Type StatsType `json:"type"`
  1055  
  1056  	// ID is a unique id that is associated with the component inspected to produce
  1057  	// this Stats object. Two Stats objects will have the same ID if they were produced
  1058  	// by inspecting the same underlying object.
  1059  	ID string `json:"id"`
  1060  
  1061  	// DataChannelsOpened represents the number of unique DataChannels that have
  1062  	// entered the "open" state during their lifetime.
  1063  	DataChannelsOpened uint32 `json:"dataChannelsOpened"`
  1064  
  1065  	// DataChannelsClosed represents the number of unique DataChannels that have
  1066  	// left the "open" state during their lifetime (due to being closed by either
  1067  	// end or the underlying transport being closed). DataChannels that transition
  1068  	// from "connecting" to "closing" or "closed" without ever being "open"
  1069  	// are not counted in this number.
  1070  	DataChannelsClosed uint32 `json:"dataChannelsClosed"`
  1071  
  1072  	// DataChannelsRequested Represents the number of unique DataChannels returned
  1073  	// from a successful createDataChannel() call on the PeerConnection. If the
  1074  	// underlying data transport is not established, these may be in the "connecting" state.
  1075  	DataChannelsRequested uint32 `json:"dataChannelsRequested"`
  1076  
  1077  	// DataChannelsAccepted represents the number of unique DataChannels signaled
  1078  	// in a "datachannel" event on the PeerConnection.
  1079  	DataChannelsAccepted uint32 `json:"dataChannelsAccepted"`
  1080  }
  1081  
  1082  func (s PeerConnectionStats) statsMarker() {}
  1083  
  1084  func unmarshalPeerConnectionStats(b []byte) (PeerConnectionStats, error) {
  1085  	var pcStats PeerConnectionStats
  1086  	err := json.Unmarshal(b, &pcStats)
  1087  	if err != nil {
  1088  		return PeerConnectionStats{}, fmt.Errorf("unmarshal pc stats: %w", err)
  1089  	}
  1090  	return pcStats, nil
  1091  }
  1092  
  1093  // DataChannelStats contains statistics related to each DataChannel ID.
  1094  type DataChannelStats struct {
  1095  	// Timestamp is the timestamp associated with this object.
  1096  	Timestamp StatsTimestamp `json:"timestamp"`
  1097  
  1098  	// Type is the object's StatsType
  1099  	Type StatsType `json:"type"`
  1100  
  1101  	// ID is a unique id that is associated with the component inspected to produce
  1102  	// this Stats object. Two Stats objects will have the same ID if they were produced
  1103  	// by inspecting the same underlying object.
  1104  	ID string `json:"id"`
  1105  
  1106  	// Label is the "label" value of the DataChannel object.
  1107  	Label string `json:"label"`
  1108  
  1109  	// Protocol is the "protocol" value of the DataChannel object.
  1110  	Protocol string `json:"protocol"`
  1111  
  1112  	// DataChannelIdentifier is the "id" attribute of the DataChannel object.
  1113  	DataChannelIdentifier int32 `json:"dataChannelIdentifier"`
  1114  
  1115  	// TransportID the ID of the TransportStats object for transport used to carry this datachannel.
  1116  	TransportID string `json:"transportId"`
  1117  
  1118  	// State is the "readyState" value of the DataChannel object.
  1119  	State DataChannelState `json:"state"`
  1120  
  1121  	// MessagesSent represents the total number of API "message" events sent.
  1122  	MessagesSent uint32 `json:"messagesSent"`
  1123  
  1124  	// BytesSent represents the total number of payload bytes sent on this
  1125  	// datachannel not including headers or padding.
  1126  	BytesSent uint64 `json:"bytesSent"`
  1127  
  1128  	// MessagesReceived represents the total number of API "message" events received.
  1129  	MessagesReceived uint32 `json:"messagesReceived"`
  1130  
  1131  	// BytesReceived represents the total number of bytes received on this
  1132  	// datachannel not including headers or padding.
  1133  	BytesReceived uint64 `json:"bytesReceived"`
  1134  }
  1135  
  1136  func (s DataChannelStats) statsMarker() {}
  1137  
  1138  func unmarshalDataChannelStats(b []byte) (DataChannelStats, error) {
  1139  	var dataChannelStats DataChannelStats
  1140  	err := json.Unmarshal(b, &dataChannelStats)
  1141  	if err != nil {
  1142  		return DataChannelStats{}, fmt.Errorf("unmarshal data channel stats: %w", err)
  1143  	}
  1144  	return dataChannelStats, nil
  1145  }
  1146  
  1147  // MediaStreamStats contains statistics related to a specific MediaStream.
  1148  type MediaStreamStats struct {
  1149  	// Timestamp is the timestamp associated with this object.
  1150  	Timestamp StatsTimestamp `json:"timestamp"`
  1151  
  1152  	// Type is the object's StatsType
  1153  	Type StatsType `json:"type"`
  1154  
  1155  	// ID is a unique id that is associated with the component inspected to produce
  1156  	// this Stats object. Two Stats objects will have the same ID if they were produced
  1157  	// by inspecting the same underlying object.
  1158  	ID string `json:"id"`
  1159  
  1160  	// StreamIdentifier is the "id" property of the MediaStream
  1161  	StreamIdentifier string `json:"streamIdentifier"`
  1162  
  1163  	// TrackIDs is a list of the identifiers of the stats object representing the
  1164  	// stream's tracks, either ReceiverAudioTrackAttachmentStats or ReceiverVideoTrackAttachmentStats.
  1165  	TrackIDs []string `json:"trackIds"`
  1166  }
  1167  
  1168  func (s MediaStreamStats) statsMarker() {}
  1169  
  1170  func unmarshalStreamStats(b []byte) (MediaStreamStats, error) {
  1171  	var streamStats MediaStreamStats
  1172  	err := json.Unmarshal(b, &streamStats)
  1173  	if err != nil {
  1174  		return MediaStreamStats{}, fmt.Errorf("unmarshal stream stats: %w", err)
  1175  	}
  1176  	return streamStats, nil
  1177  }
  1178  
  1179  // AudioSenderStats represents the stats about one audio sender of a PeerConnection
  1180  // object for which one calls GetStats.
  1181  //
  1182  // It appears in the stats as soon as the RTPSender is added by either AddTrack
  1183  // or AddTransceiver, or by media negotiation.
  1184  type AudioSenderStats struct {
  1185  	// Timestamp is the timestamp associated with this object.
  1186  	Timestamp StatsTimestamp `json:"timestamp"`
  1187  
  1188  	// Type is the object's StatsType
  1189  	Type StatsType `json:"type"`
  1190  
  1191  	// ID is a unique id that is associated with the component inspected to produce
  1192  	// this Stats object. Two Stats objects will have the same ID if they were produced
  1193  	// by inspecting the same underlying object.
  1194  	ID string `json:"id"`
  1195  
  1196  	// TrackIdentifier represents the id property of the track.
  1197  	TrackIdentifier string `json:"trackIdentifier"`
  1198  
  1199  	// RemoteSource is true if the source is remote, for instance if it is sourced
  1200  	// from another host via a PeerConnection. False otherwise. Only applicable for 'track' stats.
  1201  	RemoteSource bool `json:"remoteSource"`
  1202  
  1203  	// Ended reflects the "ended" state of the track.
  1204  	Ended bool `json:"ended"`
  1205  
  1206  	// Kind is "audio"
  1207  	Kind string `json:"kind"`
  1208  
  1209  	// AudioLevel represents the output audio level of the track.
  1210  	//
  1211  	// The value is a value between 0..1 (linear), where 1.0 represents 0 dBov,
  1212  	// 0 represents silence, and 0.5 represents approximately 6 dBSPL change in
  1213  	// the sound pressure level from 0 dBov.
  1214  	//
  1215  	// If the track is sourced from an Receiver, does no audio processing, has a
  1216  	// constant level, and has a volume setting of 1.0, the audio level is expected
  1217  	// to be the same as the audio level of the source SSRC, while if the volume setting
  1218  	// is 0.5, the AudioLevel is expected to be half that value.
  1219  	//
  1220  	// For outgoing audio tracks, the AudioLevel is the level of the audio being sent.
  1221  	AudioLevel float64 `json:"audioLevel"`
  1222  
  1223  	// TotalAudioEnergy is the total energy of all the audio samples sent/received
  1224  	// for this object, calculated by duration * Math.pow(energy/maxEnergy, 2) for
  1225  	// each audio sample seen.
  1226  	TotalAudioEnergy float64 `json:"totalAudioEnergy"`
  1227  
  1228  	// VoiceActivityFlag represents whether the last RTP packet sent or played out
  1229  	// by this track contained voice activity or not based on the presence of the
  1230  	// V bit in the extension header, as defined in [RFC6464].
  1231  	//
  1232  	// This value indicates the voice activity in the latest RTP packet played out
  1233  	// from a given SSRC, and is defined in RTPSynchronizationSource.voiceActivityFlag.
  1234  	VoiceActivityFlag bool `json:"voiceActivityFlag"`
  1235  
  1236  	// TotalSamplesDuration represents the total duration in seconds of all samples
  1237  	// that have sent or received (and thus counted by TotalSamplesSent or TotalSamplesReceived).
  1238  	// Can be used with TotalAudioEnergy to compute an average audio level over different intervals.
  1239  	TotalSamplesDuration float64 `json:"totalSamplesDuration"`
  1240  
  1241  	// EchoReturnLoss is only present while the sender is sending a track sourced from
  1242  	// a microphone where echo cancellation is applied. Calculated in decibels.
  1243  	EchoReturnLoss float64 `json:"echoReturnLoss"`
  1244  
  1245  	// EchoReturnLossEnhancement is only present while the sender is sending a track
  1246  	// sourced from a microphone where echo cancellation is applied. Calculated in decibels.
  1247  	EchoReturnLossEnhancement float64 `json:"echoReturnLossEnhancement"`
  1248  
  1249  	// TotalSamplesSent is the total number of samples that have been sent by this sender.
  1250  	TotalSamplesSent uint64 `json:"totalSamplesSent"`
  1251  }
  1252  
  1253  func (s AudioSenderStats) statsMarker() {}
  1254  
  1255  // SenderAudioTrackAttachmentStats object represents the stats about one attachment
  1256  // of an audio MediaStreamTrack to the PeerConnection object for which one calls GetStats.
  1257  //
  1258  // It appears in the stats as soon as it is attached (via AddTrack, via AddTransceiver,
  1259  // via ReplaceTrack on an RTPSender object).
  1260  //
  1261  // If an audio track is attached twice (via AddTransceiver or ReplaceTrack), there
  1262  // will be two SenderAudioTrackAttachmentStats objects, one for each attachment.
  1263  // They will have the same "TrackIdentifier" attribute, but different "ID" attributes.
  1264  //
  1265  // If the track is detached from the PeerConnection (via removeTrack or via replaceTrack),
  1266  // it continues to appear, but with the "ObjectDeleted" member set to true.
  1267  type SenderAudioTrackAttachmentStats AudioSenderStats
  1268  
  1269  func (s SenderAudioTrackAttachmentStats) statsMarker() {}
  1270  
  1271  // VideoSenderStats represents the stats about one video sender of a PeerConnection
  1272  // object for which one calls GetStats.
  1273  //
  1274  // It appears in the stats as soon as the sender is added by either AddTrack or
  1275  // AddTransceiver, or by media negotiation.
  1276  type VideoSenderStats struct {
  1277  	// Timestamp is the timestamp associated with this object.
  1278  	Timestamp StatsTimestamp `json:"timestamp"`
  1279  
  1280  	// Type is the object's StatsType
  1281  	Type StatsType `json:"type"`
  1282  
  1283  	// ID is a unique id that is associated with the component inspected to produce
  1284  	// this Stats object. Two Stats objects will have the same ID if they were produced
  1285  	// by inspecting the same underlying object.
  1286  	ID string `json:"id"`
  1287  
  1288  	// Kind is "video"
  1289  	Kind string `json:"kind"`
  1290  
  1291  	// FramesCaptured represents the total number of frames captured, before encoding,
  1292  	// for this RTPSender (or for this MediaStreamTrack, if type is "track"). For example,
  1293  	// if type is "sender" and this sender's track represents a camera, then this is the
  1294  	// number of frames produced by the camera for this track while being sent by this sender,
  1295  	// combined with the number of frames produced by all tracks previously attached to this
  1296  	// sender while being sent by this sender. Framerates can vary due to hardware limitations
  1297  	// or environmental factors such as lighting conditions.
  1298  	FramesCaptured uint32 `json:"framesCaptured"`
  1299  
  1300  	// FramesSent represents the total number of frames sent by this RTPSender
  1301  	// (or for this MediaStreamTrack, if type is "track").
  1302  	FramesSent uint32 `json:"framesSent"`
  1303  
  1304  	// HugeFramesSent represents the total number of huge frames sent by this RTPSender
  1305  	// (or for this MediaStreamTrack, if type is "track"). Huge frames, by definition,
  1306  	// are frames that have an encoded size at least 2.5 times the average size of the frames.
  1307  	// The average size of the frames is defined as the target bitrate per second divided
  1308  	// by the target fps at the time the frame was encoded. These are usually complex
  1309  	// to encode frames with a lot of changes in the picture. This can be used to estimate,
  1310  	// e.g slide changes in the streamed presentation. If a huge frame is also a key frame,
  1311  	// then both counters HugeFramesSent and KeyFramesSent are incremented.
  1312  	HugeFramesSent uint32 `json:"hugeFramesSent"`
  1313  
  1314  	// KeyFramesSent represents the total number of key frames sent by this RTPSender
  1315  	// (or for this MediaStreamTrack, if type is "track"), such as Infra-frames in
  1316  	// VP8 [RFC6386] or I-frames in H.264 [RFC6184]. This is a subset of FramesSent.
  1317  	// FramesSent - KeyFramesSent gives you the number of delta frames sent.
  1318  	KeyFramesSent uint32 `json:"keyFramesSent"`
  1319  }
  1320  
  1321  func (s VideoSenderStats) statsMarker() {}
  1322  
  1323  // SenderVideoTrackAttachmentStats represents the stats about one attachment of a
  1324  // video MediaStreamTrack to the PeerConnection object for which one calls GetStats.
  1325  //
  1326  // It appears in the stats as soon as it is attached (via AddTrack, via AddTransceiver,
  1327  // via ReplaceTrack on an RTPSender object).
  1328  //
  1329  // If a video track is attached twice (via AddTransceiver or ReplaceTrack), there
  1330  // will be two SenderVideoTrackAttachmentStats objects, one for each attachment.
  1331  // They will have the same "TrackIdentifier" attribute, but different "ID" attributes.
  1332  //
  1333  // If the track is detached from the PeerConnection (via RemoveTrack or via ReplaceTrack),
  1334  // it continues to appear, but with the "ObjectDeleted" member set to true.
  1335  type SenderVideoTrackAttachmentStats VideoSenderStats
  1336  
  1337  func (s SenderVideoTrackAttachmentStats) statsMarker() {}
  1338  
  1339  func unmarshalSenderStats(b []byte) (Stats, error) {
  1340  	type kindJSON struct {
  1341  		Kind string `json:"kind"`
  1342  	}
  1343  	kindHolder := kindJSON{}
  1344  
  1345  	err := json.Unmarshal(b, &kindHolder)
  1346  	if err != nil {
  1347  		return nil, fmt.Errorf("unmarshal json kind: %w", err)
  1348  	}
  1349  
  1350  	switch MediaKind(kindHolder.Kind) {
  1351  	case MediaKindAudio:
  1352  		var senderStats AudioSenderStats
  1353  		err := json.Unmarshal(b, &senderStats)
  1354  		if err != nil {
  1355  			return nil, fmt.Errorf("unmarshal audio sender stats: %w", err)
  1356  		}
  1357  		return senderStats, nil
  1358  	case MediaKindVideo:
  1359  		var senderStats VideoSenderStats
  1360  		err := json.Unmarshal(b, &senderStats)
  1361  		if err != nil {
  1362  			return nil, fmt.Errorf("unmarshal video sender stats: %w", err)
  1363  		}
  1364  		return senderStats, nil
  1365  	default:
  1366  		return nil, fmt.Errorf("kind: %w", ErrUnknownType)
  1367  	}
  1368  }
  1369  
  1370  func unmarshalTrackStats(b []byte) (Stats, error) {
  1371  	type kindJSON struct {
  1372  		Kind string `json:"kind"`
  1373  	}
  1374  	kindHolder := kindJSON{}
  1375  
  1376  	err := json.Unmarshal(b, &kindHolder)
  1377  	if err != nil {
  1378  		return nil, fmt.Errorf("unmarshal json kind: %w", err)
  1379  	}
  1380  
  1381  	switch MediaKind(kindHolder.Kind) {
  1382  	case MediaKindAudio:
  1383  		var trackStats SenderAudioTrackAttachmentStats
  1384  		err := json.Unmarshal(b, &trackStats)
  1385  		if err != nil {
  1386  			return nil, fmt.Errorf("unmarshal audio track stats: %w", err)
  1387  		}
  1388  		return trackStats, nil
  1389  	case MediaKindVideo:
  1390  		var trackStats SenderVideoTrackAttachmentStats
  1391  		err := json.Unmarshal(b, &trackStats)
  1392  		if err != nil {
  1393  			return nil, fmt.Errorf("unmarshal video track stats: %w", err)
  1394  		}
  1395  		return trackStats, nil
  1396  	default:
  1397  		return nil, fmt.Errorf("kind: %w", ErrUnknownType)
  1398  	}
  1399  }
  1400  
  1401  // AudioReceiverStats contains audio metrics related to a specific receiver.
  1402  type AudioReceiverStats struct {
  1403  	// Timestamp is the timestamp associated with this object.
  1404  	Timestamp StatsTimestamp `json:"timestamp"`
  1405  
  1406  	// Type is the object's StatsType
  1407  	Type StatsType `json:"type"`
  1408  
  1409  	// ID is a unique id that is associated with the component inspected to produce
  1410  	// this Stats object. Two Stats objects will have the same ID if they were produced
  1411  	// by inspecting the same underlying object.
  1412  	ID string `json:"id"`
  1413  
  1414  	// Kind is "audio"
  1415  	Kind string `json:"kind"`
  1416  
  1417  	// AudioLevel represents the output audio level of the track.
  1418  	//
  1419  	// The value is a value between 0..1 (linear), where 1.0 represents 0 dBov,
  1420  	// 0 represents silence, and 0.5 represents approximately 6 dBSPL change in
  1421  	// the sound pressure level from 0 dBov.
  1422  	//
  1423  	// If the track is sourced from an Receiver, does no audio processing, has a
  1424  	// constant level, and has a volume setting of 1.0, the audio level is expected
  1425  	// to be the same as the audio level of the source SSRC, while if the volume setting
  1426  	// is 0.5, the AudioLevel is expected to be half that value.
  1427  	//
  1428  	// For outgoing audio tracks, the AudioLevel is the level of the audio being sent.
  1429  	AudioLevel float64 `json:"audioLevel"`
  1430  
  1431  	// TotalAudioEnergy is the total energy of all the audio samples sent/received
  1432  	// for this object, calculated by duration * Math.pow(energy/maxEnergy, 2) for
  1433  	// each audio sample seen.
  1434  	TotalAudioEnergy float64 `json:"totalAudioEnergy"`
  1435  
  1436  	// VoiceActivityFlag represents whether the last RTP packet sent or played out
  1437  	// by this track contained voice activity or not based on the presence of the
  1438  	// V bit in the extension header, as defined in [RFC6464].
  1439  	//
  1440  	// This value indicates the voice activity in the latest RTP packet played out
  1441  	// from a given SSRC, and is defined in RTPSynchronizationSource.voiceActivityFlag.
  1442  	VoiceActivityFlag bool `json:"voiceActivityFlag"`
  1443  
  1444  	// TotalSamplesDuration represents the total duration in seconds of all samples
  1445  	// that have sent or received (and thus counted by TotalSamplesSent or TotalSamplesReceived).
  1446  	// Can be used with TotalAudioEnergy to compute an average audio level over different intervals.
  1447  	TotalSamplesDuration float64 `json:"totalSamplesDuration"`
  1448  
  1449  	// EstimatedPlayoutTimestamp is the estimated playout time of this receiver's
  1450  	// track. The playout time is the NTP timestamp of the last playable sample that
  1451  	// has a known timestamp (from an RTCP SR packet mapping RTP timestamps to NTP
  1452  	// timestamps), extrapolated with the time elapsed since it was ready to be played out.
  1453  	// This is the "current time" of the track in NTP clock time of the sender and
  1454  	// can be present even if there is no audio currently playing.
  1455  	//
  1456  	// This can be useful for estimating how much audio and video is out of
  1457  	// sync for two tracks from the same source:
  1458  	// 		AudioTrackStats.EstimatedPlayoutTimestamp - VideoTrackStats.EstimatedPlayoutTimestamp
  1459  	EstimatedPlayoutTimestamp StatsTimestamp `json:"estimatedPlayoutTimestamp"`
  1460  
  1461  	// JitterBufferDelay is the sum of the time, in seconds, each sample takes from
  1462  	// the time it is received and to the time it exits the jitter buffer.
  1463  	// This increases upon samples exiting, having completed their time in the buffer
  1464  	// (incrementing JitterBufferEmittedCount). The average jitter buffer delay can
  1465  	// be calculated by dividing the JitterBufferDelay with the JitterBufferEmittedCount.
  1466  	JitterBufferDelay float64 `json:"jitterBufferDelay"`
  1467  
  1468  	// JitterBufferEmittedCount is the total number of samples that have come out
  1469  	// of the jitter buffer (increasing JitterBufferDelay).
  1470  	JitterBufferEmittedCount uint64 `json:"jitterBufferEmittedCount"`
  1471  
  1472  	// TotalSamplesReceived is the total number of samples that have been received
  1473  	// by this receiver. This includes ConcealedSamples.
  1474  	TotalSamplesReceived uint64 `json:"totalSamplesReceived"`
  1475  
  1476  	// ConcealedSamples is the total number of samples that are concealed samples.
  1477  	// A concealed sample is a sample that is based on data that was synthesized
  1478  	// to conceal packet loss and does not represent incoming data.
  1479  	ConcealedSamples uint64 `json:"concealedSamples"`
  1480  
  1481  	// ConcealmentEvents is the number of concealment events. This counter increases
  1482  	// every time a concealed sample is synthesized after a non-concealed sample.
  1483  	// That is, multiple consecutive concealed samples will increase the concealedSamples
  1484  	// count multiple times but is a single concealment event.
  1485  	ConcealmentEvents uint64 `json:"concealmentEvents"`
  1486  }
  1487  
  1488  func (s AudioReceiverStats) statsMarker() {}
  1489  
  1490  // VideoReceiverStats contains video metrics related to a specific receiver.
  1491  type VideoReceiverStats struct {
  1492  	// Timestamp is the timestamp associated with this object.
  1493  	Timestamp StatsTimestamp `json:"timestamp"`
  1494  
  1495  	// Type is the object's StatsType
  1496  	Type StatsType `json:"type"`
  1497  
  1498  	// ID is a unique id that is associated with the component inspected to produce
  1499  	// this Stats object. Two Stats objects will have the same ID if they were produced
  1500  	// by inspecting the same underlying object.
  1501  	ID string `json:"id"`
  1502  
  1503  	// Kind is "video"
  1504  	Kind string `json:"kind"`
  1505  
  1506  	// FrameWidth represents the width of the last processed frame for this track.
  1507  	// Before the first frame is processed this attribute is missing.
  1508  	FrameWidth uint32 `json:"frameWidth"`
  1509  
  1510  	// FrameHeight represents the height of the last processed frame for this track.
  1511  	// Before the first frame is processed this attribute is missing.
  1512  	FrameHeight uint32 `json:"frameHeight"`
  1513  
  1514  	// FramesPerSecond represents the nominal FPS value before the degradation preference
  1515  	// is applied. It is the number of complete frames in the last second. For sending
  1516  	// tracks it is the current captured FPS and for the receiving tracks it is the
  1517  	// current decoding framerate.
  1518  	FramesPerSecond float64 `json:"framesPerSecond"`
  1519  
  1520  	// EstimatedPlayoutTimestamp is the estimated playout time of this receiver's
  1521  	// track. The playout time is the NTP timestamp of the last playable sample that
  1522  	// has a known timestamp (from an RTCP SR packet mapping RTP timestamps to NTP
  1523  	// timestamps), extrapolated with the time elapsed since it was ready to be played out.
  1524  	// This is the "current time" of the track in NTP clock time of the sender and
  1525  	// can be present even if there is no audio currently playing.
  1526  	//
  1527  	// This can be useful for estimating how much audio and video is out of
  1528  	// sync for two tracks from the same source:
  1529  	// 		AudioTrackStats.EstimatedPlayoutTimestamp - VideoTrackStats.EstimatedPlayoutTimestamp
  1530  	EstimatedPlayoutTimestamp StatsTimestamp `json:"estimatedPlayoutTimestamp"`
  1531  
  1532  	// JitterBufferDelay is the sum of the time, in seconds, each sample takes from
  1533  	// the time it is received and to the time it exits the jitter buffer.
  1534  	// This increases upon samples exiting, having completed their time in the buffer
  1535  	// (incrementing JitterBufferEmittedCount). The average jitter buffer delay can
  1536  	// be calculated by dividing the JitterBufferDelay with the JitterBufferEmittedCount.
  1537  	JitterBufferDelay float64 `json:"jitterBufferDelay"`
  1538  
  1539  	// JitterBufferEmittedCount is the total number of samples that have come out
  1540  	// of the jitter buffer (increasing JitterBufferDelay).
  1541  	JitterBufferEmittedCount uint64 `json:"jitterBufferEmittedCount"`
  1542  
  1543  	// FramesReceived Represents the total number of complete frames received for
  1544  	// this receiver. This metric is incremented when the complete frame is received.
  1545  	FramesReceived uint32 `json:"framesReceived"`
  1546  
  1547  	// KeyFramesReceived represents the total number of complete key frames received
  1548  	// for this MediaStreamTrack, such as Infra-frames in VP8 [RFC6386] or I-frames
  1549  	// in H.264 [RFC6184]. This is a subset of framesReceived. `framesReceived - keyFramesReceived`
  1550  	// gives you the number of delta frames received. This metric is incremented when
  1551  	// the complete key frame is received. It is not incremented if a partial key
  1552  	// frames is received and sent for decoding, i.e., the frame could not be recovered
  1553  	// via retransmission or FEC.
  1554  	KeyFramesReceived uint32 `json:"keyFramesReceived"`
  1555  
  1556  	// FramesDecoded represents the total number of frames correctly decoded for this
  1557  	// SSRC, i.e., frames that would be displayed if no frames are dropped.
  1558  	FramesDecoded uint32 `json:"framesDecoded"`
  1559  
  1560  	// FramesDropped is the total number of frames dropped predecode or dropped
  1561  	// because the frame missed its display deadline for this receiver's track.
  1562  	FramesDropped uint32 `json:"framesDropped"`
  1563  
  1564  	// The cumulative number of partial frames lost. This metric is incremented when
  1565  	// the frame is sent to the decoder. If the partial frame is received and recovered
  1566  	// via retransmission or FEC before decoding, the FramesReceived counter is incremented.
  1567  	PartialFramesLost uint32 `json:"partialFramesLost"`
  1568  
  1569  	// FullFramesLost is the cumulative number of full frames lost.
  1570  	FullFramesLost uint32 `json:"fullFramesLost"`
  1571  }
  1572  
  1573  func (s VideoReceiverStats) statsMarker() {}
  1574  
  1575  func unmarshalReceiverStats(b []byte) (Stats, error) {
  1576  	type kindJSON struct {
  1577  		Kind string `json:"kind"`
  1578  	}
  1579  	kindHolder := kindJSON{}
  1580  
  1581  	err := json.Unmarshal(b, &kindHolder)
  1582  	if err != nil {
  1583  		return nil, fmt.Errorf("unmarshal json kind: %w", err)
  1584  	}
  1585  
  1586  	switch MediaKind(kindHolder.Kind) {
  1587  	case MediaKindAudio:
  1588  		var receiverStats AudioReceiverStats
  1589  		err := json.Unmarshal(b, &receiverStats)
  1590  		if err != nil {
  1591  			return nil, fmt.Errorf("unmarshal audio receiver stats: %w", err)
  1592  		}
  1593  		return receiverStats, nil
  1594  	case MediaKindVideo:
  1595  		var receiverStats VideoReceiverStats
  1596  		err := json.Unmarshal(b, &receiverStats)
  1597  		if err != nil {
  1598  			return nil, fmt.Errorf("unmarshal video receiver stats: %w", err)
  1599  		}
  1600  		return receiverStats, nil
  1601  	default:
  1602  		return nil, fmt.Errorf("kind: %w", ErrUnknownType)
  1603  	}
  1604  }
  1605  
  1606  // TransportStats contains transport statistics related to the PeerConnection object.
  1607  type TransportStats struct {
  1608  	// Timestamp is the timestamp associated with this object.
  1609  	Timestamp StatsTimestamp `json:"timestamp"`
  1610  
  1611  	// Type is the object's StatsType
  1612  	Type StatsType `json:"type"`
  1613  
  1614  	// ID is a unique id that is associated with the component inspected to produce
  1615  	// this Stats object. Two Stats objects will have the same ID if they were produced
  1616  	// by inspecting the same underlying object.
  1617  	ID string `json:"id"`
  1618  
  1619  	// PacketsSent represents the total number of packets sent over this transport.
  1620  	PacketsSent uint32 `json:"packetsSent"`
  1621  
  1622  	// PacketsReceived represents the total number of packets received on this transport.
  1623  	PacketsReceived uint32 `json:"packetsReceived"`
  1624  
  1625  	// BytesSent represents the total number of payload bytes sent on this PeerConnection
  1626  	// not including headers or padding.
  1627  	BytesSent uint64 `json:"bytesSent"`
  1628  
  1629  	// BytesReceived represents the total number of bytes received on this PeerConnection
  1630  	// not including headers or padding.
  1631  	BytesReceived uint64 `json:"bytesReceived"`
  1632  
  1633  	// RTCPTransportStatsID is the ID of the transport that gives stats for the RTCP
  1634  	// component If RTP and RTCP are not multiplexed and this record has only
  1635  	// the RTP component stats.
  1636  	RTCPTransportStatsID string `json:"rtcpTransportStatsId"`
  1637  
  1638  	// ICERole is set to the current value of the "role" attribute of the underlying
  1639  	// DTLSTransport's "transport".
  1640  	ICERole ICERole `json:"iceRole"`
  1641  
  1642  	// DTLSState is set to the current value of the "state" attribute of the underlying DTLSTransport.
  1643  	DTLSState DTLSTransportState `json:"dtlsState"`
  1644  
  1645  	// SelectedCandidatePairID is a unique identifier that is associated to the object
  1646  	// that was inspected to produce the ICECandidatePairStats associated with this transport.
  1647  	SelectedCandidatePairID string `json:"selectedCandidatePairId"`
  1648  
  1649  	// LocalCertificateID is the ID of the CertificateStats for the local certificate.
  1650  	// Present only if DTLS is negotiated.
  1651  	LocalCertificateID string `json:"localCertificateId"`
  1652  
  1653  	// LocalCertificateID is the ID of the CertificateStats for the remote certificate.
  1654  	// Present only if DTLS is negotiated.
  1655  	RemoteCertificateID string `json:"remoteCertificateId"`
  1656  
  1657  	// DTLSCipher is the descriptive name of the cipher suite used for the DTLS transport,
  1658  	// as defined in the "Description" column of the IANA cipher suite registry.
  1659  	DTLSCipher string `json:"dtlsCipher"`
  1660  
  1661  	// SRTPCipher is the descriptive name of the protection profile used for the SRTP
  1662  	// transport, as defined in the "Profile" column of the IANA DTLS-SRTP protection
  1663  	// profile registry.
  1664  	SRTPCipher string `json:"srtpCipher"`
  1665  }
  1666  
  1667  func (s TransportStats) statsMarker() {}
  1668  
  1669  func unmarshalTransportStats(b []byte) (TransportStats, error) {
  1670  	var transportStats TransportStats
  1671  	err := json.Unmarshal(b, &transportStats)
  1672  	if err != nil {
  1673  		return TransportStats{}, fmt.Errorf("unmarshal transport stats: %w", err)
  1674  	}
  1675  	return transportStats, nil
  1676  }
  1677  
  1678  // StatsICECandidatePairState is the state of an ICE candidate pair used in the
  1679  // ICECandidatePairStats object.
  1680  type StatsICECandidatePairState string
  1681  
  1682  func toStatsICECandidatePairState(state ice.CandidatePairState) (StatsICECandidatePairState, error) {
  1683  	switch state {
  1684  	case ice.CandidatePairStateWaiting:
  1685  		return StatsICECandidatePairStateWaiting, nil
  1686  	case ice.CandidatePairStateInProgress:
  1687  		return StatsICECandidatePairStateInProgress, nil
  1688  	case ice.CandidatePairStateFailed:
  1689  		return StatsICECandidatePairStateFailed, nil
  1690  	case ice.CandidatePairStateSucceeded:
  1691  		return StatsICECandidatePairStateSucceeded, nil
  1692  	default:
  1693  		// NOTE: this should never happen[tm]
  1694  		err := fmt.Errorf("%w: %s", errStatsICECandidateStateInvalid, state.String())
  1695  		return StatsICECandidatePairState("Unknown"), err
  1696  	}
  1697  }
  1698  
  1699  const (
  1700  	// StatsICECandidatePairStateFrozen means a check for this pair hasn't been
  1701  	// performed, and it can't yet be performed until some other check succeeds,
  1702  	// allowing this pair to unfreeze and move into the Waiting state.
  1703  	StatsICECandidatePairStateFrozen StatsICECandidatePairState = "frozen"
  1704  
  1705  	// StatsICECandidatePairStateWaiting means a check has not been performed for
  1706  	// this pair, and can be performed as soon as it is the highest-priority Waiting
  1707  	// pair on the check list.
  1708  	StatsICECandidatePairStateWaiting StatsICECandidatePairState = "waiting"
  1709  
  1710  	// StatsICECandidatePairStateInProgress means a check has been sent for this pair,
  1711  	// but the transaction is in progress.
  1712  	StatsICECandidatePairStateInProgress StatsICECandidatePairState = "in-progress"
  1713  
  1714  	// StatsICECandidatePairStateFailed means a check for this pair was already done
  1715  	// and failed, either never producing any response or producing an unrecoverable
  1716  	// failure response.
  1717  	StatsICECandidatePairStateFailed StatsICECandidatePairState = "failed"
  1718  
  1719  	// StatsICECandidatePairStateSucceeded means a check for this pair was already
  1720  	// done and produced a successful result.
  1721  	StatsICECandidatePairStateSucceeded StatsICECandidatePairState = "succeeded"
  1722  )
  1723  
  1724  // ICECandidatePairStats contains ICE candidate pair statistics related
  1725  // to the ICETransport objects.
  1726  type ICECandidatePairStats struct {
  1727  	// Timestamp is the timestamp associated with this object.
  1728  	Timestamp StatsTimestamp `json:"timestamp"`
  1729  
  1730  	// Type is the object's StatsType
  1731  	Type StatsType `json:"type"`
  1732  
  1733  	// ID is a unique id that is associated with the component inspected to produce
  1734  	// this Stats object. Two Stats objects will have the same ID if they were produced
  1735  	// by inspecting the same underlying object.
  1736  	ID string `json:"id"`
  1737  
  1738  	// TransportID is a unique identifier that is associated to the object that
  1739  	// was inspected to produce the TransportStats associated with this candidate pair.
  1740  	TransportID string `json:"transportId"`
  1741  
  1742  	// LocalCandidateID is a unique identifier that is associated to the object
  1743  	// that was inspected to produce the ICECandidateStats for the local candidate
  1744  	// associated with this candidate pair.
  1745  	LocalCandidateID string `json:"localCandidateId"`
  1746  
  1747  	// RemoteCandidateID is a unique identifier that is associated to the object
  1748  	// that was inspected to produce the ICECandidateStats for the remote candidate
  1749  	// associated with this candidate pair.
  1750  	RemoteCandidateID string `json:"remoteCandidateId"`
  1751  
  1752  	// State represents the state of the checklist for the local and remote
  1753  	// candidates in a pair.
  1754  	State StatsICECandidatePairState `json:"state"`
  1755  
  1756  	// Nominated is true when this valid pair that should be used for media
  1757  	// if it is the highest-priority one amongst those whose nominated flag is set
  1758  	Nominated bool `json:"nominated"`
  1759  
  1760  	// PacketsSent represents the total number of packets sent on this candidate pair.
  1761  	PacketsSent uint32 `json:"packetsSent"`
  1762  
  1763  	// PacketsReceived represents the total number of packets received on this candidate pair.
  1764  	PacketsReceived uint32 `json:"packetsReceived"`
  1765  
  1766  	// BytesSent represents the total number of payload bytes sent on this candidate pair
  1767  	// not including headers or padding.
  1768  	BytesSent uint64 `json:"bytesSent"`
  1769  
  1770  	// BytesReceived represents the total number of payload bytes received on this candidate pair
  1771  	// not including headers or padding.
  1772  	BytesReceived uint64 `json:"bytesReceived"`
  1773  
  1774  	// LastPacketSentTimestamp represents the timestamp at which the last packet was
  1775  	// sent on this particular candidate pair, excluding STUN packets.
  1776  	LastPacketSentTimestamp StatsTimestamp `json:"lastPacketSentTimestamp"`
  1777  
  1778  	// LastPacketReceivedTimestamp represents the timestamp at which the last packet
  1779  	// was received on this particular candidate pair, excluding STUN packets.
  1780  	LastPacketReceivedTimestamp StatsTimestamp `json:"lastPacketReceivedTimestamp"`
  1781  
  1782  	// FirstRequestTimestamp represents the timestamp at which the first STUN request
  1783  	// was sent on this particular candidate pair.
  1784  	FirstRequestTimestamp StatsTimestamp `json:"firstRequestTimestamp"`
  1785  
  1786  	// LastRequestTimestamp represents the timestamp at which the last STUN request
  1787  	// was sent on this particular candidate pair. The average interval between two
  1788  	// consecutive connectivity checks sent can be calculated with
  1789  	// (LastRequestTimestamp - FirstRequestTimestamp) / RequestsSent.
  1790  	LastRequestTimestamp StatsTimestamp `json:"lastRequestTimestamp"`
  1791  
  1792  	// LastResponseTimestamp represents the timestamp at which the last STUN response
  1793  	// was received on this particular candidate pair.
  1794  	LastResponseTimestamp StatsTimestamp `json:"lastResponseTimestamp"`
  1795  
  1796  	// TotalRoundTripTime represents the sum of all round trip time measurements
  1797  	// in seconds since the beginning of the session, based on STUN connectivity
  1798  	// check responses (ResponsesReceived), including those that reply to requests
  1799  	// that are sent in order to verify consent. The average round trip time can
  1800  	// be computed from TotalRoundTripTime by dividing it by ResponsesReceived.
  1801  	TotalRoundTripTime float64 `json:"totalRoundTripTime"`
  1802  
  1803  	// CurrentRoundTripTime represents the latest round trip time measured in seconds,
  1804  	// computed from both STUN connectivity checks, including those that are sent
  1805  	// for consent verification.
  1806  	CurrentRoundTripTime float64 `json:"currentRoundTripTime"`
  1807  
  1808  	// AvailableOutgoingBitrate is calculated by the underlying congestion control
  1809  	// by combining the available bitrate for all the outgoing RTP streams using
  1810  	// this candidate pair. The bitrate measurement does not count the size of the
  1811  	// IP or other transport layers like TCP or UDP. It is similar to the TIAS defined
  1812  	// in RFC 3890, i.e., it is measured in bits per second and the bitrate is calculated
  1813  	// over a 1 second window.
  1814  	AvailableOutgoingBitrate float64 `json:"availableOutgoingBitrate"`
  1815  
  1816  	// AvailableIncomingBitrate is calculated by the underlying congestion control
  1817  	// by combining the available bitrate for all the incoming RTP streams using
  1818  	// this candidate pair. The bitrate measurement does not count the size of the
  1819  	// IP or other transport layers like TCP or UDP. It is similar to the TIAS defined
  1820  	// in  RFC 3890, i.e., it is measured in bits per second and the bitrate is
  1821  	// calculated over a 1 second window.
  1822  	AvailableIncomingBitrate float64 `json:"availableIncomingBitrate"`
  1823  
  1824  	// CircuitBreakerTriggerCount represents the number of times the circuit breaker
  1825  	// is triggered for this particular 5-tuple, ceasing transmission.
  1826  	CircuitBreakerTriggerCount uint32 `json:"circuitBreakerTriggerCount"`
  1827  
  1828  	// RequestsReceived represents the total number of connectivity check requests
  1829  	// received (including retransmissions). It is impossible for the receiver to
  1830  	// tell whether the request was sent in order to check connectivity or check
  1831  	// consent, so all connectivity checks requests are counted here.
  1832  	RequestsReceived uint64 `json:"requestsReceived"`
  1833  
  1834  	// RequestsSent represents the total number of connectivity check requests
  1835  	// sent (not including retransmissions).
  1836  	RequestsSent uint64 `json:"requestsSent"`
  1837  
  1838  	// ResponsesReceived represents the total number of connectivity check responses received.
  1839  	ResponsesReceived uint64 `json:"responsesReceived"`
  1840  
  1841  	// ResponsesSent represents the total number of connectivity check responses sent.
  1842  	// Since we cannot distinguish connectivity check requests and consent requests,
  1843  	// all responses are counted.
  1844  	ResponsesSent uint64 `json:"responsesSent"`
  1845  
  1846  	// RetransmissionsReceived represents the total number of connectivity check
  1847  	// request retransmissions received.
  1848  	RetransmissionsReceived uint64 `json:"retransmissionsReceived"`
  1849  
  1850  	// RetransmissionsSent represents the total number of connectivity check
  1851  	// request retransmissions sent.
  1852  	RetransmissionsSent uint64 `json:"retransmissionsSent"`
  1853  
  1854  	// ConsentRequestsSent represents the total number of consent requests sent.
  1855  	ConsentRequestsSent uint64 `json:"consentRequestsSent"`
  1856  
  1857  	// ConsentExpiredTimestamp represents the timestamp at which the latest valid
  1858  	// STUN binding response expired.
  1859  	ConsentExpiredTimestamp StatsTimestamp `json:"consentExpiredTimestamp"`
  1860  }
  1861  
  1862  func (s ICECandidatePairStats) statsMarker() {}
  1863  
  1864  func unmarshalICECandidatePairStats(b []byte) (ICECandidatePairStats, error) {
  1865  	var iceCandidatePairStats ICECandidatePairStats
  1866  	err := json.Unmarshal(b, &iceCandidatePairStats)
  1867  	if err != nil {
  1868  		return ICECandidatePairStats{}, fmt.Errorf("unmarshal ice candidate pair stats: %w", err)
  1869  	}
  1870  	return iceCandidatePairStats, nil
  1871  }
  1872  
  1873  // ICECandidateStats contains ICE candidate statistics related to the ICETransport objects.
  1874  type ICECandidateStats struct {
  1875  	// Timestamp is the timestamp associated with this object.
  1876  	Timestamp StatsTimestamp `json:"timestamp"`
  1877  
  1878  	// Type is the object's StatsType
  1879  	Type StatsType `json:"type"`
  1880  
  1881  	// ID is a unique id that is associated with the component inspected to produce
  1882  	// this Stats object. Two Stats objects will have the same ID if they were produced
  1883  	// by inspecting the same underlying object.
  1884  	ID string `json:"id"`
  1885  
  1886  	// TransportID is a unique identifier that is associated to the object that
  1887  	// was inspected to produce the TransportStats associated with this candidate.
  1888  	TransportID string `json:"transportId"`
  1889  
  1890  	// NetworkType represents the type of network interface used by the base of a
  1891  	// local candidate (the address the ICE agent sends from). Only present for
  1892  	// local candidates; it's not possible to know what type of network interface
  1893  	// a remote candidate is using.
  1894  	//
  1895  	// Note:
  1896  	// This stat only tells you about the network interface used by the first "hop";
  1897  	// it's possible that a connection will be bottlenecked by another type of network.
  1898  	// For example, when using Wi-Fi tethering, the networkType of the relevant candidate
  1899  	// would be "wifi", even when the next hop is over a cellular connection.
  1900  	//
  1901  	// DEPRECATED. Although it may still work in some browsers, the networkType property was deprecated for
  1902  	// preserving privacy.
  1903  	NetworkType NetworkType `json:"networkType,omitempty"`
  1904  
  1905  	// IP is the IP address of the candidate, allowing for IPv4 addresses and
  1906  	// IPv6 addresses, but fully qualified domain names (FQDNs) are not allowed.
  1907  	IP string `json:"ip"`
  1908  
  1909  	// Port is the port number of the candidate.
  1910  	Port int32 `json:"port"`
  1911  
  1912  	// Protocol is one of udp and tcp.
  1913  	Protocol string `json:"protocol"`
  1914  
  1915  	// CandidateType is the "Type" field of the ICECandidate.
  1916  	CandidateType ICECandidateType `json:"candidateType"`
  1917  
  1918  	// Priority is the "Priority" field of the ICECandidate.
  1919  	Priority int32 `json:"priority"`
  1920  
  1921  	// URL is the URL of the TURN or STUN server indicated in the that translated
  1922  	// this IP address. It is the URL address surfaced in an PeerConnectionICEEvent.
  1923  	URL string `json:"url"`
  1924  
  1925  	// RelayProtocol is the protocol used by the endpoint to communicate with the
  1926  	// TURN server. This is only present for local candidates. Valid values for
  1927  	// the TURN URL protocol is one of udp, tcp, or tls.
  1928  	RelayProtocol string `json:"relayProtocol"`
  1929  
  1930  	// Deleted is true if the candidate has been deleted/freed. For host candidates,
  1931  	// this means that any network resources (typically a socket) associated with the
  1932  	// candidate have been released. For TURN candidates, this means the TURN allocation
  1933  	// is no longer active.
  1934  	//
  1935  	// Only defined for local candidates. For remote candidates, this property is not applicable.
  1936  	Deleted bool `json:"deleted"`
  1937  }
  1938  
  1939  func (s ICECandidateStats) statsMarker() {}
  1940  
  1941  func unmarshalICECandidateStats(b []byte) (ICECandidateStats, error) {
  1942  	var iceCandidateStats ICECandidateStats
  1943  	err := json.Unmarshal(b, &iceCandidateStats)
  1944  	if err != nil {
  1945  		return ICECandidateStats{}, fmt.Errorf("unmarshal ice candidate stats: %w", err)
  1946  	}
  1947  	return iceCandidateStats, nil
  1948  }
  1949  
  1950  // CertificateStats contains information about a certificate used by an ICETransport.
  1951  type CertificateStats struct {
  1952  	// Timestamp is the timestamp associated with this object.
  1953  	Timestamp StatsTimestamp `json:"timestamp"`
  1954  
  1955  	// Type is the object's StatsType
  1956  	Type StatsType `json:"type"`
  1957  
  1958  	// ID is a unique id that is associated with the component inspected to produce
  1959  	// this Stats object. Two Stats objects will have the same ID if they were produced
  1960  	// by inspecting the same underlying object.
  1961  	ID string `json:"id"`
  1962  
  1963  	// Fingerprint is the fingerprint of the certificate.
  1964  	Fingerprint string `json:"fingerprint"`
  1965  
  1966  	// FingerprintAlgorithm is the hash function used to compute the certificate fingerprint. For instance, "sha-256".
  1967  	FingerprintAlgorithm string `json:"fingerprintAlgorithm"`
  1968  
  1969  	// Base64Certificate is the DER-encoded base-64 representation of the certificate.
  1970  	Base64Certificate string `json:"base64Certificate"`
  1971  
  1972  	// IssuerCertificateID refers to the stats object that contains the next certificate
  1973  	// in the certificate chain. If the current certificate is at the end of the chain
  1974  	// (i.e. a self-signed certificate), this will not be set.
  1975  	IssuerCertificateID string `json:"issuerCertificateId"`
  1976  }
  1977  
  1978  func (s CertificateStats) statsMarker() {}
  1979  
  1980  func unmarshalCertificateStats(b []byte) (CertificateStats, error) {
  1981  	var certificateStats CertificateStats
  1982  	err := json.Unmarshal(b, &certificateStats)
  1983  	if err != nil {
  1984  		return CertificateStats{}, fmt.Errorf("unmarshal certificate stats: %w", err)
  1985  	}
  1986  	return certificateStats, nil
  1987  }
  1988  
  1989  // SCTPTransportStats contains information about a certificate used by an SCTPTransport.
  1990  type SCTPTransportStats struct {
  1991  	// Timestamp is the timestamp associated with this object.
  1992  	Timestamp StatsTimestamp `json:"timestamp"`
  1993  
  1994  	// Type is the object's StatsType
  1995  	Type StatsType `json:"type"`
  1996  
  1997  	// ID is a unique id that is associated with the component inspected to produce
  1998  	// this Stats object. Two Stats objects will have the same ID if they were produced
  1999  	// by inspecting the same underlying object.
  2000  	ID string `json:"id"`
  2001  
  2002  	// TransportID is the identifier of the object that was inspected to produce the
  2003  	// RTCTransportStats for the DTLSTransport and ICETransport supporting the SCTP transport.
  2004  	TransportID string `json:"transportId"`
  2005  
  2006  	// SmoothedRoundTripTime is the latest smoothed round-trip time value, corresponding to spinfo_srtt defined in [RFC6458]
  2007  	// but converted to seconds. If there has been no round-trip time measurements yet, this value is undefined.
  2008  	SmoothedRoundTripTime float64 `json:"smoothedRoundTripTime"`
  2009  
  2010  	// CongestionWindow is the latest congestion window, corresponding to spinfo_cwnd defined in [RFC6458].
  2011  	CongestionWindow uint32 `json:"congestionWindow"`
  2012  
  2013  	// ReceiverWindow is the latest receiver window, corresponding to sstat_rwnd defined in [RFC6458].
  2014  	ReceiverWindow uint32 `json:"receiverWindow"`
  2015  
  2016  	// MTU is the latest maximum transmission unit, corresponding to spinfo_mtu defined in [RFC6458].
  2017  	MTU uint32 `json:"mtu"`
  2018  
  2019  	// UNACKData is the number of unacknowledged DATA chunks, corresponding to sstat_unackdata defined in [RFC6458].
  2020  	UNACKData uint32 `json:"unackData"`
  2021  
  2022  	// BytesSent represents the total number of bytes sent on this SCTPTransport
  2023  	BytesSent uint64 `json:"bytesSent"`
  2024  
  2025  	// BytesReceived represents the total number of bytes received on this SCTPTransport
  2026  	BytesReceived uint64 `json:"bytesReceived"`
  2027  }
  2028  
  2029  func (s SCTPTransportStats) statsMarker() {}
  2030  
  2031  func unmarshalSCTPTransportStats(b []byte) (SCTPTransportStats, error) {
  2032  	var sctpTransportStats SCTPTransportStats
  2033  	if err := json.Unmarshal(b, &sctpTransportStats); err != nil {
  2034  		return SCTPTransportStats{}, fmt.Errorf("unmarshal sctp transport stats: %w", err)
  2035  	}
  2036  	return sctpTransportStats, nil
  2037  }