|  | /* | 
|  | *  Copyright 2012 The WebRTC project authors. All Rights Reserved. | 
|  | * | 
|  | *  Use of this source code is governed by a BSD-style license | 
|  | *  that can be found in the LICENSE file in the root of the source | 
|  | *  tree. An additional intellectual property rights grant can be found | 
|  | *  in the file PATENTS.  All contributing project authors may | 
|  | *  be found in the AUTHORS file in the root of the source tree. | 
|  | */ | 
|  |  | 
|  | // This file contains structures used for retrieving statistics from an ongoing | 
|  | // libjingle session. | 
|  |  | 
|  | #ifndef API_LEGACY_STATS_TYPES_H_ | 
|  | #define API_LEGACY_STATS_TYPES_H_ | 
|  |  | 
|  | #include <stddef.h> | 
|  | #include <stdint.h> | 
|  |  | 
|  | #include <list> | 
|  | #include <map> | 
|  | #include <string> | 
|  | #include <vector> | 
|  |  | 
|  | #include "api/ref_count.h" | 
|  | #include "api/scoped_refptr.h" | 
|  | #include "api/sequence_checker.h" | 
|  | #include "rtc_base/checks.h" | 
|  | #include "rtc_base/system/rtc_export.h" | 
|  | #include "rtc_base/thread_annotations.h" | 
|  |  | 
|  | namespace webrtc { | 
|  |  | 
|  | class RTC_EXPORT StatsReport { | 
|  | public: | 
|  | // Indicates whether a track is for sending or receiving. | 
|  | // Used in reports for audio/video tracks. | 
|  | enum Direction { | 
|  | kSend = 0, | 
|  | kReceive, | 
|  | }; | 
|  |  | 
|  | enum StatsType { | 
|  | // StatsReport types. | 
|  | // A StatsReport of `type` = "googSession" contains overall information | 
|  | // about the thing libjingle calls a session (which may contain one | 
|  | // or more RTP sessions. | 
|  | kStatsReportTypeSession, | 
|  |  | 
|  | // A StatsReport of `type` = "googTransport" contains information | 
|  | // about a libjingle "transport". | 
|  | kStatsReportTypeTransport, | 
|  |  | 
|  | // A StatsReport of `type` = "googComponent" contains information | 
|  | // about a libjingle "channel" (typically, RTP or RTCP for a transport). | 
|  | // This is intended to be the same thing as an ICE "Component". | 
|  | kStatsReportTypeComponent, | 
|  |  | 
|  | // A StatsReport of `type` = "googCandidatePair" contains information | 
|  | // about a libjingle "connection" - a single source/destination port pair. | 
|  | // This is intended to be the same thing as an ICE "candidate pair". | 
|  | kStatsReportTypeCandidatePair, | 
|  |  | 
|  | // A StatsReport of `type` = "VideoBWE" is statistics for video Bandwidth | 
|  | // Estimation, which is global per-session.  The `id` field is "bweforvideo" | 
|  | // (will probably change in the future). | 
|  | kStatsReportTypeBwe, | 
|  |  | 
|  | // A StatsReport of `type` = "ssrc" is statistics for a specific rtp stream. | 
|  | // The `id` field is the SSRC in decimal form of the rtp stream. | 
|  | kStatsReportTypeSsrc, | 
|  |  | 
|  | // A StatsReport of `type` = "remoteSsrc" is statistics for a specific | 
|  | // rtp stream, generated by the remote end of the connection. | 
|  | kStatsReportTypeRemoteSsrc, | 
|  |  | 
|  | // A StatsReport of `type` = "googTrack" is statistics for a specific media | 
|  | // track. The `id` field is the track id. | 
|  | kStatsReportTypeTrack, | 
|  |  | 
|  | // A StatsReport of `type` = "localcandidate" or "remotecandidate" is | 
|  | // attributes on a specific ICE Candidate. It links to its connection pair | 
|  | // by candidate id. The string value is taken from | 
|  | // http://w3c.github.io/webrtc-stats/#rtcstatstype-enum*. | 
|  | kStatsReportTypeIceLocalCandidate, | 
|  | kStatsReportTypeIceRemoteCandidate, | 
|  |  | 
|  | // A StatsReport of `type` = "googCertificate" contains an SSL certificate | 
|  | // transmitted by one of the endpoints of this connection.  The `id` is | 
|  | // controlled by the fingerprint, and is used to identify the certificate in | 
|  | // the Channel stats (as "googLocalCertificateId" or | 
|  | // "googRemoteCertificateId") and in any child certificates (as | 
|  | // "googIssuerId"). | 
|  | kStatsReportTypeCertificate, | 
|  |  | 
|  | // A StatsReport of `type` = "datachannel" with statistics for a | 
|  | // particular DataChannel. | 
|  | kStatsReportTypeDataChannel, | 
|  | }; | 
|  |  | 
|  | enum StatsValueName { | 
|  | kStatsValueNameActiveConnection, | 
|  | kStatsValueNameAecDivergentFilterFraction, | 
|  | kStatsValueNameAudioInputLevel, | 
|  | kStatsValueNameAudioOutputLevel, | 
|  | kStatsValueNameBytesReceived, | 
|  | kStatsValueNameBytesSent, | 
|  | kStatsValueNameCodecImplementationName, | 
|  | kStatsValueNameConcealedSamples, | 
|  | kStatsValueNameConcealmentEvents, | 
|  | kStatsValueNameDataChannelId, | 
|  | kStatsValueNameFramesDecoded, | 
|  | kStatsValueNameFramesEncoded, | 
|  | kStatsValueNameJitterBufferDelay, | 
|  | kStatsValueNameMediaType, | 
|  | kStatsValueNamePacketsLost, | 
|  | kStatsValueNamePacketsReceived, | 
|  | kStatsValueNamePacketsSent, | 
|  | kStatsValueNameProtocol, | 
|  | kStatsValueNameQpSum, | 
|  | kStatsValueNameReceiving, | 
|  | kStatsValueNameSelectedCandidatePairId, | 
|  | kStatsValueNameSsrc, | 
|  | kStatsValueNameState, | 
|  | kStatsValueNameTotalAudioEnergy, | 
|  | kStatsValueNameTotalSamplesDuration, | 
|  | kStatsValueNameTotalSamplesReceived, | 
|  | kStatsValueNameTransportId, | 
|  | kStatsValueNameSentPingRequestsTotal, | 
|  | kStatsValueNameSentPingRequestsBeforeFirstResponse, | 
|  | kStatsValueNameSentPingResponses, | 
|  | kStatsValueNameRecvPingRequests, | 
|  | kStatsValueNameRecvPingResponses, | 
|  | kStatsValueNameSentStunKeepaliveRequests, | 
|  | kStatsValueNameRecvStunKeepaliveResponses, | 
|  | kStatsValueNameStunKeepaliveRttTotal, | 
|  | kStatsValueNameStunKeepaliveRttSquaredTotal, | 
|  |  | 
|  | // Internal StatsValue names. | 
|  | kStatsValueNameAccelerateRate, | 
|  | kStatsValueNameActualEncBitrate, | 
|  | kStatsValueNameAdaptationChanges, | 
|  | kStatsValueNameAvailableReceiveBandwidth, | 
|  | kStatsValueNameAvailableSendBandwidth, | 
|  | kStatsValueNameAvgEncodeMs, | 
|  | kStatsValueNameBandwidthLimitedResolution, | 
|  | kStatsValueNameBucketDelay, | 
|  | kStatsValueNameCaptureStartNtpTimeMs, | 
|  | kStatsValueNameCandidateIPAddress, | 
|  | kStatsValueNameCandidateNetworkType, | 
|  | kStatsValueNameCandidatePortNumber, | 
|  | kStatsValueNameCandidatePriority, | 
|  | kStatsValueNameCandidateTransportType, | 
|  | kStatsValueNameCandidateType, | 
|  | kStatsValueNameChannelId, | 
|  | kStatsValueNameCodecName, | 
|  | kStatsValueNameComponent, | 
|  | kStatsValueNameContentName, | 
|  | kStatsValueNameContentType, | 
|  | kStatsValueNameCpuLimitedResolution, | 
|  | kStatsValueNameCurrentDelayMs, | 
|  | kStatsValueNameDecodeMs, | 
|  | kStatsValueNameDecodingCNG, | 
|  | kStatsValueNameDecodingCTN, | 
|  | kStatsValueNameDecodingCTSG, | 
|  | kStatsValueNameDecodingMutedOutput, | 
|  | kStatsValueNameDecodingNormal, | 
|  | kStatsValueNameDecodingPLC, | 
|  | kStatsValueNameDecodingCodecPLC, | 
|  | kStatsValueNameDecodingPLCCNG, | 
|  | kStatsValueNameDer, | 
|  | kStatsValueNameDtlsCipher, | 
|  | kStatsValueNameEchoDelayMedian, | 
|  | kStatsValueNameEchoDelayStdDev, | 
|  | kStatsValueNameEchoReturnLoss, | 
|  | kStatsValueNameEchoReturnLossEnhancement, | 
|  | kStatsValueNameEncodeUsagePercent, | 
|  | kStatsValueNameExpandRate, | 
|  | kStatsValueNameFingerprint, | 
|  | kStatsValueNameFingerprintAlgorithm, | 
|  | kStatsValueNameFirsReceived, | 
|  | kStatsValueNameFirsSent, | 
|  | kStatsValueNameFirstFrameReceivedToDecodedMs, | 
|  | kStatsValueNameFrameHeightInput, | 
|  | kStatsValueNameFrameHeightReceived, | 
|  | kStatsValueNameFrameHeightSent, | 
|  | kStatsValueNameFrameRateDecoded, | 
|  | kStatsValueNameFrameRateInput, | 
|  | kStatsValueNameFrameRateOutput, | 
|  | kStatsValueNameFrameRateReceived, | 
|  | kStatsValueNameFrameRateSent, | 
|  | kStatsValueNameFrameWidthInput, | 
|  | kStatsValueNameFrameWidthReceived, | 
|  | kStatsValueNameFrameWidthSent, | 
|  | kStatsValueNameHasEnteredLowResolution, | 
|  | kStatsValueNameHugeFramesSent, | 
|  | kStatsValueNameInitiator, | 
|  | kStatsValueNameInterframeDelayMaxMs,  // Max over last 10 seconds. | 
|  | kStatsValueNameIssuerId, | 
|  | kStatsValueNameJitterBufferMs, | 
|  | kStatsValueNameJitterReceived, | 
|  | kStatsValueNameLabel, | 
|  | kStatsValueNameLocalAddress, | 
|  | kStatsValueNameLocalCandidateId, | 
|  | kStatsValueNameLocalCandidateType, | 
|  | kStatsValueNameLocalCertificateId, | 
|  | kStatsValueNameMaxDecodeMs, | 
|  | kStatsValueNameMinPlayoutDelayMs, | 
|  | kStatsValueNameNacksReceived, | 
|  | kStatsValueNameNacksSent, | 
|  | kStatsValueNamePlisReceived, | 
|  | kStatsValueNamePlisSent, | 
|  | kStatsValueNamePreemptiveExpandRate, | 
|  | kStatsValueNamePreferredJitterBufferMs, | 
|  | kStatsValueNameRemoteAddress, | 
|  | kStatsValueNameRemoteCandidateId, | 
|  | kStatsValueNameRemoteCandidateType, | 
|  | kStatsValueNameRemoteCertificateId, | 
|  | kStatsValueNameRenderDelayMs, | 
|  | kStatsValueNameResidualEchoLikelihood, | 
|  | kStatsValueNameResidualEchoLikelihoodRecentMax, | 
|  | kStatsValueNameAnaBitrateActionCounter, | 
|  | kStatsValueNameAnaChannelActionCounter, | 
|  | kStatsValueNameAnaDtxActionCounter, | 
|  | kStatsValueNameAnaFecActionCounter, | 
|  | kStatsValueNameAnaFrameLengthIncreaseCounter, | 
|  | kStatsValueNameAnaFrameLengthDecreaseCounter, | 
|  | kStatsValueNameAnaUplinkPacketLossFraction, | 
|  | kStatsValueNameRetransmitBitrate, | 
|  | kStatsValueNameRtt, | 
|  | kStatsValueNameSecondaryDecodedRate, | 
|  | kStatsValueNameSecondaryDiscardedRate, | 
|  | kStatsValueNameSendPacketsDiscarded, | 
|  | kStatsValueNameSpeechExpandRate, | 
|  | kStatsValueNameSrtpCipher, | 
|  | kStatsValueNameTargetDelayMs, | 
|  | kStatsValueNameTargetEncBitrate, | 
|  | kStatsValueNameTimingFrameInfo,  // Result of `TimingFrameInfo::ToString` | 
|  | kStatsValueNameTrackId, | 
|  | kStatsValueNameTransmitBitrate, | 
|  | kStatsValueNameTransportType, | 
|  | kStatsValueNameWritable, | 
|  | kStatsValueNameAudioDeviceUnderrunCounter, | 
|  | kStatsValueNameLocalCandidateRelayProtocol, | 
|  | }; | 
|  |  | 
|  | class RTC_EXPORT IdBase : public RefCountInterface { | 
|  | public: | 
|  | ~IdBase() override; | 
|  | StatsType type() const; | 
|  |  | 
|  | // Users of IdBase will be using the Id typedef, which is compatible with | 
|  | // this Equals() function.  It simply calls the protected (and overridden) | 
|  | // Equals() method. | 
|  | bool Equals(const scoped_refptr<IdBase>& other) const { | 
|  | return Equals(*other.get()); | 
|  | } | 
|  |  | 
|  | virtual std::string ToString() const = 0; | 
|  |  | 
|  | protected: | 
|  | // Protected since users of the IdBase type will be using the Id typedef. | 
|  | virtual bool Equals(const IdBase& other) const; | 
|  |  | 
|  | explicit IdBase(StatsType type);  // Only meant for derived classes. | 
|  | const StatsType type_; | 
|  |  | 
|  | static const char kSeparator = '_'; | 
|  | }; | 
|  |  | 
|  | typedef scoped_refptr<IdBase> Id; | 
|  |  | 
|  | struct RTC_EXPORT Value { | 
|  | enum Type { | 
|  | kInt,           // int. | 
|  | kInt64,         // int64_t. | 
|  | kFloat,         // float. | 
|  | kString,        // std::string | 
|  | kStaticString,  // const char*. | 
|  | kBool,          // bool. | 
|  | kId,            // Id. | 
|  | }; | 
|  |  | 
|  | Value(StatsValueName name, int64_t value, Type int_type); | 
|  | Value(StatsValueName name, float f); | 
|  | Value(StatsValueName name, const std::string& value); | 
|  | Value(StatsValueName name, const char* value); | 
|  | Value(StatsValueName name, bool b); | 
|  | Value(StatsValueName name, const Id& value); | 
|  |  | 
|  | ~Value(); | 
|  |  | 
|  | Value(const Value&) = delete; | 
|  | Value& operator=(const Value&) = delete; | 
|  |  | 
|  | // Support ref counting. Note that for performance reasons, we | 
|  | // don't use thread safe operations. Therefore, all operations | 
|  | // affecting the ref count (in practice, creation and copying of | 
|  | // the Values mapping) must occur on webrtc's signalling thread. | 
|  | int AddRef() const { | 
|  | RTC_DCHECK_RUN_ON(&thread_checker_); | 
|  | return ++ref_count_; | 
|  | } | 
|  | int Release() const { | 
|  | RTC_DCHECK_RUN_ON(&thread_checker_); | 
|  | int count = --ref_count_; | 
|  | if (!count) | 
|  | delete this; | 
|  | return count; | 
|  | } | 
|  |  | 
|  | // TODO(tommi): This compares name as well as value... | 
|  | // I think we should only need to compare the value part and | 
|  | // move the name part into a hash map. | 
|  | bool Equals(const Value& other) const; | 
|  |  | 
|  | // Comparison operators. Return true iff the current instance is of the | 
|  | // correct type and holds the same value.  No conversion is performed so | 
|  | // a string value of "123" is not equal to an int value of 123 and an int | 
|  | // value of 123 is not equal to a float value of 123.0f. | 
|  | // One exception to this is that types kInt and kInt64 can be compared and | 
|  | // kString and kStaticString too. | 
|  | bool operator==(const std::string& value) const; | 
|  | bool operator==(const char* value) const; | 
|  | bool operator==(int64_t value) const; | 
|  | bool operator==(bool value) const; | 
|  | bool operator==(float value) const; | 
|  | bool operator==(const Id& value) const; | 
|  |  | 
|  | // Getters that allow getting the native value directly. | 
|  | // The caller must know the type beforehand or else hit a check. | 
|  | int int_val() const; | 
|  | int64_t int64_val() const; | 
|  | float float_val() const; | 
|  | const char* static_string_val() const; | 
|  | const std::string& string_val() const; | 
|  | bool bool_val() const; | 
|  | const Id& id_val() const; | 
|  |  | 
|  | // Returns the string representation of `name`. | 
|  | const char* display_name() const; | 
|  |  | 
|  | // Converts the native value to a string representation of the value. | 
|  | std::string ToString() const; | 
|  |  | 
|  | Type type() const { return type_; } | 
|  |  | 
|  | // TODO(tommi): Move `name` and `display_name` out of the Value struct. | 
|  | const StatsValueName name; | 
|  |  | 
|  | protected: | 
|  | #if RTC_DCHECK_IS_ON | 
|  | friend class StatsReport; | 
|  | void DetachSequenceChecker() { thread_checker_.Detach(); } | 
|  | void AttachSequenceChecker() { RTC_DCHECK_RUN_ON(&thread_checker_); } | 
|  | #endif | 
|  |  | 
|  | private: | 
|  | SequenceChecker thread_checker_{SequenceChecker::kDetached}; | 
|  | mutable int ref_count_ RTC_GUARDED_BY(thread_checker_) = 0; | 
|  |  | 
|  | const Type type_; | 
|  | // TODO(tommi): Use C++ 11 union and make value_ const. | 
|  | union InternalType { | 
|  | int int_; | 
|  | int64_t int64_; | 
|  | float float_; | 
|  | bool bool_; | 
|  | std::string* string_; | 
|  | const char* static_string_; | 
|  | Id* id_; | 
|  | } value_; | 
|  | }; | 
|  |  | 
|  | typedef scoped_refptr<Value> ValuePtr; | 
|  | typedef std::map<StatsValueName, ValuePtr> Values; | 
|  |  | 
|  | // Ownership of `id` is passed to `this`. | 
|  | explicit StatsReport(const Id& id); | 
|  | ~StatsReport(); | 
|  |  | 
|  | StatsReport(const StatsReport&) = delete; | 
|  | StatsReport& operator=(const StatsReport&) = delete; | 
|  |  | 
|  | // Factory functions for various types of stats IDs. | 
|  | static Id NewBandwidthEstimationId(); | 
|  | static Id NewTypedId(StatsType type, const std::string& id); | 
|  | static Id NewTypedIntId(StatsType type, int id); | 
|  | static Id NewIdWithDirection(StatsType type, | 
|  | const std::string& id, | 
|  | Direction direction); | 
|  | static Id NewCandidateId(bool local, const std::string& id); | 
|  | static Id NewComponentId(const std::string& content_name, int component); | 
|  | static Id NewCandidatePairId(const std::string& content_name, | 
|  | int component, | 
|  | int index); | 
|  |  | 
|  | const Id& id() const { return id_; } | 
|  | StatsType type() const { return id_->type(); } | 
|  | double timestamp() const { return timestamp_; } | 
|  | void set_timestamp(double t) { timestamp_ = t; } | 
|  | bool empty() const { return values_.empty(); } | 
|  | const Values& values() const { return values_; } | 
|  |  | 
|  | const char* TypeToString() const; | 
|  |  | 
|  | void AddString(StatsValueName name, const std::string& value); | 
|  | void AddString(StatsValueName name, const char* value); | 
|  | void AddInt64(StatsValueName name, int64_t value); | 
|  | void AddInt(StatsValueName name, int value); | 
|  | void AddFloat(StatsValueName name, float value); | 
|  | void AddBoolean(StatsValueName name, bool value); | 
|  | void AddId(StatsValueName name, const Id& value); | 
|  |  | 
|  | const Value* FindValue(StatsValueName name) const; | 
|  |  | 
|  | #if RTC_DCHECK_IS_ON | 
|  | void DetachSequenceCheckers() { | 
|  | for (auto& v : values_) { | 
|  | v.second->DetachSequenceChecker(); | 
|  | } | 
|  | } | 
|  | void AttachSequenceCheckers() { | 
|  | for (auto& v : values_) { | 
|  | v.second->AttachSequenceChecker(); | 
|  | } | 
|  | } | 
|  | #endif | 
|  |  | 
|  | private: | 
|  | // The unique identifier for this object. | 
|  | // This is used as a key for this report in ordered containers, | 
|  | // so it must never be changed. | 
|  | const Id id_; | 
|  | double timestamp_;  // Time since 1970-01-01T00:00:00Z in milliseconds. | 
|  | Values values_; | 
|  | }; | 
|  |  | 
|  | // Typedef for an array of const StatsReport pointers. | 
|  | // Ownership of the pointers held by this implementation is assumed to lie | 
|  | // elsewhere and lifetime guarantees are made by the implementation that uses | 
|  | // this type.  In the StatsCollector, object ownership lies with the | 
|  | // StatsCollection class. | 
|  | typedef std::vector<const StatsReport*> StatsReports; | 
|  |  | 
|  | // A map from the report id to the report. | 
|  | // This class wraps an STL container and provides a limited set of | 
|  | // functionality in order to keep things simple. | 
|  | class StatsCollection { | 
|  | public: | 
|  | StatsCollection(); | 
|  | ~StatsCollection(); | 
|  |  | 
|  | typedef std::list<StatsReport*> Container; | 
|  | typedef Container::iterator iterator; | 
|  | typedef Container::const_iterator const_iterator; | 
|  |  | 
|  | const_iterator begin() const; | 
|  | const_iterator end() const; | 
|  | size_t size() const; | 
|  |  | 
|  | // Creates a new report object with `id` that does not already | 
|  | // exist in the list of reports. | 
|  | StatsReport* InsertNew(const StatsReport::Id& id); | 
|  | StatsReport* FindOrAddNew(const StatsReport::Id& id); | 
|  | StatsReport* ReplaceOrAddNew(const StatsReport::Id& id); | 
|  |  | 
|  | Container DetachCollection(); | 
|  | void MergeCollection(Container collection); | 
|  |  | 
|  | // Looks for a report with the given `id`.  If one is not found, null | 
|  | // will be returned. | 
|  | StatsReport* Find(const StatsReport::Id& id); | 
|  |  | 
|  | private: | 
|  | Container list_; | 
|  | SequenceChecker thread_checker_{SequenceChecker::kDetached}; | 
|  | }; | 
|  |  | 
|  | }  // namespace webrtc | 
|  |  | 
|  | #endif  // API_LEGACY_STATS_TYPES_H_ |