Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(56)

Side by Side Diff: talk/app/webrtc/statscollector.cc

Issue 1403633005: Revert of Moving MediaStreamSignaling logic into PeerConnection. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « talk/app/webrtc/statscollector.h ('k') | talk/app/webrtc/statscollector_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 12 matching lines...) Expand all
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 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 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28 #include "talk/app/webrtc/statscollector.h" 28 #include "talk/app/webrtc/statscollector.h"
29 29
30 #include <utility> 30 #include <utility>
31 #include <vector> 31 #include <vector>
32 32
33 #include "talk/app/webrtc/peerconnection.h"
34 #include "talk/session/media/channel.h" 33 #include "talk/session/media/channel.h"
35 #include "webrtc/base/base64.h" 34 #include "webrtc/base/base64.h"
36 #include "webrtc/base/checks.h" 35 #include "webrtc/base/checks.h"
37 #include "webrtc/base/scoped_ptr.h" 36 #include "webrtc/base/scoped_ptr.h"
38 #include "webrtc/base/timing.h" 37 #include "webrtc/base/timing.h"
39 38
40 using rtc::scoped_ptr; 39 using rtc::scoped_ptr;
41 40
42 namespace webrtc { 41 namespace webrtc {
43 namespace { 42 namespace {
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after
350 case rtc::ADAPTER_TYPE_VPN: 349 case rtc::ADAPTER_TYPE_VPN:
351 return STATSREPORT_ADAPTER_TYPE_VPN; 350 return STATSREPORT_ADAPTER_TYPE_VPN;
352 case rtc::ADAPTER_TYPE_LOOPBACK: 351 case rtc::ADAPTER_TYPE_LOOPBACK:
353 return STATSREPORT_ADAPTER_TYPE_LOOPBACK; 352 return STATSREPORT_ADAPTER_TYPE_LOOPBACK;
354 default: 353 default:
355 RTC_DCHECK(false); 354 RTC_DCHECK(false);
356 return ""; 355 return "";
357 } 356 }
358 } 357 }
359 358
360 StatsCollector::StatsCollector(PeerConnection* pc) 359 StatsCollector::StatsCollector(WebRtcSession* session)
361 : pc_(pc), stats_gathering_started_(0) { 360 : session_(session),
362 RTC_DCHECK(pc_); 361 stats_gathering_started_(0) {
362 RTC_DCHECK(session_);
363 } 363 }
364 364
365 StatsCollector::~StatsCollector() { 365 StatsCollector::~StatsCollector() {
366 RTC_DCHECK(pc_->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 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent()); 376 RTC_DCHECK(session_->signaling_thread()->IsCurrent());
377 RTC_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_t ssrc) { 386 uint32_t ssrc) {
387 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent()); 387 RTC_DCHECK(session_->signaling_thread()->IsCurrent());
388 RTC_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 RTC_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.
(...skipping 11 matching lines...) Expand all
409 RTC_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 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent()); 419 RTC_DCHECK(session_->signaling_thread()->IsCurrent());
420 RTC_DCHECK(reports != NULL); 420 RTC_DCHECK(reports != NULL);
421 RTC_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
432 StatsReport* report = reports_.Find(StatsReport::NewTypedId( 432 StatsReport* report = reports_.Find(StatsReport::NewTypedId(
433 StatsReport::kStatsReportTypeSession, pc_->session()->id())); 433 StatsReport::kStatsReportTypeSession, session_->id()));
434 if (report) 434 if (report)
435 reports->push_back(report); 435 reports->push_back(report);
436 436
437 report = reports_.Find(StatsReport::NewTypedId( 437 report = reports_.Find(StatsReport::NewTypedId(
438 StatsReport::kStatsReportTypeTrack, track->id())); 438 StatsReport::kStatsReportTypeTrack, track->id()));
439 439
440 if (!report) 440 if (!report)
441 return; 441 return;
442 442
443 reports->push_back(report); 443 reports->push_back(report);
444 444
445 std::string track_id; 445 std::string track_id;
446 for (const auto* r : reports_) { 446 for (const auto* r : reports_) {
447 if (r->type() != StatsReport::kStatsReportTypeSsrc) 447 if (r->type() != StatsReport::kStatsReportTypeSsrc)
448 continue; 448 continue;
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 RTC_DCHECK(pc_->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
470 if (pc_->session()) { 470 if (session_) {
471 // TODO(tommi): All of these hop over to the worker thread to fetch 471 // TODO(tommi): All of these hop over to the worker thread to fetch
472 // information. We could use an AsyncInvoker to run all of these and post 472 // information. We could use an AsyncInvoker to run all of these and post
473 // the information back to the signaling thread where we can create and 473 // the information back to the signaling thread where we can create and
474 // update stats reports. That would also clean up the threading story a bit 474 // update stats reports. That would also clean up the threading story a bit
475 // since we'd be creating/updating the stats report objects consistently on 475 // since we'd be creating/updating the stats report objects consistently on
476 // the same thread (this class has no locks right now). 476 // the same thread (this class has no locks right now).
477 ExtractSessionInfo(); 477 ExtractSessionInfo();
478 ExtractVoiceInfo(); 478 ExtractVoiceInfo();
479 ExtractVideoInfo(level); 479 ExtractVideoInfo(level);
480 ExtractDataInfo(); 480 ExtractDataInfo();
481 UpdateTrackReports(); 481 UpdateTrackReports();
482 } 482 }
483 } 483 }
484 484
485 StatsReport* StatsCollector::PrepareReport( 485 StatsReport* StatsCollector::PrepareReport(bool local,
486 bool local, 486 uint32_t ssrc,
487 uint32_t ssrc, 487 const StatsReport::Id& transport_id,
488 const StatsReport::Id& transport_id, 488 StatsReport::Direction direction) {
489 StatsReport::Direction direction) { 489 RTC_DCHECK(session_->signaling_thread()->IsCurrent());
490 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent());
491 StatsReport::Id id(StatsReport::NewIdWithDirection( 490 StatsReport::Id id(StatsReport::NewIdWithDirection(
492 local ? StatsReport::kStatsReportTypeSsrc 491 local ? StatsReport::kStatsReportTypeSsrc
493 : StatsReport::kStatsReportTypeRemoteSsrc, 492 : StatsReport::kStatsReportTypeRemoteSsrc,
494 rtc::ToString<uint32_t>(ssrc), direction)); 493 rtc::ToString<uint32_t>(ssrc), direction));
495 StatsReport* report = reports_.Find(id); 494 StatsReport* report = reports_.Find(id);
496 495
497 // Use the ID of the track that is currently mapped to the SSRC, if any. 496 // Use the ID of the track that is currently mapped to the SSRC, if any.
498 std::string track_id; 497 std::string track_id;
499 if (!GetTrackIdBySsrc(ssrc, &track_id, direction)) { 498 if (!GetTrackIdBySsrc(ssrc, &track_id, direction)) {
500 if (!report) { 499 if (!report) {
(...skipping 18 matching lines...) Expand all
519 518
520 report->AddInt64(StatsReport::kStatsValueNameSsrc, ssrc); 519 report->AddInt64(StatsReport::kStatsValueNameSsrc, ssrc);
521 report->AddString(StatsReport::kStatsValueNameTrackId, track_id); 520 report->AddString(StatsReport::kStatsValueNameTrackId, track_id);
522 // Add the mapping of SSRC to transport. 521 // Add the mapping of SSRC to transport.
523 report->AddId(StatsReport::kStatsValueNameTransportId, transport_id); 522 report->AddId(StatsReport::kStatsValueNameTransportId, transport_id);
524 return report; 523 return report;
525 } 524 }
526 525
527 StatsReport* StatsCollector::AddOneCertificateReport( 526 StatsReport* StatsCollector::AddOneCertificateReport(
528 const rtc::SSLCertificate* cert, const StatsReport* issuer) { 527 const rtc::SSLCertificate* cert, const StatsReport* issuer) {
529 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent()); 528 RTC_DCHECK(session_->signaling_thread()->IsCurrent());
530 529
531 // TODO(bemasc): Move this computation to a helper class that caches these 530 // 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 531 // values to reduce CPU use in GetStats. This will require adding a fast
533 // SSLCertificate::Equals() method to detect certificate changes. 532 // SSLCertificate::Equals() method to detect certificate changes.
534 533
535 std::string digest_algorithm; 534 std::string digest_algorithm;
536 if (!cert->GetSignatureDigestAlgorithm(&digest_algorithm)) 535 if (!cert->GetSignatureDigestAlgorithm(&digest_algorithm))
537 return nullptr; 536 return nullptr;
538 537
539 rtc::scoped_ptr<rtc::SSLFingerprint> ssl_fingerprint( 538 rtc::scoped_ptr<rtc::SSLFingerprint> ssl_fingerprint(
(...skipping 22 matching lines...) Expand all
562 report->AddString(StatsReport::kStatsValueNameFingerprintAlgorithm, 561 report->AddString(StatsReport::kStatsValueNameFingerprintAlgorithm,
563 digest_algorithm); 562 digest_algorithm);
564 report->AddString(StatsReport::kStatsValueNameDer, der_base64); 563 report->AddString(StatsReport::kStatsValueNameDer, der_base64);
565 if (issuer) 564 if (issuer)
566 report->AddId(StatsReport::kStatsValueNameIssuerId, issuer->id()); 565 report->AddId(StatsReport::kStatsValueNameIssuerId, issuer->id());
567 return report; 566 return report;
568 } 567 }
569 568
570 StatsReport* StatsCollector::AddCertificateReports( 569 StatsReport* StatsCollector::AddCertificateReports(
571 const rtc::SSLCertificate* cert) { 570 const rtc::SSLCertificate* cert) {
572 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent()); 571 RTC_DCHECK(session_->signaling_thread()->IsCurrent());
573 // Produces a chain of StatsReports representing this certificate and the rest 572 // 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 573 // 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 574 // 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 575 // one report will always be provided and the returned string will never be
577 // empty. 576 // empty.
578 RTC_DCHECK(cert != NULL); 577 RTC_DCHECK(cert != NULL);
579 578
580 StatsReport* issuer = nullptr; 579 StatsReport* issuer = nullptr;
581 rtc::scoped_ptr<rtc::SSLCertChain> chain; 580 rtc::scoped_ptr<rtc::SSLCertChain> chain;
582 if (cert->GetChain(chain.accept())) { 581 if (cert->GetChain(chain.accept())) {
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
662 report->AddString(StatsReport::kStatsValueNameCandidateType, 661 report->AddString(StatsReport::kStatsValueNameCandidateType,
663 IceCandidateTypeToStatsType(candidate.type())); 662 IceCandidateTypeToStatsType(candidate.type()));
664 report->AddString(StatsReport::kStatsValueNameCandidateTransportType, 663 report->AddString(StatsReport::kStatsValueNameCandidateTransportType,
665 candidate.protocol()); 664 candidate.protocol());
666 } 665 }
667 666
668 return report; 667 return report;
669 } 668 }
670 669
671 void StatsCollector::ExtractSessionInfo() { 670 void StatsCollector::ExtractSessionInfo() {
672 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent()); 671 RTC_DCHECK(session_->signaling_thread()->IsCurrent());
673 672
674 // Extract information from the base session. 673 // Extract information from the base session.
675 StatsReport::Id id(StatsReport::NewTypedId( 674 StatsReport::Id id(StatsReport::NewTypedId(
676 StatsReport::kStatsReportTypeSession, pc_->session()->id())); 675 StatsReport::kStatsReportTypeSession, session_->id()));
677 StatsReport* report = reports_.ReplaceOrAddNew(id); 676 StatsReport* report = reports_.ReplaceOrAddNew(id);
678 report->set_timestamp(stats_gathering_started_); 677 report->set_timestamp(stats_gathering_started_);
679 report->AddBoolean(StatsReport::kStatsValueNameInitiator, 678 report->AddBoolean(StatsReport::kStatsValueNameInitiator,
680 pc_->session()->initiator()); 679 session_->initiator());
681 680
682 cricket::SessionStats stats; 681 cricket::SessionStats stats;
683 if (!pc_->session()->GetTransportStats(&stats)) { 682 if (!session_->GetTransportStats(&stats)) {
684 return; 683 return;
685 } 684 }
686 685
687 // Store the proxy map away for use in SSRC reporting. 686 // Store the proxy map away for use in SSRC reporting.
688 // TODO(tommi): This shouldn't be necessary if we post the stats back to the 687 // TODO(tommi): This shouldn't be necessary if we post the stats back to the
689 // signaling thread after fetching them on the worker thread, then just use 688 // signaling thread after fetching them on the worker thread, then just use
690 // the proxy map directly from the session stats. 689 // the proxy map directly from the session stats.
691 // As is, if GetStats() failed, we could be using old (incorrect?) proxy 690 // As is, if GetStats() failed, we could be using old (incorrect?) proxy
692 // data. 691 // data.
693 proxy_to_transport_ = stats.proxy_to_transport; 692 proxy_to_transport_ = stats.proxy_to_transport;
694 693
695 for (const auto& transport_iter : stats.transport_stats) { 694 for (const auto& transport_iter : stats.transport_stats) {
696 // Attempt to get a copy of the certificates from the transport and 695 // Attempt to get a copy of the certificates from the transport and
697 // expose them in stats reports. All channels in a transport share the 696 // expose them in stats reports. All channels in a transport share the
698 // same local and remote certificates. 697 // same local and remote certificates.
699 // 698 //
700 StatsReport::Id local_cert_report_id, remote_cert_report_id; 699 StatsReport::Id local_cert_report_id, remote_cert_report_id;
701 rtc::scoped_refptr<rtc::RTCCertificate> certificate; 700 rtc::scoped_refptr<rtc::RTCCertificate> certificate;
702 if (pc_->session()->GetLocalCertificate( 701 if (session_->GetLocalCertificate(transport_iter.second.transport_name,
703 transport_iter.second.transport_name, &certificate)) { 702 &certificate)) {
704 StatsReport* r = AddCertificateReports(&(certificate->ssl_certificate())); 703 StatsReport* r = AddCertificateReports(&(certificate->ssl_certificate()));
705 if (r) 704 if (r)
706 local_cert_report_id = r->id(); 705 local_cert_report_id = r->id();
707 } 706 }
708 707
709 rtc::scoped_ptr<rtc::SSLCertificate> cert; 708 rtc::scoped_ptr<rtc::SSLCertificate> cert;
710 if (pc_->session()->GetRemoteSSLCertificate( 709 if (session_->GetRemoteSSLCertificate(transport_iter.second.transport_name,
711 transport_iter.second.transport_name, cert.accept())) { 710 cert.accept())) {
712 StatsReport* r = AddCertificateReports(cert.get()); 711 StatsReport* r = AddCertificateReports(cert.get());
713 if (r) 712 if (r)
714 remote_cert_report_id = r->id(); 713 remote_cert_report_id = r->id();
715 } 714 }
716 715
717 for (const auto& channel_iter : transport_iter.second.channel_stats) { 716 for (const auto& channel_iter : transport_iter.second.channel_stats) {
718 StatsReport::Id id(StatsReport::NewComponentId( 717 StatsReport::Id id(StatsReport::NewComponentId(
719 transport_iter.second.transport_name, channel_iter.component)); 718 transport_iter.second.transport_name, channel_iter.component));
720 StatsReport* channel_report = reports_.ReplaceOrAddNew(id); 719 StatsReport* channel_report = reports_.ReplaceOrAddNew(id);
721 channel_report->set_timestamp(stats_gathering_started_); 720 channel_report->set_timestamp(stats_gathering_started_);
(...skipping 30 matching lines...) Expand all
752 channel_report->AddId( 751 channel_report->AddId(
753 StatsReport::kStatsValueNameSelectedCandidatePairId, 752 StatsReport::kStatsValueNameSelectedCandidatePairId,
754 connection_report->id()); 753 connection_report->id());
755 } 754 }
756 } 755 }
757 } 756 }
758 } 757 }
759 } 758 }
760 759
761 void StatsCollector::ExtractVoiceInfo() { 760 void StatsCollector::ExtractVoiceInfo() {
762 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent()); 761 RTC_DCHECK(session_->signaling_thread()->IsCurrent());
763 762
764 if (!pc_->session()->voice_channel()) { 763 if (!session_->voice_channel()) {
765 return; 764 return;
766 } 765 }
767 cricket::VoiceMediaInfo voice_info; 766 cricket::VoiceMediaInfo voice_info;
768 if (!pc_->session()->voice_channel()->GetStats(&voice_info)) { 767 if (!session_->voice_channel()->GetStats(&voice_info)) {
769 LOG(LS_ERROR) << "Failed to get voice channel stats."; 768 LOG(LS_ERROR) << "Failed to get voice channel stats.";
770 return; 769 return;
771 } 770 }
772 771
773 // TODO(tommi): The above code should run on the worker thread and post the 772 // TODO(tommi): The above code should run on the worker thread and post the
774 // results back to the signaling thread, where we can add data to the reports. 773 // results back to the signaling thread, where we can add data to the reports.
775 rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls; 774 rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
776 775
777 StatsReport::Id transport_id(GetTransportIdFromProxy( 776 StatsReport::Id transport_id(GetTransportIdFromProxy(proxy_to_transport_,
778 proxy_to_transport_, pc_->session()->voice_channel()->content_name())); 777 session_->voice_channel()->content_name()));
779 if (!transport_id.get()) { 778 if (!transport_id.get()) {
780 LOG(LS_ERROR) << "Failed to get transport name for proxy " 779 LOG(LS_ERROR) << "Failed to get transport name for proxy "
781 << pc_->session()->voice_channel()->content_name(); 780 << session_->voice_channel()->content_name();
782 return; 781 return;
783 } 782 }
784 783
785 ExtractStatsFromList(voice_info.receivers, transport_id, this, 784 ExtractStatsFromList(voice_info.receivers, transport_id, this,
786 StatsReport::kReceive); 785 StatsReport::kReceive);
787 ExtractStatsFromList(voice_info.senders, transport_id, this, 786 ExtractStatsFromList(voice_info.senders, transport_id, this,
788 StatsReport::kSend); 787 StatsReport::kSend);
789 788
790 UpdateStatsFromExistingLocalAudioTracks(); 789 UpdateStatsFromExistingLocalAudioTracks();
791 } 790 }
792 791
793 void StatsCollector::ExtractVideoInfo( 792 void StatsCollector::ExtractVideoInfo(
794 PeerConnectionInterface::StatsOutputLevel level) { 793 PeerConnectionInterface::StatsOutputLevel level) {
795 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent()); 794 RTC_DCHECK(session_->signaling_thread()->IsCurrent());
796 795
797 if (!pc_->session()->video_channel()) 796 if (!session_->video_channel())
798 return; 797 return;
799 798
800 cricket::VideoMediaInfo video_info; 799 cricket::VideoMediaInfo video_info;
801 if (!pc_->session()->video_channel()->GetStats(&video_info)) { 800 if (!session_->video_channel()->GetStats(&video_info)) {
802 LOG(LS_ERROR) << "Failed to get video channel stats."; 801 LOG(LS_ERROR) << "Failed to get video channel stats.";
803 return; 802 return;
804 } 803 }
805 804
806 // TODO(tommi): The above code should run on the worker thread and post the 805 // TODO(tommi): The above code should run on the worker thread and post the
807 // results back to the signaling thread, where we can add data to the reports. 806 // results back to the signaling thread, where we can add data to the reports.
808 rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls; 807 rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
809 808
810 StatsReport::Id transport_id(GetTransportIdFromProxy( 809 StatsReport::Id transport_id(GetTransportIdFromProxy(proxy_to_transport_,
811 proxy_to_transport_, pc_->session()->video_channel()->content_name())); 810 session_->video_channel()->content_name()));
812 if (!transport_id.get()) { 811 if (!transport_id.get()) {
813 LOG(LS_ERROR) << "Failed to get transport name for proxy " 812 LOG(LS_ERROR) << "Failed to get transport name for proxy "
814 << pc_->session()->video_channel()->content_name(); 813 << session_->video_channel()->content_name();
815 return; 814 return;
816 } 815 }
817 ExtractStatsFromList(video_info.receivers, transport_id, this, 816 ExtractStatsFromList(video_info.receivers, transport_id, this,
818 StatsReport::kReceive); 817 StatsReport::kReceive);
819 ExtractStatsFromList(video_info.senders, transport_id, this, 818 ExtractStatsFromList(video_info.senders, transport_id, this,
820 StatsReport::kSend); 819 StatsReport::kSend);
821 if (video_info.bw_estimations.size() != 1) { 820 if (video_info.bw_estimations.size() != 1) {
822 LOG(LS_ERROR) << "BWEs count: " << video_info.bw_estimations.size(); 821 LOG(LS_ERROR) << "BWEs count: " << video_info.bw_estimations.size();
823 } else { 822 } else {
824 StatsReport::Id report_id(StatsReport::NewBandwidthEstimationId()); 823 StatsReport::Id report_id(StatsReport::NewBandwidthEstimationId());
825 StatsReport* report = reports_.FindOrAddNew(report_id); 824 StatsReport* report = reports_.FindOrAddNew(report_id);
826 ExtractStats( 825 ExtractStats(
827 video_info.bw_estimations[0], stats_gathering_started_, level, report); 826 video_info.bw_estimations[0], stats_gathering_started_, level, report);
828 } 827 }
829 } 828 }
830 829
831 void StatsCollector::ExtractDataInfo() { 830 void StatsCollector::ExtractDataInfo() {
832 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent()); 831 RTC_DCHECK(session_->signaling_thread()->IsCurrent());
833 832
834 rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls; 833 rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
835 834
836 for (const auto& dc : pc_->sctp_data_channels()) { 835 for (const auto& dc :
836 session_->mediastream_signaling()->sctp_data_channels()) {
837 StatsReport::Id id(StatsReport::NewTypedIntId( 837 StatsReport::Id id(StatsReport::NewTypedIntId(
838 StatsReport::kStatsReportTypeDataChannel, dc->id())); 838 StatsReport::kStatsReportTypeDataChannel, dc->id()));
839 StatsReport* report = reports_.ReplaceOrAddNew(id); 839 StatsReport* report = reports_.ReplaceOrAddNew(id);
840 report->set_timestamp(stats_gathering_started_); 840 report->set_timestamp(stats_gathering_started_);
841 report->AddString(StatsReport::kStatsValueNameLabel, dc->label()); 841 report->AddString(StatsReport::kStatsValueNameLabel, dc->label());
842 report->AddInt(StatsReport::kStatsValueNameDataChannelId, dc->id()); 842 report->AddInt(StatsReport::kStatsValueNameDataChannelId, dc->id());
843 report->AddString(StatsReport::kStatsValueNameProtocol, dc->protocol()); 843 report->AddString(StatsReport::kStatsValueNameProtocol, dc->protocol());
844 report->AddString(StatsReport::kStatsValueNameState, 844 report->AddString(StatsReport::kStatsValueNameState,
845 DataChannelInterface::DataStateString(dc->state())); 845 DataChannelInterface::DataStateString(dc->state()));
846 } 846 }
847 } 847 }
848 848
849 StatsReport* StatsCollector::GetReport(const StatsReport::StatsType& type, 849 StatsReport* StatsCollector::GetReport(const StatsReport::StatsType& type,
850 const std::string& id, 850 const std::string& id,
851 StatsReport::Direction direction) { 851 StatsReport::Direction direction) {
852 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent()); 852 RTC_DCHECK(session_->signaling_thread()->IsCurrent());
853 RTC_DCHECK(type == StatsReport::kStatsReportTypeSsrc || 853 RTC_DCHECK(type == StatsReport::kStatsReportTypeSsrc ||
854 type == StatsReport::kStatsReportTypeRemoteSsrc); 854 type == StatsReport::kStatsReportTypeRemoteSsrc);
855 return reports_.Find(StatsReport::NewIdWithDirection(type, id, direction)); 855 return reports_.Find(StatsReport::NewIdWithDirection(type, id, direction));
856 } 856 }
857 857
858 void StatsCollector::UpdateStatsFromExistingLocalAudioTracks() { 858 void StatsCollector::UpdateStatsFromExistingLocalAudioTracks() {
859 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent()); 859 RTC_DCHECK(session_->signaling_thread()->IsCurrent());
860 // Loop through the existing local audio tracks. 860 // Loop through the existing local audio tracks.
861 for (const auto& it : local_audio_tracks_) { 861 for (const auto& it : local_audio_tracks_) {
862 AudioTrackInterface* track = it.first; 862 AudioTrackInterface* track = it.first;
863 uint32_t ssrc = it.second; 863 uint32_t ssrc = it.second;
864 StatsReport* report = 864 StatsReport* report =
865 GetReport(StatsReport::kStatsReportTypeSsrc, 865 GetReport(StatsReport::kStatsReportTypeSsrc,
866 rtc::ToString<uint32_t>(ssrc), StatsReport::kSend); 866 rtc::ToString<uint32_t>(ssrc), StatsReport::kSend);
867 if (report == NULL) { 867 if (report == NULL) {
868 // This can happen if a local audio track is added to a stream on the 868 // This can happen if a local audio track is added to a stream on the
869 // fly and the report has not been set up yet. Do nothing in this case. 869 // fly and the report has not been set up yet. Do nothing in this case.
870 LOG(LS_ERROR) << "Stats report does not exist for ssrc " << ssrc; 870 LOG(LS_ERROR) << "Stats report does not exist for ssrc " << ssrc;
871 continue; 871 continue;
872 } 872 }
873 873
874 // The same ssrc can be used by both local and remote audio tracks. 874 // The same ssrc can be used by both local and remote audio tracks.
875 const StatsReport::Value* v = 875 const StatsReport::Value* v =
876 report->FindValue(StatsReport::kStatsValueNameTrackId); 876 report->FindValue(StatsReport::kStatsValueNameTrackId);
877 if (!v || v->string_val() != track->id()) 877 if (!v || v->string_val() != track->id())
878 continue; 878 continue;
879 879
880 report->set_timestamp(stats_gathering_started_); 880 report->set_timestamp(stats_gathering_started_);
881 UpdateReportFromAudioTrack(track, report); 881 UpdateReportFromAudioTrack(track, report);
882 } 882 }
883 } 883 }
884 884
885 void StatsCollector::UpdateReportFromAudioTrack(AudioTrackInterface* track, 885 void StatsCollector::UpdateReportFromAudioTrack(AudioTrackInterface* track,
886 StatsReport* report) { 886 StatsReport* report) {
887 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent()); 887 RTC_DCHECK(session_->signaling_thread()->IsCurrent());
888 RTC_DCHECK(track != NULL); 888 RTC_DCHECK(track != NULL);
889 889
890 int signal_level = 0; 890 int signal_level = 0;
891 if (!track->GetSignalLevel(&signal_level)) 891 if (!track->GetSignalLevel(&signal_level))
892 signal_level = -1; 892 signal_level = -1;
893 893
894 rtc::scoped_refptr<AudioProcessorInterface> audio_processor( 894 rtc::scoped_refptr<AudioProcessorInterface> audio_processor(
895 track->GetAudioProcessor()); 895 track->GetAudioProcessor());
896 896
897 AudioProcessorInterface::AudioProcessorStats stats; 897 AudioProcessorInterface::AudioProcessorStats stats;
898 if (audio_processor.get()) 898 if (audio_processor.get())
899 audio_processor->GetStats(&stats); 899 audio_processor->GetStats(&stats);
900 900
901 SetAudioProcessingStats(report, signal_level, stats.typing_noise_detected, 901 SetAudioProcessingStats(report, signal_level, stats.typing_noise_detected,
902 stats.echo_return_loss, stats.echo_return_loss_enhancement, 902 stats.echo_return_loss, stats.echo_return_loss_enhancement,
903 stats.echo_delay_median_ms, stats.aec_quality_min, 903 stats.echo_delay_median_ms, stats.aec_quality_min,
904 stats.echo_delay_std_ms); 904 stats.echo_delay_std_ms);
905 } 905 }
906 906
907 bool StatsCollector::GetTrackIdBySsrc(uint32_t ssrc, 907 bool StatsCollector::GetTrackIdBySsrc(uint32_t ssrc,
908 std::string* track_id, 908 std::string* track_id,
909 StatsReport::Direction direction) { 909 StatsReport::Direction direction) {
910 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent()); 910 RTC_DCHECK(session_->signaling_thread()->IsCurrent());
911 if (direction == StatsReport::kSend) { 911 if (direction == StatsReport::kSend) {
912 if (!pc_->session()->GetLocalTrackIdBySsrc(ssrc, track_id)) { 912 if (!session_->GetLocalTrackIdBySsrc(ssrc, track_id)) {
913 LOG(LS_WARNING) << "The SSRC " << ssrc 913 LOG(LS_WARNING) << "The SSRC " << ssrc
914 << " is not associated with a sending track"; 914 << " is not associated with a sending track";
915 return false; 915 return false;
916 } 916 }
917 } else { 917 } else {
918 RTC_DCHECK(direction == StatsReport::kReceive); 918 RTC_DCHECK(direction == StatsReport::kReceive);
919 if (!pc_->session()->GetRemoteTrackIdBySsrc(ssrc, track_id)) { 919 if (!session_->GetRemoteTrackIdBySsrc(ssrc, track_id)) {
920 LOG(LS_WARNING) << "The SSRC " << ssrc 920 LOG(LS_WARNING) << "The SSRC " << ssrc
921 << " is not associated with a receiving track"; 921 << " is not associated with a receiving track";
922 return false; 922 return false;
923 } 923 }
924 } 924 }
925 925
926 return true; 926 return true;
927 } 927 }
928 928
929 void StatsCollector::UpdateTrackReports() { 929 void StatsCollector::UpdateTrackReports() {
930 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent()); 930 RTC_DCHECK(session_->signaling_thread()->IsCurrent());
931 931
932 rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls; 932 rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
933 933
934 for (const auto& entry : track_ids_) { 934 for (const auto& entry : track_ids_) {
935 StatsReport* report = entry.second; 935 StatsReport* report = entry.second;
936 report->set_timestamp(stats_gathering_started_); 936 report->set_timestamp(stats_gathering_started_);
937 } 937 }
938 } 938 }
939 939
940 void StatsCollector::ClearUpdateStatsCacheForTest() { 940 void StatsCollector::ClearUpdateStatsCacheForTest() {
941 stats_gathering_started_ = 0; 941 stats_gathering_started_ = 0;
942 } 942 }
943 943
944 } // namespace webrtc 944 } // namespace webrtc
OLDNEW
« no previous file with comments | « talk/app/webrtc/statscollector.h ('k') | talk/app/webrtc/statscollector_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698