stats.go 87 KB

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