tommi@webrtc.org | 5c3ee4b | 2014-12-09 10:47:01 | [diff] [blame] | 1 | /* |
| 2 | * libjingle |
| 3 | * Copyright 2014, Google Inc. |
| 4 | * |
| 5 | * Redistribution and use in source and binary forms, with or without |
| 6 | * modification, are permitted provided that the following conditions are met: |
| 7 | * |
| 8 | * 1. Redistributions of source code must retain the above copyright notice, |
| 9 | * this list of conditions and the following disclaimer. |
| 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, |
| 11 | * this list of conditions and the following disclaimer in the documentation |
| 12 | * and/or other materials provided with the distribution. |
| 13 | * 3. The name of the author may not be used to endorse or promote products |
| 14 | * derived from this software without specific prior written permission. |
| 15 | * |
| 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
| 17 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| 18 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO |
| 19 | * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 20 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| 21 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
| 22 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| 23 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
| 24 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
| 25 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 26 | */ |
| 27 | |
| 28 | #include "talk/app/webrtc/statstypes.h" |
| 29 | |
| 30 | namespace webrtc { |
| 31 | |
tommi@webrtc.org | c9d155f | 2014-12-09 18:18:06 | [diff] [blame] | 32 | const char StatsReport::kStatsReportTypeSession[] = "googLibjingleSession"; |
| 33 | const char StatsReport::kStatsReportTypeBwe[] = "VideoBwe"; |
| 34 | const char StatsReport::kStatsReportTypeRemoteSsrc[] = "remoteSsrc"; |
| 35 | const char StatsReport::kStatsReportTypeSsrc[] = "ssrc"; |
| 36 | const char StatsReport::kStatsReportTypeTrack[] = "googTrack"; |
guoweis@webrtc.org | 950c518 | 2014-12-16 23:01:31 | [diff] [blame] | 37 | const char StatsReport::kStatsReportTypeIceLocalCandidate[] = "localcandidate"; |
| 38 | const char StatsReport::kStatsReportTypeIceRemoteCandidate[] = |
| 39 | "remotecandidate"; |
tommi@webrtc.org | c9d155f | 2014-12-09 18:18:06 | [diff] [blame] | 40 | const char StatsReport::kStatsReportTypeTransport[] = "googTransport"; |
| 41 | const char StatsReport::kStatsReportTypeComponent[] = "googComponent"; |
| 42 | const char StatsReport::kStatsReportTypeCandidatePair[] = "googCandidatePair"; |
| 43 | const char StatsReport::kStatsReportTypeCertificate[] = "googCertificate"; |
decurtis@webrtc.org | 487a444 | 2015-01-15 22:55:07 | [diff] [blame^] | 44 | const char StatsReport::kStatsReportTypeDataChannel[] = "datachannel"; |
tommi@webrtc.org | c9d155f | 2014-12-09 18:18:06 | [diff] [blame] | 45 | |
| 46 | const char StatsReport::kStatsReportVideoBweId[] = "bweforvideo"; |
| 47 | |
| 48 | StatsReport::StatsReport(const StatsReport& src) |
| 49 | : id(src.id), |
| 50 | type(src.type), |
| 51 | timestamp(src.timestamp), |
| 52 | values(src.values) { |
| 53 | } |
| 54 | |
| 55 | StatsReport::StatsReport(const std::string& id) |
| 56 | : id(id), timestamp(0) { |
| 57 | } |
| 58 | |
| 59 | StatsReport& StatsReport::operator=(const StatsReport& src) { |
| 60 | ASSERT(id == src.id); |
| 61 | type = src.type; |
| 62 | timestamp = src.timestamp; |
| 63 | values = src.values; |
| 64 | return *this; |
| 65 | } |
| 66 | |
| 67 | // Operators provided for STL container/algorithm support. |
| 68 | bool StatsReport::operator<(const StatsReport& other) const { |
| 69 | return id < other.id; |
| 70 | } |
| 71 | |
| 72 | bool StatsReport::operator==(const StatsReport& other) const { |
| 73 | return id == other.id; |
| 74 | } |
| 75 | |
| 76 | // Special support for being able to use std::find on a container |
| 77 | // without requiring a new StatsReport instance. |
| 78 | bool StatsReport::operator==(const std::string& other_id) const { |
| 79 | return id == other_id; |
| 80 | } |
| 81 | |
tommi@webrtc.org | c9d155f | 2014-12-09 18:18:06 | [diff] [blame] | 82 | // The copy ctor can't be declared as explicit due to problems with STL. |
| 83 | StatsReport::Value::Value(const Value& other) |
| 84 | : name(other.name), value(other.value) { |
| 85 | } |
| 86 | |
| 87 | StatsReport::Value::Value(StatsValueName name) |
| 88 | : name(name) { |
| 89 | } |
| 90 | |
| 91 | StatsReport::Value::Value(StatsValueName name, const std::string& value) |
| 92 | : name(name), value(value) { |
| 93 | } |
| 94 | |
| 95 | StatsReport::Value& StatsReport::Value::operator=(const Value& other) { |
| 96 | const_cast<StatsValueName&>(name) = other.name; |
| 97 | value = other.value; |
| 98 | return *this; |
| 99 | } |
| 100 | |
tommi@webrtc.org | c9d155f | 2014-12-09 18:18:06 | [diff] [blame] | 101 | const char* StatsReport::Value::display_name() const { |
tommi@webrtc.org | c57310b | 2014-12-12 17:41:28 | [diff] [blame] | 102 | switch (name) { |
| 103 | case kStatsValueNameAudioOutputLevel: |
| 104 | return "audioOutputLevel"; |
| 105 | case kStatsValueNameAudioInputLevel: |
| 106 | return "audioInputLevel"; |
| 107 | case kStatsValueNameBytesSent: |
| 108 | return "bytesSent"; |
| 109 | case kStatsValueNamePacketsSent: |
| 110 | return "packetsSent"; |
| 111 | case kStatsValueNameBytesReceived: |
| 112 | return "bytesReceived"; |
decurtis@webrtc.org | 487a444 | 2015-01-15 22:55:07 | [diff] [blame^] | 113 | case kStatsValueNameLabel: |
| 114 | return "label"; |
tommi@webrtc.org | c57310b | 2014-12-12 17:41:28 | [diff] [blame] | 115 | case kStatsValueNamePacketsReceived: |
| 116 | return "packetsReceived"; |
| 117 | case kStatsValueNamePacketsLost: |
| 118 | return "packetsLost"; |
decurtis@webrtc.org | 487a444 | 2015-01-15 22:55:07 | [diff] [blame^] | 119 | case kStatsValueNameProtocol: |
| 120 | return "protocol"; |
tommi@webrtc.org | c57310b | 2014-12-12 17:41:28 | [diff] [blame] | 121 | case kStatsValueNameTransportId: |
| 122 | return "transportId"; |
| 123 | case kStatsValueNameSsrc: |
| 124 | return "ssrc"; |
decurtis@webrtc.org | 487a444 | 2015-01-15 22:55:07 | [diff] [blame^] | 125 | case kStatsValueNameState: |
| 126 | return "state"; |
| 127 | case kStatsValueNameDataChannelId: |
| 128 | return "datachannelid"; |
tommi@webrtc.org | c57310b | 2014-12-12 17:41:28 | [diff] [blame] | 129 | |
| 130 | // 'goog' prefixed constants. |
| 131 | case kStatsValueNameActiveConnection: |
| 132 | return "googActiveConnection"; |
| 133 | case kStatsValueNameActualEncBitrate: |
| 134 | return "googActualEncBitrate"; |
| 135 | case kStatsValueNameAvailableReceiveBandwidth: |
| 136 | return "googAvailableReceiveBandwidth"; |
| 137 | case kStatsValueNameAvailableSendBandwidth: |
| 138 | return "googAvailableSendBandwidth"; |
| 139 | case kStatsValueNameAvgEncodeMs: |
| 140 | return "googAvgEncodeMs"; |
| 141 | case kStatsValueNameBucketDelay: |
| 142 | return "googBucketDelay"; |
| 143 | case kStatsValueNameBandwidthLimitedResolution: |
| 144 | return "googBandwidthLimitedResolution"; |
| 145 | case kStatsValueNameCaptureJitterMs: |
| 146 | return "googCaptureJitterMs"; |
| 147 | case kStatsValueNameCaptureQueueDelayMsPerS: |
| 148 | return "googCaptureQueueDelayMsPerS"; |
guoweis@webrtc.org | 950c518 | 2014-12-16 23:01:31 | [diff] [blame] | 149 | |
| 150 | // Candidate related attributes. Values are taken from |
| 151 | // http://w3c.github.io/webrtc-stats/#rtcstatstype-enum*. |
| 152 | case kStatsValueNameCandidateIPAddress: |
| 153 | return "ipAddress"; |
| 154 | case kStatsValueNameCandidateNetworkType: |
| 155 | return "networkType"; |
| 156 | case kStatsValueNameCandidatePortNumber: |
| 157 | return "portNumber"; |
| 158 | case kStatsValueNameCandidatePriority: |
| 159 | return "priority"; |
| 160 | case kStatsValueNameCandidateTransportType: |
| 161 | return "transport"; |
| 162 | case kStatsValueNameCandidateType: |
| 163 | return "candidateType"; |
| 164 | |
tommi@webrtc.org | c57310b | 2014-12-12 17:41:28 | [diff] [blame] | 165 | case kStatsValueNameChannelId: |
| 166 | return "googChannelId"; |
| 167 | case kStatsValueNameCodecName: |
| 168 | return "googCodecName"; |
| 169 | case kStatsValueNameComponent: |
| 170 | return "googComponent"; |
| 171 | case kStatsValueNameContentName: |
| 172 | return "googContentName"; |
| 173 | case kStatsValueNameCpuLimitedResolution: |
| 174 | return "googCpuLimitedResolution"; |
| 175 | case kStatsValueNameDecodingCTSG: |
| 176 | return "googDecodingCTSG"; |
| 177 | case kStatsValueNameDecodingCTN: |
| 178 | return "googDecodingCTN"; |
| 179 | case kStatsValueNameDecodingNormal: |
| 180 | return "googDecodingNormal"; |
| 181 | case kStatsValueNameDecodingPLC: |
| 182 | return "googDecodingPLC"; |
| 183 | case kStatsValueNameDecodingCNG: |
| 184 | return "googDecodingCNG"; |
| 185 | case kStatsValueNameDecodingPLCCNG: |
| 186 | return "googDecodingPLCCNG"; |
| 187 | case kStatsValueNameDer: |
| 188 | return "googDerBase64"; |
| 189 | case kStatsValueNameEchoCancellationQualityMin: |
| 190 | return "googEchoCancellationQualityMin"; |
| 191 | case kStatsValueNameEchoDelayMedian: |
| 192 | return "googEchoCancellationEchoDelayMedian"; |
| 193 | case kStatsValueNameEchoDelayStdDev: |
| 194 | return "googEchoCancellationEchoDelayStdDev"; |
| 195 | case kStatsValueNameEchoReturnLoss: |
| 196 | return "googEchoCancellationReturnLoss"; |
| 197 | case kStatsValueNameEchoReturnLossEnhancement: |
| 198 | return "googEchoCancellationReturnLossEnhancement"; |
| 199 | case kStatsValueNameEncodeUsagePercent: |
| 200 | return "googEncodeUsagePercent"; |
| 201 | case kStatsValueNameExpandRate: |
| 202 | return "googExpandRate"; |
| 203 | case kStatsValueNameFingerprint: |
| 204 | return "googFingerprint"; |
| 205 | case kStatsValueNameFingerprintAlgorithm: |
| 206 | return "googFingerprintAlgorithm"; |
| 207 | case kStatsValueNameFirsReceived: |
| 208 | return "googFirsReceived"; |
| 209 | case kStatsValueNameFirsSent: |
| 210 | return "googFirsSent"; |
| 211 | case kStatsValueNameFrameHeightInput: |
| 212 | return "googFrameHeightInput"; |
| 213 | case kStatsValueNameFrameHeightReceived: |
| 214 | return "googFrameHeightReceived"; |
| 215 | case kStatsValueNameFrameHeightSent: |
| 216 | return "googFrameHeightSent"; |
| 217 | case kStatsValueNameFrameRateReceived: |
| 218 | return "googFrameRateReceived"; |
| 219 | case kStatsValueNameFrameRateDecoded: |
| 220 | return "googFrameRateDecoded"; |
| 221 | case kStatsValueNameFrameRateOutput: |
| 222 | return "googFrameRateOutput"; |
| 223 | case kStatsValueNameDecodeMs: |
| 224 | return "googDecodeMs"; |
| 225 | case kStatsValueNameMaxDecodeMs: |
| 226 | return "googMaxDecodeMs"; |
| 227 | case kStatsValueNameCurrentDelayMs: |
| 228 | return "googCurrentDelayMs"; |
| 229 | case kStatsValueNameTargetDelayMs: |
| 230 | return "googTargetDelayMs"; |
| 231 | case kStatsValueNameJitterBufferMs: |
| 232 | return "googJitterBufferMs"; |
| 233 | case kStatsValueNameMinPlayoutDelayMs: |
| 234 | return "googMinPlayoutDelayMs"; |
| 235 | case kStatsValueNameRenderDelayMs: |
| 236 | return "googRenderDelayMs"; |
| 237 | case kStatsValueNameCaptureStartNtpTimeMs: |
| 238 | return "googCaptureStartNtpTimeMs"; |
| 239 | case kStatsValueNameFrameRateInput: |
| 240 | return "googFrameRateInput"; |
| 241 | case kStatsValueNameFrameRateSent: |
| 242 | return "googFrameRateSent"; |
| 243 | case kStatsValueNameFrameWidthInput: |
| 244 | return "googFrameWidthInput"; |
| 245 | case kStatsValueNameFrameWidthReceived: |
| 246 | return "googFrameWidthReceived"; |
| 247 | case kStatsValueNameFrameWidthSent: |
| 248 | return "googFrameWidthSent"; |
| 249 | case kStatsValueNameInitiator: |
| 250 | return "googInitiator"; |
| 251 | case kStatsValueNameIssuerId: |
| 252 | return "googIssuerId"; |
| 253 | case kStatsValueNameJitterReceived: |
| 254 | return "googJitterReceived"; |
| 255 | case kStatsValueNameLocalAddress: |
| 256 | return "googLocalAddress"; |
guoweis@webrtc.org | 950c518 | 2014-12-16 23:01:31 | [diff] [blame] | 257 | case kStatsValueNameLocalCandidateId: |
| 258 | return "localCandidateId"; |
tommi@webrtc.org | c57310b | 2014-12-12 17:41:28 | [diff] [blame] | 259 | case kStatsValueNameLocalCandidateType: |
| 260 | return "googLocalCandidateType"; |
| 261 | case kStatsValueNameLocalCertificateId: |
| 262 | return "googLocalCertificateId"; |
| 263 | case kStatsValueNameAdaptationChanges: |
| 264 | return "googAdaptationChanges"; |
| 265 | case kStatsValueNameNacksReceived: |
| 266 | return "googNacksReceived"; |
| 267 | case kStatsValueNameNacksSent: |
| 268 | return "googNacksSent"; |
| 269 | case kStatsValueNamePlisReceived: |
| 270 | return "googPlisReceived"; |
| 271 | case kStatsValueNamePlisSent: |
| 272 | return "googPlisSent"; |
| 273 | case kStatsValueNamePreferredJitterBufferMs: |
| 274 | return "googPreferredJitterBufferMs"; |
| 275 | case kStatsValueNameReadable: |
| 276 | return "googReadable"; |
| 277 | case kStatsValueNameRecvPacketGroupArrivalTimeDebug: |
| 278 | return "googReceivedPacketGroupArrivalTimeDebug"; |
| 279 | case kStatsValueNameRecvPacketGroupPropagationDeltaDebug: |
| 280 | return "googReceivedPacketGroupPropagationDeltaDebug"; |
| 281 | case kStatsValueNameRecvPacketGroupPropagationDeltaSumDebug: |
| 282 | return "googReceivedPacketGroupPropagationDeltaSumDebug"; |
| 283 | case kStatsValueNameRemoteAddress: |
| 284 | return "googRemoteAddress"; |
guoweis@webrtc.org | 950c518 | 2014-12-16 23:01:31 | [diff] [blame] | 285 | case kStatsValueNameRemoteCandidateId: |
| 286 | return "remoteCandidateId"; |
tommi@webrtc.org | c57310b | 2014-12-12 17:41:28 | [diff] [blame] | 287 | case kStatsValueNameRemoteCandidateType: |
| 288 | return "googRemoteCandidateType"; |
| 289 | case kStatsValueNameRemoteCertificateId: |
| 290 | return "googRemoteCertificateId"; |
| 291 | case kStatsValueNameRetransmitBitrate: |
| 292 | return "googRetransmitBitrate"; |
| 293 | case kStatsValueNameRtt: |
| 294 | return "googRtt"; |
| 295 | case kStatsValueNameSendPacketsDiscarded: |
| 296 | return "packetsDiscardedOnSend"; |
| 297 | case kStatsValueNameTargetEncBitrate: |
| 298 | return "googTargetEncBitrate"; |
| 299 | case kStatsValueNameTransmitBitrate: |
| 300 | return "googTransmitBitrate"; |
| 301 | case kStatsValueNameTransportType: |
| 302 | return "googTransportType"; |
| 303 | case kStatsValueNameTrackId: |
| 304 | return "googTrackId"; |
| 305 | case kStatsValueNameTypingNoiseState: |
| 306 | return "googTypingNoiseState"; |
| 307 | case kStatsValueNameViewLimitedResolution: |
| 308 | return "googViewLimitedResolution"; |
| 309 | case kStatsValueNameWritable: |
| 310 | return "googWritable"; |
| 311 | default: |
| 312 | ASSERT(false); |
| 313 | break; |
| 314 | } |
| 315 | |
| 316 | return nullptr; |
tommi@webrtc.org | c9d155f | 2014-12-09 18:18:06 | [diff] [blame] | 317 | } |
| 318 | |
| 319 | void StatsReport::AddValue(StatsReport::StatsValueName name, |
| 320 | const std::string& value) { |
| 321 | values.push_back(Value(name, value)); |
| 322 | } |
| 323 | |
| 324 | void StatsReport::AddValue(StatsReport::StatsValueName name, int64 value) { |
| 325 | AddValue(name, rtc::ToString<int64>(value)); |
| 326 | } |
| 327 | |
| 328 | template <typename T> |
| 329 | void StatsReport::AddValue(StatsReport::StatsValueName name, |
| 330 | const std::vector<T>& value) { |
| 331 | std::ostringstream oss; |
| 332 | oss << "["; |
| 333 | for (size_t i = 0; i < value.size(); ++i) { |
| 334 | oss << rtc::ToString<T>(value[i]); |
| 335 | if (i != value.size() - 1) |
| 336 | oss << ", "; |
| 337 | } |
| 338 | oss << "]"; |
| 339 | AddValue(name, oss.str()); |
| 340 | } |
| 341 | |
| 342 | // Implementation specializations for the variants of AddValue that we use. |
| 343 | // TODO(tommi): Converting these ints to strings and copying strings, is not |
| 344 | // very efficient. Figure out a way to reduce the string churn. |
| 345 | template |
| 346 | void StatsReport::AddValue<std::string>( |
| 347 | StatsReport::StatsValueName, const std::vector<std::string>&); |
| 348 | |
| 349 | template |
| 350 | void StatsReport::AddValue<int>( |
| 351 | StatsReport::StatsValueName, const std::vector<int>&); |
| 352 | |
| 353 | template |
| 354 | void StatsReport::AddValue<int64_t>( |
| 355 | StatsReport::StatsValueName, const std::vector<int64_t>&); |
| 356 | |
| 357 | void StatsReport::AddBoolean(StatsReport::StatsValueName name, bool value) { |
| 358 | AddValue(name, value ? "true" : "false"); |
| 359 | } |
| 360 | |
| 361 | void StatsReport::ReplaceValue(StatsReport::StatsValueName name, |
| 362 | const std::string& value) { |
| 363 | for (Values::iterator it = values.begin(); it != values.end(); ++it) { |
| 364 | if ((*it).name == name) { |
| 365 | it->value = value; |
| 366 | return; |
| 367 | } |
| 368 | } |
| 369 | // It is not reachable here, add an ASSERT to make sure the overwriting is |
| 370 | // always a success. |
| 371 | ASSERT(false); |
| 372 | } |
| 373 | |
| 374 | StatsSet::StatsSet() { |
| 375 | } |
| 376 | |
| 377 | StatsSet::~StatsSet() { |
| 378 | } |
| 379 | |
| 380 | StatsSet::const_iterator StatsSet::begin() const { |
| 381 | return list_.begin(); |
| 382 | } |
| 383 | |
| 384 | StatsSet::const_iterator StatsSet::end() const { |
| 385 | return list_.end(); |
| 386 | } |
| 387 | |
| 388 | StatsReport* StatsSet::InsertNew(const std::string& id) { |
| 389 | ASSERT(Find(id) == NULL); |
| 390 | const StatsReport* ret = &(*list_.insert(StatsReportCopyable(id)).first); |
| 391 | return const_cast<StatsReport*>(ret); |
| 392 | } |
| 393 | |
| 394 | StatsReport* StatsSet::FindOrAddNew(const std::string& id) { |
| 395 | StatsReport* ret = Find(id); |
| 396 | return ret ? ret : InsertNew(id); |
| 397 | } |
| 398 | |
| 399 | StatsReport* StatsSet::ReplaceOrAddNew(const std::string& id) { |
| 400 | list_.erase(id); |
| 401 | return InsertNew(id); |
| 402 | } |
| 403 | |
| 404 | // Looks for a report with the given |id|. If one is not found, NULL |
| 405 | // will be returned. |
| 406 | StatsReport* StatsSet::Find(const std::string& id) { |
| 407 | const_iterator it = std::find(begin(), end(), id); |
| 408 | return it == end() ? NULL : |
| 409 | const_cast<StatsReport*>(static_cast<const StatsReport*>(&(*it))); |
| 410 | } |
tommi@webrtc.org | 5c3ee4b | 2014-12-09 10:47:01 | [diff] [blame] | 411 | |
| 412 | } // namespace webrtc |