OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright 2012 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
351 return ""; | 351 return ""; |
352 } | 352 } |
353 } | 353 } |
354 | 354 |
355 StatsCollector::StatsCollector(PeerConnection* pc) | 355 StatsCollector::StatsCollector(PeerConnection* pc) |
356 : pc_(pc), stats_gathering_started_(0) { | 356 : pc_(pc), stats_gathering_started_(0) { |
357 RTC_DCHECK(pc_); | 357 RTC_DCHECK(pc_); |
358 } | 358 } |
359 | 359 |
360 StatsCollector::~StatsCollector() { | 360 StatsCollector::~StatsCollector() { |
361 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent()); | 361 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); |
362 } | 362 } |
363 | 363 |
364 double StatsCollector::GetTimeNow() { | 364 double StatsCollector::GetTimeNow() { |
| 365 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); |
365 return rtc::Timing::WallTimeNow() * rtc::kNumMillisecsPerSec; | 366 return rtc::Timing::WallTimeNow() * rtc::kNumMillisecsPerSec; |
366 } | 367 } |
367 | 368 |
368 // Adds a MediaStream with tracks that can be used as a |selector| in a call | 369 // Adds a MediaStream with tracks that can be used as a |selector| in a call |
369 // to GetStats. | 370 // to GetStats. |
370 void StatsCollector::AddStream(MediaStreamInterface* stream) { | 371 void StatsCollector::AddStream(MediaStreamInterface* stream) { |
371 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent()); | 372 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); |
372 RTC_DCHECK(stream != NULL); | 373 RTC_DCHECK(stream != NULL); |
373 | 374 |
374 CreateTrackReports<AudioTrackVector>(stream->GetAudioTracks(), | 375 CreateTrackReports<AudioTrackVector>(stream->GetAudioTracks(), |
375 &reports_, track_ids_); | 376 &reports_, track_ids_); |
376 CreateTrackReports<VideoTrackVector>(stream->GetVideoTracks(), | 377 CreateTrackReports<VideoTrackVector>(stream->GetVideoTracks(), |
377 &reports_, track_ids_); | 378 &reports_, track_ids_); |
378 } | 379 } |
379 | 380 |
380 void StatsCollector::AddLocalAudioTrack(AudioTrackInterface* audio_track, | 381 void StatsCollector::AddLocalAudioTrack(AudioTrackInterface* audio_track, |
381 uint32_t ssrc) { | 382 uint32_t ssrc) { |
382 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent()); | 383 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); |
383 RTC_DCHECK(audio_track != NULL); | 384 RTC_DCHECK(audio_track != NULL); |
384 #if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) | 385 #if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) |
385 for (const auto& track : local_audio_tracks_) | 386 for (const auto& track : local_audio_tracks_) |
386 RTC_DCHECK(track.first != audio_track || track.second != ssrc); | 387 RTC_DCHECK(track.first != audio_track || track.second != ssrc); |
387 #endif | 388 #endif |
388 | 389 |
389 local_audio_tracks_.push_back(std::make_pair(audio_track, ssrc)); | 390 local_audio_tracks_.push_back(std::make_pair(audio_track, ssrc)); |
390 | 391 |
391 // Create the kStatsReportTypeTrack report for the new track if there is no | 392 // Create the kStatsReportTypeTrack report for the new track if there is no |
392 // report yet. | 393 // report yet. |
393 StatsReport::Id id(StatsReport::NewTypedId(StatsReport::kStatsReportTypeTrack, | 394 StatsReport::Id id(StatsReport::NewTypedId(StatsReport::kStatsReportTypeTrack, |
394 audio_track->id())); | 395 audio_track->id())); |
395 StatsReport* report = reports_.Find(id); | 396 StatsReport* report = reports_.Find(id); |
396 if (!report) { | 397 if (!report) { |
397 report = reports_.InsertNew(id); | 398 report = reports_.InsertNew(id); |
398 report->AddString(StatsReport::kStatsValueNameTrackId, audio_track->id()); | 399 report->AddString(StatsReport::kStatsValueNameTrackId, audio_track->id()); |
399 } | 400 } |
400 } | 401 } |
401 | 402 |
402 void StatsCollector::RemoveLocalAudioTrack(AudioTrackInterface* audio_track, | 403 void StatsCollector::RemoveLocalAudioTrack(AudioTrackInterface* audio_track, |
403 uint32_t ssrc) { | 404 uint32_t ssrc) { |
| 405 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); |
404 RTC_DCHECK(audio_track != NULL); | 406 RTC_DCHECK(audio_track != NULL); |
405 local_audio_tracks_.erase(std::remove_if(local_audio_tracks_.begin(), | 407 local_audio_tracks_.erase(std::remove_if(local_audio_tracks_.begin(), |
406 local_audio_tracks_.end(), | 408 local_audio_tracks_.end(), |
407 [audio_track, ssrc](const LocalAudioTrackVector::value_type& track) { | 409 [audio_track, ssrc](const LocalAudioTrackVector::value_type& track) { |
408 return track.first == audio_track && track.second == ssrc; | 410 return track.first == audio_track && track.second == ssrc; |
409 })); | 411 })); |
410 } | 412 } |
411 | 413 |
412 void StatsCollector::GetStats(MediaStreamTrackInterface* track, | 414 void StatsCollector::GetStats(MediaStreamTrackInterface* track, |
413 StatsReports* reports) { | 415 StatsReports* reports) { |
414 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent()); | 416 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); |
415 RTC_DCHECK(reports != NULL); | 417 RTC_DCHECK(reports != NULL); |
416 RTC_DCHECK(reports->empty()); | 418 RTC_DCHECK(reports->empty()); |
417 | 419 |
418 rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls; | 420 rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls; |
419 | 421 |
420 if (!track) { | 422 if (!track) { |
421 reports->reserve(reports_.size()); | 423 reports->reserve(reports_.size()); |
422 for (auto* r : reports_) | 424 for (auto* r : reports_) |
423 reports->push_back(r); | 425 reports->push_back(r); |
424 return; | 426 return; |
(...skipping 19 matching lines...) Expand all Loading... |
444 | 446 |
445 const StatsReport::Value* v = | 447 const StatsReport::Value* v = |
446 r->FindValue(StatsReport::kStatsValueNameTrackId); | 448 r->FindValue(StatsReport::kStatsValueNameTrackId); |
447 if (v && v->string_val() == track->id()) | 449 if (v && v->string_val() == track->id()) |
448 reports->push_back(r); | 450 reports->push_back(r); |
449 } | 451 } |
450 } | 452 } |
451 | 453 |
452 void | 454 void |
453 StatsCollector::UpdateStats(PeerConnectionInterface::StatsOutputLevel level) { | 455 StatsCollector::UpdateStats(PeerConnectionInterface::StatsOutputLevel level) { |
454 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent()); | 456 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); |
455 double time_now = GetTimeNow(); | 457 double time_now = GetTimeNow(); |
456 // Calls to UpdateStats() that occur less than kMinGatherStatsPeriod number of | 458 // Calls to UpdateStats() that occur less than kMinGatherStatsPeriod number of |
457 // ms apart will be ignored. | 459 // ms apart will be ignored. |
458 const double kMinGatherStatsPeriod = 50; | 460 const double kMinGatherStatsPeriod = 50; |
459 if (stats_gathering_started_ != 0 && | 461 if (stats_gathering_started_ != 0 && |
460 stats_gathering_started_ + kMinGatherStatsPeriod > time_now) { | 462 stats_gathering_started_ + kMinGatherStatsPeriod > time_now) { |
461 return; | 463 return; |
462 } | 464 } |
463 stats_gathering_started_ = time_now; | 465 stats_gathering_started_ = time_now; |
464 | 466 |
(...skipping 10 matching lines...) Expand all Loading... |
475 ExtractDataInfo(); | 477 ExtractDataInfo(); |
476 UpdateTrackReports(); | 478 UpdateTrackReports(); |
477 } | 479 } |
478 } | 480 } |
479 | 481 |
480 StatsReport* StatsCollector::PrepareReport( | 482 StatsReport* StatsCollector::PrepareReport( |
481 bool local, | 483 bool local, |
482 uint32_t ssrc, | 484 uint32_t ssrc, |
483 const StatsReport::Id& transport_id, | 485 const StatsReport::Id& transport_id, |
484 StatsReport::Direction direction) { | 486 StatsReport::Direction direction) { |
485 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent()); | 487 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); |
486 StatsReport::Id id(StatsReport::NewIdWithDirection( | 488 StatsReport::Id id(StatsReport::NewIdWithDirection( |
487 local ? StatsReport::kStatsReportTypeSsrc | 489 local ? StatsReport::kStatsReportTypeSsrc |
488 : StatsReport::kStatsReportTypeRemoteSsrc, | 490 : StatsReport::kStatsReportTypeRemoteSsrc, |
489 rtc::ToString<uint32_t>(ssrc), direction)); | 491 rtc::ToString<uint32_t>(ssrc), direction)); |
490 StatsReport* report = reports_.Find(id); | 492 StatsReport* report = reports_.Find(id); |
491 | 493 |
492 // Use the ID of the track that is currently mapped to the SSRC, if any. | 494 // Use the ID of the track that is currently mapped to the SSRC, if any. |
493 std::string track_id; | 495 std::string track_id; |
494 if (!GetTrackIdBySsrc(ssrc, &track_id, direction)) { | 496 if (!GetTrackIdBySsrc(ssrc, &track_id, direction)) { |
495 if (!report) { | 497 if (!report) { |
(...skipping 18 matching lines...) Expand all Loading... |
514 | 516 |
515 report->AddInt64(StatsReport::kStatsValueNameSsrc, ssrc); | 517 report->AddInt64(StatsReport::kStatsValueNameSsrc, ssrc); |
516 report->AddString(StatsReport::kStatsValueNameTrackId, track_id); | 518 report->AddString(StatsReport::kStatsValueNameTrackId, track_id); |
517 // Add the mapping of SSRC to transport. | 519 // Add the mapping of SSRC to transport. |
518 report->AddId(StatsReport::kStatsValueNameTransportId, transport_id); | 520 report->AddId(StatsReport::kStatsValueNameTransportId, transport_id); |
519 return report; | 521 return report; |
520 } | 522 } |
521 | 523 |
522 StatsReport* StatsCollector::AddOneCertificateReport( | 524 StatsReport* StatsCollector::AddOneCertificateReport( |
523 const rtc::SSLCertificate* cert, const StatsReport* issuer) { | 525 const rtc::SSLCertificate* cert, const StatsReport* issuer) { |
524 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent()); | 526 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); |
525 | 527 |
526 // TODO(bemasc): Move this computation to a helper class that caches these | 528 // TODO(bemasc): Move this computation to a helper class that caches these |
527 // values to reduce CPU use in GetStats. This will require adding a fast | 529 // values to reduce CPU use in GetStats. This will require adding a fast |
528 // SSLCertificate::Equals() method to detect certificate changes. | 530 // SSLCertificate::Equals() method to detect certificate changes. |
529 | 531 |
530 std::string digest_algorithm; | 532 std::string digest_algorithm; |
531 if (!cert->GetSignatureDigestAlgorithm(&digest_algorithm)) | 533 if (!cert->GetSignatureDigestAlgorithm(&digest_algorithm)) |
532 return nullptr; | 534 return nullptr; |
533 | 535 |
534 rtc::scoped_ptr<rtc::SSLFingerprint> ssl_fingerprint( | 536 rtc::scoped_ptr<rtc::SSLFingerprint> ssl_fingerprint( |
(...skipping 22 matching lines...) Expand all Loading... |
557 report->AddString(StatsReport::kStatsValueNameFingerprintAlgorithm, | 559 report->AddString(StatsReport::kStatsValueNameFingerprintAlgorithm, |
558 digest_algorithm); | 560 digest_algorithm); |
559 report->AddString(StatsReport::kStatsValueNameDer, der_base64); | 561 report->AddString(StatsReport::kStatsValueNameDer, der_base64); |
560 if (issuer) | 562 if (issuer) |
561 report->AddId(StatsReport::kStatsValueNameIssuerId, issuer->id()); | 563 report->AddId(StatsReport::kStatsValueNameIssuerId, issuer->id()); |
562 return report; | 564 return report; |
563 } | 565 } |
564 | 566 |
565 StatsReport* StatsCollector::AddCertificateReports( | 567 StatsReport* StatsCollector::AddCertificateReports( |
566 const rtc::SSLCertificate* cert) { | 568 const rtc::SSLCertificate* cert) { |
567 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent()); | 569 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); |
568 // Produces a chain of StatsReports representing this certificate and the rest | 570 // Produces a chain of StatsReports representing this certificate and the rest |
569 // of its chain, and adds those reports to |reports_|. The return value is | 571 // of its chain, and adds those reports to |reports_|. The return value is |
570 // the id of the leaf report. The provided cert must be non-null, so at least | 572 // the id of the leaf report. The provided cert must be non-null, so at least |
571 // one report will always be provided and the returned string will never be | 573 // one report will always be provided and the returned string will never be |
572 // empty. | 574 // empty. |
573 RTC_DCHECK(cert != NULL); | 575 RTC_DCHECK(cert != NULL); |
574 | 576 |
575 StatsReport* issuer = nullptr; | 577 StatsReport* issuer = nullptr; |
576 rtc::scoped_ptr<rtc::SSLCertChain> chain; | 578 rtc::scoped_ptr<rtc::SSLCertChain> chain; |
577 if (cert->GetChain(chain.accept())) { | 579 if (cert->GetChain(chain.accept())) { |
578 // This loop runs in reverse, i.e. from root to leaf, so that each | 580 // This loop runs in reverse, i.e. from root to leaf, so that each |
579 // certificate's issuer's report ID is known before the child certificate's | 581 // certificate's issuer's report ID is known before the child certificate's |
580 // report is generated. The root certificate does not have an issuer ID | 582 // report is generated. The root certificate does not have an issuer ID |
581 // value. | 583 // value. |
582 for (ptrdiff_t i = chain->GetSize() - 1; i >= 0; --i) { | 584 for (ptrdiff_t i = chain->GetSize() - 1; i >= 0; --i) { |
583 const rtc::SSLCertificate& cert_i = chain->Get(i); | 585 const rtc::SSLCertificate& cert_i = chain->Get(i); |
584 issuer = AddOneCertificateReport(&cert_i, issuer); | 586 issuer = AddOneCertificateReport(&cert_i, issuer); |
585 } | 587 } |
586 } | 588 } |
587 // Add the leaf certificate. | 589 // Add the leaf certificate. |
588 return AddOneCertificateReport(cert, issuer); | 590 return AddOneCertificateReport(cert, issuer); |
589 } | 591 } |
590 | 592 |
591 StatsReport* StatsCollector::AddConnectionInfoReport( | 593 StatsReport* StatsCollector::AddConnectionInfoReport( |
592 const std::string& content_name, int component, int connection_id, | 594 const std::string& content_name, int component, int connection_id, |
593 const StatsReport::Id& channel_report_id, | 595 const StatsReport::Id& channel_report_id, |
594 const cricket::ConnectionInfo& info) { | 596 const cricket::ConnectionInfo& info) { |
| 597 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); |
595 StatsReport::Id id(StatsReport::NewCandidatePairId(content_name, component, | 598 StatsReport::Id id(StatsReport::NewCandidatePairId(content_name, component, |
596 connection_id)); | 599 connection_id)); |
597 StatsReport* report = reports_.ReplaceOrAddNew(id); | 600 StatsReport* report = reports_.ReplaceOrAddNew(id); |
598 report->set_timestamp(stats_gathering_started_); | 601 report->set_timestamp(stats_gathering_started_); |
599 | 602 |
600 const BoolForAdd bools[] = { | 603 const BoolForAdd bools[] = { |
601 {StatsReport::kStatsValueNameActiveConnection, info.best_connection}, | 604 {StatsReport::kStatsValueNameActiveConnection, info.best_connection}, |
602 {StatsReport::kStatsValueNameReceiving, info.receiving}, | 605 {StatsReport::kStatsValueNameReceiving, info.receiving}, |
603 {StatsReport::kStatsValueNameWritable, info.writable}, | 606 {StatsReport::kStatsValueNameWritable, info.writable}, |
604 }; | 607 }; |
(...skipping 27 matching lines...) Expand all Loading... |
632 info.remote_candidate.type()); | 635 info.remote_candidate.type()); |
633 report->AddString(StatsReport::kStatsValueNameTransportType, | 636 report->AddString(StatsReport::kStatsValueNameTransportType, |
634 info.local_candidate.protocol()); | 637 info.local_candidate.protocol()); |
635 | 638 |
636 return report; | 639 return report; |
637 } | 640 } |
638 | 641 |
639 StatsReport* StatsCollector::AddCandidateReport( | 642 StatsReport* StatsCollector::AddCandidateReport( |
640 const cricket::Candidate& candidate, | 643 const cricket::Candidate& candidate, |
641 bool local) { | 644 bool local) { |
| 645 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); |
642 StatsReport::Id id(StatsReport::NewCandidateId(local, candidate.id())); | 646 StatsReport::Id id(StatsReport::NewCandidateId(local, candidate.id())); |
643 StatsReport* report = reports_.Find(id); | 647 StatsReport* report = reports_.Find(id); |
644 if (!report) { | 648 if (!report) { |
645 report = reports_.InsertNew(id); | 649 report = reports_.InsertNew(id); |
646 report->set_timestamp(stats_gathering_started_); | 650 report->set_timestamp(stats_gathering_started_); |
647 if (local) { | 651 if (local) { |
648 report->AddString(StatsReport::kStatsValueNameCandidateNetworkType, | 652 report->AddString(StatsReport::kStatsValueNameCandidateNetworkType, |
649 AdapterTypeToStatsType(candidate.network_type())); | 653 AdapterTypeToStatsType(candidate.network_type())); |
650 } | 654 } |
651 report->AddString(StatsReport::kStatsValueNameCandidateIPAddress, | 655 report->AddString(StatsReport::kStatsValueNameCandidateIPAddress, |
652 candidate.address().ipaddr().ToString()); | 656 candidate.address().ipaddr().ToString()); |
653 report->AddString(StatsReport::kStatsValueNameCandidatePortNumber, | 657 report->AddString(StatsReport::kStatsValueNameCandidatePortNumber, |
654 candidate.address().PortAsString()); | 658 candidate.address().PortAsString()); |
655 report->AddInt(StatsReport::kStatsValueNameCandidatePriority, | 659 report->AddInt(StatsReport::kStatsValueNameCandidatePriority, |
656 candidate.priority()); | 660 candidate.priority()); |
657 report->AddString(StatsReport::kStatsValueNameCandidateType, | 661 report->AddString(StatsReport::kStatsValueNameCandidateType, |
658 IceCandidateTypeToStatsType(candidate.type())); | 662 IceCandidateTypeToStatsType(candidate.type())); |
659 report->AddString(StatsReport::kStatsValueNameCandidateTransportType, | 663 report->AddString(StatsReport::kStatsValueNameCandidateTransportType, |
660 candidate.protocol()); | 664 candidate.protocol()); |
661 } | 665 } |
662 | 666 |
663 return report; | 667 return report; |
664 } | 668 } |
665 | 669 |
666 void StatsCollector::ExtractSessionInfo() { | 670 void StatsCollector::ExtractSessionInfo() { |
667 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent()); | 671 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); |
668 | 672 |
669 // Extract information from the base session. | 673 // Extract information from the base session. |
670 StatsReport::Id id(StatsReport::NewTypedId( | 674 StatsReport::Id id(StatsReport::NewTypedId( |
671 StatsReport::kStatsReportTypeSession, pc_->session()->id())); | 675 StatsReport::kStatsReportTypeSession, pc_->session()->id())); |
672 StatsReport* report = reports_.ReplaceOrAddNew(id); | 676 StatsReport* report = reports_.ReplaceOrAddNew(id); |
673 report->set_timestamp(stats_gathering_started_); | 677 report->set_timestamp(stats_gathering_started_); |
674 report->AddBoolean(StatsReport::kStatsValueNameInitiator, | 678 report->AddBoolean(StatsReport::kStatsValueNameInitiator, |
675 pc_->session()->initial_offerer()); | 679 pc_->session()->initial_offerer()); |
676 | 680 |
677 SessionStats stats; | 681 SessionStats stats; |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
750 channel_report->AddId( | 754 channel_report->AddId( |
751 StatsReport::kStatsValueNameSelectedCandidatePairId, | 755 StatsReport::kStatsValueNameSelectedCandidatePairId, |
752 connection_report->id()); | 756 connection_report->id()); |
753 } | 757 } |
754 } | 758 } |
755 } | 759 } |
756 } | 760 } |
757 } | 761 } |
758 | 762 |
759 void StatsCollector::ExtractVoiceInfo() { | 763 void StatsCollector::ExtractVoiceInfo() { |
760 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent()); | 764 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); |
761 | 765 |
762 if (!pc_->session()->voice_channel()) { | 766 if (!pc_->session()->voice_channel()) { |
763 return; | 767 return; |
764 } | 768 } |
765 cricket::VoiceMediaInfo voice_info; | 769 cricket::VoiceMediaInfo voice_info; |
766 if (!pc_->session()->voice_channel()->GetStats(&voice_info)) { | 770 if (!pc_->session()->voice_channel()->GetStats(&voice_info)) { |
767 LOG(LS_ERROR) << "Failed to get voice channel stats."; | 771 LOG(LS_ERROR) << "Failed to get voice channel stats."; |
768 return; | 772 return; |
769 } | 773 } |
770 | 774 |
(...skipping 12 matching lines...) Expand all Loading... |
783 ExtractStatsFromList(voice_info.receivers, transport_id, this, | 787 ExtractStatsFromList(voice_info.receivers, transport_id, this, |
784 StatsReport::kReceive); | 788 StatsReport::kReceive); |
785 ExtractStatsFromList(voice_info.senders, transport_id, this, | 789 ExtractStatsFromList(voice_info.senders, transport_id, this, |
786 StatsReport::kSend); | 790 StatsReport::kSend); |
787 | 791 |
788 UpdateStatsFromExistingLocalAudioTracks(); | 792 UpdateStatsFromExistingLocalAudioTracks(); |
789 } | 793 } |
790 | 794 |
791 void StatsCollector::ExtractVideoInfo( | 795 void StatsCollector::ExtractVideoInfo( |
792 PeerConnectionInterface::StatsOutputLevel level) { | 796 PeerConnectionInterface::StatsOutputLevel level) { |
793 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent()); | 797 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); |
794 | 798 |
795 if (!pc_->session()->video_channel()) | 799 if (!pc_->session()->video_channel()) |
796 return; | 800 return; |
797 | 801 |
798 cricket::VideoMediaInfo video_info; | 802 cricket::VideoMediaInfo video_info; |
799 if (!pc_->session()->video_channel()->GetStats(&video_info)) { | 803 if (!pc_->session()->video_channel()->GetStats(&video_info)) { |
800 LOG(LS_ERROR) << "Failed to get video channel stats."; | 804 LOG(LS_ERROR) << "Failed to get video channel stats."; |
801 return; | 805 return; |
802 } | 806 } |
803 | 807 |
(...skipping 16 matching lines...) Expand all Loading... |
820 LOG(LS_ERROR) << "BWEs count: " << video_info.bw_estimations.size(); | 824 LOG(LS_ERROR) << "BWEs count: " << video_info.bw_estimations.size(); |
821 } else { | 825 } else { |
822 StatsReport::Id report_id(StatsReport::NewBandwidthEstimationId()); | 826 StatsReport::Id report_id(StatsReport::NewBandwidthEstimationId()); |
823 StatsReport* report = reports_.FindOrAddNew(report_id); | 827 StatsReport* report = reports_.FindOrAddNew(report_id); |
824 ExtractStats( | 828 ExtractStats( |
825 video_info.bw_estimations[0], stats_gathering_started_, level, report); | 829 video_info.bw_estimations[0], stats_gathering_started_, level, report); |
826 } | 830 } |
827 } | 831 } |
828 | 832 |
829 void StatsCollector::ExtractDataInfo() { | 833 void StatsCollector::ExtractDataInfo() { |
830 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent()); | 834 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); |
831 | 835 |
832 rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls; | 836 rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls; |
833 | 837 |
834 for (const auto& dc : pc_->sctp_data_channels()) { | 838 for (const auto& dc : pc_->sctp_data_channels()) { |
835 StatsReport::Id id(StatsReport::NewTypedIntId( | 839 StatsReport::Id id(StatsReport::NewTypedIntId( |
836 StatsReport::kStatsReportTypeDataChannel, dc->id())); | 840 StatsReport::kStatsReportTypeDataChannel, dc->id())); |
837 StatsReport* report = reports_.ReplaceOrAddNew(id); | 841 StatsReport* report = reports_.ReplaceOrAddNew(id); |
838 report->set_timestamp(stats_gathering_started_); | 842 report->set_timestamp(stats_gathering_started_); |
839 report->AddString(StatsReport::kStatsValueNameLabel, dc->label()); | 843 report->AddString(StatsReport::kStatsValueNameLabel, dc->label()); |
840 report->AddInt(StatsReport::kStatsValueNameDataChannelId, dc->id()); | 844 report->AddInt(StatsReport::kStatsValueNameDataChannelId, dc->id()); |
841 report->AddString(StatsReport::kStatsValueNameProtocol, dc->protocol()); | 845 report->AddString(StatsReport::kStatsValueNameProtocol, dc->protocol()); |
842 report->AddString(StatsReport::kStatsValueNameState, | 846 report->AddString(StatsReport::kStatsValueNameState, |
843 DataChannelInterface::DataStateString(dc->state())); | 847 DataChannelInterface::DataStateString(dc->state())); |
844 } | 848 } |
845 } | 849 } |
846 | 850 |
847 StatsReport* StatsCollector::GetReport(const StatsReport::StatsType& type, | 851 StatsReport* StatsCollector::GetReport(const StatsReport::StatsType& type, |
848 const std::string& id, | 852 const std::string& id, |
849 StatsReport::Direction direction) { | 853 StatsReport::Direction direction) { |
850 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent()); | 854 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); |
851 RTC_DCHECK(type == StatsReport::kStatsReportTypeSsrc || | 855 RTC_DCHECK(type == StatsReport::kStatsReportTypeSsrc || |
852 type == StatsReport::kStatsReportTypeRemoteSsrc); | 856 type == StatsReport::kStatsReportTypeRemoteSsrc); |
853 return reports_.Find(StatsReport::NewIdWithDirection(type, id, direction)); | 857 return reports_.Find(StatsReport::NewIdWithDirection(type, id, direction)); |
854 } | 858 } |
855 | 859 |
856 void StatsCollector::UpdateStatsFromExistingLocalAudioTracks() { | 860 void StatsCollector::UpdateStatsFromExistingLocalAudioTracks() { |
857 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent()); | 861 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); |
858 // Loop through the existing local audio tracks. | 862 // Loop through the existing local audio tracks. |
859 for (const auto& it : local_audio_tracks_) { | 863 for (const auto& it : local_audio_tracks_) { |
860 AudioTrackInterface* track = it.first; | 864 AudioTrackInterface* track = it.first; |
861 uint32_t ssrc = it.second; | 865 uint32_t ssrc = it.second; |
862 StatsReport* report = | 866 StatsReport* report = |
863 GetReport(StatsReport::kStatsReportTypeSsrc, | 867 GetReport(StatsReport::kStatsReportTypeSsrc, |
864 rtc::ToString<uint32_t>(ssrc), StatsReport::kSend); | 868 rtc::ToString<uint32_t>(ssrc), StatsReport::kSend); |
865 if (report == NULL) { | 869 if (report == NULL) { |
866 // This can happen if a local audio track is added to a stream on the | 870 // This can happen if a local audio track is added to a stream on the |
867 // fly and the report has not been set up yet. Do nothing in this case. | 871 // fly and the report has not been set up yet. Do nothing in this case. |
868 LOG(LS_ERROR) << "Stats report does not exist for ssrc " << ssrc; | 872 LOG(LS_ERROR) << "Stats report does not exist for ssrc " << ssrc; |
869 continue; | 873 continue; |
870 } | 874 } |
871 | 875 |
872 // The same ssrc can be used by both local and remote audio tracks. | 876 // The same ssrc can be used by both local and remote audio tracks. |
873 const StatsReport::Value* v = | 877 const StatsReport::Value* v = |
874 report->FindValue(StatsReport::kStatsValueNameTrackId); | 878 report->FindValue(StatsReport::kStatsValueNameTrackId); |
875 if (!v || v->string_val() != track->id()) | 879 if (!v || v->string_val() != track->id()) |
876 continue; | 880 continue; |
877 | 881 |
878 report->set_timestamp(stats_gathering_started_); | 882 report->set_timestamp(stats_gathering_started_); |
879 UpdateReportFromAudioTrack(track, report); | 883 UpdateReportFromAudioTrack(track, report); |
880 } | 884 } |
881 } | 885 } |
882 | 886 |
883 void StatsCollector::UpdateReportFromAudioTrack(AudioTrackInterface* track, | 887 void StatsCollector::UpdateReportFromAudioTrack(AudioTrackInterface* track, |
884 StatsReport* report) { | 888 StatsReport* report) { |
885 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent()); | 889 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); |
886 RTC_DCHECK(track != NULL); | 890 RTC_DCHECK(track != NULL); |
887 | 891 |
888 // Don't overwrite report values if they're not available. | 892 // Don't overwrite report values if they're not available. |
889 int signal_level; | 893 int signal_level; |
890 if (track->GetSignalLevel(&signal_level)) { | 894 if (track->GetSignalLevel(&signal_level)) { |
891 RTC_DCHECK_GE(signal_level, 0); | 895 RTC_DCHECK_GE(signal_level, 0); |
892 report->AddInt(StatsReport::kStatsValueNameAudioInputLevel, signal_level); | 896 report->AddInt(StatsReport::kStatsValueNameAudioInputLevel, signal_level); |
893 } | 897 } |
894 | 898 |
895 auto audio_processor(track->GetAudioProcessor()); | 899 auto audio_processor(track->GetAudioProcessor()); |
896 | 900 |
897 if (audio_processor.get()) { | 901 if (audio_processor.get()) { |
898 AudioProcessorInterface::AudioProcessorStats stats; | 902 AudioProcessorInterface::AudioProcessorStats stats; |
899 audio_processor->GetStats(&stats); | 903 audio_processor->GetStats(&stats); |
900 | 904 |
901 SetAudioProcessingStats( | 905 SetAudioProcessingStats( |
902 report, stats.typing_noise_detected, stats.echo_return_loss, | 906 report, stats.typing_noise_detected, stats.echo_return_loss, |
903 stats.echo_return_loss_enhancement, stats.echo_delay_median_ms, | 907 stats.echo_return_loss_enhancement, stats.echo_delay_median_ms, |
904 stats.aec_quality_min, stats.echo_delay_std_ms); | 908 stats.aec_quality_min, stats.echo_delay_std_ms); |
905 } | 909 } |
906 } | 910 } |
907 | 911 |
908 bool StatsCollector::GetTrackIdBySsrc(uint32_t ssrc, | 912 bool StatsCollector::GetTrackIdBySsrc(uint32_t ssrc, |
909 std::string* track_id, | 913 std::string* track_id, |
910 StatsReport::Direction direction) { | 914 StatsReport::Direction direction) { |
911 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent()); | 915 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); |
912 if (direction == StatsReport::kSend) { | 916 if (direction == StatsReport::kSend) { |
913 if (!pc_->session()->GetLocalTrackIdBySsrc(ssrc, track_id)) { | 917 if (!pc_->session()->GetLocalTrackIdBySsrc(ssrc, track_id)) { |
914 LOG(LS_WARNING) << "The SSRC " << ssrc | 918 LOG(LS_WARNING) << "The SSRC " << ssrc |
915 << " is not associated with a sending track"; | 919 << " is not associated with a sending track"; |
916 return false; | 920 return false; |
917 } | 921 } |
918 } else { | 922 } else { |
919 RTC_DCHECK(direction == StatsReport::kReceive); | 923 RTC_DCHECK(direction == StatsReport::kReceive); |
920 if (!pc_->session()->GetRemoteTrackIdBySsrc(ssrc, track_id)) { | 924 if (!pc_->session()->GetRemoteTrackIdBySsrc(ssrc, track_id)) { |
921 LOG(LS_WARNING) << "The SSRC " << ssrc | 925 LOG(LS_WARNING) << "The SSRC " << ssrc |
922 << " is not associated with a receiving track"; | 926 << " is not associated with a receiving track"; |
923 return false; | 927 return false; |
924 } | 928 } |
925 } | 929 } |
926 | 930 |
927 return true; | 931 return true; |
928 } | 932 } |
929 | 933 |
930 void StatsCollector::UpdateTrackReports() { | 934 void StatsCollector::UpdateTrackReports() { |
931 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent()); | 935 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); |
932 | 936 |
933 rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls; | 937 rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls; |
934 | 938 |
935 for (const auto& entry : track_ids_) { | 939 for (const auto& entry : track_ids_) { |
936 StatsReport* report = entry.second; | 940 StatsReport* report = entry.second; |
937 report->set_timestamp(stats_gathering_started_); | 941 report->set_timestamp(stats_gathering_started_); |
938 } | 942 } |
939 } | 943 } |
940 | 944 |
941 void StatsCollector::ClearUpdateStatsCacheForTest() { | 945 void StatsCollector::ClearUpdateStatsCacheForTest() { |
| 946 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); |
942 stats_gathering_started_ = 0; | 947 stats_gathering_started_ = 0; |
943 } | 948 } |
944 | 949 |
945 } // namespace webrtc | 950 } // namespace webrtc |
OLD | NEW |