github.com/pion/webrtc/v4@v4.0.1/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/v4"
    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  	// Mid represents a mid value of RTPTransceiver owning this stream, if that value is not
   279  	// null. Otherwise, this member is not present.
   280  	Mid string `json:"mid"`
   281  
   282  	// Timestamp is the timestamp associated with this object.
   283  	Timestamp StatsTimestamp `json:"timestamp"`
   284  
   285  	// Type is the object's StatsType
   286  	Type StatsType `json:"type"`
   287  
   288  	// ID is a unique id that is associated with the component inspected to produce
   289  	// this Stats object. Two Stats objects will have the same ID if they were produced
   290  	// by inspecting the same underlying object.
   291  	ID string `json:"id"`
   292  
   293  	// SSRC is the 32-bit unsigned integer value used to identify the source of the
   294  	// stream of RTP packets that this stats object concerns.
   295  	SSRC SSRC `json:"ssrc"`
   296  
   297  	// Kind is either "audio" or "video"
   298  	Kind string `json:"kind"`
   299  
   300  	// It is a unique identifier that is associated to the object that was inspected
   301  	// to produce the TransportStats associated with this RTP stream.
   302  	TransportID string `json:"transportId"`
   303  
   304  	// CodecID is a unique identifier that is associated to the object that was inspected
   305  	// to produce the CodecStats associated with this RTP stream.
   306  	CodecID string `json:"codecId"`
   307  
   308  	// FIRCount counts the total number of Full Intra Request (FIR) packets received
   309  	// by the sender. This metric is only valid for video and is sent by receiver.
   310  	FIRCount uint32 `json:"firCount"`
   311  
   312  	// PLICount counts the total number of Picture Loss Indication (PLI) packets
   313  	// received by the sender. This metric is only valid for video and is sent by receiver.
   314  	PLICount uint32 `json:"pliCount"`
   315  
   316  	// TotalProcessingDelay is the sum of the time, in seconds, each audio sample or video frame
   317  	// takes from the time the first RTP packet is received (reception timestamp) and to the time
   318  	// the corresponding sample or frame is decoded (decoded timestamp). At this point the audio
   319  	// sample or video frame is ready for playout by the MediaStreamTrack. Typically ready for
   320  	// playout here means after the audio sample or video frame is fully decoded by the decoder.
   321  	TotalProcessingDelay float64 `json:"totalProcessingDelay"`
   322  
   323  	// NACKCount counts the total number of Negative ACKnowledgement (NACK) packets
   324  	// received by the sender and is sent by receiver.
   325  	NACKCount uint32 `json:"nackCount"`
   326  
   327  	// JitterBufferDelay is the sum of the time, in seconds, each audio sample or a video frame
   328  	// takes from the time the first packet is received by the jitter buffer (ingest timestamp)
   329  	// to the time it exits the jitter buffer (emit timestamp). The average jitter buffer delay
   330  	// can be calculated by dividing the JitterBufferDelay with the JitterBufferEmittedCount.
   331  	JitterBufferDelay float64 `json:"jitterBufferDelay"`
   332  
   333  	// JitterBufferTargetDelay is increased by the target jitter buffer delay every time a sample is emitted
   334  	// by the jitter buffer. The added target is the target delay, in seconds, at the time that
   335  	// the sample was emitted from the jitter buffer. To get the average target delay,
   336  	// divide by JitterBufferEmittedCount
   337  	JitterBufferTargetDelay float64 `json:"jitterBufferTargetDelay"`
   338  
   339  	// JitterBufferEmittedCount is the total number of audio samples or video frames that
   340  	// have come out of the jitter buffer (increasing jitterBufferDelay).
   341  	JitterBufferEmittedCount uint64 `json:"jitterBufferEmittedCount"`
   342  
   343  	// JitterBufferMinimumDelay works the same way as jitterBufferTargetDelay, except that
   344  	// it is not affected by external mechanisms that increase the jitter buffer target delay,
   345  	// such as  jitterBufferTarget, AV sync, or any other mechanisms. This metric is purely
   346  	// based on the network characteristics such as jitter and packet loss, and can be seen
   347  	// as the minimum obtainable jitter  buffer delay if no external factors would affect it.
   348  	// The metric is updated every time JitterBufferEmittedCount is updated.
   349  	JitterBufferMinimumDelay float64 `json:"jitterBufferMinimumDelay"`
   350  
   351  	// TotalSamplesReceived is the total number of samples that have been received on
   352  	// this RTP stream. This includes concealedSamples. Does not exist for video.
   353  	TotalSamplesReceived uint64 `json:"totalSamplesReceived"`
   354  
   355  	// ConcealedSamples is the total number of samples that are concealed samples.
   356  	// A concealed sample is a sample that was replaced with synthesized samples generated
   357  	// locally before being played out. Examples of samples that have to be concealed are
   358  	// samples from lost packets (reported in packetsLost) or samples from packets that
   359  	// arrive too late to be played out (reported in packetsDiscarded). Does not exist for video.
   360  	ConcealedSamples uint64 `json:"concealedSamples"`
   361  
   362  	// SilentConcealedSamples is the total number of concealed samples inserted that
   363  	// are "silent". Playing out silent samples results in silence or comfort noise.
   364  	// This is a subset of concealedSamples. Does not exist for video.
   365  	SilentConcealedSamples uint64 `json:"silentConcealedSamples"`
   366  
   367  	// ConcealmentEvents increases every time a concealed sample is synthesized after
   368  	// a non-concealed sample. That is, multiple consecutive concealed samples will increase
   369  	// the concealedSamples count multiple times but is a single concealment event.
   370  	// Does not exist for video.
   371  	ConcealmentEvents uint64 `json:"concealmentEvents"`
   372  
   373  	// InsertedSamplesForDeceleration is increased by the difference between the number of
   374  	// samples received and the number of samples played out when playout is slowed down.
   375  	// If playout is slowed down by inserting samples, this will be the number of inserted samples.
   376  	// Does not exist for video.
   377  	InsertedSamplesForDeceleration uint64 `json:"insertedSamplesForDeceleration"`
   378  
   379  	// RemovedSamplesForAcceleration is increased by the difference between the number of
   380  	// samples received and the number of samples played out when playout is sped up. If speedup
   381  	// is achieved by removing samples, this will be the count of samples removed.
   382  	// Does not exist for video.
   383  	RemovedSamplesForAcceleration uint64 `json:"removedSamplesForAcceleration"`
   384  
   385  	// AudioLevel represents the audio level of the receiving track..
   386  	//
   387  	// The value is a value between 0..1 (linear), where 1.0 represents 0 dBov,
   388  	// 0 represents silence, and 0.5 represents approximately 6 dBSPL change in
   389  	// the sound pressure level from 0 dBov. Does not exist for video.
   390  	AudioLevel float64 `json:"audioLevel"`
   391  
   392  	// TotalAudioEnergy represents the audio energy of the receiving track. It is calculated
   393  	// by duration * Math.pow(energy/maxEnergy, 2) for each audio sample received (and thus
   394  	// counted by TotalSamplesReceived). Does not exist for video.
   395  	TotalAudioEnergy float64 `json:"totalAudioEnergy"`
   396  
   397  	// TotalSamplesDuration represents the total duration in seconds of all samples that have been
   398  	// received (and thus counted by TotalSamplesReceived). Can be used with totalAudioEnergy to
   399  	// compute an average audio level over different intervals. Does not exist for video.
   400  	TotalSamplesDuration float64 `json:"totalSamplesDuration"`
   401  
   402  	// SLICount counts the total number of Slice Loss Indication (SLI) packets received
   403  	// by the sender. This metric is only valid for video and is sent by receiver.
   404  	SLICount uint32 `json:"sliCount"`
   405  
   406  	// QPSum is the sum of the QP values of frames passed. The count of frames is
   407  	// in FramesDecoded for inbound stream stats, and in FramesEncoded for outbound stream stats.
   408  	QPSum uint64 `json:"qpSum"`
   409  
   410  	// TotalDecodeTime is the total number of seconds that have been spent decoding the FramesDecoded
   411  	// frames of this stream. The average decode time can be calculated by dividing this value
   412  	// with FramesDecoded. The time it takes to decode one frame is the time passed between
   413  	// feeding the decoder a frame and the decoder returning decoded data for that frame.
   414  	TotalDecodeTime float64 `json:"totalDecodeTime"`
   415  
   416  	// TotalInterFrameDelay is the sum of the interframe delays in seconds between consecutively
   417  	// rendered frames, recorded just after a frame has been rendered. The interframe delay variance
   418  	// be calculated from TotalInterFrameDelay, TotalSquaredInterFrameDelay, and FramesRendered according
   419  	// to the formula: (TotalSquaredInterFrameDelay - TotalInterFrameDelay^2 / FramesRendered) / FramesRendered.
   420  	// Does not exist for audio.
   421  	TotalInterFrameDelay float64 `json:"totalInterFrameDelay"`
   422  
   423  	// TotalSquaredInterFrameDelay is the sum of the squared interframe delays in seconds
   424  	// between consecutively rendered frames, recorded just after a frame has been rendered.
   425  	// See TotalInterFrameDelay for details on how to calculate the interframe delay variance.
   426  	// Does not exist for audio.
   427  	TotalSquaredInterFrameDelay float64 `json:"totalSquaredInterFrameDelay"`
   428  
   429  	// PacketsReceived is the total number of RTP packets received for this SSRC.
   430  	PacketsReceived uint32 `json:"packetsReceived"`
   431  
   432  	// PacketsLost is the total number of RTP packets lost for this SSRC. Note that
   433  	// because of how this is estimated, it can be negative if more packets are received than sent.
   434  	PacketsLost int32 `json:"packetsLost"`
   435  
   436  	// Jitter is the packet jitter measured in seconds for this SSRC
   437  	Jitter float64 `json:"jitter"`
   438  
   439  	// PacketsDiscarded is the cumulative number of RTP packets discarded by the jitter
   440  	// buffer due to late or early-arrival, i.e., these packets are not played out.
   441  	// RTP packets discarded due to packet duplication are not reported in this metric.
   442  	PacketsDiscarded uint32 `json:"packetsDiscarded"`
   443  
   444  	// PacketsRepaired is the cumulative number of lost RTP packets repaired after applying
   445  	// an error-resilience mechanism. It is measured for the primary source RTP packets
   446  	// and only counted for RTP packets that have no further chance of repair.
   447  	PacketsRepaired uint32 `json:"packetsRepaired"`
   448  
   449  	// BurstPacketsLost is the cumulative number of RTP packets lost during loss bursts.
   450  	BurstPacketsLost uint32 `json:"burstPacketsLost"`
   451  
   452  	// BurstPacketsDiscarded is the cumulative number of RTP packets discarded during discard bursts.
   453  	BurstPacketsDiscarded uint32 `json:"burstPacketsDiscarded"`
   454  
   455  	// BurstLossCount is the cumulative number of bursts of lost RTP packets.
   456  	BurstLossCount uint32 `json:"burstLossCount"`
   457  
   458  	// BurstDiscardCount is the cumulative number of bursts of discarded RTP packets.
   459  	BurstDiscardCount uint32 `json:"burstDiscardCount"`
   460  
   461  	// BurstLossRate is the fraction of RTP packets lost during bursts to the
   462  	// total number of RTP packets expected in the bursts.
   463  	BurstLossRate float64 `json:"burstLossRate"`
   464  
   465  	// BurstDiscardRate is the fraction of RTP packets discarded during bursts to
   466  	// the total number of RTP packets expected in bursts.
   467  	BurstDiscardRate float64 `json:"burstDiscardRate"`
   468  
   469  	// GapLossRate is the fraction of RTP packets lost during the gap periods.
   470  	GapLossRate float64 `json:"gapLossRate"`
   471  
   472  	// GapDiscardRate is the fraction of RTP packets discarded during the gap periods.
   473  	GapDiscardRate float64 `json:"gapDiscardRate"`
   474  
   475  	// TrackID is the identifier of the stats object representing the receiving track,
   476  	// a ReceiverAudioTrackAttachmentStats or ReceiverVideoTrackAttachmentStats.
   477  	TrackID string `json:"trackId"`
   478  
   479  	// ReceiverID is the stats ID used to look up the AudioReceiverStats or VideoReceiverStats
   480  	// object receiving this stream.
   481  	ReceiverID string `json:"receiverId"`
   482  
   483  	// RemoteID is used for looking up the remote RemoteOutboundRTPStreamStats object
   484  	// for the same SSRC.
   485  	RemoteID string `json:"remoteId"`
   486  
   487  	// FramesDecoded represents the total number of frames correctly decoded for this SSRC,
   488  	// i.e., frames that would be displayed if no frames are dropped. Only valid for video.
   489  	FramesDecoded uint32 `json:"framesDecoded"`
   490  
   491  	// KeyFramesDecoded represents the total number of key frames, such as key frames in
   492  	// VP8 [RFC6386] or IDR-frames in H.264 [RFC6184], successfully decoded for this RTP
   493  	// media stream. This is a subset of FramesDecoded. FramesDecoded - KeyFramesDecoded
   494  	// gives you the number of delta frames decoded. Does not exist for audio.
   495  	KeyFramesDecoded uint32 `json:"keyFramesDecoded"`
   496  
   497  	// FramesRendered represents the total number of frames that have been rendered.
   498  	// It is incremented just after a frame has been rendered. Does not exist for audio.
   499  	FramesRendered uint32 `json:"framesRendered"`
   500  
   501  	// FramesDropped is the total number of frames dropped prior to decode or dropped
   502  	// because the frame missed its display deadline for this receiver's track.
   503  	// The measurement begins when the receiver is created and is a cumulative metric
   504  	// as defined in Appendix A (g) of [RFC7004]. Does not exist for audio.
   505  	FramesDropped uint32 `json:"framesDropped"`
   506  
   507  	// FrameWidth represents the width of the last decoded frame. Before the first
   508  	// frame is decoded this member does not exist. Does not exist for audio.
   509  	FrameWidth uint32 `json:"frameWidth"`
   510  
   511  	// FrameHeight represents the height of the last decoded frame. Before the first
   512  	// frame is decoded this member does not exist. Does not exist for audio.
   513  	FrameHeight uint32 `json:"frameHeight"`
   514  
   515  	// LastPacketReceivedTimestamp represents the timestamp at which the last packet was
   516  	// received for this SSRC. This differs from Timestamp, which represents the time
   517  	// at which the statistics were generated by the local endpoint.
   518  	LastPacketReceivedTimestamp StatsTimestamp `json:"lastPacketReceivedTimestamp"`
   519  
   520  	// HeaderBytesReceived is the total number of RTP header and padding bytes received for this SSRC.
   521  	// This includes retransmissions. This does not include the size of transport layer headers such
   522  	// as IP or UDP. headerBytesReceived + bytesReceived equals the number of bytes received as
   523  	// payload over the transport.
   524  	HeaderBytesReceived uint64 `json:"headerBytesReceived"`
   525  
   526  	// AverageRTCPInterval is the average RTCP interval between two consecutive compound RTCP packets.
   527  	// This is calculated by the sending endpoint when sending compound RTCP reports.
   528  	// Compound packets must contain at least a RTCP RR or SR packet and an SDES packet
   529  	// with the CNAME item.
   530  	AverageRTCPInterval float64 `json:"averageRtcpInterval"`
   531  
   532  	// FECPacketsReceived is the total number of RTP FEC packets received for this SSRC.
   533  	// This counter can also be incremented when receiving FEC packets in-band with media packets (e.g., with Opus).
   534  	FECPacketsReceived uint32 `json:"fecPacketsReceived"`
   535  
   536  	// FECPacketsDiscarded is the total number of RTP FEC packets received for this SSRC where the
   537  	// error correction payload was discarded by the application. This may happen
   538  	// 1. if all the source packets protected by the FEC packet were received or already
   539  	// recovered by a separate FEC packet, or
   540  	// 2. if the FEC packet arrived late, i.e., outside the recovery window, and the
   541  	// lost RTP packets have already been skipped during playout.
   542  	// This is a subset of FECPacketsReceived.
   543  	FECPacketsDiscarded uint64 `json:"fecPacketsDiscarded"`
   544  
   545  	// BytesReceived is the total number of bytes received for this SSRC.
   546  	BytesReceived uint64 `json:"bytesReceived"`
   547  
   548  	// FramesReceived represents the total number of complete frames received on this RTP stream.
   549  	// This metric is incremented when the complete frame is received. Does not exist for audio.
   550  	FramesReceived uint32 `json:"framesReceived"`
   551  
   552  	// PacketsFailedDecryption is the cumulative number of RTP packets that failed
   553  	// to be decrypted. These packets are not counted by PacketsDiscarded.
   554  	PacketsFailedDecryption uint32 `json:"packetsFailedDecryption"`
   555  
   556  	// PacketsDuplicated is the cumulative number of packets discarded because they
   557  	// are duplicated. Duplicate packets are not counted in PacketsDiscarded.
   558  	//
   559  	// Duplicated packets have the same RTP sequence number and content as a previously
   560  	// received packet. If multiple duplicates of a packet are received, all of them are counted.
   561  	// An improved estimate of lost packets can be calculated by adding PacketsDuplicated to PacketsLost.
   562  	PacketsDuplicated uint32 `json:"packetsDuplicated"`
   563  
   564  	// PerDSCPPacketsReceived is the total number of packets received for this SSRC,
   565  	// per Differentiated Services code point (DSCP) [RFC2474]. DSCPs are identified
   566  	// as decimal integers in string form. Note that due to network remapping and bleaching,
   567  	// these numbers are not expected to match the numbers seen on sending. Not all
   568  	// OSes make this information available.
   569  	PerDSCPPacketsReceived map[string]uint32 `json:"perDscpPacketsReceived"`
   570  }
   571  
   572  func (s InboundRTPStreamStats) statsMarker() {}
   573  
   574  func unmarshalInboundRTPStreamStats(b []byte) (InboundRTPStreamStats, error) {
   575  	var inboundRTPStreamStats InboundRTPStreamStats
   576  	err := json.Unmarshal(b, &inboundRTPStreamStats)
   577  	if err != nil {
   578  		return InboundRTPStreamStats{}, fmt.Errorf("unmarshal inbound rtp stream stats: %w", err)
   579  	}
   580  	return inboundRTPStreamStats, nil
   581  }
   582  
   583  // QualityLimitationReason lists the reason for limiting the resolution and/or framerate.
   584  // Only valid for video.
   585  type QualityLimitationReason string
   586  
   587  const (
   588  	// QualityLimitationReasonNone means the resolution and/or framerate is not limited.
   589  	QualityLimitationReasonNone QualityLimitationReason = "none"
   590  
   591  	// QualityLimitationReasonCPU means the resolution and/or framerate is primarily limited due to CPU load.
   592  	QualityLimitationReasonCPU QualityLimitationReason = "cpu"
   593  
   594  	// 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.
   595  	QualityLimitationReasonBandwidth QualityLimitationReason = "bandwidth"
   596  
   597  	// QualityLimitationReasonOther means the resolution and/or framerate is primarily limited for a reason other than the above.
   598  	QualityLimitationReasonOther QualityLimitationReason = "other"
   599  )
   600  
   601  // OutboundRTPStreamStats contains statistics for an outbound RTP stream that is
   602  // currently sent with this PeerConnection object.
   603  type OutboundRTPStreamStats struct {
   604  	// Mid represents a mid value of RTPTransceiver owning this stream, if that value is not
   605  	// null. Otherwise, this member is not present.
   606  	Mid string `json:"mid"`
   607  
   608  	// Rid only exists if a rid has been set for this RTP stream.
   609  	// Must not exist for audio.
   610  	Rid string `json:"rid"`
   611  
   612  	// MediaSourceID is the identifier of the stats object representing the track currently
   613  	// attached to the sender of this stream, an RTCMediaSourceStats.
   614  	MediaSourceID string `json:"mediaSourceId"`
   615  
   616  	// Timestamp is the timestamp associated with this object.
   617  	Timestamp StatsTimestamp `json:"timestamp"`
   618  
   619  	// Type is the object's StatsType
   620  	Type StatsType `json:"type"`
   621  
   622  	// ID is a unique id that is associated with the component inspected to produce
   623  	// this Stats object. Two Stats objects will have the same ID if they were produced
   624  	// by inspecting the same underlying object.
   625  	ID string `json:"id"`
   626  
   627  	// SSRC is the 32-bit unsigned integer value used to identify the source of the
   628  	// stream of RTP packets that this stats object concerns.
   629  	SSRC SSRC `json:"ssrc"`
   630  
   631  	// Kind is either "audio" or "video"
   632  	Kind string `json:"kind"`
   633  
   634  	// It is a unique identifier that is associated to the object that was inspected
   635  	// to produce the TransportStats associated with this RTP stream.
   636  	TransportID string `json:"transportId"`
   637  
   638  	// CodecID is a unique identifier that is associated to the object that was inspected
   639  	// to produce the CodecStats associated with this RTP stream.
   640  	CodecID string `json:"codecId"`
   641  
   642  	// HeaderBytesSent is the total number of RTP header and padding bytes sent for this SSRC. This does not
   643  	// include the size of transport layer headers such as IP or UDP.
   644  	// HeaderBytesSent + BytesSent equals the number of bytes sent as payload over the transport.
   645  	HeaderBytesSent uint64 `json:"headerBytesSent"`
   646  
   647  	// RetransmittedPacketsSent is the total number of packets that were retransmitted for this SSRC.
   648  	// This is a subset of packetsSent. If RTX is not negotiated, retransmitted packets are sent
   649  	// over this ssrc. If RTX was negotiated, retransmitted packets are sent over a separate SSRC
   650  	// but is still accounted for here.
   651  	RetransmittedPacketsSent uint64 `json:"retransmittedPacketsSent"`
   652  
   653  	// RetransmittedBytesSent is the total number of bytes that were retransmitted for this SSRC,
   654  	// only including payload bytes. This is a subset of bytesSent. If RTX is not negotiated,
   655  	// retransmitted bytes are sent over this ssrc. If RTX was negotiated, retransmitted bytes
   656  	// are sent over a separate SSRC but is still accounted for here.
   657  	RetransmittedBytesSent uint64 `json:"retransmittedBytesSent"`
   658  
   659  	// FIRCount counts the total number of Full Intra Request (FIR) packets received
   660  	// by the sender. This metric is only valid for video and is sent by receiver.
   661  	FIRCount uint32 `json:"firCount"`
   662  
   663  	// PLICount counts the total number of Picture Loss Indication (PLI) packets
   664  	// received by the sender. This metric is only valid for video and is sent by receiver.
   665  	PLICount uint32 `json:"pliCount"`
   666  
   667  	// NACKCount counts the total number of Negative ACKnowledgement (NACK) packets
   668  	// received by the sender and is sent by receiver.
   669  	NACKCount uint32 `json:"nackCount"`
   670  
   671  	// SLICount counts the total number of Slice Loss Indication (SLI) packets received
   672  	// by the sender. This metric is only valid for video and is sent by receiver.
   673  	SLICount uint32 `json:"sliCount"`
   674  
   675  	// QPSum is the sum of the QP values of frames passed. The count of frames is
   676  	// in FramesDecoded for inbound stream stats, and in FramesEncoded for outbound stream stats.
   677  	QPSum uint64 `json:"qpSum"`
   678  
   679  	// PacketsSent is the total number of RTP packets sent for this SSRC.
   680  	PacketsSent uint32 `json:"packetsSent"`
   681  
   682  	// PacketsDiscardedOnSend is the total number of RTP packets for this SSRC that
   683  	// have been discarded due to socket errors, i.e. a socket error occurred when handing
   684  	// the packets to the socket. This might happen due to various reasons, including
   685  	// full buffer or no available memory.
   686  	PacketsDiscardedOnSend uint32 `json:"packetsDiscardedOnSend"`
   687  
   688  	// FECPacketsSent is the total number of RTP FEC packets sent for this SSRC.
   689  	// This counter can also be incremented when sending FEC packets in-band with
   690  	// media packets (e.g., with Opus).
   691  	FECPacketsSent uint32 `json:"fecPacketsSent"`
   692  
   693  	// BytesSent is the total number of bytes sent for this SSRC.
   694  	BytesSent uint64 `json:"bytesSent"`
   695  
   696  	// BytesDiscardedOnSend is the total number of bytes for this SSRC that have
   697  	// been discarded due to socket errors, i.e. a socket error occurred when handing
   698  	// the packets containing the bytes to the socket. This might happen due to various
   699  	// reasons, including full buffer or no available memory.
   700  	BytesDiscardedOnSend uint64 `json:"bytesDiscardedOnSend"`
   701  
   702  	// TrackID is the identifier of the stats object representing the current track
   703  	// attachment to the sender of this stream, a SenderAudioTrackAttachmentStats
   704  	// or SenderVideoTrackAttachmentStats.
   705  	TrackID string `json:"trackId"`
   706  
   707  	// SenderID is the stats ID used to look up the AudioSenderStats or VideoSenderStats
   708  	// object sending this stream.
   709  	SenderID string `json:"senderId"`
   710  
   711  	// RemoteID is used for looking up the remote RemoteInboundRTPStreamStats object
   712  	// for the same SSRC.
   713  	RemoteID string `json:"remoteId"`
   714  
   715  	// LastPacketSentTimestamp represents the timestamp at which the last packet was
   716  	// sent for this SSRC. This differs from timestamp, which represents the time at
   717  	// which the statistics were generated by the local endpoint.
   718  	LastPacketSentTimestamp StatsTimestamp `json:"lastPacketSentTimestamp"`
   719  
   720  	// TargetBitrate is the current target bitrate configured for this particular SSRC
   721  	// and is the Transport Independent Application Specific (TIAS) bitrate [RFC3890].
   722  	// Typically, the target bitrate is a configuration parameter provided to the codec's
   723  	// encoder and does not count the size of the IP or other transport layers like TCP or UDP.
   724  	// It is measured in bits per second and the bitrate is calculated over a 1 second window.
   725  	TargetBitrate float64 `json:"targetBitrate"`
   726  
   727  	// TotalEncodedBytesTarget is increased by the target frame size in bytes every time
   728  	// a frame has been encoded. The actual frame size may be bigger or smaller than this number.
   729  	// This value goes up every time framesEncoded goes up.
   730  	TotalEncodedBytesTarget uint64 `json:"totalEncodedBytesTarget"`
   731  
   732  	// FrameWidth represents the width of the last encoded frame. The resolution of the
   733  	// encoded frame may be lower than the media source. Before the first frame is encoded
   734  	// this member does not exist. Does not exist for audio.
   735  	FrameWidth uint32 `json:"frameWidth"`
   736  
   737  	// FrameHeight represents the height of the last encoded frame. The resolution of the
   738  	// encoded frame may be lower than the media source. Before the first frame is encoded
   739  	// this member does not exist. Does not exist for audio.
   740  	FrameHeight uint32 `json:"frameHeight"`
   741  
   742  	// FramesPerSecond is the number of encoded frames during the last second. This may be
   743  	// lower than the media source frame rate. Does not exist for audio.
   744  	FramesPerSecond float64 `json:"framesPerSecond"`
   745  
   746  	// FramesSent represents the total number of frames sent on this RTP stream. Does not exist for audio.
   747  	FramesSent uint32 `json:"framesSent"`
   748  
   749  	// HugeFramesSent represents the total number of huge frames sent by this RTP stream.
   750  	// Huge frames, by definition, are frames that have an encoded size at least 2.5 times
   751  	// the average size of the frames. The average size of the frames is defined as the
   752  	// target bitrate per second divided by the target FPS at the time the frame was encoded.
   753  	// These are usually complex to encode frames with a lot of changes in the picture.
   754  	// This can be used to estimate, e.g slide changes in the streamed presentation.
   755  	// Does not exist for audio.
   756  	HugeFramesSent uint32 `json:"hugeFramesSent"`
   757  
   758  	// FramesEncoded represents the total number of frames successfully encoded for this RTP media stream.
   759  	// Only valid for video.
   760  	FramesEncoded uint32 `json:"framesEncoded"`
   761  
   762  	// KeyFramesEncoded represents the total number of key frames, such as key frames in VP8 [RFC6386] or
   763  	// IDR-frames in H.264 [RFC6184], successfully encoded for this RTP media stream. This is a subset of
   764  	// FramesEncoded. FramesEncoded - KeyFramesEncoded gives you the number of delta frames encoded.
   765  	// Does not exist for audio.
   766  	KeyFramesEncoded uint32 `json:"keyFramesEncoded"`
   767  
   768  	// TotalEncodeTime is the total number of seconds that has been spent encoding the
   769  	// framesEncoded frames of this stream. The average encode time can be calculated by
   770  	// dividing this value with FramesEncoded. The time it takes to encode one frame is the
   771  	// time passed between feeding the encoder a frame and the encoder returning encoded data
   772  	// for that frame. This does not include any additional time it may take to packetize the resulting data.
   773  	TotalEncodeTime float64 `json:"totalEncodeTime"`
   774  
   775  	// TotalPacketSendDelay is the total number of seconds that packets have spent buffered
   776  	// locally before being transmitted onto the network. The time is measured from when
   777  	// a packet is emitted from the RTP packetizer until it is handed over to the OS network socket.
   778  	// This measurement is added to totalPacketSendDelay when packetsSent is incremented.
   779  	TotalPacketSendDelay float64 `json:"totalPacketSendDelay"`
   780  
   781  	// AverageRTCPInterval is the average RTCP interval between two consecutive compound RTCP
   782  	// packets. This is calculated by the sending endpoint when sending compound RTCP reports.
   783  	// Compound packets must contain at least a RTCP RR or SR packet and an SDES packet with the CNAME item.
   784  	AverageRTCPInterval float64 `json:"averageRtcpInterval"`
   785  
   786  	// QualityLimitationReason is the current reason for limiting the resolution and/or framerate,
   787  	// or "none" if not limited. Only valid for video.
   788  	QualityLimitationReason QualityLimitationReason `json:"qualityLimitationReason"`
   789  
   790  	// QualityLimitationDurations is record of the total time, in seconds, that this
   791  	// stream has spent in each quality limitation state. The record includes a mapping
   792  	// for all QualityLimitationReason types, including "none". Only valid for video.
   793  	QualityLimitationDurations map[string]float64 `json:"qualityLimitationDurations"`
   794  
   795  	// QualityLimitationResolutionChanges is the number of times that the resolution has changed
   796  	// because we are quality limited (qualityLimitationReason has a value other than "none").
   797  	// The counter is initially zero and increases when the resolution goes up or down.
   798  	// For example, if a 720p track is sent as 480p for some time and then recovers to 720p,
   799  	// qualityLimitationResolutionChanges will have the value 2. Does not exist for audio.
   800  	QualityLimitationResolutionChanges uint32 `json:"qualityLimitationResolutionChanges"`
   801  
   802  	// PerDSCPPacketsSent is the total number of packets sent for this SSRC, per DSCP.
   803  	// DSCPs are identified as decimal integers in string form.
   804  	PerDSCPPacketsSent map[string]uint32 `json:"perDscpPacketsSent"`
   805  
   806  	// Active indicates whether this RTP stream is configured to be sent or disabled. Note that an
   807  	// active stream can still not be sending, e.g. when being limited by network conditions.
   808  	Active bool `json:"active"`
   809  }
   810  
   811  func (s OutboundRTPStreamStats) statsMarker() {}
   812  
   813  func unmarshalOutboundRTPStreamStats(b []byte) (OutboundRTPStreamStats, error) {
   814  	var outboundRTPStreamStats OutboundRTPStreamStats
   815  	err := json.Unmarshal(b, &outboundRTPStreamStats)
   816  	if err != nil {
   817  		return OutboundRTPStreamStats{}, fmt.Errorf("unmarshal outbound rtp stream stats: %w", err)
   818  	}
   819  	return outboundRTPStreamStats, nil
   820  }
   821  
   822  // RemoteInboundRTPStreamStats contains statistics for the remote endpoint's inbound
   823  // RTP stream corresponding to an outbound stream that is currently sent with this
   824  // PeerConnection object. It is measured at the remote endpoint and reported in an RTCP
   825  // Receiver Report (RR) or RTCP Extended Report (XR).
   826  type RemoteInboundRTPStreamStats struct {
   827  	// Timestamp is the timestamp associated with this object.
   828  	Timestamp StatsTimestamp `json:"timestamp"`
   829  
   830  	// Type is the object's StatsType
   831  	Type StatsType `json:"type"`
   832  
   833  	// ID is a unique id that is associated with the component inspected to produce
   834  	// this Stats object. Two Stats objects will have the same ID if they were produced
   835  	// by inspecting the same underlying object.
   836  	ID string `json:"id"`
   837  
   838  	// SSRC is the 32-bit unsigned integer value used to identify the source of the
   839  	// stream of RTP packets that this stats object concerns.
   840  	SSRC SSRC `json:"ssrc"`
   841  
   842  	// Kind is either "audio" or "video"
   843  	Kind string `json:"kind"`
   844  
   845  	// It is a unique identifier that is associated to the object that was inspected
   846  	// to produce the TransportStats associated with this RTP stream.
   847  	TransportID string `json:"transportId"`
   848  
   849  	// CodecID is a unique identifier that is associated to the object that was inspected
   850  	// to produce the CodecStats associated with this RTP stream.
   851  	CodecID string `json:"codecId"`
   852  
   853  	// FIRCount counts the total number of Full Intra Request (FIR) packets received
   854  	// by the sender. This metric is only valid for video and is sent by receiver.
   855  	FIRCount uint32 `json:"firCount"`
   856  
   857  	// PLICount counts the total number of Picture Loss Indication (PLI) packets
   858  	// received by the sender. This metric is only valid for video and is sent by receiver.
   859  	PLICount uint32 `json:"pliCount"`
   860  
   861  	// NACKCount counts the total number of Negative ACKnowledgement (NACK) packets
   862  	// received by the sender and is sent by receiver.
   863  	NACKCount uint32 `json:"nackCount"`
   864  
   865  	// SLICount counts the total number of Slice Loss Indication (SLI) packets received
   866  	// by the sender. This metric is only valid for video and is sent by receiver.
   867  	SLICount uint32 `json:"sliCount"`
   868  
   869  	// QPSum is the sum of the QP values of frames passed. The count of frames is
   870  	// in FramesDecoded for inbound stream stats, and in FramesEncoded for outbound stream stats.
   871  	QPSum uint64 `json:"qpSum"`
   872  
   873  	// PacketsReceived is the total number of RTP packets received for this SSRC.
   874  	PacketsReceived uint32 `json:"packetsReceived"`
   875  
   876  	// PacketsLost is the total number of RTP packets lost for this SSRC. Note that
   877  	// because of how this is estimated, it can be negative if more packets are received than sent.
   878  	PacketsLost int32 `json:"packetsLost"`
   879  
   880  	// Jitter is the packet jitter measured in seconds for this SSRC
   881  	Jitter float64 `json:"jitter"`
   882  
   883  	// PacketsDiscarded is the cumulative number of RTP packets discarded by the jitter
   884  	// buffer due to late or early-arrival, i.e., these packets are not played out.
   885  	// RTP packets discarded due to packet duplication are not reported in this metric.
   886  	PacketsDiscarded uint32 `json:"packetsDiscarded"`
   887  
   888  	// PacketsRepaired is the cumulative number of lost RTP packets repaired after applying
   889  	// an error-resilience mechanism. It is measured for the primary source RTP packets
   890  	// and only counted for RTP packets that have no further chance of repair.
   891  	PacketsRepaired uint32 `json:"packetsRepaired"`
   892  
   893  	// BurstPacketsLost is the cumulative number of RTP packets lost during loss bursts.
   894  	BurstPacketsLost uint32 `json:"burstPacketsLost"`
   895  
   896  	// BurstPacketsDiscarded is the cumulative number of RTP packets discarded during discard bursts.
   897  	BurstPacketsDiscarded uint32 `json:"burstPacketsDiscarded"`
   898  
   899  	// BurstLossCount is the cumulative number of bursts of lost RTP packets.
   900  	BurstLossCount uint32 `json:"burstLossCount"`
   901  
   902  	// BurstDiscardCount is the cumulative number of bursts of discarded RTP packets.
   903  	BurstDiscardCount uint32 `json:"burstDiscardCount"`
   904  
   905  	// BurstLossRate is the fraction of RTP packets lost during bursts to the
   906  	// total number of RTP packets expected in the bursts.
   907  	BurstLossRate float64 `json:"burstLossRate"`
   908  
   909  	// BurstDiscardRate is the fraction of RTP packets discarded during bursts to
   910  	// the total number of RTP packets expected in bursts.
   911  	BurstDiscardRate float64 `json:"burstDiscardRate"`
   912  
   913  	// GapLossRate is the fraction of RTP packets lost during the gap periods.
   914  	GapLossRate float64 `json:"gapLossRate"`
   915  
   916  	// GapDiscardRate is the fraction of RTP packets discarded during the gap periods.
   917  	GapDiscardRate float64 `json:"gapDiscardRate"`
   918  
   919  	// LocalID is used for looking up the local OutboundRTPStreamStats object for the same SSRC.
   920  	LocalID string `json:"localId"`
   921  
   922  	// RoundTripTime is the estimated round trip time for this SSRC based on the
   923  	// RTCP timestamps in the RTCP Receiver Report (RR) and measured in seconds.
   924  	RoundTripTime float64 `json:"roundTripTime"`
   925  
   926  	// TotalRoundTripTime represents the cumulative sum of all round trip time measurements
   927  	// in seconds since the beginning of the session. The individual round trip time is calculated
   928  	// based on the RTCP timestamps in the RTCP Receiver Report (RR) [RFC3550], hence requires
   929  	// a DLSR value other than 0. The average round trip time can be computed from
   930  	// TotalRoundTripTime by dividing it by RoundTripTimeMeasurements.
   931  	TotalRoundTripTime float64 `json:"totalRoundTripTime"`
   932  
   933  	// FractionLost is the fraction packet loss reported for this SSRC.
   934  	FractionLost float64 `json:"fractionLost"`
   935  
   936  	// RoundTripTimeMeasurements represents the total number of RTCP RR blocks received for this SSRC
   937  	// that contain a valid round trip time. This counter will not increment if the RoundTripTime can
   938  	// not be calculated because no RTCP Receiver Report with a DLSR value other than 0 has been received.
   939  	RoundTripTimeMeasurements uint64 `json:"roundTripTimeMeasurements"`
   940  }
   941  
   942  func (s RemoteInboundRTPStreamStats) statsMarker() {}
   943  
   944  func unmarshalRemoteInboundRTPStreamStats(b []byte) (RemoteInboundRTPStreamStats, error) {
   945  	var remoteInboundRTPStreamStats RemoteInboundRTPStreamStats
   946  	err := json.Unmarshal(b, &remoteInboundRTPStreamStats)
   947  	if err != nil {
   948  		return RemoteInboundRTPStreamStats{}, fmt.Errorf("unmarshal remote inbound rtp stream stats: %w", err)
   949  	}
   950  	return remoteInboundRTPStreamStats, nil
   951  }
   952  
   953  // RemoteOutboundRTPStreamStats contains statistics for the remote endpoint's outbound
   954  // RTP stream corresponding to an inbound stream that is currently received with this
   955  // PeerConnection object. It is measured at the remote endpoint and reported in an
   956  // RTCP Sender Report (SR).
   957  type RemoteOutboundRTPStreamStats struct {
   958  	// Timestamp is the timestamp associated with this object.
   959  	Timestamp StatsTimestamp `json:"timestamp"`
   960  
   961  	// Type is the object's StatsType
   962  	Type StatsType `json:"type"`
   963  
   964  	// ID is a unique id that is associated with the component inspected to produce
   965  	// this Stats object. Two Stats objects will have the same ID if they were produced
   966  	// by inspecting the same underlying object.
   967  	ID string `json:"id"`
   968  
   969  	// SSRC is the 32-bit unsigned integer value used to identify the source of the
   970  	// stream of RTP packets that this stats object concerns.
   971  	SSRC SSRC `json:"ssrc"`
   972  
   973  	// Kind is either "audio" or "video"
   974  	Kind string `json:"kind"`
   975  
   976  	// It is a unique identifier that is associated to the object that was inspected
   977  	// to produce the TransportStats associated with this RTP stream.
   978  	TransportID string `json:"transportId"`
   979  
   980  	// CodecID is a unique identifier that is associated to the object that was inspected
   981  	// to produce the CodecStats associated with this RTP stream.
   982  	CodecID string `json:"codecId"`
   983  
   984  	// FIRCount counts the total number of Full Intra Request (FIR) packets received
   985  	// by the sender. This metric is only valid for video and is sent by receiver.
   986  	FIRCount uint32 `json:"firCount"`
   987  
   988  	// PLICount counts the total number of Picture Loss Indication (PLI) packets
   989  	// received by the sender. This metric is only valid for video and is sent by receiver.
   990  	PLICount uint32 `json:"pliCount"`
   991  
   992  	// NACKCount counts the total number of Negative ACKnowledgement (NACK) packets
   993  	// received by the sender and is sent by receiver.
   994  	NACKCount uint32 `json:"nackCount"`
   995  
   996  	// SLICount counts the total number of Slice Loss Indication (SLI) packets received
   997  	// by the sender. This metric is only valid for video and is sent by receiver.
   998  	SLICount uint32 `json:"sliCount"`
   999  
  1000  	// QPSum is the sum of the QP values of frames passed. The count of frames is
  1001  	// in FramesDecoded for inbound stream stats, and in FramesEncoded for outbound stream stats.
  1002  	QPSum uint64 `json:"qpSum"`
  1003  
  1004  	// PacketsSent is the total number of RTP packets sent for this SSRC.
  1005  	PacketsSent uint32 `json:"packetsSent"`
  1006  
  1007  	// PacketsDiscardedOnSend is the total number of RTP packets for this SSRC that
  1008  	// have been discarded due to socket errors, i.e. a socket error occurred when handing
  1009  	// the packets to the socket. This might happen due to various reasons, including
  1010  	// full buffer or no available memory.
  1011  	PacketsDiscardedOnSend uint32 `json:"packetsDiscardedOnSend"`
  1012  
  1013  	// FECPacketsSent is the total number of RTP FEC packets sent for this SSRC.
  1014  	// This counter can also be incremented when sending FEC packets in-band with
  1015  	// media packets (e.g., with Opus).
  1016  	FECPacketsSent uint32 `json:"fecPacketsSent"`
  1017  
  1018  	// BytesSent is the total number of bytes sent for this SSRC.
  1019  	BytesSent uint64 `json:"bytesSent"`
  1020  
  1021  	// BytesDiscardedOnSend is the total number of bytes for this SSRC that have
  1022  	// been discarded due to socket errors, i.e. a socket error occurred when handing
  1023  	// the packets containing the bytes to the socket. This might happen due to various
  1024  	// reasons, including full buffer or no available memory.
  1025  	BytesDiscardedOnSend uint64 `json:"bytesDiscardedOnSend"`
  1026  
  1027  	// LocalID is used for looking up the local InboundRTPStreamStats object for the same SSRC.
  1028  	LocalID string `json:"localId"`
  1029  
  1030  	// RemoteTimestamp represents the remote timestamp at which these statistics were
  1031  	// sent by the remote endpoint. This differs from timestamp, which represents the
  1032  	// time at which the statistics were generated or received by the local endpoint.
  1033  	// The RemoteTimestamp, if present, is derived from the NTP timestamp in an RTCP
  1034  	// Sender Report (SR) packet, which reflects the remote endpoint's clock.
  1035  	// That clock may not be synchronized with the local clock.
  1036  	RemoteTimestamp StatsTimestamp `json:"remoteTimestamp"`
  1037  
  1038  	// ReportsSent represents the total number of RTCP Sender Report (SR) blocks sent for this SSRC.
  1039  	ReportsSent uint64 `json:"reportsSent"`
  1040  
  1041  	// RoundTripTime is estimated round trip time for this SSRC based on the latest
  1042  	// RTCP Sender Report (SR) that contains a DLRR report block as defined in [RFC3611].
  1043  	// The Calculation of the round trip time is defined in section 4.5. of [RFC3611].
  1044  	// Does not exist if the latest SR does not contain the DLRR report block, or if the last RR timestamp
  1045  	// in the DLRR report block is zero, or if the delay since last RR value in the DLRR report block is zero.
  1046  	RoundTripTime float64 `json:"roundTripTime"`
  1047  
  1048  	// TotalRoundTripTime represents the cumulative sum of all round trip time measurements in seconds
  1049  	// since the beginning of the session. The individual round trip time is calculated based on the DLRR
  1050  	// report block in the RTCP Sender Report (SR) [RFC3611]. This counter will not increment if the
  1051  	// RoundTripTime can not be calculated. The average round trip time can be computed from
  1052  	// TotalRoundTripTime by dividing it by RoundTripTimeMeasurements.
  1053  	TotalRoundTripTime float64 `json:"totalRoundTripTime"`
  1054  
  1055  	// RoundTripTimeMeasurements represents the total number of RTCP Sender Report (SR) blocks
  1056  	// received for this SSRC that contain a DLRR report block that can derive a valid round trip time
  1057  	// according to [RFC3611]. This counter will not increment if the RoundTripTime can not be calculated.
  1058  	RoundTripTimeMeasurements uint64 `json:"roundTripTimeMeasurements"`
  1059  }
  1060  
  1061  func (s RemoteOutboundRTPStreamStats) statsMarker() {}
  1062  
  1063  func unmarshalRemoteOutboundRTPStreamStats(b []byte) (RemoteOutboundRTPStreamStats, error) {
  1064  	var remoteOutboundRTPStreamStats RemoteOutboundRTPStreamStats
  1065  	err := json.Unmarshal(b, &remoteOutboundRTPStreamStats)
  1066  	if err != nil {
  1067  		return RemoteOutboundRTPStreamStats{}, fmt.Errorf("unmarshal remote outbound rtp stream stats: %w", err)
  1068  	}
  1069  	return remoteOutboundRTPStreamStats, nil
  1070  }
  1071  
  1072  // RTPContributingSourceStats contains statistics for a contributing source (CSRC) that contributed
  1073  // to an inbound RTP stream.
  1074  type RTPContributingSourceStats struct {
  1075  	// Timestamp is the timestamp associated with this object.
  1076  	Timestamp StatsTimestamp `json:"timestamp"`
  1077  
  1078  	// Type is the object's StatsType
  1079  	Type StatsType `json:"type"`
  1080  
  1081  	// ID is a unique id that is associated with the component inspected to produce
  1082  	// this Stats object. Two Stats objects will have the same ID if they were produced
  1083  	// by inspecting the same underlying object.
  1084  	ID string `json:"id"`
  1085  
  1086  	// ContributorSSRC is the SSRC identifier of the contributing source represented
  1087  	// by this stats object. It is a 32-bit unsigned integer that appears in the CSRC
  1088  	// list of any packets the relevant source contributed to.
  1089  	ContributorSSRC SSRC `json:"contributorSsrc"`
  1090  
  1091  	// InboundRTPStreamID is the ID of the InboundRTPStreamStats object representing
  1092  	// the inbound RTP stream that this contributing source is contributing to.
  1093  	InboundRTPStreamID string `json:"inboundRtpStreamId"`
  1094  
  1095  	// PacketsContributedTo is the total number of RTP packets that this contributing
  1096  	// source contributed to. This value is incremented each time a packet is counted
  1097  	// by InboundRTPStreamStats.packetsReceived, and the packet's CSRC list contains
  1098  	// the SSRC identifier of this contributing source, ContributorSSRC.
  1099  	PacketsContributedTo uint32 `json:"packetsContributedTo"`
  1100  
  1101  	// AudioLevel is present if the last received RTP packet that this source contributed
  1102  	// to contained an [RFC6465] mixer-to-client audio level header extension. The value
  1103  	// of audioLevel is between 0..1 (linear), where 1.0 represents 0 dBov, 0 represents
  1104  	// silence, and 0.5 represents approximately 6 dBSPL change in the sound pressure level from 0 dBov.
  1105  	AudioLevel float64 `json:"audioLevel"`
  1106  }
  1107  
  1108  func (s RTPContributingSourceStats) statsMarker() {}
  1109  
  1110  func unmarshalCSRCStats(b []byte) (RTPContributingSourceStats, error) {
  1111  	var csrcStats RTPContributingSourceStats
  1112  	err := json.Unmarshal(b, &csrcStats)
  1113  	if err != nil {
  1114  		return RTPContributingSourceStats{}, fmt.Errorf("unmarshal csrc stats: %w", err)
  1115  	}
  1116  	return csrcStats, nil
  1117  }
  1118  
  1119  // AudioSourceStats represents an audio track that is attached to one or more senders.
  1120  type AudioSourceStats struct {
  1121  	// Timestamp is the timestamp associated with this object.
  1122  	Timestamp StatsTimestamp `json:"timestamp"`
  1123  
  1124  	// Type is the object's StatsType
  1125  	Type StatsType `json:"type"`
  1126  
  1127  	// ID is a unique id that is associated with the component inspected to produce
  1128  	// this Stats object. Two Stats objects will have the same ID if they were produced
  1129  	// by inspecting the same underlying object.
  1130  	ID string `json:"id"`
  1131  
  1132  	// TrackIdentifier represents the id property of the track.
  1133  	TrackIdentifier string `json:"trackIdentifier"`
  1134  
  1135  	// Kind is "audio"
  1136  	Kind string `json:"kind"`
  1137  
  1138  	// AudioLevel represents the output audio level of the track.
  1139  	//
  1140  	// The value is a value between 0..1 (linear), where 1.0 represents 0 dBov,
  1141  	// 0 represents silence, and 0.5 represents approximately 6 dBSPL change in
  1142  	// the sound pressure level from 0 dBov.
  1143  	//
  1144  	// If the track is sourced from an Receiver, does no audio processing, has a
  1145  	// constant level, and has a volume setting of 1.0, the audio level is expected
  1146  	// to be the same as the audio level of the source SSRC, while if the volume setting
  1147  	// is 0.5, the AudioLevel is expected to be half that value.
  1148  	AudioLevel float64 `json:"audioLevel"`
  1149  
  1150  	// TotalAudioEnergy is the total energy of all the audio samples sent/received
  1151  	// for this object, calculated by duration * Math.pow(energy/maxEnergy, 2) for
  1152  	// each audio sample seen.
  1153  	TotalAudioEnergy float64 `json:"totalAudioEnergy"`
  1154  
  1155  	// TotalSamplesDuration represents the total duration in seconds of all samples
  1156  	// that have sent or received (and thus counted by TotalSamplesSent or TotalSamplesReceived).
  1157  	// Can be used with TotalAudioEnergy to compute an average audio level over different intervals.
  1158  	TotalSamplesDuration float64 `json:"totalSamplesDuration"`
  1159  
  1160  	// EchoReturnLoss is only present while the sender is sending a track sourced from
  1161  	// a microphone where echo cancellation is applied. Calculated in decibels.
  1162  	EchoReturnLoss float64 `json:"echoReturnLoss"`
  1163  
  1164  	// EchoReturnLossEnhancement is only present while the sender is sending a track
  1165  	// sourced from a microphone where echo cancellation is applied. Calculated in decibels.
  1166  	EchoReturnLossEnhancement float64 `json:"echoReturnLossEnhancement"`
  1167  
  1168  	// DroppedSamplesDuration represents the total duration, in seconds, of samples produced by the device that got
  1169  	// dropped before reaching the media source. Only applicable if this media source is backed by an audio capture device.
  1170  	DroppedSamplesDuration float64 `json:"droppedSamplesDuration"`
  1171  
  1172  	// DroppedSamplesEvents is the number of dropped samples events. This counter increases every time a sample is
  1173  	// dropped after a non-dropped sample. That is, multiple consecutive dropped samples will increase
  1174  	// droppedSamplesDuration multiple times but is a single dropped samples event.
  1175  	DroppedSamplesEvents uint64 `json:"droppedSamplesEvents"`
  1176  
  1177  	// TotalCaptureDelay is the total delay, in seconds, for each audio sample between the time the sample was emitted
  1178  	// by the capture device and the sample reaching the source. This can be used together with totalSamplesCaptured to
  1179  	// calculate the average capture delay per sample. Only applicable if the audio source represents an audio capture device.
  1180  	TotalCaptureDelay float64 `json:"totalCaptureDelay"`
  1181  
  1182  	// TotalSamplesCaptured is the total number of captured samples reaching the audio source, i.e. that were not dropped
  1183  	// by the capture pipeline. The frequency of the media source is not necessarily the same as the frequency of encoders
  1184  	// later in the pipeline. Only applicable if the audio source represents an audio capture device.
  1185  	TotalSamplesCaptured uint64 `json:"totalSamplesCaptured"`
  1186  }
  1187  
  1188  func (s AudioSourceStats) statsMarker() {}
  1189  
  1190  // VideoSourceStats represents a video track that is attached to one or more senders.
  1191  type VideoSourceStats struct {
  1192  	// Timestamp is the timestamp associated with this object.
  1193  	Timestamp StatsTimestamp `json:"timestamp"`
  1194  
  1195  	// Type is the object's StatsType
  1196  	Type StatsType `json:"type"`
  1197  
  1198  	// ID is a unique id that is associated with the component inspected to produce
  1199  	// this Stats object. Two Stats objects will have the same ID if they were produced
  1200  	// by inspecting the same underlying object.
  1201  	ID string `json:"id"`
  1202  
  1203  	// TrackIdentifier represents the id property of the track.
  1204  	TrackIdentifier string `json:"trackIdentifier"`
  1205  
  1206  	// Kind is "video"
  1207  	Kind string `json:"kind"`
  1208  
  1209  	// Width is width of the last frame originating from this source in pixels.
  1210  	Width uint32 `json:"width"`
  1211  
  1212  	// Height is height of the last frame originating from this source in pixels.
  1213  	Height uint32 `json:"height"`
  1214  
  1215  	// Frames is the total number of frames originating from this source.
  1216  	Frames uint32 `json:"frames"`
  1217  
  1218  	// FramesPerSecond is the number of frames originating from this source, measured during the last second.
  1219  	FramesPerSecond float64 `json:"framesPerSecond"`
  1220  }
  1221  
  1222  func (s VideoSourceStats) statsMarker() {}
  1223  
  1224  func unmarshalMediaSourceStats(b []byte) (Stats, error) {
  1225  	type kindJSON struct {
  1226  		Kind string `json:"kind"`
  1227  	}
  1228  	kindHolder := kindJSON{}
  1229  
  1230  	err := json.Unmarshal(b, &kindHolder)
  1231  	if err != nil {
  1232  		return nil, fmt.Errorf("unmarshal json kind: %w", err)
  1233  	}
  1234  
  1235  	switch MediaKind(kindHolder.Kind) {
  1236  	case MediaKindAudio:
  1237  		var mediaSourceStats AudioSourceStats
  1238  		err := json.Unmarshal(b, &mediaSourceStats)
  1239  		if err != nil {
  1240  			return nil, fmt.Errorf("unmarshal audio source stats: %w", err)
  1241  		}
  1242  		return mediaSourceStats, nil
  1243  	case MediaKindVideo:
  1244  		var mediaSourceStats VideoSourceStats
  1245  		err := json.Unmarshal(b, &mediaSourceStats)
  1246  		if err != nil {
  1247  			return nil, fmt.Errorf("unmarshal video source stats: %w", err)
  1248  		}
  1249  		return mediaSourceStats, nil
  1250  	default:
  1251  		return nil, fmt.Errorf("kind: %w", ErrUnknownType)
  1252  	}
  1253  }
  1254  
  1255  // AudioPlayoutStats represents one playout path - if the same playout stats object is referenced by multiple
  1256  // RTCInboundRtpStreamStats this is an indication that audio mixing is happening in which case sample counters in this
  1257  // stats object refer to the samples after mixing. Only applicable if the playout path represents an audio device.
  1258  type AudioPlayoutStats struct {
  1259  	// Timestamp is the timestamp associated with this object.
  1260  	Timestamp StatsTimestamp `json:"timestamp"`
  1261  
  1262  	// Type is the object's StatsType
  1263  	Type StatsType `json:"type"`
  1264  
  1265  	// ID is a unique id that is associated with the component inspected to produce
  1266  	// this Stats object. Two Stats objects will have the same ID if they were produced
  1267  	// by inspecting the same underlying object.
  1268  	ID string `json:"id"`
  1269  
  1270  	// Kind is "audio"
  1271  	Kind string `json:"kind"`
  1272  
  1273  	// SynthesizedSamplesDuration is measured in seconds and is incremented each time an audio sample is synthesized by
  1274  	// this playout path. This metric can be used together with totalSamplesDuration to calculate the percentage of played
  1275  	// out media being synthesized. If the playout path is unable to produce audio samples on time for device playout,
  1276  	// samples are synthesized to be playout out instead. Synthesization typically only happens if the pipeline is
  1277  	// underperforming. Samples synthesized by the RTCInboundRtpStreamStats are not counted for here, but in
  1278  	// InboundRtpStreamStats.concealedSamples.
  1279  	SynthesizedSamplesDuration float64 `json:"synthesizedSamplesDuration"`
  1280  
  1281  	// SynthesizedSamplesEvents is the number of synthesized samples events. This counter increases every time a sample
  1282  	// is synthesized after a non-synthesized sample. That is, multiple consecutive synthesized samples will increase
  1283  	// synthesizedSamplesDuration multiple times but is a single synthesization samples event.
  1284  	SynthesizedSamplesEvents uint64 `json:"synthesizedSamplesEvents"`
  1285  
  1286  	// TotalSamplesDuration represents the total duration in seconds of all samples
  1287  	// that have sent or received (and thus counted by TotalSamplesSent or TotalSamplesReceived).
  1288  	// Can be used with TotalAudioEnergy to compute an average audio level over different intervals.
  1289  	TotalSamplesDuration float64 `json:"totalSamplesDuration"`
  1290  
  1291  	// When audio samples are pulled by the playout device, this counter is incremented with the estimated delay of the
  1292  	// playout path for that audio sample. The playout delay includes the delay from being emitted to the actual time of
  1293  	// playout on the device. This metric can be used together with totalSamplesCount to calculate the average
  1294  	// playout delay per sample.
  1295  	TotalPlayoutDelay float64 `json:"totalPlayoutDelay"`
  1296  
  1297  	// When audio samples are pulled by the playout device, this counter is incremented with the number of samples
  1298  	// emitted for playout.
  1299  	TotalSamplesCount uint64 `json:"totalSamplesCount"`
  1300  }
  1301  
  1302  func (s AudioPlayoutStats) statsMarker() {}
  1303  
  1304  func unmarshalMediaPlayoutStats(b []byte) (Stats, error) {
  1305  	var audioPlayoutStats AudioPlayoutStats
  1306  	err := json.Unmarshal(b, &audioPlayoutStats)
  1307  	if err != nil {
  1308  		return nil, fmt.Errorf("unmarshal audio playout stats: %w", err)
  1309  	}
  1310  	return audioPlayoutStats, nil
  1311  }
  1312  
  1313  // PeerConnectionStats contains statistics related to the PeerConnection object.
  1314  type PeerConnectionStats struct {
  1315  	// Timestamp is the timestamp associated with this object.
  1316  	Timestamp StatsTimestamp `json:"timestamp"`
  1317  
  1318  	// Type is the object's StatsType
  1319  	Type StatsType `json:"type"`
  1320  
  1321  	// ID is a unique id that is associated with the component inspected to produce
  1322  	// this Stats object. Two Stats objects will have the same ID if they were produced
  1323  	// by inspecting the same underlying object.
  1324  	ID string `json:"id"`
  1325  
  1326  	// DataChannelsOpened represents the number of unique DataChannels that have
  1327  	// entered the "open" state during their lifetime.
  1328  	DataChannelsOpened uint32 `json:"dataChannelsOpened"`
  1329  
  1330  	// DataChannelsClosed represents the number of unique DataChannels that have
  1331  	// left the "open" state during their lifetime (due to being closed by either
  1332  	// end or the underlying transport being closed). DataChannels that transition
  1333  	// from "connecting" to "closing" or "closed" without ever being "open"
  1334  	// are not counted in this number.
  1335  	DataChannelsClosed uint32 `json:"dataChannelsClosed"`
  1336  
  1337  	// DataChannelsRequested Represents the number of unique DataChannels returned
  1338  	// from a successful createDataChannel() call on the PeerConnection. If the
  1339  	// underlying data transport is not established, these may be in the "connecting" state.
  1340  	DataChannelsRequested uint32 `json:"dataChannelsRequested"`
  1341  
  1342  	// DataChannelsAccepted represents the number of unique DataChannels signaled
  1343  	// in a "datachannel" event on the PeerConnection.
  1344  	DataChannelsAccepted uint32 `json:"dataChannelsAccepted"`
  1345  }
  1346  
  1347  func (s PeerConnectionStats) statsMarker() {}
  1348  
  1349  func unmarshalPeerConnectionStats(b []byte) (PeerConnectionStats, error) {
  1350  	var pcStats PeerConnectionStats
  1351  	err := json.Unmarshal(b, &pcStats)
  1352  	if err != nil {
  1353  		return PeerConnectionStats{}, fmt.Errorf("unmarshal pc stats: %w", err)
  1354  	}
  1355  	return pcStats, nil
  1356  }
  1357  
  1358  // DataChannelStats contains statistics related to each DataChannel ID.
  1359  type DataChannelStats struct {
  1360  	// Timestamp is the timestamp associated with this object.
  1361  	Timestamp StatsTimestamp `json:"timestamp"`
  1362  
  1363  	// Type is the object's StatsType
  1364  	Type StatsType `json:"type"`
  1365  
  1366  	// ID is a unique id that is associated with the component inspected to produce
  1367  	// this Stats object. Two Stats objects will have the same ID if they were produced
  1368  	// by inspecting the same underlying object.
  1369  	ID string `json:"id"`
  1370  
  1371  	// Label is the "label" value of the DataChannel object.
  1372  	Label string `json:"label"`
  1373  
  1374  	// Protocol is the "protocol" value of the DataChannel object.
  1375  	Protocol string `json:"protocol"`
  1376  
  1377  	// DataChannelIdentifier is the "id" attribute of the DataChannel object.
  1378  	DataChannelIdentifier int32 `json:"dataChannelIdentifier"`
  1379  
  1380  	// TransportID the ID of the TransportStats object for transport used to carry this datachannel.
  1381  	TransportID string `json:"transportId"`
  1382  
  1383  	// State is the "readyState" value of the DataChannel object.
  1384  	State DataChannelState `json:"state"`
  1385  
  1386  	// MessagesSent represents the total number of API "message" events sent.
  1387  	MessagesSent uint32 `json:"messagesSent"`
  1388  
  1389  	// BytesSent represents the total number of payload bytes sent on this
  1390  	// datachannel not including headers or padding.
  1391  	BytesSent uint64 `json:"bytesSent"`
  1392  
  1393  	// MessagesReceived represents the total number of API "message" events received.
  1394  	MessagesReceived uint32 `json:"messagesReceived"`
  1395  
  1396  	// BytesReceived represents the total number of bytes received on this
  1397  	// datachannel not including headers or padding.
  1398  	BytesReceived uint64 `json:"bytesReceived"`
  1399  }
  1400  
  1401  func (s DataChannelStats) statsMarker() {}
  1402  
  1403  func unmarshalDataChannelStats(b []byte) (DataChannelStats, error) {
  1404  	var dataChannelStats DataChannelStats
  1405  	err := json.Unmarshal(b, &dataChannelStats)
  1406  	if err != nil {
  1407  		return DataChannelStats{}, fmt.Errorf("unmarshal data channel stats: %w", err)
  1408  	}
  1409  	return dataChannelStats, nil
  1410  }
  1411  
  1412  // MediaStreamStats contains statistics related to a specific MediaStream.
  1413  type MediaStreamStats struct {
  1414  	// Timestamp is the timestamp associated with this object.
  1415  	Timestamp StatsTimestamp `json:"timestamp"`
  1416  
  1417  	// Type is the object's StatsType
  1418  	Type StatsType `json:"type"`
  1419  
  1420  	// ID is a unique id that is associated with the component inspected to produce
  1421  	// this Stats object. Two Stats objects will have the same ID if they were produced
  1422  	// by inspecting the same underlying object.
  1423  	ID string `json:"id"`
  1424  
  1425  	// StreamIdentifier is the "id" property of the MediaStream
  1426  	StreamIdentifier string `json:"streamIdentifier"`
  1427  
  1428  	// TrackIDs is a list of the identifiers of the stats object representing the
  1429  	// stream's tracks, either ReceiverAudioTrackAttachmentStats or ReceiverVideoTrackAttachmentStats.
  1430  	TrackIDs []string `json:"trackIds"`
  1431  }
  1432  
  1433  func (s MediaStreamStats) statsMarker() {}
  1434  
  1435  func unmarshalStreamStats(b []byte) (MediaStreamStats, error) {
  1436  	var streamStats MediaStreamStats
  1437  	err := json.Unmarshal(b, &streamStats)
  1438  	if err != nil {
  1439  		return MediaStreamStats{}, fmt.Errorf("unmarshal stream stats: %w", err)
  1440  	}
  1441  	return streamStats, nil
  1442  }
  1443  
  1444  // AudioSenderStats represents the stats about one audio sender of a PeerConnection
  1445  // object for which one calls GetStats.
  1446  //
  1447  // It appears in the stats as soon as the RTPSender is added by either AddTrack
  1448  // or AddTransceiver, or by media negotiation.
  1449  type AudioSenderStats struct {
  1450  	// Timestamp is the timestamp associated with this object.
  1451  	Timestamp StatsTimestamp `json:"timestamp"`
  1452  
  1453  	// Type is the object's StatsType
  1454  	Type StatsType `json:"type"`
  1455  
  1456  	// ID is a unique id that is associated with the component inspected to produce
  1457  	// this Stats object. Two Stats objects will have the same ID if they were produced
  1458  	// by inspecting the same underlying object.
  1459  	ID string `json:"id"`
  1460  
  1461  	// TrackIdentifier represents the id property of the track.
  1462  	TrackIdentifier string `json:"trackIdentifier"`
  1463  
  1464  	// RemoteSource is true if the source is remote, for instance if it is sourced
  1465  	// from another host via a PeerConnection. False otherwise. Only applicable for 'track' stats.
  1466  	RemoteSource bool `json:"remoteSource"`
  1467  
  1468  	// Ended reflects the "ended" state of the track.
  1469  	Ended bool `json:"ended"`
  1470  
  1471  	// Kind is "audio"
  1472  	Kind string `json:"kind"`
  1473  
  1474  	// AudioLevel represents the output audio level of the track.
  1475  	//
  1476  	// The value is a value between 0..1 (linear), where 1.0 represents 0 dBov,
  1477  	// 0 represents silence, and 0.5 represents approximately 6 dBSPL change in
  1478  	// the sound pressure level from 0 dBov.
  1479  	//
  1480  	// If the track is sourced from an Receiver, does no audio processing, has a
  1481  	// constant level, and has a volume setting of 1.0, the audio level is expected
  1482  	// to be the same as the audio level of the source SSRC, while if the volume setting
  1483  	// is 0.5, the AudioLevel is expected to be half that value.
  1484  	//
  1485  	// For outgoing audio tracks, the AudioLevel is the level of the audio being sent.
  1486  	AudioLevel float64 `json:"audioLevel"`
  1487  
  1488  	// TotalAudioEnergy is the total energy of all the audio samples sent/received
  1489  	// for this object, calculated by duration * Math.pow(energy/maxEnergy, 2) for
  1490  	// each audio sample seen.
  1491  	TotalAudioEnergy float64 `json:"totalAudioEnergy"`
  1492  
  1493  	// VoiceActivityFlag represents whether the last RTP packet sent or played out
  1494  	// by this track contained voice activity or not based on the presence of the
  1495  	// V bit in the extension header, as defined in [RFC6464].
  1496  	//
  1497  	// This value indicates the voice activity in the latest RTP packet played out
  1498  	// from a given SSRC, and is defined in RTPSynchronizationSource.voiceActivityFlag.
  1499  	VoiceActivityFlag bool `json:"voiceActivityFlag"`
  1500  
  1501  	// TotalSamplesDuration represents the total duration in seconds of all samples
  1502  	// that have sent or received (and thus counted by TotalSamplesSent or TotalSamplesReceived).
  1503  	// Can be used with TotalAudioEnergy to compute an average audio level over different intervals.
  1504  	TotalSamplesDuration float64 `json:"totalSamplesDuration"`
  1505  
  1506  	// EchoReturnLoss is only present while the sender is sending a track sourced from
  1507  	// a microphone where echo cancellation is applied. Calculated in decibels.
  1508  	EchoReturnLoss float64 `json:"echoReturnLoss"`
  1509  
  1510  	// EchoReturnLossEnhancement is only present while the sender is sending a track
  1511  	// sourced from a microphone where echo cancellation is applied. Calculated in decibels.
  1512  	EchoReturnLossEnhancement float64 `json:"echoReturnLossEnhancement"`
  1513  
  1514  	// TotalSamplesSent is the total number of samples that have been sent by this sender.
  1515  	TotalSamplesSent uint64 `json:"totalSamplesSent"`
  1516  }
  1517  
  1518  func (s AudioSenderStats) statsMarker() {}
  1519  
  1520  // SenderAudioTrackAttachmentStats object represents the stats about one attachment
  1521  // of an audio MediaStreamTrack to the PeerConnection object for which one calls GetStats.
  1522  //
  1523  // It appears in the stats as soon as it is attached (via AddTrack, via AddTransceiver,
  1524  // via ReplaceTrack on an RTPSender object).
  1525  //
  1526  // If an audio track is attached twice (via AddTransceiver or ReplaceTrack), there
  1527  // will be two SenderAudioTrackAttachmentStats objects, one for each attachment.
  1528  // They will have the same "TrackIdentifier" attribute, but different "ID" attributes.
  1529  //
  1530  // If the track is detached from the PeerConnection (via removeTrack or via replaceTrack),
  1531  // it continues to appear, but with the "ObjectDeleted" member set to true.
  1532  type SenderAudioTrackAttachmentStats AudioSenderStats
  1533  
  1534  func (s SenderAudioTrackAttachmentStats) statsMarker() {}
  1535  
  1536  // VideoSenderStats represents the stats about one video sender of a PeerConnection
  1537  // object for which one calls GetStats.
  1538  //
  1539  // It appears in the stats as soon as the sender is added by either AddTrack or
  1540  // AddTransceiver, or by media negotiation.
  1541  type VideoSenderStats struct {
  1542  	// Timestamp is the timestamp associated with this object.
  1543  	Timestamp StatsTimestamp `json:"timestamp"`
  1544  
  1545  	// Type is the object's StatsType
  1546  	Type StatsType `json:"type"`
  1547  
  1548  	// ID is a unique id that is associated with the component inspected to produce
  1549  	// this Stats object. Two Stats objects will have the same ID if they were produced
  1550  	// by inspecting the same underlying object.
  1551  	ID string `json:"id"`
  1552  
  1553  	// Kind is "video"
  1554  	Kind string `json:"kind"`
  1555  
  1556  	// FramesCaptured represents the total number of frames captured, before encoding,
  1557  	// for this RTPSender (or for this MediaStreamTrack, if type is "track"). For example,
  1558  	// if type is "sender" and this sender's track represents a camera, then this is the
  1559  	// number of frames produced by the camera for this track while being sent by this sender,
  1560  	// combined with the number of frames produced by all tracks previously attached to this
  1561  	// sender while being sent by this sender. Framerates can vary due to hardware limitations
  1562  	// or environmental factors such as lighting conditions.
  1563  	FramesCaptured uint32 `json:"framesCaptured"`
  1564  
  1565  	// FramesSent represents the total number of frames sent by this RTPSender
  1566  	// (or for this MediaStreamTrack, if type is "track").
  1567  	FramesSent uint32 `json:"framesSent"`
  1568  
  1569  	// HugeFramesSent represents the total number of huge frames sent by this RTPSender
  1570  	// (or for this MediaStreamTrack, if type is "track"). Huge frames, by definition,
  1571  	// are frames that have an encoded size at least 2.5 times the average size of the frames.
  1572  	// The average size of the frames is defined as the target bitrate per second divided
  1573  	// by the target fps at the time the frame was encoded. These are usually complex
  1574  	// to encode frames with a lot of changes in the picture. This can be used to estimate,
  1575  	// e.g slide changes in the streamed presentation. If a huge frame is also a key frame,
  1576  	// then both counters HugeFramesSent and KeyFramesSent are incremented.
  1577  	HugeFramesSent uint32 `json:"hugeFramesSent"`
  1578  
  1579  	// KeyFramesSent represents the total number of key frames sent by this RTPSender
  1580  	// (or for this MediaStreamTrack, if type is "track"), such as Infra-frames in
  1581  	// VP8 [RFC6386] or I-frames in H.264 [RFC6184]. This is a subset of FramesSent.
  1582  	// FramesSent - KeyFramesSent gives you the number of delta frames sent.
  1583  	KeyFramesSent uint32 `json:"keyFramesSent"`
  1584  }
  1585  
  1586  func (s VideoSenderStats) statsMarker() {}
  1587  
  1588  // SenderVideoTrackAttachmentStats represents the stats about one attachment of a
  1589  // video MediaStreamTrack to the PeerConnection object for which one calls GetStats.
  1590  //
  1591  // It appears in the stats as soon as it is attached (via AddTrack, via AddTransceiver,
  1592  // via ReplaceTrack on an RTPSender object).
  1593  //
  1594  // If a video track is attached twice (via AddTransceiver or ReplaceTrack), there
  1595  // will be two SenderVideoTrackAttachmentStats objects, one for each attachment.
  1596  // They will have the same "TrackIdentifier" attribute, but different "ID" attributes.
  1597  //
  1598  // If the track is detached from the PeerConnection (via RemoveTrack or via ReplaceTrack),
  1599  // it continues to appear, but with the "ObjectDeleted" member set to true.
  1600  type SenderVideoTrackAttachmentStats VideoSenderStats
  1601  
  1602  func (s SenderVideoTrackAttachmentStats) statsMarker() {}
  1603  
  1604  func unmarshalSenderStats(b []byte) (Stats, error) {
  1605  	type kindJSON struct {
  1606  		Kind string `json:"kind"`
  1607  	}
  1608  	kindHolder := kindJSON{}
  1609  
  1610  	err := json.Unmarshal(b, &kindHolder)
  1611  	if err != nil {
  1612  		return nil, fmt.Errorf("unmarshal json kind: %w", err)
  1613  	}
  1614  
  1615  	switch MediaKind(kindHolder.Kind) {
  1616  	case MediaKindAudio:
  1617  		var senderStats AudioSenderStats
  1618  		err := json.Unmarshal(b, &senderStats)
  1619  		if err != nil {
  1620  			return nil, fmt.Errorf("unmarshal audio sender stats: %w", err)
  1621  		}
  1622  		return senderStats, nil
  1623  	case MediaKindVideo:
  1624  		var senderStats VideoSenderStats
  1625  		err := json.Unmarshal(b, &senderStats)
  1626  		if err != nil {
  1627  			return nil, fmt.Errorf("unmarshal video sender stats: %w", err)
  1628  		}
  1629  		return senderStats, nil
  1630  	default:
  1631  		return nil, fmt.Errorf("kind: %w", ErrUnknownType)
  1632  	}
  1633  }
  1634  
  1635  func unmarshalTrackStats(b []byte) (Stats, error) {
  1636  	type kindJSON struct {
  1637  		Kind string `json:"kind"`
  1638  	}
  1639  	kindHolder := kindJSON{}
  1640  
  1641  	err := json.Unmarshal(b, &kindHolder)
  1642  	if err != nil {
  1643  		return nil, fmt.Errorf("unmarshal json kind: %w", err)
  1644  	}
  1645  
  1646  	switch MediaKind(kindHolder.Kind) {
  1647  	case MediaKindAudio:
  1648  		var trackStats SenderAudioTrackAttachmentStats
  1649  		err := json.Unmarshal(b, &trackStats)
  1650  		if err != nil {
  1651  			return nil, fmt.Errorf("unmarshal audio track stats: %w", err)
  1652  		}
  1653  		return trackStats, nil
  1654  	case MediaKindVideo:
  1655  		var trackStats SenderVideoTrackAttachmentStats
  1656  		err := json.Unmarshal(b, &trackStats)
  1657  		if err != nil {
  1658  			return nil, fmt.Errorf("unmarshal video track stats: %w", err)
  1659  		}
  1660  		return trackStats, nil
  1661  	default:
  1662  		return nil, fmt.Errorf("kind: %w", ErrUnknownType)
  1663  	}
  1664  }
  1665  
  1666  // AudioReceiverStats contains audio metrics related to a specific receiver.
  1667  type AudioReceiverStats struct {
  1668  	// Timestamp is the timestamp associated with this object.
  1669  	Timestamp StatsTimestamp `json:"timestamp"`
  1670  
  1671  	// Type is the object's StatsType
  1672  	Type StatsType `json:"type"`
  1673  
  1674  	// ID is a unique id that is associated with the component inspected to produce
  1675  	// this Stats object. Two Stats objects will have the same ID if they were produced
  1676  	// by inspecting the same underlying object.
  1677  	ID string `json:"id"`
  1678  
  1679  	// Kind is "audio"
  1680  	Kind string `json:"kind"`
  1681  
  1682  	// AudioLevel represents the output audio level of the track.
  1683  	//
  1684  	// The value is a value between 0..1 (linear), where 1.0 represents 0 dBov,
  1685  	// 0 represents silence, and 0.5 represents approximately 6 dBSPL change in
  1686  	// the sound pressure level from 0 dBov.
  1687  	//
  1688  	// If the track is sourced from an Receiver, does no audio processing, has a
  1689  	// constant level, and has a volume setting of 1.0, the audio level is expected
  1690  	// to be the same as the audio level of the source SSRC, while if the volume setting
  1691  	// is 0.5, the AudioLevel is expected to be half that value.
  1692  	//
  1693  	// For outgoing audio tracks, the AudioLevel is the level of the audio being sent.
  1694  	AudioLevel float64 `json:"audioLevel"`
  1695  
  1696  	// TotalAudioEnergy is the total energy of all the audio samples sent/received
  1697  	// for this object, calculated by duration * Math.pow(energy/maxEnergy, 2) for
  1698  	// each audio sample seen.
  1699  	TotalAudioEnergy float64 `json:"totalAudioEnergy"`
  1700  
  1701  	// VoiceActivityFlag represents whether the last RTP packet sent or played out
  1702  	// by this track contained voice activity or not based on the presence of the
  1703  	// V bit in the extension header, as defined in [RFC6464].
  1704  	//
  1705  	// This value indicates the voice activity in the latest RTP packet played out
  1706  	// from a given SSRC, and is defined in RTPSynchronizationSource.voiceActivityFlag.
  1707  	VoiceActivityFlag bool `json:"voiceActivityFlag"`
  1708  
  1709  	// TotalSamplesDuration represents the total duration in seconds of all samples
  1710  	// that have sent or received (and thus counted by TotalSamplesSent or TotalSamplesReceived).
  1711  	// Can be used with TotalAudioEnergy to compute an average audio level over different intervals.
  1712  	TotalSamplesDuration float64 `json:"totalSamplesDuration"`
  1713  
  1714  	// EstimatedPlayoutTimestamp is the estimated playout time of this receiver's
  1715  	// track. The playout time is the NTP timestamp of the last playable sample that
  1716  	// has a known timestamp (from an RTCP SR packet mapping RTP timestamps to NTP
  1717  	// timestamps), extrapolated with the time elapsed since it was ready to be played out.
  1718  	// This is the "current time" of the track in NTP clock time of the sender and
  1719  	// can be present even if there is no audio currently playing.
  1720  	//
  1721  	// This can be useful for estimating how much audio and video is out of
  1722  	// sync for two tracks from the same source:
  1723  	// 		AudioTrackStats.EstimatedPlayoutTimestamp - VideoTrackStats.EstimatedPlayoutTimestamp
  1724  	EstimatedPlayoutTimestamp StatsTimestamp `json:"estimatedPlayoutTimestamp"`
  1725  
  1726  	// JitterBufferDelay is the sum of the time, in seconds, each sample takes from
  1727  	// the time it is received and to the time it exits the jitter buffer.
  1728  	// This increases upon samples exiting, having completed their time in the buffer
  1729  	// (incrementing JitterBufferEmittedCount). The average jitter buffer delay can
  1730  	// be calculated by dividing the JitterBufferDelay with the JitterBufferEmittedCount.
  1731  	JitterBufferDelay float64 `json:"jitterBufferDelay"`
  1732  
  1733  	// JitterBufferEmittedCount is the total number of samples that have come out
  1734  	// of the jitter buffer (increasing JitterBufferDelay).
  1735  	JitterBufferEmittedCount uint64 `json:"jitterBufferEmittedCount"`
  1736  
  1737  	// TotalSamplesReceived is the total number of samples that have been received
  1738  	// by this receiver. This includes ConcealedSamples.
  1739  	TotalSamplesReceived uint64 `json:"totalSamplesReceived"`
  1740  
  1741  	// ConcealedSamples is the total number of samples that are concealed samples.
  1742  	// A concealed sample is a sample that is based on data that was synthesized
  1743  	// to conceal packet loss and does not represent incoming data.
  1744  	ConcealedSamples uint64 `json:"concealedSamples"`
  1745  
  1746  	// ConcealmentEvents is the number of concealment events. This counter increases
  1747  	// every time a concealed sample is synthesized after a non-concealed sample.
  1748  	// That is, multiple consecutive concealed samples will increase the concealedSamples
  1749  	// count multiple times but is a single concealment event.
  1750  	ConcealmentEvents uint64 `json:"concealmentEvents"`
  1751  }
  1752  
  1753  func (s AudioReceiverStats) statsMarker() {}
  1754  
  1755  // VideoReceiverStats contains video metrics related to a specific receiver.
  1756  type VideoReceiverStats struct {
  1757  	// Timestamp is the timestamp associated with this object.
  1758  	Timestamp StatsTimestamp `json:"timestamp"`
  1759  
  1760  	// Type is the object's StatsType
  1761  	Type StatsType `json:"type"`
  1762  
  1763  	// ID is a unique id that is associated with the component inspected to produce
  1764  	// this Stats object. Two Stats objects will have the same ID if they were produced
  1765  	// by inspecting the same underlying object.
  1766  	ID string `json:"id"`
  1767  
  1768  	// Kind is "video"
  1769  	Kind string `json:"kind"`
  1770  
  1771  	// FrameWidth represents the width of the last processed frame for this track.
  1772  	// Before the first frame is processed this attribute is missing.
  1773  	FrameWidth uint32 `json:"frameWidth"`
  1774  
  1775  	// FrameHeight represents the height of the last processed frame for this track.
  1776  	// Before the first frame is processed this attribute is missing.
  1777  	FrameHeight uint32 `json:"frameHeight"`
  1778  
  1779  	// FramesPerSecond represents the nominal FPS value before the degradation preference
  1780  	// is applied. It is the number of complete frames in the last second. For sending
  1781  	// tracks it is the current captured FPS and for the receiving tracks it is the
  1782  	// current decoding framerate.
  1783  	FramesPerSecond float64 `json:"framesPerSecond"`
  1784  
  1785  	// EstimatedPlayoutTimestamp is the estimated playout time of this receiver's
  1786  	// track. The playout time is the NTP timestamp of the last playable sample that
  1787  	// has a known timestamp (from an RTCP SR packet mapping RTP timestamps to NTP
  1788  	// timestamps), extrapolated with the time elapsed since it was ready to be played out.
  1789  	// This is the "current time" of the track in NTP clock time of the sender and
  1790  	// can be present even if there is no audio currently playing.
  1791  	//
  1792  	// This can be useful for estimating how much audio and video is out of
  1793  	// sync for two tracks from the same source:
  1794  	// 		AudioTrackStats.EstimatedPlayoutTimestamp - VideoTrackStats.EstimatedPlayoutTimestamp
  1795  	EstimatedPlayoutTimestamp StatsTimestamp `json:"estimatedPlayoutTimestamp"`
  1796  
  1797  	// JitterBufferDelay is the sum of the time, in seconds, each sample takes from
  1798  	// the time it is received and to the time it exits the jitter buffer.
  1799  	// This increases upon samples exiting, having completed their time in the buffer
  1800  	// (incrementing JitterBufferEmittedCount). The average jitter buffer delay can
  1801  	// be calculated by dividing the JitterBufferDelay with the JitterBufferEmittedCount.
  1802  	JitterBufferDelay float64 `json:"jitterBufferDelay"`
  1803  
  1804  	// JitterBufferEmittedCount is the total number of samples that have come out
  1805  	// of the jitter buffer (increasing JitterBufferDelay).
  1806  	JitterBufferEmittedCount uint64 `json:"jitterBufferEmittedCount"`
  1807  
  1808  	// FramesReceived Represents the total number of complete frames received for
  1809  	// this receiver. This metric is incremented when the complete frame is received.
  1810  	FramesReceived uint32 `json:"framesReceived"`
  1811  
  1812  	// KeyFramesReceived represents the total number of complete key frames received
  1813  	// for this MediaStreamTrack, such as Infra-frames in VP8 [RFC6386] or I-frames
  1814  	// in H.264 [RFC6184]. This is a subset of framesReceived. `framesReceived - keyFramesReceived`
  1815  	// gives you the number of delta frames received. This metric is incremented when
  1816  	// the complete key frame is received. It is not incremented if a partial key
  1817  	// frames is received and sent for decoding, i.e., the frame could not be recovered
  1818  	// via retransmission or FEC.
  1819  	KeyFramesReceived uint32 `json:"keyFramesReceived"`
  1820  
  1821  	// FramesDecoded represents the total number of frames correctly decoded for this
  1822  	// SSRC, i.e., frames that would be displayed if no frames are dropped.
  1823  	FramesDecoded uint32 `json:"framesDecoded"`
  1824  
  1825  	// FramesDropped is the total number of frames dropped predecode or dropped
  1826  	// because the frame missed its display deadline for this receiver's track.
  1827  	FramesDropped uint32 `json:"framesDropped"`
  1828  
  1829  	// The cumulative number of partial frames lost. This metric is incremented when
  1830  	// the frame is sent to the decoder. If the partial frame is received and recovered
  1831  	// via retransmission or FEC before decoding, the FramesReceived counter is incremented.
  1832  	PartialFramesLost uint32 `json:"partialFramesLost"`
  1833  
  1834  	// FullFramesLost is the cumulative number of full frames lost.
  1835  	FullFramesLost uint32 `json:"fullFramesLost"`
  1836  }
  1837  
  1838  func (s VideoReceiverStats) statsMarker() {}
  1839  
  1840  func unmarshalReceiverStats(b []byte) (Stats, error) {
  1841  	type kindJSON struct {
  1842  		Kind string `json:"kind"`
  1843  	}
  1844  	kindHolder := kindJSON{}
  1845  
  1846  	err := json.Unmarshal(b, &kindHolder)
  1847  	if err != nil {
  1848  		return nil, fmt.Errorf("unmarshal json kind: %w", err)
  1849  	}
  1850  
  1851  	switch MediaKind(kindHolder.Kind) {
  1852  	case MediaKindAudio:
  1853  		var receiverStats AudioReceiverStats
  1854  		err := json.Unmarshal(b, &receiverStats)
  1855  		if err != nil {
  1856  			return nil, fmt.Errorf("unmarshal audio receiver stats: %w", err)
  1857  		}
  1858  		return receiverStats, nil
  1859  	case MediaKindVideo:
  1860  		var receiverStats VideoReceiverStats
  1861  		err := json.Unmarshal(b, &receiverStats)
  1862  		if err != nil {
  1863  			return nil, fmt.Errorf("unmarshal video receiver stats: %w", err)
  1864  		}
  1865  		return receiverStats, nil
  1866  	default:
  1867  		return nil, fmt.Errorf("kind: %w", ErrUnknownType)
  1868  	}
  1869  }
  1870  
  1871  // TransportStats contains transport statistics related to the PeerConnection object.
  1872  type TransportStats struct {
  1873  	// Timestamp is the timestamp associated with this object.
  1874  	Timestamp StatsTimestamp `json:"timestamp"`
  1875  
  1876  	// Type is the object's StatsType
  1877  	Type StatsType `json:"type"`
  1878  
  1879  	// ID is a unique id that is associated with the component inspected to produce
  1880  	// this Stats object. Two Stats objects will have the same ID if they were produced
  1881  	// by inspecting the same underlying object.
  1882  	ID string `json:"id"`
  1883  
  1884  	// PacketsSent represents the total number of packets sent over this transport.
  1885  	PacketsSent uint32 `json:"packetsSent"`
  1886  
  1887  	// PacketsReceived represents the total number of packets received on this transport.
  1888  	PacketsReceived uint32 `json:"packetsReceived"`
  1889  
  1890  	// BytesSent represents the total number of payload bytes sent on this PeerConnection
  1891  	// not including headers or padding.
  1892  	BytesSent uint64 `json:"bytesSent"`
  1893  
  1894  	// BytesReceived represents the total number of bytes received on this PeerConnection
  1895  	// not including headers or padding.
  1896  	BytesReceived uint64 `json:"bytesReceived"`
  1897  
  1898  	// RTCPTransportStatsID is the ID of the transport that gives stats for the RTCP
  1899  	// component If RTP and RTCP are not multiplexed and this record has only
  1900  	// the RTP component stats.
  1901  	RTCPTransportStatsID string `json:"rtcpTransportStatsId"`
  1902  
  1903  	// ICERole is set to the current value of the "role" attribute of the underlying
  1904  	// DTLSTransport's "iceTransport".
  1905  	ICERole ICERole `json:"iceRole"`
  1906  
  1907  	// DTLSState is set to the current value of the "state" attribute of the underlying DTLSTransport.
  1908  	DTLSState DTLSTransportState `json:"dtlsState"`
  1909  
  1910  	// ICEState is set to the current value of the "state" attribute of the underlying
  1911  	// RTCIceTransport's "state".
  1912  	ICEState ICETransportState `json:"iceState"`
  1913  
  1914  	// SelectedCandidatePairID is a unique identifier that is associated to the object
  1915  	// that was inspected to produce the ICECandidatePairStats associated with this transport.
  1916  	SelectedCandidatePairID string `json:"selectedCandidatePairId"`
  1917  
  1918  	// LocalCertificateID is the ID of the CertificateStats for the local certificate.
  1919  	// Present only if DTLS is negotiated.
  1920  	LocalCertificateID string `json:"localCertificateId"`
  1921  
  1922  	// LocalCertificateID is the ID of the CertificateStats for the remote certificate.
  1923  	// Present only if DTLS is negotiated.
  1924  	RemoteCertificateID string `json:"remoteCertificateId"`
  1925  
  1926  	// DTLSCipher is the descriptive name of the cipher suite used for the DTLS transport,
  1927  	// as defined in the "Description" column of the IANA cipher suite registry.
  1928  	DTLSCipher string `json:"dtlsCipher"`
  1929  
  1930  	// SRTPCipher is the descriptive name of the protection profile used for the SRTP
  1931  	// transport, as defined in the "Profile" column of the IANA DTLS-SRTP protection
  1932  	// profile registry.
  1933  	SRTPCipher string `json:"srtpCipher"`
  1934  }
  1935  
  1936  func (s TransportStats) statsMarker() {}
  1937  
  1938  func unmarshalTransportStats(b []byte) (TransportStats, error) {
  1939  	var transportStats TransportStats
  1940  	err := json.Unmarshal(b, &transportStats)
  1941  	if err != nil {
  1942  		return TransportStats{}, fmt.Errorf("unmarshal transport stats: %w", err)
  1943  	}
  1944  	return transportStats, nil
  1945  }
  1946  
  1947  // StatsICECandidatePairState is the state of an ICE candidate pair used in the
  1948  // ICECandidatePairStats object.
  1949  type StatsICECandidatePairState string
  1950  
  1951  func toStatsICECandidatePairState(state ice.CandidatePairState) (StatsICECandidatePairState, error) {
  1952  	switch state {
  1953  	case ice.CandidatePairStateWaiting:
  1954  		return StatsICECandidatePairStateWaiting, nil
  1955  	case ice.CandidatePairStateInProgress:
  1956  		return StatsICECandidatePairStateInProgress, nil
  1957  	case ice.CandidatePairStateFailed:
  1958  		return StatsICECandidatePairStateFailed, nil
  1959  	case ice.CandidatePairStateSucceeded:
  1960  		return StatsICECandidatePairStateSucceeded, nil
  1961  	default:
  1962  		// NOTE: this should never happen[tm]
  1963  		err := fmt.Errorf("%w: %s", errStatsICECandidateStateInvalid, state.String())
  1964  		return StatsICECandidatePairState("Unknown"), err
  1965  	}
  1966  }
  1967  
  1968  func toICECandidatePairStats(candidatePairStats ice.CandidatePairStats) (ICECandidatePairStats, error) {
  1969  	state, err := toStatsICECandidatePairState(candidatePairStats.State)
  1970  	if err != nil {
  1971  		return ICECandidatePairStats{}, err
  1972  	}
  1973  
  1974  	return ICECandidatePairStats{
  1975  		Timestamp: statsTimestampFrom(candidatePairStats.Timestamp),
  1976  		Type:      StatsTypeCandidatePair,
  1977  		ID:        newICECandidatePairStatsID(candidatePairStats.LocalCandidateID, candidatePairStats.RemoteCandidateID),
  1978  		// TransportID:
  1979  		LocalCandidateID:            candidatePairStats.LocalCandidateID,
  1980  		RemoteCandidateID:           candidatePairStats.RemoteCandidateID,
  1981  		State:                       state,
  1982  		Nominated:                   candidatePairStats.Nominated,
  1983  		PacketsSent:                 candidatePairStats.PacketsSent,
  1984  		PacketsReceived:             candidatePairStats.PacketsReceived,
  1985  		BytesSent:                   candidatePairStats.BytesSent,
  1986  		BytesReceived:               candidatePairStats.BytesReceived,
  1987  		LastPacketSentTimestamp:     statsTimestampFrom(candidatePairStats.LastPacketSentTimestamp),
  1988  		LastPacketReceivedTimestamp: statsTimestampFrom(candidatePairStats.LastPacketReceivedTimestamp),
  1989  		FirstRequestTimestamp:       statsTimestampFrom(candidatePairStats.FirstRequestTimestamp),
  1990  		LastRequestTimestamp:        statsTimestampFrom(candidatePairStats.LastRequestTimestamp),
  1991  		LastResponseTimestamp:       statsTimestampFrom(candidatePairStats.LastResponseTimestamp),
  1992  		TotalRoundTripTime:          candidatePairStats.TotalRoundTripTime,
  1993  		CurrentRoundTripTime:        candidatePairStats.CurrentRoundTripTime,
  1994  		AvailableOutgoingBitrate:    candidatePairStats.AvailableOutgoingBitrate,
  1995  		AvailableIncomingBitrate:    candidatePairStats.AvailableIncomingBitrate,
  1996  		CircuitBreakerTriggerCount:  candidatePairStats.CircuitBreakerTriggerCount,
  1997  		RequestsReceived:            candidatePairStats.RequestsReceived,
  1998  		RequestsSent:                candidatePairStats.RequestsSent,
  1999  		ResponsesReceived:           candidatePairStats.ResponsesReceived,
  2000  		ResponsesSent:               candidatePairStats.ResponsesSent,
  2001  		RetransmissionsReceived:     candidatePairStats.RetransmissionsReceived,
  2002  		RetransmissionsSent:         candidatePairStats.RetransmissionsSent,
  2003  		ConsentRequestsSent:         candidatePairStats.ConsentRequestsSent,
  2004  		ConsentExpiredTimestamp:     statsTimestampFrom(candidatePairStats.ConsentExpiredTimestamp),
  2005  	}, nil
  2006  }
  2007  
  2008  const (
  2009  	// StatsICECandidatePairStateFrozen means a check for this pair hasn't been
  2010  	// performed, and it can't yet be performed until some other check succeeds,
  2011  	// allowing this pair to unfreeze and move into the Waiting state.
  2012  	StatsICECandidatePairStateFrozen StatsICECandidatePairState = "frozen"
  2013  
  2014  	// StatsICECandidatePairStateWaiting means a check has not been performed for
  2015  	// this pair, and can be performed as soon as it is the highest-priority Waiting
  2016  	// pair on the check list.
  2017  	StatsICECandidatePairStateWaiting StatsICECandidatePairState = "waiting"
  2018  
  2019  	// StatsICECandidatePairStateInProgress means a check has been sent for this pair,
  2020  	// but the transaction is in progress.
  2021  	StatsICECandidatePairStateInProgress StatsICECandidatePairState = "in-progress"
  2022  
  2023  	// StatsICECandidatePairStateFailed means a check for this pair was already done
  2024  	// and failed, either never producing any response or producing an unrecoverable
  2025  	// failure response.
  2026  	StatsICECandidatePairStateFailed StatsICECandidatePairState = "failed"
  2027  
  2028  	// StatsICECandidatePairStateSucceeded means a check for this pair was already
  2029  	// done and produced a successful result.
  2030  	StatsICECandidatePairStateSucceeded StatsICECandidatePairState = "succeeded"
  2031  )
  2032  
  2033  // ICECandidatePairStats contains ICE candidate pair statistics related
  2034  // to the ICETransport objects.
  2035  type ICECandidatePairStats struct {
  2036  	// Timestamp is the timestamp associated with this object.
  2037  	Timestamp StatsTimestamp `json:"timestamp"`
  2038  
  2039  	// Type is the object's StatsType
  2040  	Type StatsType `json:"type"`
  2041  
  2042  	// ID is a unique id that is associated with the component inspected to produce
  2043  	// this Stats object. Two Stats objects will have the same ID if they were produced
  2044  	// by inspecting the same underlying object.
  2045  	ID string `json:"id"`
  2046  
  2047  	// TransportID is a unique identifier that is associated to the object that
  2048  	// was inspected to produce the TransportStats associated with this candidate pair.
  2049  	TransportID string `json:"transportId"`
  2050  
  2051  	// LocalCandidateID is a unique identifier that is associated to the object
  2052  	// that was inspected to produce the ICECandidateStats for the local candidate
  2053  	// associated with this candidate pair.
  2054  	LocalCandidateID string `json:"localCandidateId"`
  2055  
  2056  	// RemoteCandidateID is a unique identifier that is associated to the object
  2057  	// that was inspected to produce the ICECandidateStats for the remote candidate
  2058  	// associated with this candidate pair.
  2059  	RemoteCandidateID string `json:"remoteCandidateId"`
  2060  
  2061  	// State represents the state of the checklist for the local and remote
  2062  	// candidates in a pair.
  2063  	State StatsICECandidatePairState `json:"state"`
  2064  
  2065  	// Nominated is true when this valid pair that should be used for media
  2066  	// if it is the highest-priority one amongst those whose nominated flag is set
  2067  	Nominated bool `json:"nominated"`
  2068  
  2069  	// PacketsSent represents the total number of packets sent on this candidate pair.
  2070  	PacketsSent uint32 `json:"packetsSent"`
  2071  
  2072  	// PacketsReceived represents the total number of packets received on this candidate pair.
  2073  	PacketsReceived uint32 `json:"packetsReceived"`
  2074  
  2075  	// BytesSent represents the total number of payload bytes sent on this candidate pair
  2076  	// not including headers or padding.
  2077  	BytesSent uint64 `json:"bytesSent"`
  2078  
  2079  	// BytesReceived represents the total number of payload bytes received on this candidate pair
  2080  	// not including headers or padding.
  2081  	BytesReceived uint64 `json:"bytesReceived"`
  2082  
  2083  	// LastPacketSentTimestamp represents the timestamp at which the last packet was
  2084  	// sent on this particular candidate pair, excluding STUN packets.
  2085  	LastPacketSentTimestamp StatsTimestamp `json:"lastPacketSentTimestamp"`
  2086  
  2087  	// LastPacketReceivedTimestamp represents the timestamp at which the last packet
  2088  	// was received on this particular candidate pair, excluding STUN packets.
  2089  	LastPacketReceivedTimestamp StatsTimestamp `json:"lastPacketReceivedTimestamp"`
  2090  
  2091  	// FirstRequestTimestamp represents the timestamp at which the first STUN request
  2092  	// was sent on this particular candidate pair.
  2093  	FirstRequestTimestamp StatsTimestamp `json:"firstRequestTimestamp"`
  2094  
  2095  	// LastRequestTimestamp represents the timestamp at which the last STUN request
  2096  	// was sent on this particular candidate pair. The average interval between two
  2097  	// consecutive connectivity checks sent can be calculated with
  2098  	// (LastRequestTimestamp - FirstRequestTimestamp) / RequestsSent.
  2099  	LastRequestTimestamp StatsTimestamp `json:"lastRequestTimestamp"`
  2100  
  2101  	// LastResponseTimestamp represents the timestamp at which the last STUN response
  2102  	// was received on this particular candidate pair.
  2103  	LastResponseTimestamp StatsTimestamp `json:"lastResponseTimestamp"`
  2104  
  2105  	// TotalRoundTripTime represents the sum of all round trip time measurements
  2106  	// in seconds since the beginning of the session, based on STUN connectivity
  2107  	// check responses (ResponsesReceived), including those that reply to requests
  2108  	// that are sent in order to verify consent. The average round trip time can
  2109  	// be computed from TotalRoundTripTime by dividing it by ResponsesReceived.
  2110  	TotalRoundTripTime float64 `json:"totalRoundTripTime"`
  2111  
  2112  	// CurrentRoundTripTime represents the latest round trip time measured in seconds,
  2113  	// computed from both STUN connectivity checks, including those that are sent
  2114  	// for consent verification.
  2115  	CurrentRoundTripTime float64 `json:"currentRoundTripTime"`
  2116  
  2117  	// AvailableOutgoingBitrate is calculated by the underlying congestion control
  2118  	// by combining the available bitrate for all the outgoing RTP streams using
  2119  	// this candidate pair. The bitrate measurement does not count the size of the
  2120  	// IP or other transport layers like TCP or UDP. It is similar to the TIAS defined
  2121  	// in RFC 3890, i.e., it is measured in bits per second and the bitrate is calculated
  2122  	// over a 1 second window.
  2123  	AvailableOutgoingBitrate float64 `json:"availableOutgoingBitrate"`
  2124  
  2125  	// AvailableIncomingBitrate is calculated by the underlying congestion control
  2126  	// by combining the available bitrate for all the incoming RTP streams using
  2127  	// this candidate pair. The bitrate measurement does not count the size of the
  2128  	// IP or other transport layers like TCP or UDP. It is similar to the TIAS defined
  2129  	// in  RFC 3890, i.e., it is measured in bits per second and the bitrate is
  2130  	// calculated over a 1 second window.
  2131  	AvailableIncomingBitrate float64 `json:"availableIncomingBitrate"`
  2132  
  2133  	// CircuitBreakerTriggerCount represents the number of times the circuit breaker
  2134  	// is triggered for this particular 5-tuple, ceasing transmission.
  2135  	CircuitBreakerTriggerCount uint32 `json:"circuitBreakerTriggerCount"`
  2136  
  2137  	// RequestsReceived represents the total number of connectivity check requests
  2138  	// received (including retransmissions). It is impossible for the receiver to
  2139  	// tell whether the request was sent in order to check connectivity or check
  2140  	// consent, so all connectivity checks requests are counted here.
  2141  	RequestsReceived uint64 `json:"requestsReceived"`
  2142  
  2143  	// RequestsSent represents the total number of connectivity check requests
  2144  	// sent (not including retransmissions).
  2145  	RequestsSent uint64 `json:"requestsSent"`
  2146  
  2147  	// ResponsesReceived represents the total number of connectivity check responses received.
  2148  	ResponsesReceived uint64 `json:"responsesReceived"`
  2149  
  2150  	// ResponsesSent represents the total number of connectivity check responses sent.
  2151  	// Since we cannot distinguish connectivity check requests and consent requests,
  2152  	// all responses are counted.
  2153  	ResponsesSent uint64 `json:"responsesSent"`
  2154  
  2155  	// RetransmissionsReceived represents the total number of connectivity check
  2156  	// request retransmissions received.
  2157  	RetransmissionsReceived uint64 `json:"retransmissionsReceived"`
  2158  
  2159  	// RetransmissionsSent represents the total number of connectivity check
  2160  	// request retransmissions sent.
  2161  	RetransmissionsSent uint64 `json:"retransmissionsSent"`
  2162  
  2163  	// ConsentRequestsSent represents the total number of consent requests sent.
  2164  	ConsentRequestsSent uint64 `json:"consentRequestsSent"`
  2165  
  2166  	// ConsentExpiredTimestamp represents the timestamp at which the latest valid
  2167  	// STUN binding response expired.
  2168  	ConsentExpiredTimestamp StatsTimestamp `json:"consentExpiredTimestamp"`
  2169  
  2170  	// PacketsDiscardedOnSend retpresents the total number of packets for this candidate pair
  2171  	// that have been discarded due to socket errors, i.e. a socket error occurred
  2172  	// when handing the packets to the socket. This might happen due to various reasons,
  2173  	// including full buffer or no available memory.
  2174  	PacketsDiscardedOnSend uint32 `json:"packetsDiscardedOnSend"`
  2175  
  2176  	// BytesDiscardedOnSend represents the total number of bytes for this candidate pair
  2177  	// that have been discarded due to socket errors, i.e. a socket error occurred
  2178  	// when handing the packets containing the bytes to the socket. This might happen due
  2179  	// to various reasons, including full buffer or no available memory.
  2180  	// Calculated as defined in [RFC3550] section 6.4.1.
  2181  	BytesDiscardedOnSend uint32 `json:"bytesDiscardedOnSend"`
  2182  }
  2183  
  2184  func (s ICECandidatePairStats) statsMarker() {}
  2185  
  2186  func unmarshalICECandidatePairStats(b []byte) (ICECandidatePairStats, error) {
  2187  	var iceCandidatePairStats ICECandidatePairStats
  2188  	err := json.Unmarshal(b, &iceCandidatePairStats)
  2189  	if err != nil {
  2190  		return ICECandidatePairStats{}, fmt.Errorf("unmarshal ice candidate pair stats: %w", err)
  2191  	}
  2192  	return iceCandidatePairStats, nil
  2193  }
  2194  
  2195  // ICECandidateStats contains ICE candidate statistics related to the ICETransport objects.
  2196  type ICECandidateStats struct {
  2197  	// Timestamp is the timestamp associated with this object.
  2198  	Timestamp StatsTimestamp `json:"timestamp"`
  2199  
  2200  	// Type is the object's StatsType
  2201  	Type StatsType `json:"type"`
  2202  
  2203  	// ID is a unique id that is associated with the component inspected to produce
  2204  	// this Stats object. Two Stats objects will have the same ID if they were produced
  2205  	// by inspecting the same underlying object.
  2206  	ID string `json:"id"`
  2207  
  2208  	// TransportID is a unique identifier that is associated to the object that
  2209  	// was inspected to produce the TransportStats associated with this candidate.
  2210  	TransportID string `json:"transportId"`
  2211  
  2212  	// NetworkType represents the type of network interface used by the base of a
  2213  	// local candidate (the address the ICE agent sends from). Only present for
  2214  	// local candidates; it's not possible to know what type of network interface
  2215  	// a remote candidate is using.
  2216  	//
  2217  	// Note:
  2218  	// This stat only tells you about the network interface used by the first "hop";
  2219  	// it's possible that a connection will be bottlenecked by another type of network.
  2220  	// For example, when using Wi-Fi tethering, the networkType of the relevant candidate
  2221  	// would be "wifi", even when the next hop is over a cellular connection.
  2222  	//
  2223  	// DEPRECATED. Although it may still work in some browsers, the networkType property was deprecated for
  2224  	// preserving privacy.
  2225  	NetworkType string `json:"networkType,omitempty"`
  2226  
  2227  	// IP is the IP address of the candidate, allowing for IPv4 addresses and
  2228  	// IPv6 addresses, but fully qualified domain names (FQDNs) are not allowed.
  2229  	IP string `json:"ip"`
  2230  
  2231  	// Port is the port number of the candidate.
  2232  	Port int32 `json:"port"`
  2233  
  2234  	// Protocol is one of udp and tcp.
  2235  	Protocol string `json:"protocol"`
  2236  
  2237  	// CandidateType is the "Type" field of the ICECandidate.
  2238  	CandidateType ICECandidateType `json:"candidateType"`
  2239  
  2240  	// Priority is the "Priority" field of the ICECandidate.
  2241  	Priority int32 `json:"priority"`
  2242  
  2243  	// URL is the URL of the TURN or STUN server indicated in the that translated
  2244  	// this IP address. It is the URL address surfaced in an PeerConnectionICEEvent.
  2245  	URL string `json:"url"`
  2246  
  2247  	// RelayProtocol is the protocol used by the endpoint to communicate with the
  2248  	// TURN server. This is only present for local candidates. Valid values for
  2249  	// the TURN URL protocol is one of udp, tcp, or tls.
  2250  	RelayProtocol string `json:"relayProtocol"`
  2251  
  2252  	// Deleted is true if the candidate has been deleted/freed. For host candidates,
  2253  	// this means that any network resources (typically a socket) associated with the
  2254  	// candidate have been released. For TURN candidates, this means the TURN allocation
  2255  	// is no longer active.
  2256  	//
  2257  	// Only defined for local candidates. For remote candidates, this property is not applicable.
  2258  	Deleted bool `json:"deleted"`
  2259  }
  2260  
  2261  func (s ICECandidateStats) statsMarker() {}
  2262  
  2263  func unmarshalICECandidateStats(b []byte) (ICECandidateStats, error) {
  2264  	var iceCandidateStats ICECandidateStats
  2265  	err := json.Unmarshal(b, &iceCandidateStats)
  2266  	if err != nil {
  2267  		return ICECandidateStats{}, fmt.Errorf("unmarshal ice candidate stats: %w", err)
  2268  	}
  2269  	return iceCandidateStats, nil
  2270  }
  2271  
  2272  // CertificateStats contains information about a certificate used by an ICETransport.
  2273  type CertificateStats struct {
  2274  	// Timestamp is the timestamp associated with this object.
  2275  	Timestamp StatsTimestamp `json:"timestamp"`
  2276  
  2277  	// Type is the object's StatsType
  2278  	Type StatsType `json:"type"`
  2279  
  2280  	// ID is a unique id that is associated with the component inspected to produce
  2281  	// this Stats object. Two Stats objects will have the same ID if they were produced
  2282  	// by inspecting the same underlying object.
  2283  	ID string `json:"id"`
  2284  
  2285  	// Fingerprint is the fingerprint of the certificate.
  2286  	Fingerprint string `json:"fingerprint"`
  2287  
  2288  	// FingerprintAlgorithm is the hash function used to compute the certificate fingerprint. For instance, "sha-256".
  2289  	FingerprintAlgorithm string `json:"fingerprintAlgorithm"`
  2290  
  2291  	// Base64Certificate is the DER-encoded base-64 representation of the certificate.
  2292  	Base64Certificate string `json:"base64Certificate"`
  2293  
  2294  	// IssuerCertificateID refers to the stats object that contains the next certificate
  2295  	// in the certificate chain. If the current certificate is at the end of the chain
  2296  	// (i.e. a self-signed certificate), this will not be set.
  2297  	IssuerCertificateID string `json:"issuerCertificateId"`
  2298  }
  2299  
  2300  func (s CertificateStats) statsMarker() {}
  2301  
  2302  func unmarshalCertificateStats(b []byte) (CertificateStats, error) {
  2303  	var certificateStats CertificateStats
  2304  	err := json.Unmarshal(b, &certificateStats)
  2305  	if err != nil {
  2306  		return CertificateStats{}, fmt.Errorf("unmarshal certificate stats: %w", err)
  2307  	}
  2308  	return certificateStats, nil
  2309  }
  2310  
  2311  // SCTPTransportStats contains information about a certificate used by an SCTPTransport.
  2312  type SCTPTransportStats struct {
  2313  	// Timestamp is the timestamp associated with this object.
  2314  	Timestamp StatsTimestamp `json:"timestamp"`
  2315  
  2316  	// Type is the object's StatsType
  2317  	Type StatsType `json:"type"`
  2318  
  2319  	// ID is a unique id that is associated with the component inspected to produce
  2320  	// this Stats object. Two Stats objects will have the same ID if they were produced
  2321  	// by inspecting the same underlying object.
  2322  	ID string `json:"id"`
  2323  
  2324  	// TransportID is the identifier of the object that was inspected to produce the
  2325  	// RTCTransportStats for the DTLSTransport and ICETransport supporting the SCTP transport.
  2326  	TransportID string `json:"transportId"`
  2327  
  2328  	// SmoothedRoundTripTime is the latest smoothed round-trip time value, corresponding to spinfo_srtt defined in [RFC6458]
  2329  	// but converted to seconds. If there has been no round-trip time measurements yet, this value is undefined.
  2330  	SmoothedRoundTripTime float64 `json:"smoothedRoundTripTime"`
  2331  
  2332  	// CongestionWindow is the latest congestion window, corresponding to spinfo_cwnd defined in [RFC6458].
  2333  	CongestionWindow uint32 `json:"congestionWindow"`
  2334  
  2335  	// ReceiverWindow is the latest receiver window, corresponding to sstat_rwnd defined in [RFC6458].
  2336  	ReceiverWindow uint32 `json:"receiverWindow"`
  2337  
  2338  	// MTU is the latest maximum transmission unit, corresponding to spinfo_mtu defined in [RFC6458].
  2339  	MTU uint32 `json:"mtu"`
  2340  
  2341  	// UNACKData is the number of unacknowledged DATA chunks, corresponding to sstat_unackdata defined in [RFC6458].
  2342  	UNACKData uint32 `json:"unackData"`
  2343  
  2344  	// BytesSent represents the total number of bytes sent on this SCTPTransport
  2345  	BytesSent uint64 `json:"bytesSent"`
  2346  
  2347  	// BytesReceived represents the total number of bytes received on this SCTPTransport
  2348  	BytesReceived uint64 `json:"bytesReceived"`
  2349  }
  2350  
  2351  func (s SCTPTransportStats) statsMarker() {}
  2352  
  2353  func unmarshalSCTPTransportStats(b []byte) (SCTPTransportStats, error) {
  2354  	var sctpTransportStats SCTPTransportStats
  2355  	if err := json.Unmarshal(b, &sctpTransportStats); err != nil {
  2356  		return SCTPTransportStats{}, fmt.Errorf("unmarshal sctp transport stats: %w", err)
  2357  	}
  2358  	return sctpTransportStats, nil
  2359  }