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; |
425 } | 427 } |
426 | 428 |
429 // TODO(solenberg): Need to pull out session id so we have that even when | |
430 // there is no session. | |
427 StatsReport* report = reports_.Find(StatsReport::NewTypedId( | 431 StatsReport* report = reports_.Find(StatsReport::NewTypedId( |
428 StatsReport::kStatsReportTypeSession, pc_->session()->id())); | 432 StatsReport::kStatsReportTypeSession, pc_->session()->id())); |
429 if (report) | 433 if (report) |
430 reports->push_back(report); | 434 reports->push_back(report); |
431 | 435 |
432 report = reports_.Find(StatsReport::NewTypedId( | 436 report = reports_.Find(StatsReport::NewTypedId( |
433 StatsReport::kStatsReportTypeTrack, track->id())); | 437 StatsReport::kStatsReportTypeTrack, track->id())); |
434 | 438 |
435 if (!report) | 439 if (!report) |
436 return; | 440 return; |
437 | 441 |
438 reports->push_back(report); | 442 reports->push_back(report); |
439 | 443 |
440 std::string track_id; | 444 std::string track_id; |
441 for (const auto* r : reports_) { | 445 for (const auto* r : reports_) { |
442 if (r->type() != StatsReport::kStatsReportTypeSsrc) | 446 if (r->type() != StatsReport::kStatsReportTypeSsrc) |
443 continue; | 447 continue; |
444 | 448 |
445 const StatsReport::Value* v = | 449 const StatsReport::Value* v = |
446 r->FindValue(StatsReport::kStatsValueNameTrackId); | 450 r->FindValue(StatsReport::kStatsValueNameTrackId); |
447 if (v && v->string_val() == track->id()) | 451 if (v && v->string_val() == track->id()) |
448 reports->push_back(r); | 452 reports->push_back(r); |
449 } | 453 } |
450 } | 454 } |
451 | 455 |
452 void | 456 void |
453 StatsCollector::UpdateStats(PeerConnectionInterface::StatsOutputLevel level) { | 457 StatsCollector::UpdateStats(PeerConnectionInterface::StatsOutputLevel level) { |
454 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent()); | 458 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); |
455 double time_now = GetTimeNow(); | 459 double time_now = GetTimeNow(); |
456 // Calls to UpdateStats() that occur less than kMinGatherStatsPeriod number of | 460 // Calls to UpdateStats() that occur less than kMinGatherStatsPeriod number of |
457 // ms apart will be ignored. | 461 // ms apart will be ignored. |
458 const double kMinGatherStatsPeriod = 50; | 462 const double kMinGatherStatsPeriod = 50; |
459 if (stats_gathering_started_ != 0 && | 463 if (stats_gathering_started_ != 0 && |
460 stats_gathering_started_ + kMinGatherStatsPeriod > time_now) { | 464 stats_gathering_started_ + kMinGatherStatsPeriod > time_now) { |
461 return; | 465 return; |
462 } | 466 } |
463 stats_gathering_started_ = time_now; | 467 stats_gathering_started_ = time_now; |
464 | 468 |
469 // TODO(solenberg): Need to use a call which won't auto-create the session! | |
470 // Likely, this condition needs to go (PC always used to have a WebRtcSession) | |
471 // and some of the info at the beginning of ExtractSessionInfo is added even | |
472 // when there isn't a session. | |
pthatcher1
2016/02/26 21:51:20
I think we can just make this:
TODO(pthatcher): M
the sun
2016/02/29 15:58:22
Done.
| |
465 if (pc_->session()) { | 473 if (pc_->session()) { |
466 // TODO(tommi): All of these hop over to the worker thread to fetch | 474 // TODO(tommi): All of these hop over to the worker thread to fetch |
467 // information. We could use an AsyncInvoker to run all of these and post | 475 // information. We could use an AsyncInvoker to run all of these and post |
468 // the information back to the signaling thread where we can create and | 476 // the information back to the signaling thread where we can create and |
469 // update stats reports. That would also clean up the threading story a bit | 477 // update stats reports. That would also clean up the threading story a bit |
470 // since we'd be creating/updating the stats report objects consistently on | 478 // since we'd be creating/updating the stats report objects consistently on |
471 // the same thread (this class has no locks right now). | 479 // the same thread (this class has no locks right now). |
472 ExtractSessionInfo(); | 480 ExtractSessionInfo(); |
473 ExtractVoiceInfo(); | 481 ExtractVoiceInfo(); |
474 ExtractVideoInfo(level); | 482 ExtractVideoInfo(level); |
475 ExtractDataInfo(); | 483 ExtractDataInfo(); |
476 UpdateTrackReports(); | 484 UpdateTrackReports(); |
477 } | 485 } |
478 } | 486 } |
479 | 487 |
480 StatsReport* StatsCollector::PrepareReport( | 488 StatsReport* StatsCollector::PrepareReport( |
481 bool local, | 489 bool local, |
482 uint32_t ssrc, | 490 uint32_t ssrc, |
483 const StatsReport::Id& transport_id, | 491 const StatsReport::Id& transport_id, |
484 StatsReport::Direction direction) { | 492 StatsReport::Direction direction) { |
485 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent()); | 493 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); |
486 StatsReport::Id id(StatsReport::NewIdWithDirection( | 494 StatsReport::Id id(StatsReport::NewIdWithDirection( |
487 local ? StatsReport::kStatsReportTypeSsrc | 495 local ? StatsReport::kStatsReportTypeSsrc |
488 : StatsReport::kStatsReportTypeRemoteSsrc, | 496 : StatsReport::kStatsReportTypeRemoteSsrc, |
489 rtc::ToString<uint32_t>(ssrc), direction)); | 497 rtc::ToString<uint32_t>(ssrc), direction)); |
490 StatsReport* report = reports_.Find(id); | 498 StatsReport* report = reports_.Find(id); |
491 | 499 |
492 // Use the ID of the track that is currently mapped to the SSRC, if any. | 500 // Use the ID of the track that is currently mapped to the SSRC, if any. |
493 std::string track_id; | 501 std::string track_id; |
494 if (!GetTrackIdBySsrc(ssrc, &track_id, direction)) { | 502 if (!GetTrackIdBySsrc(ssrc, &track_id, direction)) { |
495 if (!report) { | 503 if (!report) { |
(...skipping 18 matching lines...) Expand all Loading... | |
514 | 522 |
515 report->AddInt64(StatsReport::kStatsValueNameSsrc, ssrc); | 523 report->AddInt64(StatsReport::kStatsValueNameSsrc, ssrc); |
516 report->AddString(StatsReport::kStatsValueNameTrackId, track_id); | 524 report->AddString(StatsReport::kStatsValueNameTrackId, track_id); |
517 // Add the mapping of SSRC to transport. | 525 // Add the mapping of SSRC to transport. |
518 report->AddId(StatsReport::kStatsValueNameTransportId, transport_id); | 526 report->AddId(StatsReport::kStatsValueNameTransportId, transport_id); |
519 return report; | 527 return report; |
520 } | 528 } |
521 | 529 |
522 StatsReport* StatsCollector::AddOneCertificateReport( | 530 StatsReport* StatsCollector::AddOneCertificateReport( |
523 const rtc::SSLCertificate* cert, const StatsReport* issuer) { | 531 const rtc::SSLCertificate* cert, const StatsReport* issuer) { |
524 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent()); | 532 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); |
525 | 533 |
526 // TODO(bemasc): Move this computation to a helper class that caches these | 534 // 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 | 535 // values to reduce CPU use in GetStats. This will require adding a fast |
528 // SSLCertificate::Equals() method to detect certificate changes. | 536 // SSLCertificate::Equals() method to detect certificate changes. |
529 | 537 |
530 std::string digest_algorithm; | 538 std::string digest_algorithm; |
531 if (!cert->GetSignatureDigestAlgorithm(&digest_algorithm)) | 539 if (!cert->GetSignatureDigestAlgorithm(&digest_algorithm)) |
532 return nullptr; | 540 return nullptr; |
533 | 541 |
534 rtc::scoped_ptr<rtc::SSLFingerprint> ssl_fingerprint( | 542 rtc::scoped_ptr<rtc::SSLFingerprint> ssl_fingerprint( |
(...skipping 22 matching lines...) Expand all Loading... | |
557 report->AddString(StatsReport::kStatsValueNameFingerprintAlgorithm, | 565 report->AddString(StatsReport::kStatsValueNameFingerprintAlgorithm, |
558 digest_algorithm); | 566 digest_algorithm); |
559 report->AddString(StatsReport::kStatsValueNameDer, der_base64); | 567 report->AddString(StatsReport::kStatsValueNameDer, der_base64); |
560 if (issuer) | 568 if (issuer) |
561 report->AddId(StatsReport::kStatsValueNameIssuerId, issuer->id()); | 569 report->AddId(StatsReport::kStatsValueNameIssuerId, issuer->id()); |
562 return report; | 570 return report; |
563 } | 571 } |
564 | 572 |
565 StatsReport* StatsCollector::AddCertificateReports( | 573 StatsReport* StatsCollector::AddCertificateReports( |
566 const rtc::SSLCertificate* cert) { | 574 const rtc::SSLCertificate* cert) { |
567 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent()); | 575 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); |
568 // Produces a chain of StatsReports representing this certificate and the rest | 576 // 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 | 577 // 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 | 578 // 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 | 579 // one report will always be provided and the returned string will never be |
572 // empty. | 580 // empty. |
573 RTC_DCHECK(cert != NULL); | 581 RTC_DCHECK(cert != NULL); |
574 | 582 |
575 StatsReport* issuer = nullptr; | 583 StatsReport* issuer = nullptr; |
576 rtc::scoped_ptr<rtc::SSLCertChain> chain; | 584 rtc::scoped_ptr<rtc::SSLCertChain> chain; |
577 if (cert->GetChain(chain.accept())) { | 585 if (cert->GetChain(chain.accept())) { |
578 // This loop runs in reverse, i.e. from root to leaf, so that each | 586 // 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 | 587 // 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 | 588 // report is generated. The root certificate does not have an issuer ID |
581 // value. | 589 // value. |
582 for (ptrdiff_t i = chain->GetSize() - 1; i >= 0; --i) { | 590 for (ptrdiff_t i = chain->GetSize() - 1; i >= 0; --i) { |
583 const rtc::SSLCertificate& cert_i = chain->Get(i); | 591 const rtc::SSLCertificate& cert_i = chain->Get(i); |
584 issuer = AddOneCertificateReport(&cert_i, issuer); | 592 issuer = AddOneCertificateReport(&cert_i, issuer); |
585 } | 593 } |
586 } | 594 } |
587 // Add the leaf certificate. | 595 // Add the leaf certificate. |
588 return AddOneCertificateReport(cert, issuer); | 596 return AddOneCertificateReport(cert, issuer); |
589 } | 597 } |
590 | 598 |
591 StatsReport* StatsCollector::AddConnectionInfoReport( | 599 StatsReport* StatsCollector::AddConnectionInfoReport( |
592 const std::string& content_name, int component, int connection_id, | 600 const std::string& content_name, int component, int connection_id, |
593 const StatsReport::Id& channel_report_id, | 601 const StatsReport::Id& channel_report_id, |
594 const cricket::ConnectionInfo& info) { | 602 const cricket::ConnectionInfo& info) { |
603 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); | |
595 StatsReport::Id id(StatsReport::NewCandidatePairId(content_name, component, | 604 StatsReport::Id id(StatsReport::NewCandidatePairId(content_name, component, |
596 connection_id)); | 605 connection_id)); |
597 StatsReport* report = reports_.ReplaceOrAddNew(id); | 606 StatsReport* report = reports_.ReplaceOrAddNew(id); |
598 report->set_timestamp(stats_gathering_started_); | 607 report->set_timestamp(stats_gathering_started_); |
599 | 608 |
600 const BoolForAdd bools[] = { | 609 const BoolForAdd bools[] = { |
601 {StatsReport::kStatsValueNameActiveConnection, info.best_connection}, | 610 {StatsReport::kStatsValueNameActiveConnection, info.best_connection}, |
602 {StatsReport::kStatsValueNameReceiving, info.receiving}, | 611 {StatsReport::kStatsValueNameReceiving, info.receiving}, |
603 {StatsReport::kStatsValueNameWritable, info.writable}, | 612 {StatsReport::kStatsValueNameWritable, info.writable}, |
604 }; | 613 }; |
(...skipping 27 matching lines...) Expand all Loading... | |
632 info.remote_candidate.type()); | 641 info.remote_candidate.type()); |
633 report->AddString(StatsReport::kStatsValueNameTransportType, | 642 report->AddString(StatsReport::kStatsValueNameTransportType, |
634 info.local_candidate.protocol()); | 643 info.local_candidate.protocol()); |
635 | 644 |
636 return report; | 645 return report; |
637 } | 646 } |
638 | 647 |
639 StatsReport* StatsCollector::AddCandidateReport( | 648 StatsReport* StatsCollector::AddCandidateReport( |
640 const cricket::Candidate& candidate, | 649 const cricket::Candidate& candidate, |
641 bool local) { | 650 bool local) { |
651 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); | |
642 StatsReport::Id id(StatsReport::NewCandidateId(local, candidate.id())); | 652 StatsReport::Id id(StatsReport::NewCandidateId(local, candidate.id())); |
643 StatsReport* report = reports_.Find(id); | 653 StatsReport* report = reports_.Find(id); |
644 if (!report) { | 654 if (!report) { |
645 report = reports_.InsertNew(id); | 655 report = reports_.InsertNew(id); |
646 report->set_timestamp(stats_gathering_started_); | 656 report->set_timestamp(stats_gathering_started_); |
647 if (local) { | 657 if (local) { |
648 report->AddString(StatsReport::kStatsValueNameCandidateNetworkType, | 658 report->AddString(StatsReport::kStatsValueNameCandidateNetworkType, |
649 AdapterTypeToStatsType(candidate.network_type())); | 659 AdapterTypeToStatsType(candidate.network_type())); |
650 } | 660 } |
651 report->AddString(StatsReport::kStatsValueNameCandidateIPAddress, | 661 report->AddString(StatsReport::kStatsValueNameCandidateIPAddress, |
652 candidate.address().ipaddr().ToString()); | 662 candidate.address().ipaddr().ToString()); |
653 report->AddString(StatsReport::kStatsValueNameCandidatePortNumber, | 663 report->AddString(StatsReport::kStatsValueNameCandidatePortNumber, |
654 candidate.address().PortAsString()); | 664 candidate.address().PortAsString()); |
655 report->AddInt(StatsReport::kStatsValueNameCandidatePriority, | 665 report->AddInt(StatsReport::kStatsValueNameCandidatePriority, |
656 candidate.priority()); | 666 candidate.priority()); |
657 report->AddString(StatsReport::kStatsValueNameCandidateType, | 667 report->AddString(StatsReport::kStatsValueNameCandidateType, |
658 IceCandidateTypeToStatsType(candidate.type())); | 668 IceCandidateTypeToStatsType(candidate.type())); |
659 report->AddString(StatsReport::kStatsValueNameCandidateTransportType, | 669 report->AddString(StatsReport::kStatsValueNameCandidateTransportType, |
660 candidate.protocol()); | 670 candidate.protocol()); |
661 } | 671 } |
662 | 672 |
663 return report; | 673 return report; |
664 } | 674 } |
665 | 675 |
666 void StatsCollector::ExtractSessionInfo() { | 676 void StatsCollector::ExtractSessionInfo() { |
667 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent()); | 677 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); |
668 | 678 |
669 // Extract information from the base session. | 679 // Extract information from the base session. |
670 StatsReport::Id id(StatsReport::NewTypedId( | 680 StatsReport::Id id(StatsReport::NewTypedId( |
671 StatsReport::kStatsReportTypeSession, pc_->session()->id())); | 681 StatsReport::kStatsReportTypeSession, pc_->session()->id())); |
672 StatsReport* report = reports_.ReplaceOrAddNew(id); | 682 StatsReport* report = reports_.ReplaceOrAddNew(id); |
673 report->set_timestamp(stats_gathering_started_); | 683 report->set_timestamp(stats_gathering_started_); |
674 report->AddBoolean(StatsReport::kStatsValueNameInitiator, | 684 report->AddBoolean(StatsReport::kStatsValueNameInitiator, |
675 pc_->session()->initial_offerer()); | 685 pc_->session()->initial_offerer()); |
676 | 686 |
677 SessionStats stats; | 687 SessionStats stats; |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
750 channel_report->AddId( | 760 channel_report->AddId( |
751 StatsReport::kStatsValueNameSelectedCandidatePairId, | 761 StatsReport::kStatsValueNameSelectedCandidatePairId, |
752 connection_report->id()); | 762 connection_report->id()); |
753 } | 763 } |
754 } | 764 } |
755 } | 765 } |
756 } | 766 } |
757 } | 767 } |
758 | 768 |
759 void StatsCollector::ExtractVoiceInfo() { | 769 void StatsCollector::ExtractVoiceInfo() { |
760 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent()); | 770 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); |
761 | 771 |
762 if (!pc_->session()->voice_channel()) { | 772 if (!pc_->session()->voice_channel()) { |
763 return; | 773 return; |
764 } | 774 } |
765 cricket::VoiceMediaInfo voice_info; | 775 cricket::VoiceMediaInfo voice_info; |
766 if (!pc_->session()->voice_channel()->GetStats(&voice_info)) { | 776 if (!pc_->session()->voice_channel()->GetStats(&voice_info)) { |
767 LOG(LS_ERROR) << "Failed to get voice channel stats."; | 777 LOG(LS_ERROR) << "Failed to get voice channel stats."; |
768 return; | 778 return; |
769 } | 779 } |
770 | 780 |
(...skipping 12 matching lines...) Expand all Loading... | |
783 ExtractStatsFromList(voice_info.receivers, transport_id, this, | 793 ExtractStatsFromList(voice_info.receivers, transport_id, this, |
784 StatsReport::kReceive); | 794 StatsReport::kReceive); |
785 ExtractStatsFromList(voice_info.senders, transport_id, this, | 795 ExtractStatsFromList(voice_info.senders, transport_id, this, |
786 StatsReport::kSend); | 796 StatsReport::kSend); |
787 | 797 |
788 UpdateStatsFromExistingLocalAudioTracks(); | 798 UpdateStatsFromExistingLocalAudioTracks(); |
789 } | 799 } |
790 | 800 |
791 void StatsCollector::ExtractVideoInfo( | 801 void StatsCollector::ExtractVideoInfo( |
792 PeerConnectionInterface::StatsOutputLevel level) { | 802 PeerConnectionInterface::StatsOutputLevel level) { |
793 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent()); | 803 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); |
794 | 804 |
795 if (!pc_->session()->video_channel()) | 805 if (!pc_->session()->video_channel()) |
796 return; | 806 return; |
797 | 807 |
798 cricket::VideoMediaInfo video_info; | 808 cricket::VideoMediaInfo video_info; |
799 if (!pc_->session()->video_channel()->GetStats(&video_info)) { | 809 if (!pc_->session()->video_channel()->GetStats(&video_info)) { |
800 LOG(LS_ERROR) << "Failed to get video channel stats."; | 810 LOG(LS_ERROR) << "Failed to get video channel stats."; |
801 return; | 811 return; |
802 } | 812 } |
803 | 813 |
(...skipping 16 matching lines...) Expand all Loading... | |
820 LOG(LS_ERROR) << "BWEs count: " << video_info.bw_estimations.size(); | 830 LOG(LS_ERROR) << "BWEs count: " << video_info.bw_estimations.size(); |
821 } else { | 831 } else { |
822 StatsReport::Id report_id(StatsReport::NewBandwidthEstimationId()); | 832 StatsReport::Id report_id(StatsReport::NewBandwidthEstimationId()); |
823 StatsReport* report = reports_.FindOrAddNew(report_id); | 833 StatsReport* report = reports_.FindOrAddNew(report_id); |
824 ExtractStats( | 834 ExtractStats( |
825 video_info.bw_estimations[0], stats_gathering_started_, level, report); | 835 video_info.bw_estimations[0], stats_gathering_started_, level, report); |
826 } | 836 } |
827 } | 837 } |
828 | 838 |
829 void StatsCollector::ExtractDataInfo() { | 839 void StatsCollector::ExtractDataInfo() { |
830 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent()); | 840 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); |
831 | 841 |
832 rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls; | 842 rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls; |
833 | 843 |
834 for (const auto& dc : pc_->sctp_data_channels()) { | 844 for (const auto& dc : pc_->sctp_data_channels()) { |
835 StatsReport::Id id(StatsReport::NewTypedIntId( | 845 StatsReport::Id id(StatsReport::NewTypedIntId( |
836 StatsReport::kStatsReportTypeDataChannel, dc->id())); | 846 StatsReport::kStatsReportTypeDataChannel, dc->id())); |
837 StatsReport* report = reports_.ReplaceOrAddNew(id); | 847 StatsReport* report = reports_.ReplaceOrAddNew(id); |
838 report->set_timestamp(stats_gathering_started_); | 848 report->set_timestamp(stats_gathering_started_); |
839 report->AddString(StatsReport::kStatsValueNameLabel, dc->label()); | 849 report->AddString(StatsReport::kStatsValueNameLabel, dc->label()); |
840 report->AddInt(StatsReport::kStatsValueNameDataChannelId, dc->id()); | 850 report->AddInt(StatsReport::kStatsValueNameDataChannelId, dc->id()); |
841 report->AddString(StatsReport::kStatsValueNameProtocol, dc->protocol()); | 851 report->AddString(StatsReport::kStatsValueNameProtocol, dc->protocol()); |
842 report->AddString(StatsReport::kStatsValueNameState, | 852 report->AddString(StatsReport::kStatsValueNameState, |
843 DataChannelInterface::DataStateString(dc->state())); | 853 DataChannelInterface::DataStateString(dc->state())); |
844 } | 854 } |
845 } | 855 } |
846 | 856 |
847 StatsReport* StatsCollector::GetReport(const StatsReport::StatsType& type, | 857 StatsReport* StatsCollector::GetReport(const StatsReport::StatsType& type, |
848 const std::string& id, | 858 const std::string& id, |
849 StatsReport::Direction direction) { | 859 StatsReport::Direction direction) { |
850 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent()); | 860 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); |
851 RTC_DCHECK(type == StatsReport::kStatsReportTypeSsrc || | 861 RTC_DCHECK(type == StatsReport::kStatsReportTypeSsrc || |
852 type == StatsReport::kStatsReportTypeRemoteSsrc); | 862 type == StatsReport::kStatsReportTypeRemoteSsrc); |
853 return reports_.Find(StatsReport::NewIdWithDirection(type, id, direction)); | 863 return reports_.Find(StatsReport::NewIdWithDirection(type, id, direction)); |
854 } | 864 } |
855 | 865 |
856 void StatsCollector::UpdateStatsFromExistingLocalAudioTracks() { | 866 void StatsCollector::UpdateStatsFromExistingLocalAudioTracks() { |
857 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent()); | 867 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); |
858 // Loop through the existing local audio tracks. | 868 // Loop through the existing local audio tracks. |
859 for (const auto& it : local_audio_tracks_) { | 869 for (const auto& it : local_audio_tracks_) { |
860 AudioTrackInterface* track = it.first; | 870 AudioTrackInterface* track = it.first; |
861 uint32_t ssrc = it.second; | 871 uint32_t ssrc = it.second; |
862 StatsReport* report = | 872 StatsReport* report = |
863 GetReport(StatsReport::kStatsReportTypeSsrc, | 873 GetReport(StatsReport::kStatsReportTypeSsrc, |
864 rtc::ToString<uint32_t>(ssrc), StatsReport::kSend); | 874 rtc::ToString<uint32_t>(ssrc), StatsReport::kSend); |
865 if (report == NULL) { | 875 if (report == NULL) { |
866 // This can happen if a local audio track is added to a stream on the | 876 // 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. | 877 // 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; | 878 LOG(LS_ERROR) << "Stats report does not exist for ssrc " << ssrc; |
869 continue; | 879 continue; |
870 } | 880 } |
871 | 881 |
872 // The same ssrc can be used by both local and remote audio tracks. | 882 // The same ssrc can be used by both local and remote audio tracks. |
873 const StatsReport::Value* v = | 883 const StatsReport::Value* v = |
874 report->FindValue(StatsReport::kStatsValueNameTrackId); | 884 report->FindValue(StatsReport::kStatsValueNameTrackId); |
875 if (!v || v->string_val() != track->id()) | 885 if (!v || v->string_val() != track->id()) |
876 continue; | 886 continue; |
877 | 887 |
878 report->set_timestamp(stats_gathering_started_); | 888 report->set_timestamp(stats_gathering_started_); |
879 UpdateReportFromAudioTrack(track, report); | 889 UpdateReportFromAudioTrack(track, report); |
880 } | 890 } |
881 } | 891 } |
882 | 892 |
883 void StatsCollector::UpdateReportFromAudioTrack(AudioTrackInterface* track, | 893 void StatsCollector::UpdateReportFromAudioTrack(AudioTrackInterface* track, |
884 StatsReport* report) { | 894 StatsReport* report) { |
885 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent()); | 895 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); |
886 RTC_DCHECK(track != NULL); | 896 RTC_DCHECK(track != NULL); |
887 | 897 |
888 // Don't overwrite report values if they're not available. | 898 // Don't overwrite report values if they're not available. |
889 int signal_level; | 899 int signal_level; |
890 if (track->GetSignalLevel(&signal_level)) { | 900 if (track->GetSignalLevel(&signal_level)) { |
891 RTC_DCHECK_GE(signal_level, 0); | 901 RTC_DCHECK_GE(signal_level, 0); |
892 report->AddInt(StatsReport::kStatsValueNameAudioInputLevel, signal_level); | 902 report->AddInt(StatsReport::kStatsValueNameAudioInputLevel, signal_level); |
893 } | 903 } |
894 | 904 |
895 auto audio_processor(track->GetAudioProcessor()); | 905 auto audio_processor(track->GetAudioProcessor()); |
896 | 906 |
897 if (audio_processor.get()) { | 907 if (audio_processor.get()) { |
898 AudioProcessorInterface::AudioProcessorStats stats; | 908 AudioProcessorInterface::AudioProcessorStats stats; |
899 audio_processor->GetStats(&stats); | 909 audio_processor->GetStats(&stats); |
900 | 910 |
901 SetAudioProcessingStats( | 911 SetAudioProcessingStats( |
902 report, stats.typing_noise_detected, stats.echo_return_loss, | 912 report, stats.typing_noise_detected, stats.echo_return_loss, |
903 stats.echo_return_loss_enhancement, stats.echo_delay_median_ms, | 913 stats.echo_return_loss_enhancement, stats.echo_delay_median_ms, |
904 stats.aec_quality_min, stats.echo_delay_std_ms); | 914 stats.aec_quality_min, stats.echo_delay_std_ms); |
905 } | 915 } |
906 } | 916 } |
907 | 917 |
908 bool StatsCollector::GetTrackIdBySsrc(uint32_t ssrc, | 918 bool StatsCollector::GetTrackIdBySsrc(uint32_t ssrc, |
909 std::string* track_id, | 919 std::string* track_id, |
910 StatsReport::Direction direction) { | 920 StatsReport::Direction direction) { |
911 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent()); | 921 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); |
912 if (direction == StatsReport::kSend) { | 922 if (direction == StatsReport::kSend) { |
913 if (!pc_->session()->GetLocalTrackIdBySsrc(ssrc, track_id)) { | 923 if (!pc_->session()->GetLocalTrackIdBySsrc(ssrc, track_id)) { |
914 LOG(LS_WARNING) << "The SSRC " << ssrc | 924 LOG(LS_WARNING) << "The SSRC " << ssrc |
915 << " is not associated with a sending track"; | 925 << " is not associated with a sending track"; |
916 return false; | 926 return false; |
917 } | 927 } |
918 } else { | 928 } else { |
919 RTC_DCHECK(direction == StatsReport::kReceive); | 929 RTC_DCHECK(direction == StatsReport::kReceive); |
920 if (!pc_->session()->GetRemoteTrackIdBySsrc(ssrc, track_id)) { | 930 if (!pc_->session()->GetRemoteTrackIdBySsrc(ssrc, track_id)) { |
921 LOG(LS_WARNING) << "The SSRC " << ssrc | 931 LOG(LS_WARNING) << "The SSRC " << ssrc |
922 << " is not associated with a receiving track"; | 932 << " is not associated with a receiving track"; |
923 return false; | 933 return false; |
924 } | 934 } |
925 } | 935 } |
926 | 936 |
927 return true; | 937 return true; |
928 } | 938 } |
929 | 939 |
930 void StatsCollector::UpdateTrackReports() { | 940 void StatsCollector::UpdateTrackReports() { |
931 RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent()); | 941 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); |
932 | 942 |
933 rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls; | 943 rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls; |
934 | 944 |
935 for (const auto& entry : track_ids_) { | 945 for (const auto& entry : track_ids_) { |
936 StatsReport* report = entry.second; | 946 StatsReport* report = entry.second; |
937 report->set_timestamp(stats_gathering_started_); | 947 report->set_timestamp(stats_gathering_started_); |
938 } | 948 } |
939 } | 949 } |
940 | 950 |
941 void StatsCollector::ClearUpdateStatsCacheForTest() { | 951 void StatsCollector::ClearUpdateStatsCacheForTest() { |
952 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread()); | |
942 stats_gathering_started_ = 0; | 953 stats_gathering_started_ = 0; |
943 } | 954 } |
944 | 955 |
945 } // namespace webrtc | 956 } // namespace webrtc |
OLD | NEW |