xref: /aosp_15_r20/external/webrtc/api/legacy_stats_types.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright 2014 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "api/legacy_stats_types.h"
12 
13 #include <string.h>
14 
15 #include "absl/algorithm/container.h"
16 #include "api/make_ref_counted.h"
17 #include "rtc_base/checks.h"
18 #include "rtc_base/string_encode.h"
19 
20 // TODO(tommi): Could we have a static map of value name -> expected type
21 // and use this to RTC_DCHECK on correct usage (somewhat strongly typed values)?
22 // Alternatively, we could define the names+type in a separate document and
23 // generate strongly typed inline C++ code that forces the correct type to be
24 // used for a given name at compile time.
25 
26 namespace webrtc {
27 namespace {
28 
29 // The id of StatsReport of type kStatsReportTypeBwe.
30 const char kStatsReportVideoBweId[] = "bweforvideo";
31 
32 // NOTE: These names need to be consistent with an external
33 // specification (W3C Stats Identifiers).
InternalTypeToString(StatsReport::StatsType type)34 const char* InternalTypeToString(StatsReport::StatsType type) {
35   switch (type) {
36     case StatsReport::kStatsReportTypeSession:
37       return "googLibjingleSession";
38     case StatsReport::kStatsReportTypeBwe:
39       return "VideoBwe";
40     case StatsReport::kStatsReportTypeRemoteSsrc:
41       return "remoteSsrc";
42     case StatsReport::kStatsReportTypeSsrc:
43       return "ssrc";
44     case StatsReport::kStatsReportTypeTrack:
45       return "googTrack";
46     case StatsReport::kStatsReportTypeIceLocalCandidate:
47       return "localcandidate";
48     case StatsReport::kStatsReportTypeIceRemoteCandidate:
49       return "remotecandidate";
50     case StatsReport::kStatsReportTypeTransport:
51       return "transport";
52     case StatsReport::kStatsReportTypeComponent:
53       return "googComponent";
54     case StatsReport::kStatsReportTypeCandidatePair:
55       return "googCandidatePair";
56     case StatsReport::kStatsReportTypeCertificate:
57       return "googCertificate";
58     case StatsReport::kStatsReportTypeDataChannel:
59       return "datachannel";
60   }
61   RTC_DCHECK_NOTREACHED();
62   return nullptr;
63 }
64 
65 class BandwidthEstimationId : public StatsReport::IdBase {
66  public:
BandwidthEstimationId()67   BandwidthEstimationId()
68       : StatsReport::IdBase(StatsReport::kStatsReportTypeBwe) {}
ToString() const69   std::string ToString() const override { return kStatsReportVideoBweId; }
70 };
71 
72 class TypedId : public StatsReport::IdBase {
73  public:
TypedId(StatsReport::StatsType type,const std::string & id)74   TypedId(StatsReport::StatsType type, const std::string& id)
75       : StatsReport::IdBase(type), id_(id) {}
76 
Equals(const IdBase & other) const77   bool Equals(const IdBase& other) const override {
78     return IdBase::Equals(other) &&
79            static_cast<const TypedId&>(other).id_ == id_;
80   }
81 
ToString() const82   std::string ToString() const override {
83     return std::string(InternalTypeToString(type_)) + kSeparator + id_;
84   }
85 
86  protected:
87   const std::string id_;
88 };
89 
90 class TypedIntId : public StatsReport::IdBase {
91  public:
TypedIntId(StatsReport::StatsType type,int id)92   TypedIntId(StatsReport::StatsType type, int id)
93       : StatsReport::IdBase(type), id_(id) {}
94 
Equals(const IdBase & other) const95   bool Equals(const IdBase& other) const override {
96     return IdBase::Equals(other) &&
97            static_cast<const TypedIntId&>(other).id_ == id_;
98   }
99 
ToString() const100   std::string ToString() const override {
101     return std::string(InternalTypeToString(type_)) + kSeparator +
102            rtc::ToString(id_);
103   }
104 
105  protected:
106   const int id_;
107 };
108 
109 class IdWithDirection : public TypedId {
110  public:
IdWithDirection(StatsReport::StatsType type,const std::string & id,StatsReport::Direction direction)111   IdWithDirection(StatsReport::StatsType type,
112                   const std::string& id,
113                   StatsReport::Direction direction)
114       : TypedId(type, id), direction_(direction) {}
115 
Equals(const IdBase & other) const116   bool Equals(const IdBase& other) const override {
117     return TypedId::Equals(other) &&
118            static_cast<const IdWithDirection&>(other).direction_ == direction_;
119   }
120 
ToString() const121   std::string ToString() const override {
122     std::string ret(TypedId::ToString());
123     ret += kSeparator;
124     ret += direction_ == StatsReport::kSend ? "send" : "recv";
125     return ret;
126   }
127 
128  private:
129   const StatsReport::Direction direction_;
130 };
131 
132 class CandidateId : public TypedId {
133  public:
CandidateId(bool local,const std::string & id)134   CandidateId(bool local, const std::string& id)
135       : TypedId(local ? StatsReport::kStatsReportTypeIceLocalCandidate
136                       : StatsReport::kStatsReportTypeIceRemoteCandidate,
137                 id) {}
138 
ToString() const139   std::string ToString() const override { return "Cand-" + id_; }
140 };
141 
142 class ComponentId : public StatsReport::IdBase {
143  public:
ComponentId(const std::string & content_name,int component)144   ComponentId(const std::string& content_name, int component)
145       : ComponentId(StatsReport::kStatsReportTypeComponent,
146                     content_name,
147                     component) {}
148 
Equals(const IdBase & other) const149   bool Equals(const IdBase& other) const override {
150     return IdBase::Equals(other) &&
151            static_cast<const ComponentId&>(other).component_ == component_ &&
152            static_cast<const ComponentId&>(other).content_name_ ==
153                content_name_;
154   }
155 
ToString() const156   std::string ToString() const override { return ToString("Channel-"); }
157 
158  protected:
ComponentId(StatsReport::StatsType type,const std::string & content_name,int component)159   ComponentId(StatsReport::StatsType type,
160               const std::string& content_name,
161               int component)
162       : IdBase(type), content_name_(content_name), component_(component) {}
163 
ToString(const char * prefix) const164   std::string ToString(const char* prefix) const {
165     std::string ret(prefix);
166     ret += content_name_;
167     ret += '-';
168     ret += rtc::ToString(component_);
169     return ret;
170   }
171 
172  private:
173   const std::string content_name_;
174   const int component_;
175 };
176 
177 class CandidatePairId : public ComponentId {
178  public:
CandidatePairId(const std::string & content_name,int component,int index)179   CandidatePairId(const std::string& content_name, int component, int index)
180       : ComponentId(StatsReport::kStatsReportTypeCandidatePair,
181                     content_name,
182                     component),
183         index_(index) {}
184 
Equals(const IdBase & other) const185   bool Equals(const IdBase& other) const override {
186     return ComponentId::Equals(other) &&
187            static_cast<const CandidatePairId&>(other).index_ == index_;
188   }
189 
ToString() const190   std::string ToString() const override {
191     std::string ret(ComponentId::ToString("Conn-"));
192     ret += '-';
193     ret += rtc::ToString(index_);
194     return ret;
195   }
196 
197  private:
198   const int index_;
199 };
200 
201 }  // namespace
202 
IdBase(StatsType type)203 StatsReport::IdBase::IdBase(StatsType type) : type_(type) {}
~IdBase()204 StatsReport::IdBase::~IdBase() {}
205 
type() const206 StatsReport::StatsType StatsReport::IdBase::type() const {
207   return type_;
208 }
209 
Equals(const IdBase & other) const210 bool StatsReport::IdBase::Equals(const IdBase& other) const {
211   return other.type_ == type_;
212 }
213 
Value(StatsValueName name,int64_t value,Type int_type)214 StatsReport::Value::Value(StatsValueName name, int64_t value, Type int_type)
215     : name(name), type_(int_type) {
216   RTC_DCHECK(type_ == kInt || type_ == kInt64);
217   type_ == kInt ? value_.int_ = static_cast<int>(value) : value_.int64_ = value;
218 }
219 
Value(StatsValueName name,float f)220 StatsReport::Value::Value(StatsValueName name, float f)
221     : name(name), type_(kFloat) {
222   value_.float_ = f;
223 }
224 
Value(StatsValueName name,const std::string & value)225 StatsReport::Value::Value(StatsValueName name, const std::string& value)
226     : name(name), type_(kString) {
227   value_.string_ = new std::string(value);
228 }
229 
Value(StatsValueName name,const char * value)230 StatsReport::Value::Value(StatsValueName name, const char* value)
231     : name(name), type_(kStaticString) {
232   value_.static_string_ = value;
233 }
234 
Value(StatsValueName name,bool b)235 StatsReport::Value::Value(StatsValueName name, bool b)
236     : name(name), type_(kBool) {
237   value_.bool_ = b;
238 }
239 
Value(StatsValueName name,const Id & value)240 StatsReport::Value::Value(StatsValueName name, const Id& value)
241     : name(name), type_(kId) {
242   value_.id_ = new Id(value);
243 }
244 
~Value()245 StatsReport::Value::~Value() {
246   switch (type_) {
247     case kInt:
248     case kInt64:
249     case kFloat:
250     case kBool:
251     case kStaticString:
252       break;
253     case kString:
254       delete value_.string_;
255       break;
256     case kId:
257       delete value_.id_;
258       break;
259   }
260 }
261 
Equals(const Value & other) const262 bool StatsReport::Value::Equals(const Value& other) const {
263   if (name != other.name)
264     return false;
265 
266   // There's a 1:1 relation between a name and a type, so we don't have to
267   // check that.
268   RTC_DCHECK_EQ(type_, other.type_);
269 
270   switch (type_) {
271     case kInt:
272       return value_.int_ == other.value_.int_;
273     case kInt64:
274       return value_.int64_ == other.value_.int64_;
275     case kFloat:
276       return value_.float_ == other.value_.float_;
277     case kStaticString: {
278 #if RTC_DCHECK_IS_ON
279       if (value_.static_string_ != other.value_.static_string_) {
280         RTC_DCHECK(strcmp(value_.static_string_, other.value_.static_string_) !=
281                    0)
282             << "Duplicate global?";
283       }
284 #endif
285       return value_.static_string_ == other.value_.static_string_;
286     }
287     case kString:
288       return *value_.string_ == *other.value_.string_;
289     case kBool:
290       return value_.bool_ == other.value_.bool_;
291     case kId:
292       return (*value_.id_)->Equals(*other.value_.id_);
293   }
294   RTC_DCHECK_NOTREACHED();
295   return false;
296 }
297 
operator ==(const std::string & value) const298 bool StatsReport::Value::operator==(const std::string& value) const {
299   return (type_ == kString && value_.string_->compare(value) == 0) ||
300          (type_ == kStaticString && value.compare(value_.static_string_) == 0);
301 }
302 
operator ==(const char * value) const303 bool StatsReport::Value::operator==(const char* value) const {
304   if (type_ == kString)
305     return value_.string_->compare(value) == 0;
306   if (type_ != kStaticString)
307     return false;
308 #if RTC_DCHECK_IS_ON
309   if (value_.static_string_ != value)
310     RTC_DCHECK(strcmp(value_.static_string_, value) != 0)
311         << "Duplicate global?";
312 #endif
313   return value == value_.static_string_;
314 }
315 
operator ==(int64_t value) const316 bool StatsReport::Value::operator==(int64_t value) const {
317   return type_ == kInt ? value_.int_ == static_cast<int>(value)
318                        : (type_ == kInt64 ? value_.int64_ == value : false);
319 }
320 
operator ==(bool value) const321 bool StatsReport::Value::operator==(bool value) const {
322   return type_ == kBool && value_.bool_ == value;
323 }
324 
operator ==(float value) const325 bool StatsReport::Value::operator==(float value) const {
326   return type_ == kFloat && value_.float_ == value;
327 }
328 
operator ==(const Id & value) const329 bool StatsReport::Value::operator==(const Id& value) const {
330   return type_ == kId && (*value_.id_)->Equals(value);
331 }
332 
int_val() const333 int StatsReport::Value::int_val() const {
334   RTC_DCHECK_EQ(type_, kInt);
335   return value_.int_;
336 }
337 
int64_val() const338 int64_t StatsReport::Value::int64_val() const {
339   RTC_DCHECK_EQ(type_, kInt64);
340   return value_.int64_;
341 }
342 
float_val() const343 float StatsReport::Value::float_val() const {
344   RTC_DCHECK_EQ(type_, kFloat);
345   return value_.float_;
346 }
347 
static_string_val() const348 const char* StatsReport::Value::static_string_val() const {
349   RTC_DCHECK_EQ(type_, kStaticString);
350   return value_.static_string_;
351 }
352 
string_val() const353 const std::string& StatsReport::Value::string_val() const {
354   RTC_DCHECK_EQ(type_, kString);
355   return *value_.string_;
356 }
357 
bool_val() const358 bool StatsReport::Value::bool_val() const {
359   RTC_DCHECK_EQ(type_, kBool);
360   return value_.bool_;
361 }
362 
display_name() const363 const char* StatsReport::Value::display_name() const {
364   switch (name) {
365     case kStatsValueNameAecDivergentFilterFraction:
366       return "aecDivergentFilterFraction";
367     case kStatsValueNameAudioOutputLevel:
368       return "audioOutputLevel";
369     case kStatsValueNameAudioInputLevel:
370       return "audioInputLevel";
371     case kStatsValueNameBytesSent:
372       return "bytesSent";
373     case kStatsValueNameConcealedSamples:
374       return "concealedSamples";
375     case kStatsValueNameConcealmentEvents:
376       return "concealmentEvents";
377     case kStatsValueNamePacketsSent:
378       return "packetsSent";
379     case kStatsValueNameBytesReceived:
380       return "bytesReceived";
381     case kStatsValueNameLabel:
382       return "label";
383     case kStatsValueNamePacketsReceived:
384       return "packetsReceived";
385     case kStatsValueNamePacketsLost:
386       return "packetsLost";
387     case kStatsValueNameProtocol:
388       return "protocol";
389     case kStatsValueNameTotalSamplesReceived:
390       return "totalSamplesReceived";
391     case kStatsValueNameTransportId:
392       return "transportId";
393     case kStatsValueNameSelectedCandidatePairId:
394       return "selectedCandidatePairId";
395     case kStatsValueNameSsrc:
396       return "ssrc";
397     case kStatsValueNameState:
398       return "state";
399     case kStatsValueNameDataChannelId:
400       return "datachannelid";
401     case kStatsValueNameFramesDecoded:
402       return "framesDecoded";
403     case kStatsValueNameFramesEncoded:
404       return "framesEncoded";
405     case kStatsValueNameJitterBufferDelay:
406       return "jitterBufferDelay";
407     case kStatsValueNameCodecImplementationName:
408       return "codecImplementationName";
409     case kStatsValueNameMediaType:
410       return "mediaType";
411     case kStatsValueNameQpSum:
412       return "qpSum";
413     // 'goog' prefixed constants.
414     case kStatsValueNameAccelerateRate:
415       return "googAccelerateRate";
416     case kStatsValueNameActiveConnection:
417       return "googActiveConnection";
418     case kStatsValueNameActualEncBitrate:
419       return "googActualEncBitrate";
420     case kStatsValueNameAvailableReceiveBandwidth:
421       return "googAvailableReceiveBandwidth";
422     case kStatsValueNameAvailableSendBandwidth:
423       return "googAvailableSendBandwidth";
424     case kStatsValueNameAvgEncodeMs:
425       return "googAvgEncodeMs";
426     case kStatsValueNameBucketDelay:
427       return "googBucketDelay";
428     case kStatsValueNameBandwidthLimitedResolution:
429       return "googBandwidthLimitedResolution";
430     // STUN ping related attributes.
431     //
432     // TODO(zhihuang) Rename these stats to follow the standards.
433     // Connectivity checks.
434     case kStatsValueNameSentPingRequestsTotal:
435       return "requestsSent";
436     case kStatsValueNameSentPingRequestsBeforeFirstResponse:
437       return "consentRequestsSent";
438     case kStatsValueNameSentPingResponses:
439       return "responsesSent";
440     case kStatsValueNameRecvPingRequests:
441       return "requestsReceived";
442     case kStatsValueNameRecvPingResponses:
443       return "responsesReceived";
444     // STUN Keepalive pings.
445     case kStatsValueNameSentStunKeepaliveRequests:
446       return "stunKeepaliveRequestsSent";
447     case kStatsValueNameRecvStunKeepaliveResponses:
448       return "stunKeepaliveResponsesReceived";
449     case kStatsValueNameStunKeepaliveRttTotal:
450       return "stunKeepaliveRttTotal";
451     case kStatsValueNameStunKeepaliveRttSquaredTotal:
452       return "stunKeepaliveRttSquaredTotal";
453 
454     // Candidate related attributes. Values are taken from
455     // http://w3c.github.io/webrtc-stats/#rtcstatstype-enum*.
456     case kStatsValueNameCandidateIPAddress:
457       return "ipAddress";
458     case kStatsValueNameCandidateNetworkType:
459       return "networkType";
460     case kStatsValueNameCandidatePortNumber:
461       return "portNumber";
462     case kStatsValueNameCandidatePriority:
463       return "priority";
464     case kStatsValueNameCandidateTransportType:
465       return "transport";
466     case kStatsValueNameCandidateType:
467       return "candidateType";
468 
469     case kStatsValueNameChannelId:
470       return "googChannelId";
471     case kStatsValueNameCodecName:
472       return "googCodecName";
473     case kStatsValueNameComponent:
474       return "googComponent";
475     case kStatsValueNameContentName:
476       return "googContentName";
477     case kStatsValueNameContentType:
478       return "googContentType";
479     case kStatsValueNameCpuLimitedResolution:
480       return "googCpuLimitedResolution";
481     case kStatsValueNameDecodingCTSG:
482       return "googDecodingCTSG";
483     case kStatsValueNameDecodingCTN:
484       return "googDecodingCTN";
485     case kStatsValueNameDecodingMutedOutput:
486       return "googDecodingMuted";
487     case kStatsValueNameDecodingNormal:
488       return "googDecodingNormal";
489     case kStatsValueNameDecodingPLC:
490       return "googDecodingPLC";
491     case kStatsValueNameDecodingCodecPLC:
492       return "googDecodingCodecPLC";
493     case kStatsValueNameDecodingCNG:
494       return "googDecodingCNG";
495     case kStatsValueNameDecodingPLCCNG:
496       return "googDecodingPLCCNG";
497     case kStatsValueNameDer:
498       return "googDerBase64";
499     case kStatsValueNameDtlsCipher:
500       return "dtlsCipher";
501     case kStatsValueNameEchoDelayMedian:
502       return "googEchoCancellationEchoDelayMedian";
503     case kStatsValueNameEchoDelayStdDev:
504       return "googEchoCancellationEchoDelayStdDev";
505     case kStatsValueNameEchoReturnLoss:
506       return "googEchoCancellationReturnLoss";
507     case kStatsValueNameEchoReturnLossEnhancement:
508       return "googEchoCancellationReturnLossEnhancement";
509     case kStatsValueNameEncodeUsagePercent:
510       return "googEncodeUsagePercent";
511     case kStatsValueNameExpandRate:
512       return "googExpandRate";
513     case kStatsValueNameFingerprint:
514       return "googFingerprint";
515     case kStatsValueNameFingerprintAlgorithm:
516       return "googFingerprintAlgorithm";
517     case kStatsValueNameFirsReceived:
518       return "googFirsReceived";
519     case kStatsValueNameFirsSent:
520       return "googFirsSent";
521     case kStatsValueNameFirstFrameReceivedToDecodedMs:
522       return "googFirstFrameReceivedToDecodedMs";
523     case kStatsValueNameFrameHeightInput:
524       return "googFrameHeightInput";
525     case kStatsValueNameFrameHeightReceived:
526       return "googFrameHeightReceived";
527     case kStatsValueNameFrameHeightSent:
528       return "googFrameHeightSent";
529     case kStatsValueNameFrameRateReceived:
530       return "googFrameRateReceived";
531     case kStatsValueNameFrameRateDecoded:
532       return "googFrameRateDecoded";
533     case kStatsValueNameFrameRateOutput:
534       return "googFrameRateOutput";
535     case kStatsValueNameDecodeMs:
536       return "googDecodeMs";
537     case kStatsValueNameMaxDecodeMs:
538       return "googMaxDecodeMs";
539     case kStatsValueNameCurrentDelayMs:
540       return "googCurrentDelayMs";
541     case kStatsValueNameTargetDelayMs:
542       return "googTargetDelayMs";
543     case kStatsValueNameJitterBufferMs:
544       return "googJitterBufferMs";
545     case kStatsValueNameMinPlayoutDelayMs:
546       return "googMinPlayoutDelayMs";
547     case kStatsValueNameRenderDelayMs:
548       return "googRenderDelayMs";
549     case kStatsValueNameCaptureStartNtpTimeMs:
550       return "googCaptureStartNtpTimeMs";
551     case kStatsValueNameFrameRateInput:
552       return "googFrameRateInput";
553     case kStatsValueNameFrameRateSent:
554       return "googFrameRateSent";
555     case kStatsValueNameFrameWidthInput:
556       return "googFrameWidthInput";
557     case kStatsValueNameFrameWidthReceived:
558       return "googFrameWidthReceived";
559     case kStatsValueNameFrameWidthSent:
560       return "googFrameWidthSent";
561     case kStatsValueNameHasEnteredLowResolution:
562       return "googHasEnteredLowResolution";
563     case kStatsValueNameHugeFramesSent:
564       return "hugeFramesSent";
565     case kStatsValueNameInitiator:
566       return "googInitiator";
567     case kStatsValueNameInterframeDelayMaxMs:
568       return "googInterframeDelayMax";
569     case kStatsValueNameIssuerId:
570       return "googIssuerId";
571     case kStatsValueNameJitterReceived:
572       return "googJitterReceived";
573     case kStatsValueNameLocalAddress:
574       return "googLocalAddress";
575     case kStatsValueNameLocalCandidateId:
576       return "localCandidateId";
577     case kStatsValueNameLocalCandidateType:
578       return "googLocalCandidateType";
579     case kStatsValueNameLocalCertificateId:
580       return "localCertificateId";
581     case kStatsValueNameAdaptationChanges:
582       return "googAdaptationChanges";
583     case kStatsValueNameNacksReceived:
584       return "googNacksReceived";
585     case kStatsValueNameNacksSent:
586       return "googNacksSent";
587     case kStatsValueNamePreemptiveExpandRate:
588       return "googPreemptiveExpandRate";
589     case kStatsValueNamePlisReceived:
590       return "googPlisReceived";
591     case kStatsValueNamePlisSent:
592       return "googPlisSent";
593     case kStatsValueNamePreferredJitterBufferMs:
594       return "googPreferredJitterBufferMs";
595     case kStatsValueNameReceiving:
596       return "googReadable";
597     case kStatsValueNameRemoteAddress:
598       return "googRemoteAddress";
599     case kStatsValueNameRemoteCandidateId:
600       return "remoteCandidateId";
601     case kStatsValueNameRemoteCandidateType:
602       return "googRemoteCandidateType";
603     case kStatsValueNameRemoteCertificateId:
604       return "remoteCertificateId";
605     case kStatsValueNameResidualEchoLikelihood:
606       return "googResidualEchoLikelihood";
607     case kStatsValueNameResidualEchoLikelihoodRecentMax:
608       return "googResidualEchoLikelihoodRecentMax";
609     case kStatsValueNameAnaBitrateActionCounter:
610       return "googAnaBitrateActionCounter";
611     case kStatsValueNameAnaChannelActionCounter:
612       return "googAnaChannelActionCounter";
613     case kStatsValueNameAnaDtxActionCounter:
614       return "googAnaDtxActionCounter";
615     case kStatsValueNameAnaFecActionCounter:
616       return "googAnaFecActionCounter";
617     case kStatsValueNameAnaFrameLengthIncreaseCounter:
618       return "googAnaFrameLengthIncreaseCounter";
619     case kStatsValueNameAnaFrameLengthDecreaseCounter:
620       return "googAnaFrameLengthDecreaseCounter";
621     case kStatsValueNameAnaUplinkPacketLossFraction:
622       return "googAnaUplinkPacketLossFraction";
623     case kStatsValueNameRetransmitBitrate:
624       return "googRetransmitBitrate";
625     case kStatsValueNameRtt:
626       return "googRtt";
627     case kStatsValueNameSecondaryDecodedRate:
628       return "googSecondaryDecodedRate";
629     case kStatsValueNameSecondaryDiscardedRate:
630       return "googSecondaryDiscardedRate";
631     case kStatsValueNameSendPacketsDiscarded:
632       return "packetsDiscardedOnSend";
633     case kStatsValueNameSpeechExpandRate:
634       return "googSpeechExpandRate";
635     case kStatsValueNameSrtpCipher:
636       return "srtpCipher";
637     case kStatsValueNameTargetEncBitrate:
638       return "googTargetEncBitrate";
639     case kStatsValueNameTotalAudioEnergy:
640       return "totalAudioEnergy";
641     case kStatsValueNameTotalSamplesDuration:
642       return "totalSamplesDuration";
643     case kStatsValueNameTransmitBitrate:
644       return "googTransmitBitrate";
645     case kStatsValueNameTransportType:
646       return "googTransportType";
647     case kStatsValueNameTrackId:
648       return "googTrackId";
649     case kStatsValueNameTimingFrameInfo:
650       return "googTimingFrameInfo";
651     case kStatsValueNameWritable:
652       return "googWritable";
653     case kStatsValueNameAudioDeviceUnderrunCounter:
654       return "googAudioDeviceUnderrunCounter";
655     case kStatsValueNameLocalCandidateRelayProtocol:
656       return "googLocalCandidateRelayProtocol";
657   }
658 
659   return nullptr;
660 }
661 
ToString() const662 std::string StatsReport::Value::ToString() const {
663   switch (type_) {
664     case kInt:
665       return rtc::ToString(value_.int_);
666     case kInt64:
667       return rtc::ToString(value_.int64_);
668     case kFloat:
669       return rtc::ToString(value_.float_);
670     case kStaticString:
671       return std::string(value_.static_string_);
672     case kString:
673       return *value_.string_;
674     case kBool:
675       return value_.bool_ ? "true" : "false";
676     case kId:
677       return (*value_.id_)->ToString();
678   }
679   RTC_DCHECK_NOTREACHED();
680   return std::string();
681 }
682 
StatsReport(const Id & id)683 StatsReport::StatsReport(const Id& id) : id_(id), timestamp_(0.0) {
684   RTC_DCHECK(id_.get());
685 }
686 
687 StatsReport::~StatsReport() = default;
688 
689 // static
NewBandwidthEstimationId()690 StatsReport::Id StatsReport::NewBandwidthEstimationId() {
691   return rtc::make_ref_counted<BandwidthEstimationId>();
692 }
693 
694 // static
NewTypedId(StatsType type,const std::string & id)695 StatsReport::Id StatsReport::NewTypedId(StatsType type, const std::string& id) {
696   return rtc::make_ref_counted<TypedId>(type, id);
697 }
698 
699 // static
NewTypedIntId(StatsType type,int id)700 StatsReport::Id StatsReport::NewTypedIntId(StatsType type, int id) {
701   return rtc::make_ref_counted<TypedIntId>(type, id);
702 }
703 
704 // static
NewIdWithDirection(StatsType type,const std::string & id,StatsReport::Direction direction)705 StatsReport::Id StatsReport::NewIdWithDirection(
706     StatsType type,
707     const std::string& id,
708     StatsReport::Direction direction) {
709   return rtc::make_ref_counted<IdWithDirection>(type, id, direction);
710 }
711 
712 // static
NewCandidateId(bool local,const std::string & id)713 StatsReport::Id StatsReport::NewCandidateId(bool local, const std::string& id) {
714   return rtc::make_ref_counted<CandidateId>(local, id);
715 }
716 
717 // static
NewComponentId(const std::string & content_name,int component)718 StatsReport::Id StatsReport::NewComponentId(const std::string& content_name,
719                                             int component) {
720   return rtc::make_ref_counted<ComponentId>(content_name, component);
721 }
722 
723 // static
NewCandidatePairId(const std::string & content_name,int component,int index)724 StatsReport::Id StatsReport::NewCandidatePairId(const std::string& content_name,
725                                                 int component,
726                                                 int index) {
727   return rtc::make_ref_counted<CandidatePairId>(content_name, component, index);
728 }
729 
TypeToString() const730 const char* StatsReport::TypeToString() const {
731   return InternalTypeToString(id_->type());
732 }
733 
AddString(StatsReport::StatsValueName name,const std::string & value)734 void StatsReport::AddString(StatsReport::StatsValueName name,
735                             const std::string& value) {
736   const Value* found = FindValue(name);
737   if (!found || !(*found == value))
738     values_[name] = ValuePtr(new Value(name, value));
739 }
740 
AddString(StatsReport::StatsValueName name,const char * value)741 void StatsReport::AddString(StatsReport::StatsValueName name,
742                             const char* value) {
743   const Value* found = FindValue(name);
744   if (!found || !(*found == value))
745     values_[name] = ValuePtr(new Value(name, value));
746 }
747 
AddInt64(StatsReport::StatsValueName name,int64_t value)748 void StatsReport::AddInt64(StatsReport::StatsValueName name, int64_t value) {
749   const Value* found = FindValue(name);
750   if (!found || !(*found == value))
751     values_[name] = ValuePtr(new Value(name, value, Value::kInt64));
752 }
753 
AddInt(StatsReport::StatsValueName name,int value)754 void StatsReport::AddInt(StatsReport::StatsValueName name, int value) {
755   const Value* found = FindValue(name);
756   if (!found || !(*found == static_cast<int64_t>(value)))
757     values_[name] = ValuePtr(new Value(name, value, Value::kInt));
758 }
759 
AddFloat(StatsReport::StatsValueName name,float value)760 void StatsReport::AddFloat(StatsReport::StatsValueName name, float value) {
761   const Value* found = FindValue(name);
762   if (!found || !(*found == value))
763     values_[name] = ValuePtr(new Value(name, value));
764 }
765 
AddBoolean(StatsReport::StatsValueName name,bool value)766 void StatsReport::AddBoolean(StatsReport::StatsValueName name, bool value) {
767   const Value* found = FindValue(name);
768   if (!found || !(*found == value))
769     values_[name] = ValuePtr(new Value(name, value));
770 }
771 
AddId(StatsReport::StatsValueName name,const Id & value)772 void StatsReport::AddId(StatsReport::StatsValueName name, const Id& value) {
773   const Value* found = FindValue(name);
774   if (!found || !(*found == value))
775     values_[name] = ValuePtr(new Value(name, value));
776 }
777 
FindValue(StatsValueName name) const778 const StatsReport::Value* StatsReport::FindValue(StatsValueName name) const {
779   Values::const_iterator it = values_.find(name);
780   return it == values_.end() ? nullptr : it->second.get();
781 }
782 
StatsCollection()783 StatsCollection::StatsCollection() {}
784 
~StatsCollection()785 StatsCollection::~StatsCollection() {
786   RTC_DCHECK(thread_checker_.IsCurrent());
787   for (auto* r : list_)
788     delete r;
789 }
790 
begin() const791 StatsCollection::const_iterator StatsCollection::begin() const {
792   RTC_DCHECK(thread_checker_.IsCurrent());
793   return list_.begin();
794 }
795 
end() const796 StatsCollection::const_iterator StatsCollection::end() const {
797   RTC_DCHECK(thread_checker_.IsCurrent());
798   return list_.end();
799 }
800 
size() const801 size_t StatsCollection::size() const {
802   RTC_DCHECK(thread_checker_.IsCurrent());
803   return list_.size();
804 }
805 
InsertNew(const StatsReport::Id & id)806 StatsReport* StatsCollection::InsertNew(const StatsReport::Id& id) {
807   RTC_DCHECK(thread_checker_.IsCurrent());
808   RTC_DCHECK(Find(id) == nullptr);
809   StatsReport* report = new StatsReport(id);
810   list_.push_back(report);
811   return report;
812 }
813 
FindOrAddNew(const StatsReport::Id & id)814 StatsReport* StatsCollection::FindOrAddNew(const StatsReport::Id& id) {
815   RTC_DCHECK(thread_checker_.IsCurrent());
816   StatsReport* ret = Find(id);
817   return ret ? ret : InsertNew(id);
818 }
819 
ReplaceOrAddNew(const StatsReport::Id & id)820 StatsReport* StatsCollection::ReplaceOrAddNew(const StatsReport::Id& id) {
821   RTC_DCHECK(thread_checker_.IsCurrent());
822   RTC_DCHECK(id.get());
823   Container::iterator it = absl::c_find_if(
824       list_,
825       [&id](const StatsReport* r) -> bool { return r->id()->Equals(id); });
826   if (it != end()) {
827     StatsReport* report = new StatsReport((*it)->id());
828     delete *it;
829     *it = report;
830     return report;
831   }
832   return InsertNew(id);
833 }
834 
835 // Looks for a report with the given `id`.  If one is not found, null
836 // will be returned.
Find(const StatsReport::Id & id)837 StatsReport* StatsCollection::Find(const StatsReport::Id& id) {
838   RTC_DCHECK(thread_checker_.IsCurrent());
839   Container::iterator it = absl::c_find_if(
840       list_,
841       [&id](const StatsReport* r) -> bool { return r->id()->Equals(id); });
842   return it == list_.end() ? nullptr : *it;
843 }
844 
845 }  // namespace webrtc
846