| OLD | NEW |
| 1 /* | 1 /* |
| 2 * libjingle | 2 * libjingle |
| 3 * Copyright 2012 Google Inc. | 3 * Copyright 2012 Google Inc. |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions are met: | 6 * modification, are permitted provided that the following conditions are met: |
| 7 * | 7 * |
| 8 * 1. Redistributions of source code must retain the above copyright notice, | 8 * 1. Redistributions of source code must retain the above copyright notice, |
| 9 * this list of conditions and the following disclaimer. | 9 * this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright notice, | 10 * 2. Redistributions in binary form must reproduce the above copyright notice, |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 64 const ValueType& value; | 64 const ValueType& value; |
| 65 }; | 65 }; |
| 66 | 66 |
| 67 typedef TypeForAdd<bool> BoolForAdd; | 67 typedef TypeForAdd<bool> BoolForAdd; |
| 68 typedef TypeForAdd<float> FloatForAdd; | 68 typedef TypeForAdd<float> FloatForAdd; |
| 69 typedef TypeForAdd<int64> Int64ForAdd; | 69 typedef TypeForAdd<int64> Int64ForAdd; |
| 70 typedef TypeForAdd<int> IntForAdd; | 70 typedef TypeForAdd<int> IntForAdd; |
| 71 | 71 |
| 72 StatsReport::Id GetTransportIdFromProxy(const cricket::ProxyTransportMap& map, | 72 StatsReport::Id GetTransportIdFromProxy(const cricket::ProxyTransportMap& map, |
| 73 const std::string& proxy) { | 73 const std::string& proxy) { |
| 74 DCHECK(!proxy.empty()); | 74 RTC_DCHECK(!proxy.empty()); |
| 75 cricket::ProxyTransportMap::const_iterator found = map.find(proxy); | 75 cricket::ProxyTransportMap::const_iterator found = map.find(proxy); |
| 76 if (found == map.end()) | 76 if (found == map.end()) |
| 77 return StatsReport::Id(); | 77 return StatsReport::Id(); |
| 78 | 78 |
| 79 return StatsReport::NewComponentId( | 79 return StatsReport::NewComponentId( |
| 80 found->second, cricket::ICE_CANDIDATE_COMPONENT_RTP); | 80 found->second, cricket::ICE_CANDIDATE_COMPONENT_RTP); |
| 81 } | 81 } |
| 82 | 82 |
| 83 StatsReport* AddTrackReport(StatsCollection* reports, | 83 StatsReport* AddTrackReport(StatsCollection* reports, |
| 84 const std::string& track_id) { | 84 const std::string& track_id) { |
| 85 // Adds an empty track report. | 85 // Adds an empty track report. |
| 86 StatsReport::Id id( | 86 StatsReport::Id id( |
| 87 StatsReport::NewTypedId(StatsReport::kStatsReportTypeTrack, track_id)); | 87 StatsReport::NewTypedId(StatsReport::kStatsReportTypeTrack, track_id)); |
| 88 StatsReport* report = reports->ReplaceOrAddNew(id); | 88 StatsReport* report = reports->ReplaceOrAddNew(id); |
| 89 report->AddString(StatsReport::kStatsValueNameTrackId, track_id); | 89 report->AddString(StatsReport::kStatsValueNameTrackId, track_id); |
| 90 return report; | 90 return report; |
| 91 } | 91 } |
| 92 | 92 |
| 93 template <class TrackVector> | 93 template <class TrackVector> |
| 94 void CreateTrackReports(const TrackVector& tracks, StatsCollection* reports, | 94 void CreateTrackReports(const TrackVector& tracks, StatsCollection* reports, |
| 95 TrackIdMap& track_ids) { | 95 TrackIdMap& track_ids) { |
| 96 for (const auto& track : tracks) { | 96 for (const auto& track : tracks) { |
| 97 const std::string& track_id = track->id(); | 97 const std::string& track_id = track->id(); |
| 98 StatsReport* report = AddTrackReport(reports, track_id); | 98 StatsReport* report = AddTrackReport(reports, track_id); |
| 99 DCHECK(report != nullptr); | 99 RTC_DCHECK(report != nullptr); |
| 100 track_ids[track_id] = report; | 100 track_ids[track_id] = report; |
| 101 } | 101 } |
| 102 } | 102 } |
| 103 | 103 |
| 104 void ExtractCommonSendProperties(const cricket::MediaSenderInfo& info, | 104 void ExtractCommonSendProperties(const cricket::MediaSenderInfo& info, |
| 105 StatsReport* report) { | 105 StatsReport* report) { |
| 106 report->AddString(StatsReport::kStatsValueNameCodecName, info.codec_name); | 106 report->AddString(StatsReport::kStatsValueNameCodecName, info.codec_name); |
| 107 report->AddInt64(StatsReport::kStatsValueNameBytesSent, info.bytes_sent); | 107 report->AddInt64(StatsReport::kStatsValueNameBytesSent, info.bytes_sent); |
| 108 report->AddInt64(StatsReport::kStatsValueNameRtt, info.rtt_ms); | 108 report->AddInt64(StatsReport::kStatsValueNameRtt, info.rtt_ms); |
| 109 } | 109 } |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 254 }; | 254 }; |
| 255 | 255 |
| 256 for (const auto& i : ints) | 256 for (const auto& i : ints) |
| 257 report->AddInt(i.name, i.value); | 257 report->AddInt(i.name, i.value); |
| 258 } | 258 } |
| 259 | 259 |
| 260 void ExtractStats(const cricket::BandwidthEstimationInfo& info, | 260 void ExtractStats(const cricket::BandwidthEstimationInfo& info, |
| 261 double stats_gathering_started, | 261 double stats_gathering_started, |
| 262 PeerConnectionInterface::StatsOutputLevel level, | 262 PeerConnectionInterface::StatsOutputLevel level, |
| 263 StatsReport* report) { | 263 StatsReport* report) { |
| 264 DCHECK(report->type() == StatsReport::kStatsReportTypeBwe); | 264 RTC_DCHECK(report->type() == StatsReport::kStatsReportTypeBwe); |
| 265 | 265 |
| 266 report->set_timestamp(stats_gathering_started); | 266 report->set_timestamp(stats_gathering_started); |
| 267 const IntForAdd ints[] = { | 267 const IntForAdd ints[] = { |
| 268 { StatsReport::kStatsValueNameAvailableSendBandwidth, | 268 { StatsReport::kStatsValueNameAvailableSendBandwidth, |
| 269 info.available_send_bandwidth }, | 269 info.available_send_bandwidth }, |
| 270 { StatsReport::kStatsValueNameAvailableReceiveBandwidth, | 270 { StatsReport::kStatsValueNameAvailableReceiveBandwidth, |
| 271 info.available_recv_bandwidth }, | 271 info.available_recv_bandwidth }, |
| 272 { StatsReport::kStatsValueNameTargetEncBitrate, info.target_enc_bitrate }, | 272 { StatsReport::kStatsValueNameTargetEncBitrate, info.target_enc_bitrate }, |
| 273 { StatsReport::kStatsValueNameActualEncBitrate, info.actual_enc_bitrate }, | 273 { StatsReport::kStatsValueNameActualEncBitrate, info.actual_enc_bitrate }, |
| 274 { StatsReport::kStatsValueNameRetransmitBitrate, info.retransmit_bitrate }, | 274 { StatsReport::kStatsValueNameRetransmitBitrate, info.retransmit_bitrate }, |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 325 } | 325 } |
| 326 if (candidate_type == cricket::STUN_PORT_TYPE) { | 326 if (candidate_type == cricket::STUN_PORT_TYPE) { |
| 327 return STATSREPORT_STUN_PORT_TYPE; | 327 return STATSREPORT_STUN_PORT_TYPE; |
| 328 } | 328 } |
| 329 if (candidate_type == cricket::PRFLX_PORT_TYPE) { | 329 if (candidate_type == cricket::PRFLX_PORT_TYPE) { |
| 330 return STATSREPORT_PRFLX_PORT_TYPE; | 330 return STATSREPORT_PRFLX_PORT_TYPE; |
| 331 } | 331 } |
| 332 if (candidate_type == cricket::RELAY_PORT_TYPE) { | 332 if (candidate_type == cricket::RELAY_PORT_TYPE) { |
| 333 return STATSREPORT_RELAY_PORT_TYPE; | 333 return STATSREPORT_RELAY_PORT_TYPE; |
| 334 } | 334 } |
| 335 DCHECK(false); | 335 RTC_DCHECK(false); |
| 336 return "unknown"; | 336 return "unknown"; |
| 337 } | 337 } |
| 338 | 338 |
| 339 const char* AdapterTypeToStatsType(rtc::AdapterType type) { | 339 const char* AdapterTypeToStatsType(rtc::AdapterType type) { |
| 340 switch (type) { | 340 switch (type) { |
| 341 case rtc::ADAPTER_TYPE_UNKNOWN: | 341 case rtc::ADAPTER_TYPE_UNKNOWN: |
| 342 return "unknown"; | 342 return "unknown"; |
| 343 case rtc::ADAPTER_TYPE_ETHERNET: | 343 case rtc::ADAPTER_TYPE_ETHERNET: |
| 344 return STATSREPORT_ADAPTER_TYPE_ETHERNET; | 344 return STATSREPORT_ADAPTER_TYPE_ETHERNET; |
| 345 case rtc::ADAPTER_TYPE_WIFI: | 345 case rtc::ADAPTER_TYPE_WIFI: |
| 346 return STATSREPORT_ADAPTER_TYPE_WIFI; | 346 return STATSREPORT_ADAPTER_TYPE_WIFI; |
| 347 case rtc::ADAPTER_TYPE_CELLULAR: | 347 case rtc::ADAPTER_TYPE_CELLULAR: |
| 348 return STATSREPORT_ADAPTER_TYPE_WWAN; | 348 return STATSREPORT_ADAPTER_TYPE_WWAN; |
| 349 case rtc::ADAPTER_TYPE_VPN: | 349 case rtc::ADAPTER_TYPE_VPN: |
| 350 return STATSREPORT_ADAPTER_TYPE_VPN; | 350 return STATSREPORT_ADAPTER_TYPE_VPN; |
| 351 case rtc::ADAPTER_TYPE_LOOPBACK: | 351 case rtc::ADAPTER_TYPE_LOOPBACK: |
| 352 return STATSREPORT_ADAPTER_TYPE_LOOPBACK; | 352 return STATSREPORT_ADAPTER_TYPE_LOOPBACK; |
| 353 default: | 353 default: |
| 354 DCHECK(false); | 354 RTC_DCHECK(false); |
| 355 return ""; | 355 return ""; |
| 356 } | 356 } |
| 357 } | 357 } |
| 358 | 358 |
| 359 StatsCollector::StatsCollector(WebRtcSession* session) | 359 StatsCollector::StatsCollector(WebRtcSession* session) |
| 360 : session_(session), | 360 : session_(session), |
| 361 stats_gathering_started_(0) { | 361 stats_gathering_started_(0) { |
| 362 DCHECK(session_); | 362 RTC_DCHECK(session_); |
| 363 } | 363 } |
| 364 | 364 |
| 365 StatsCollector::~StatsCollector() { | 365 StatsCollector::~StatsCollector() { |
| 366 DCHECK(session_->signaling_thread()->IsCurrent()); | 366 RTC_DCHECK(session_->signaling_thread()->IsCurrent()); |
| 367 } | 367 } |
| 368 | 368 |
| 369 double StatsCollector::GetTimeNow() { | 369 double StatsCollector::GetTimeNow() { |
| 370 return rtc::Timing::WallTimeNow() * rtc::kNumMillisecsPerSec; | 370 return rtc::Timing::WallTimeNow() * rtc::kNumMillisecsPerSec; |
| 371 } | 371 } |
| 372 | 372 |
| 373 // Adds a MediaStream with tracks that can be used as a |selector| in a call | 373 // Adds a MediaStream with tracks that can be used as a |selector| in a call |
| 374 // to GetStats. | 374 // to GetStats. |
| 375 void StatsCollector::AddStream(MediaStreamInterface* stream) { | 375 void StatsCollector::AddStream(MediaStreamInterface* stream) { |
| 376 DCHECK(session_->signaling_thread()->IsCurrent()); | 376 RTC_DCHECK(session_->signaling_thread()->IsCurrent()); |
| 377 DCHECK(stream != NULL); | 377 RTC_DCHECK(stream != NULL); |
| 378 | 378 |
| 379 CreateTrackReports<AudioTrackVector>(stream->GetAudioTracks(), | 379 CreateTrackReports<AudioTrackVector>(stream->GetAudioTracks(), |
| 380 &reports_, track_ids_); | 380 &reports_, track_ids_); |
| 381 CreateTrackReports<VideoTrackVector>(stream->GetVideoTracks(), | 381 CreateTrackReports<VideoTrackVector>(stream->GetVideoTracks(), |
| 382 &reports_, track_ids_); | 382 &reports_, track_ids_); |
| 383 } | 383 } |
| 384 | 384 |
| 385 void StatsCollector::AddLocalAudioTrack(AudioTrackInterface* audio_track, | 385 void StatsCollector::AddLocalAudioTrack(AudioTrackInterface* audio_track, |
| 386 uint32 ssrc) { | 386 uint32 ssrc) { |
| 387 DCHECK(session_->signaling_thread()->IsCurrent()); | 387 RTC_DCHECK(session_->signaling_thread()->IsCurrent()); |
| 388 DCHECK(audio_track != NULL); | 388 RTC_DCHECK(audio_track != NULL); |
| 389 #if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) | 389 #if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) |
| 390 for (const auto& track : local_audio_tracks_) | 390 for (const auto& track : local_audio_tracks_) |
| 391 DCHECK(track.first != audio_track || track.second != ssrc); | 391 RTC_DCHECK(track.first != audio_track || track.second != ssrc); |
| 392 #endif | 392 #endif |
| 393 | 393 |
| 394 local_audio_tracks_.push_back(std::make_pair(audio_track, ssrc)); | 394 local_audio_tracks_.push_back(std::make_pair(audio_track, ssrc)); |
| 395 | 395 |
| 396 // Create the kStatsReportTypeTrack report for the new track if there is no | 396 // Create the kStatsReportTypeTrack report for the new track if there is no |
| 397 // report yet. | 397 // report yet. |
| 398 StatsReport::Id id(StatsReport::NewTypedId(StatsReport::kStatsReportTypeTrack, | 398 StatsReport::Id id(StatsReport::NewTypedId(StatsReport::kStatsReportTypeTrack, |
| 399 audio_track->id())); | 399 audio_track->id())); |
| 400 StatsReport* report = reports_.Find(id); | 400 StatsReport* report = reports_.Find(id); |
| 401 if (!report) { | 401 if (!report) { |
| 402 report = reports_.InsertNew(id); | 402 report = reports_.InsertNew(id); |
| 403 report->AddString(StatsReport::kStatsValueNameTrackId, audio_track->id()); | 403 report->AddString(StatsReport::kStatsValueNameTrackId, audio_track->id()); |
| 404 } | 404 } |
| 405 } | 405 } |
| 406 | 406 |
| 407 void StatsCollector::RemoveLocalAudioTrack(AudioTrackInterface* audio_track, | 407 void StatsCollector::RemoveLocalAudioTrack(AudioTrackInterface* audio_track, |
| 408 uint32 ssrc) { | 408 uint32 ssrc) { |
| 409 DCHECK(audio_track != NULL); | 409 RTC_DCHECK(audio_track != NULL); |
| 410 local_audio_tracks_.erase(std::remove_if(local_audio_tracks_.begin(), | 410 local_audio_tracks_.erase(std::remove_if(local_audio_tracks_.begin(), |
| 411 local_audio_tracks_.end(), | 411 local_audio_tracks_.end(), |
| 412 [audio_track, ssrc](const LocalAudioTrackVector::value_type& track) { | 412 [audio_track, ssrc](const LocalAudioTrackVector::value_type& track) { |
| 413 return track.first == audio_track && track.second == ssrc; | 413 return track.first == audio_track && track.second == ssrc; |
| 414 })); | 414 })); |
| 415 } | 415 } |
| 416 | 416 |
| 417 void StatsCollector::GetStats(MediaStreamTrackInterface* track, | 417 void StatsCollector::GetStats(MediaStreamTrackInterface* track, |
| 418 StatsReports* reports) { | 418 StatsReports* reports) { |
| 419 DCHECK(session_->signaling_thread()->IsCurrent()); | 419 RTC_DCHECK(session_->signaling_thread()->IsCurrent()); |
| 420 DCHECK(reports != NULL); | 420 RTC_DCHECK(reports != NULL); |
| 421 DCHECK(reports->empty()); | 421 RTC_DCHECK(reports->empty()); |
| 422 | 422 |
| 423 rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls; | 423 rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls; |
| 424 | 424 |
| 425 if (!track) { | 425 if (!track) { |
| 426 reports->reserve(reports_.size()); | 426 reports->reserve(reports_.size()); |
| 427 for (auto* r : reports_) | 427 for (auto* r : reports_) |
| 428 reports->push_back(r); | 428 reports->push_back(r); |
| 429 return; | 429 return; |
| 430 } | 430 } |
| 431 | 431 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 449 | 449 |
| 450 const StatsReport::Value* v = | 450 const StatsReport::Value* v = |
| 451 r->FindValue(StatsReport::kStatsValueNameTrackId); | 451 r->FindValue(StatsReport::kStatsValueNameTrackId); |
| 452 if (v && v->string_val() == track->id()) | 452 if (v && v->string_val() == track->id()) |
| 453 reports->push_back(r); | 453 reports->push_back(r); |
| 454 } | 454 } |
| 455 } | 455 } |
| 456 | 456 |
| 457 void | 457 void |
| 458 StatsCollector::UpdateStats(PeerConnectionInterface::StatsOutputLevel level) { | 458 StatsCollector::UpdateStats(PeerConnectionInterface::StatsOutputLevel level) { |
| 459 DCHECK(session_->signaling_thread()->IsCurrent()); | 459 RTC_DCHECK(session_->signaling_thread()->IsCurrent()); |
| 460 double time_now = GetTimeNow(); | 460 double time_now = GetTimeNow(); |
| 461 // Calls to UpdateStats() that occur less than kMinGatherStatsPeriod number of | 461 // Calls to UpdateStats() that occur less than kMinGatherStatsPeriod number of |
| 462 // ms apart will be ignored. | 462 // ms apart will be ignored. |
| 463 const double kMinGatherStatsPeriod = 50; | 463 const double kMinGatherStatsPeriod = 50; |
| 464 if (stats_gathering_started_ != 0 && | 464 if (stats_gathering_started_ != 0 && |
| 465 stats_gathering_started_ + kMinGatherStatsPeriod > time_now) { | 465 stats_gathering_started_ + kMinGatherStatsPeriod > time_now) { |
| 466 return; | 466 return; |
| 467 } | 467 } |
| 468 stats_gathering_started_ = time_now; | 468 stats_gathering_started_ = time_now; |
| 469 | 469 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 480 ExtractDataInfo(); | 480 ExtractDataInfo(); |
| 481 UpdateTrackReports(); | 481 UpdateTrackReports(); |
| 482 } | 482 } |
| 483 } | 483 } |
| 484 | 484 |
| 485 StatsReport* StatsCollector::PrepareReport( | 485 StatsReport* StatsCollector::PrepareReport( |
| 486 bool local, | 486 bool local, |
| 487 uint32 ssrc, | 487 uint32 ssrc, |
| 488 const StatsReport::Id& transport_id, | 488 const StatsReport::Id& transport_id, |
| 489 StatsReport::Direction direction) { | 489 StatsReport::Direction direction) { |
| 490 DCHECK(session_->signaling_thread()->IsCurrent()); | 490 RTC_DCHECK(session_->signaling_thread()->IsCurrent()); |
| 491 StatsReport::Id id(StatsReport::NewIdWithDirection( | 491 StatsReport::Id id(StatsReport::NewIdWithDirection( |
| 492 local ? StatsReport::kStatsReportTypeSsrc : | 492 local ? StatsReport::kStatsReportTypeSsrc : |
| 493 StatsReport::kStatsReportTypeRemoteSsrc, | 493 StatsReport::kStatsReportTypeRemoteSsrc, |
| 494 rtc::ToString<uint32>(ssrc), direction)); | 494 rtc::ToString<uint32>(ssrc), direction)); |
| 495 StatsReport* report = reports_.Find(id); | 495 StatsReport* report = reports_.Find(id); |
| 496 | 496 |
| 497 // Use the ID of the track that is currently mapped to the SSRC, if any. | 497 // Use the ID of the track that is currently mapped to the SSRC, if any. |
| 498 std::string track_id; | 498 std::string track_id; |
| 499 if (!GetTrackIdBySsrc(ssrc, &track_id, direction)) { | 499 if (!GetTrackIdBySsrc(ssrc, &track_id, direction)) { |
| 500 if (!report) { | 500 if (!report) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 519 | 519 |
| 520 report->AddInt64(StatsReport::kStatsValueNameSsrc, ssrc); | 520 report->AddInt64(StatsReport::kStatsValueNameSsrc, ssrc); |
| 521 report->AddString(StatsReport::kStatsValueNameTrackId, track_id); | 521 report->AddString(StatsReport::kStatsValueNameTrackId, track_id); |
| 522 // Add the mapping of SSRC to transport. | 522 // Add the mapping of SSRC to transport. |
| 523 report->AddId(StatsReport::kStatsValueNameTransportId, transport_id); | 523 report->AddId(StatsReport::kStatsValueNameTransportId, transport_id); |
| 524 return report; | 524 return report; |
| 525 } | 525 } |
| 526 | 526 |
| 527 StatsReport* StatsCollector::AddOneCertificateReport( | 527 StatsReport* StatsCollector::AddOneCertificateReport( |
| 528 const rtc::SSLCertificate* cert, const StatsReport* issuer) { | 528 const rtc::SSLCertificate* cert, const StatsReport* issuer) { |
| 529 DCHECK(session_->signaling_thread()->IsCurrent()); | 529 RTC_DCHECK(session_->signaling_thread()->IsCurrent()); |
| 530 | 530 |
| 531 // TODO(bemasc): Move this computation to a helper class that caches these | 531 // TODO(bemasc): Move this computation to a helper class that caches these |
| 532 // values to reduce CPU use in GetStats. This will require adding a fast | 532 // values to reduce CPU use in GetStats. This will require adding a fast |
| 533 // SSLCertificate::Equals() method to detect certificate changes. | 533 // SSLCertificate::Equals() method to detect certificate changes. |
| 534 | 534 |
| 535 std::string digest_algorithm; | 535 std::string digest_algorithm; |
| 536 if (!cert->GetSignatureDigestAlgorithm(&digest_algorithm)) | 536 if (!cert->GetSignatureDigestAlgorithm(&digest_algorithm)) |
| 537 return nullptr; | 537 return nullptr; |
| 538 | 538 |
| 539 rtc::scoped_ptr<rtc::SSLFingerprint> ssl_fingerprint( | 539 rtc::scoped_ptr<rtc::SSLFingerprint> ssl_fingerprint( |
| (...skipping 22 matching lines...) Expand all Loading... |
| 562 report->AddString(StatsReport::kStatsValueNameFingerprintAlgorithm, | 562 report->AddString(StatsReport::kStatsValueNameFingerprintAlgorithm, |
| 563 digest_algorithm); | 563 digest_algorithm); |
| 564 report->AddString(StatsReport::kStatsValueNameDer, der_base64); | 564 report->AddString(StatsReport::kStatsValueNameDer, der_base64); |
| 565 if (issuer) | 565 if (issuer) |
| 566 report->AddId(StatsReport::kStatsValueNameIssuerId, issuer->id()); | 566 report->AddId(StatsReport::kStatsValueNameIssuerId, issuer->id()); |
| 567 return report; | 567 return report; |
| 568 } | 568 } |
| 569 | 569 |
| 570 StatsReport* StatsCollector::AddCertificateReports( | 570 StatsReport* StatsCollector::AddCertificateReports( |
| 571 const rtc::SSLCertificate* cert) { | 571 const rtc::SSLCertificate* cert) { |
| 572 DCHECK(session_->signaling_thread()->IsCurrent()); | 572 RTC_DCHECK(session_->signaling_thread()->IsCurrent()); |
| 573 // Produces a chain of StatsReports representing this certificate and the rest | 573 // Produces a chain of StatsReports representing this certificate and the rest |
| 574 // of its chain, and adds those reports to |reports_|. The return value is | 574 // of its chain, and adds those reports to |reports_|. The return value is |
| 575 // the id of the leaf report. The provided cert must be non-null, so at least | 575 // the id of the leaf report. The provided cert must be non-null, so at least |
| 576 // one report will always be provided and the returned string will never be | 576 // one report will always be provided and the returned string will never be |
| 577 // empty. | 577 // empty. |
| 578 DCHECK(cert != NULL); | 578 RTC_DCHECK(cert != NULL); |
| 579 | 579 |
| 580 StatsReport* issuer = nullptr; | 580 StatsReport* issuer = nullptr; |
| 581 rtc::scoped_ptr<rtc::SSLCertChain> chain; | 581 rtc::scoped_ptr<rtc::SSLCertChain> chain; |
| 582 if (cert->GetChain(chain.accept())) { | 582 if (cert->GetChain(chain.accept())) { |
| 583 // This loop runs in reverse, i.e. from root to leaf, so that each | 583 // This loop runs in reverse, i.e. from root to leaf, so that each |
| 584 // certificate's issuer's report ID is known before the child certificate's | 584 // certificate's issuer's report ID is known before the child certificate's |
| 585 // report is generated. The root certificate does not have an issuer ID | 585 // report is generated. The root certificate does not have an issuer ID |
| 586 // value. | 586 // value. |
| 587 for (ptrdiff_t i = chain->GetSize() - 1; i >= 0; --i) { | 587 for (ptrdiff_t i = chain->GetSize() - 1; i >= 0; --i) { |
| 588 const rtc::SSLCertificate& cert_i = chain->Get(i); | 588 const rtc::SSLCertificate& cert_i = chain->Get(i); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 662 report->AddString(StatsReport::kStatsValueNameCandidateType, | 662 report->AddString(StatsReport::kStatsValueNameCandidateType, |
| 663 IceCandidateTypeToStatsType(candidate.type())); | 663 IceCandidateTypeToStatsType(candidate.type())); |
| 664 report->AddString(StatsReport::kStatsValueNameCandidateTransportType, | 664 report->AddString(StatsReport::kStatsValueNameCandidateTransportType, |
| 665 candidate.protocol()); | 665 candidate.protocol()); |
| 666 } | 666 } |
| 667 | 667 |
| 668 return report; | 668 return report; |
| 669 } | 669 } |
| 670 | 670 |
| 671 void StatsCollector::ExtractSessionInfo() { | 671 void StatsCollector::ExtractSessionInfo() { |
| 672 DCHECK(session_->signaling_thread()->IsCurrent()); | 672 RTC_DCHECK(session_->signaling_thread()->IsCurrent()); |
| 673 | 673 |
| 674 // Extract information from the base session. | 674 // Extract information from the base session. |
| 675 StatsReport::Id id(StatsReport::NewTypedId( | 675 StatsReport::Id id(StatsReport::NewTypedId( |
| 676 StatsReport::kStatsReportTypeSession, session_->id())); | 676 StatsReport::kStatsReportTypeSession, session_->id())); |
| 677 StatsReport* report = reports_.ReplaceOrAddNew(id); | 677 StatsReport* report = reports_.ReplaceOrAddNew(id); |
| 678 report->set_timestamp(stats_gathering_started_); | 678 report->set_timestamp(stats_gathering_started_); |
| 679 report->AddBoolean(StatsReport::kStatsValueNameInitiator, | 679 report->AddBoolean(StatsReport::kStatsValueNameInitiator, |
| 680 session_->initiator()); | 680 session_->initiator()); |
| 681 | 681 |
| 682 cricket::SessionStats stats; | 682 cricket::SessionStats stats; |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 756 channel_report->AddId( | 756 channel_report->AddId( |
| 757 StatsReport::kStatsValueNameSelectedCandidatePairId, | 757 StatsReport::kStatsValueNameSelectedCandidatePairId, |
| 758 connection_report->id()); | 758 connection_report->id()); |
| 759 } | 759 } |
| 760 } | 760 } |
| 761 } | 761 } |
| 762 } | 762 } |
| 763 } | 763 } |
| 764 | 764 |
| 765 void StatsCollector::ExtractVoiceInfo() { | 765 void StatsCollector::ExtractVoiceInfo() { |
| 766 DCHECK(session_->signaling_thread()->IsCurrent()); | 766 RTC_DCHECK(session_->signaling_thread()->IsCurrent()); |
| 767 | 767 |
| 768 if (!session_->voice_channel()) { | 768 if (!session_->voice_channel()) { |
| 769 return; | 769 return; |
| 770 } | 770 } |
| 771 cricket::VoiceMediaInfo voice_info; | 771 cricket::VoiceMediaInfo voice_info; |
| 772 if (!session_->voice_channel()->GetStats(&voice_info)) { | 772 if (!session_->voice_channel()->GetStats(&voice_info)) { |
| 773 LOG(LS_ERROR) << "Failed to get voice channel stats."; | 773 LOG(LS_ERROR) << "Failed to get voice channel stats."; |
| 774 return; | 774 return; |
| 775 } | 775 } |
| 776 | 776 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 789 ExtractStatsFromList(voice_info.receivers, transport_id, this, | 789 ExtractStatsFromList(voice_info.receivers, transport_id, this, |
| 790 StatsReport::kReceive); | 790 StatsReport::kReceive); |
| 791 ExtractStatsFromList(voice_info.senders, transport_id, this, | 791 ExtractStatsFromList(voice_info.senders, transport_id, this, |
| 792 StatsReport::kSend); | 792 StatsReport::kSend); |
| 793 | 793 |
| 794 UpdateStatsFromExistingLocalAudioTracks(); | 794 UpdateStatsFromExistingLocalAudioTracks(); |
| 795 } | 795 } |
| 796 | 796 |
| 797 void StatsCollector::ExtractVideoInfo( | 797 void StatsCollector::ExtractVideoInfo( |
| 798 PeerConnectionInterface::StatsOutputLevel level) { | 798 PeerConnectionInterface::StatsOutputLevel level) { |
| 799 DCHECK(session_->signaling_thread()->IsCurrent()); | 799 RTC_DCHECK(session_->signaling_thread()->IsCurrent()); |
| 800 | 800 |
| 801 if (!session_->video_channel()) | 801 if (!session_->video_channel()) |
| 802 return; | 802 return; |
| 803 | 803 |
| 804 cricket::VideoMediaInfo video_info; | 804 cricket::VideoMediaInfo video_info; |
| 805 if (!session_->video_channel()->GetStats(&video_info)) { | 805 if (!session_->video_channel()->GetStats(&video_info)) { |
| 806 LOG(LS_ERROR) << "Failed to get video channel stats."; | 806 LOG(LS_ERROR) << "Failed to get video channel stats."; |
| 807 return; | 807 return; |
| 808 } | 808 } |
| 809 | 809 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 826 LOG(LS_ERROR) << "BWEs count: " << video_info.bw_estimations.size(); | 826 LOG(LS_ERROR) << "BWEs count: " << video_info.bw_estimations.size(); |
| 827 } else { | 827 } else { |
| 828 StatsReport::Id report_id(StatsReport::NewBandwidthEstimationId()); | 828 StatsReport::Id report_id(StatsReport::NewBandwidthEstimationId()); |
| 829 StatsReport* report = reports_.FindOrAddNew(report_id); | 829 StatsReport* report = reports_.FindOrAddNew(report_id); |
| 830 ExtractStats( | 830 ExtractStats( |
| 831 video_info.bw_estimations[0], stats_gathering_started_, level, report); | 831 video_info.bw_estimations[0], stats_gathering_started_, level, report); |
| 832 } | 832 } |
| 833 } | 833 } |
| 834 | 834 |
| 835 void StatsCollector::ExtractDataInfo() { | 835 void StatsCollector::ExtractDataInfo() { |
| 836 DCHECK(session_->signaling_thread()->IsCurrent()); | 836 RTC_DCHECK(session_->signaling_thread()->IsCurrent()); |
| 837 | 837 |
| 838 rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls; | 838 rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls; |
| 839 | 839 |
| 840 for (const auto& dc : | 840 for (const auto& dc : |
| 841 session_->mediastream_signaling()->sctp_data_channels()) { | 841 session_->mediastream_signaling()->sctp_data_channels()) { |
| 842 StatsReport::Id id(StatsReport::NewTypedIntId( | 842 StatsReport::Id id(StatsReport::NewTypedIntId( |
| 843 StatsReport::kStatsReportTypeDataChannel, dc->id())); | 843 StatsReport::kStatsReportTypeDataChannel, dc->id())); |
| 844 StatsReport* report = reports_.ReplaceOrAddNew(id); | 844 StatsReport* report = reports_.ReplaceOrAddNew(id); |
| 845 report->set_timestamp(stats_gathering_started_); | 845 report->set_timestamp(stats_gathering_started_); |
| 846 report->AddString(StatsReport::kStatsValueNameLabel, dc->label()); | 846 report->AddString(StatsReport::kStatsValueNameLabel, dc->label()); |
| 847 report->AddInt(StatsReport::kStatsValueNameDataChannelId, dc->id()); | 847 report->AddInt(StatsReport::kStatsValueNameDataChannelId, dc->id()); |
| 848 report->AddString(StatsReport::kStatsValueNameProtocol, dc->protocol()); | 848 report->AddString(StatsReport::kStatsValueNameProtocol, dc->protocol()); |
| 849 report->AddString(StatsReport::kStatsValueNameState, | 849 report->AddString(StatsReport::kStatsValueNameState, |
| 850 DataChannelInterface::DataStateString(dc->state())); | 850 DataChannelInterface::DataStateString(dc->state())); |
| 851 } | 851 } |
| 852 } | 852 } |
| 853 | 853 |
| 854 StatsReport* StatsCollector::GetReport(const StatsReport::StatsType& type, | 854 StatsReport* StatsCollector::GetReport(const StatsReport::StatsType& type, |
| 855 const std::string& id, | 855 const std::string& id, |
| 856 StatsReport::Direction direction) { | 856 StatsReport::Direction direction) { |
| 857 DCHECK(session_->signaling_thread()->IsCurrent()); | 857 RTC_DCHECK(session_->signaling_thread()->IsCurrent()); |
| 858 DCHECK(type == StatsReport::kStatsReportTypeSsrc || | 858 RTC_DCHECK(type == StatsReport::kStatsReportTypeSsrc || |
| 859 type == StatsReport::kStatsReportTypeRemoteSsrc); | 859 type == StatsReport::kStatsReportTypeRemoteSsrc); |
| 860 return reports_.Find(StatsReport::NewIdWithDirection(type, id, direction)); | 860 return reports_.Find(StatsReport::NewIdWithDirection(type, id, direction)); |
| 861 } | 861 } |
| 862 | 862 |
| 863 void StatsCollector::UpdateStatsFromExistingLocalAudioTracks() { | 863 void StatsCollector::UpdateStatsFromExistingLocalAudioTracks() { |
| 864 DCHECK(session_->signaling_thread()->IsCurrent()); | 864 RTC_DCHECK(session_->signaling_thread()->IsCurrent()); |
| 865 // Loop through the existing local audio tracks. | 865 // Loop through the existing local audio tracks. |
| 866 for (const auto& it : local_audio_tracks_) { | 866 for (const auto& it : local_audio_tracks_) { |
| 867 AudioTrackInterface* track = it.first; | 867 AudioTrackInterface* track = it.first; |
| 868 uint32 ssrc = it.second; | 868 uint32 ssrc = it.second; |
| 869 StatsReport* report = GetReport(StatsReport::kStatsReportTypeSsrc, | 869 StatsReport* report = GetReport(StatsReport::kStatsReportTypeSsrc, |
| 870 rtc::ToString<uint32>(ssrc), | 870 rtc::ToString<uint32>(ssrc), |
| 871 StatsReport::kSend); | 871 StatsReport::kSend); |
| 872 if (report == NULL) { | 872 if (report == NULL) { |
| 873 // This can happen if a local audio track is added to a stream on the | 873 // This can happen if a local audio track is added to a stream on the |
| 874 // fly and the report has not been set up yet. Do nothing in this case. | 874 // fly and the report has not been set up yet. Do nothing in this case. |
| 875 LOG(LS_ERROR) << "Stats report does not exist for ssrc " << ssrc; | 875 LOG(LS_ERROR) << "Stats report does not exist for ssrc " << ssrc; |
| 876 continue; | 876 continue; |
| 877 } | 877 } |
| 878 | 878 |
| 879 // The same ssrc can be used by both local and remote audio tracks. | 879 // The same ssrc can be used by both local and remote audio tracks. |
| 880 const StatsReport::Value* v = | 880 const StatsReport::Value* v = |
| 881 report->FindValue(StatsReport::kStatsValueNameTrackId); | 881 report->FindValue(StatsReport::kStatsValueNameTrackId); |
| 882 if (!v || v->string_val() != track->id()) | 882 if (!v || v->string_val() != track->id()) |
| 883 continue; | 883 continue; |
| 884 | 884 |
| 885 report->set_timestamp(stats_gathering_started_); | 885 report->set_timestamp(stats_gathering_started_); |
| 886 UpdateReportFromAudioTrack(track, report); | 886 UpdateReportFromAudioTrack(track, report); |
| 887 } | 887 } |
| 888 } | 888 } |
| 889 | 889 |
| 890 void StatsCollector::UpdateReportFromAudioTrack(AudioTrackInterface* track, | 890 void StatsCollector::UpdateReportFromAudioTrack(AudioTrackInterface* track, |
| 891 StatsReport* report) { | 891 StatsReport* report) { |
| 892 DCHECK(session_->signaling_thread()->IsCurrent()); | 892 RTC_DCHECK(session_->signaling_thread()->IsCurrent()); |
| 893 DCHECK(track != NULL); | 893 RTC_DCHECK(track != NULL); |
| 894 | 894 |
| 895 int signal_level = 0; | 895 int signal_level = 0; |
| 896 if (!track->GetSignalLevel(&signal_level)) | 896 if (!track->GetSignalLevel(&signal_level)) |
| 897 signal_level = -1; | 897 signal_level = -1; |
| 898 | 898 |
| 899 rtc::scoped_refptr<AudioProcessorInterface> audio_processor( | 899 rtc::scoped_refptr<AudioProcessorInterface> audio_processor( |
| 900 track->GetAudioProcessor()); | 900 track->GetAudioProcessor()); |
| 901 | 901 |
| 902 AudioProcessorInterface::AudioProcessorStats stats; | 902 AudioProcessorInterface::AudioProcessorStats stats; |
| 903 if (audio_processor.get()) | 903 if (audio_processor.get()) |
| 904 audio_processor->GetStats(&stats); | 904 audio_processor->GetStats(&stats); |
| 905 | 905 |
| 906 SetAudioProcessingStats(report, signal_level, stats.typing_noise_detected, | 906 SetAudioProcessingStats(report, signal_level, stats.typing_noise_detected, |
| 907 stats.echo_return_loss, stats.echo_return_loss_enhancement, | 907 stats.echo_return_loss, stats.echo_return_loss_enhancement, |
| 908 stats.echo_delay_median_ms, stats.aec_quality_min, | 908 stats.echo_delay_median_ms, stats.aec_quality_min, |
| 909 stats.echo_delay_std_ms); | 909 stats.echo_delay_std_ms); |
| 910 } | 910 } |
| 911 | 911 |
| 912 bool StatsCollector::GetTrackIdBySsrc(uint32 ssrc, std::string* track_id, | 912 bool StatsCollector::GetTrackIdBySsrc(uint32 ssrc, std::string* track_id, |
| 913 StatsReport::Direction direction) { | 913 StatsReport::Direction direction) { |
| 914 DCHECK(session_->signaling_thread()->IsCurrent()); | 914 RTC_DCHECK(session_->signaling_thread()->IsCurrent()); |
| 915 if (direction == StatsReport::kSend) { | 915 if (direction == StatsReport::kSend) { |
| 916 if (!session_->GetLocalTrackIdBySsrc(ssrc, track_id)) { | 916 if (!session_->GetLocalTrackIdBySsrc(ssrc, track_id)) { |
| 917 LOG(LS_WARNING) << "The SSRC " << ssrc | 917 LOG(LS_WARNING) << "The SSRC " << ssrc |
| 918 << " is not associated with a sending track"; | 918 << " is not associated with a sending track"; |
| 919 return false; | 919 return false; |
| 920 } | 920 } |
| 921 } else { | 921 } else { |
| 922 DCHECK(direction == StatsReport::kReceive); | 922 RTC_DCHECK(direction == StatsReport::kReceive); |
| 923 if (!session_->GetRemoteTrackIdBySsrc(ssrc, track_id)) { | 923 if (!session_->GetRemoteTrackIdBySsrc(ssrc, track_id)) { |
| 924 LOG(LS_WARNING) << "The SSRC " << ssrc | 924 LOG(LS_WARNING) << "The SSRC " << ssrc |
| 925 << " is not associated with a receiving track"; | 925 << " is not associated with a receiving track"; |
| 926 return false; | 926 return false; |
| 927 } | 927 } |
| 928 } | 928 } |
| 929 | 929 |
| 930 return true; | 930 return true; |
| 931 } | 931 } |
| 932 | 932 |
| 933 void StatsCollector::UpdateTrackReports() { | 933 void StatsCollector::UpdateTrackReports() { |
| 934 DCHECK(session_->signaling_thread()->IsCurrent()); | 934 RTC_DCHECK(session_->signaling_thread()->IsCurrent()); |
| 935 | 935 |
| 936 rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls; | 936 rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls; |
| 937 | 937 |
| 938 for (const auto& entry : track_ids_) { | 938 for (const auto& entry : track_ids_) { |
| 939 StatsReport* report = entry.second; | 939 StatsReport* report = entry.second; |
| 940 report->set_timestamp(stats_gathering_started_); | 940 report->set_timestamp(stats_gathering_started_); |
| 941 } | 941 } |
| 942 | 942 |
| 943 } | 943 } |
| 944 | 944 |
| 945 void StatsCollector::ClearUpdateStatsCacheForTest() { | 945 void StatsCollector::ClearUpdateStatsCacheForTest() { |
| 946 stats_gathering_started_ = 0; | 946 stats_gathering_started_ = 0; |
| 947 } | 947 } |
| 948 | 948 |
| 949 } // namespace webrtc | 949 } // namespace webrtc |
| OLD | NEW |