Prepare StatsCollector to work with RtpTransceivers
This changes the StatsCollector to handle stats from multiple
MediaChannels of the same type (e.g., audio or video).
Bug: webrtc:8764
Change-Id: I91ba50d10cf469420189a311acdafbf6f78579b2
Reviewed-on: https://webrtc-review.googlesource.com/49560
Reviewed-by: Taylor Brandstetter <deadbeef@webrtc.org>
Commit-Queue: Steve Anton <steveanton@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22009}
diff --git a/pc/peerconnection.cc b/pc/peerconnection.cc
index 1bdd640..881c883 100644
--- a/pc/peerconnection.cc
+++ b/pc/peerconnection.cc
@@ -4388,23 +4388,6 @@
role);
}
-// TODO(steveanton): Eventually it'd be nice to store the channels as a single
-// vector of BaseChannel pointers instead of separate voice and video channel
-// vectors. At that point, this will become a simple getter.
-std::vector<cricket::BaseChannel*> PeerConnection::Channels() const {
- std::vector<cricket::BaseChannel*> channels;
- if (voice_channel()) {
- channels.push_back(voice_channel());
- }
- if (video_channel()) {
- channels.push_back(video_channel());
- }
- if (rtp_data_channel_) {
- channels.push_back(rtp_data_channel_);
- }
- return channels;
-}
-
void PeerConnection::SetSessionError(SessionError error,
const std::string& error_desc) {
RTC_DCHECK_RUN_ON(signaling_thread());
diff --git a/pc/peerconnection.h b/pc/peerconnection.h
index 05a1171..617aa37 100644
--- a/pc/peerconnection.h
+++ b/pc/peerconnection.h
@@ -225,7 +225,7 @@
std::vector<
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>>
- GetTransceiversForTesting() const override {
+ GetTransceiversInternal() const override {
return transceivers_;
}
@@ -723,9 +723,6 @@
return transport_controller_.get();
}
- // Return all managed, non-null channels.
- std::vector<cricket::BaseChannel*> Channels() const;
-
// Non-const versions of local_description()/remote_description(), for use
// internally.
SessionDescriptionInterface* mutable_local_description() {
diff --git a/pc/peerconnection_bundle_unittest.cc b/pc/peerconnection_bundle_unittest.cc
index 116a598..616a076 100644
--- a/pc/peerconnection_bundle_unittest.cc
+++ b/pc/peerconnection_bundle_unittest.cc
@@ -76,8 +76,7 @@
}
cricket::VoiceChannel* voice_channel() {
- auto transceivers =
- GetInternalPeerConnection()->GetTransceiversForTesting();
+ auto transceivers = GetInternalPeerConnection()->GetTransceiversInternal();
for (auto transceiver : transceivers) {
if (transceiver->media_type() == cricket::MEDIA_TYPE_AUDIO) {
return static_cast<cricket::VoiceChannel*>(
@@ -96,8 +95,7 @@
}
cricket::VideoChannel* video_channel() {
- auto transceivers =
- GetInternalPeerConnection()->GetTransceiversForTesting();
+ auto transceivers = GetInternalPeerConnection()->GetTransceiversInternal();
for (auto transceiver : transceivers) {
if (transceiver->media_type() == cricket::MEDIA_TYPE_VIDEO) {
return static_cast<cricket::VideoChannel*>(
diff --git a/pc/peerconnection_ice_unittest.cc b/pc/peerconnection_ice_unittest.cc
index c1d7551..06dd876 100644
--- a/pc/peerconnection_ice_unittest.cc
+++ b/pc/peerconnection_ice_unittest.cc
@@ -196,7 +196,7 @@
static_cast<PeerConnectionProxyWithInternal<PeerConnectionInterface>*>(
pc_wrapper_ptr->pc());
PeerConnection* pc = static_cast<PeerConnection*>(pc_proxy->internal());
- for (auto transceiver : pc->GetTransceiversForTesting()) {
+ for (auto transceiver : pc->GetTransceiversInternal()) {
if (transceiver->media_type() == cricket::MEDIA_TYPE_AUDIO) {
cricket::BaseChannel* channel = transceiver->internal()->channel();
if (channel) {
diff --git a/pc/peerconnectioninternal.h b/pc/peerconnectioninternal.h
index 18a24b8..0f942d2 100644
--- a/pc/peerconnectioninternal.h
+++ b/pc/peerconnectioninternal.h
@@ -36,14 +36,13 @@
// Returns true if we were the initial offerer.
virtual bool initial_offerer() const = 0;
- // TODO(steveanton): Remove these.
+ // TODO(steveanton): Remove these and replace with GetTransceiversInternal.
virtual cricket::VoiceChannel* voice_channel() const = 0;
virtual cricket::VideoChannel* video_channel() const = 0;
- // Exposed for tests.
virtual std::vector<
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>>
- GetTransceiversForTesting() const = 0;
+ GetTransceiversInternal() const = 0;
// Get the id used as a media stream track's "id" field from ssrc.
virtual bool GetLocalTrackIdBySsrc(uint32_t ssrc, std::string* track_id) = 0;
diff --git a/pc/statscollector.cc b/pc/statscollector.cc
index d816899..5154cbc 100644
--- a/pc/statscollector.cc
+++ b/pc/statscollector.cc
@@ -569,8 +569,7 @@
// the same thread (this class has no locks right now).
ExtractSessionInfo();
ExtractBweInfo();
- ExtractVoiceInfo();
- ExtractVideoInfo(level);
+ ExtractMediaInfo();
ExtractSenderInfo();
ExtractDataInfo();
UpdateTrackReports();
@@ -846,59 +845,100 @@
ExtractStats(bwe_info, stats_gathering_started_, report);
}
-void StatsCollector::ExtractVoiceInfo() {
- RTC_DCHECK(pc_->signaling_thread()->IsCurrent());
+namespace {
- if (!pc_->voice_channel()) {
- return;
- }
- cricket::VoiceMediaInfo voice_info;
- if (!pc_->voice_channel()->GetStats(&voice_info)) {
- RTC_LOG(LS_ERROR) << "Failed to get voice channel stats.";
- return;
+struct VoiceChannelStatsInfo {
+ std::string transport_name;
+ cricket::VoiceMediaChannel* voice_media_channel;
+ cricket::VoiceMediaInfo voice_media_info;
+};
+
+struct VideoChannelStatsInfo {
+ std::string transport_name;
+ cricket::VideoMediaChannel* video_media_channel;
+ cricket::VideoMediaInfo video_media_info;
+};
+
+} // namespace
+
+void StatsCollector::ExtractMediaInfo() {
+ RTC_DCHECK_RUN_ON(pc_->signaling_thread());
+
+ std::vector<VoiceChannelStatsInfo> voice_channel_infos;
+ std::vector<VideoChannelStatsInfo> video_channel_infos;
+
+ {
+ rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
+ for (auto transceiver : pc_->GetTransceiversInternal()) {
+ if (!transceiver->internal()->channel()) {
+ continue;
+ }
+ cricket::MediaType media_type = transceiver->internal()->media_type();
+ if (media_type == cricket::MEDIA_TYPE_AUDIO) {
+ auto* voice_channel = static_cast<cricket::VoiceChannel*>(
+ transceiver->internal()->channel());
+ voice_channel_infos.emplace_back();
+ VoiceChannelStatsInfo& info = voice_channel_infos.back();
+ info.transport_name = voice_channel->transport_name();
+ info.voice_media_channel = voice_channel->media_channel();
+ } else {
+ RTC_DCHECK_EQ(media_type, cricket::MEDIA_TYPE_VIDEO);
+ auto* video_channel = static_cast<cricket::VideoChannel*>(
+ transceiver->internal()->channel());
+ video_channel_infos.emplace_back();
+ VideoChannelStatsInfo& info = video_channel_infos.back();
+ info.transport_name = video_channel->transport_name();
+ info.video_media_channel = video_channel->media_channel();
+ }
+ }
}
- // TODO(tommi): The above code should run on the worker thread and post the
- // results back to the signaling thread, where we can add data to the reports.
+ pc_->worker_thread()->Invoke<void>(RTC_FROM_HERE, [&] {
+ rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
+ for (auto it = voice_channel_infos.begin(); it != voice_channel_infos.end();
+ /* incremented manually */) {
+ if (!it->voice_media_channel->GetStats(&it->voice_media_info)) {
+ RTC_LOG(LS_ERROR) << "Failed to get voice channel stats";
+ it = voice_channel_infos.erase(it);
+ continue;
+ }
+ ++it;
+ }
+ for (auto it = video_channel_infos.begin(); it != video_channel_infos.end();
+ /* incremented manually */) {
+ if (!it->video_media_channel->GetStats(&it->video_media_info)) {
+ RTC_LOG(LS_ERROR) << "Failed to get video channel stats";
+ it = video_channel_infos.erase(it);
+ continue;
+ }
+ ++it;
+ }
+ });
+
rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
- StatsReport::Id transport_id =
- StatsReport::NewComponentId(pc_->voice_channel()->transport_name(),
- cricket::ICE_CANDIDATE_COMPONENT_RTP);
-
- ExtractStatsFromList(voice_info.receivers, transport_id, this,
- StatsReport::kReceive);
- ExtractStatsFromList(voice_info.senders, transport_id, this,
- StatsReport::kSend);
-
- UpdateStatsFromExistingLocalAudioTracks(voice_info.receivers.size() > 0);
-}
-
-void StatsCollector::ExtractVideoInfo(
- PeerConnectionInterface::StatsOutputLevel level) {
- RTC_DCHECK(pc_->signaling_thread()->IsCurrent());
-
- if (!pc_->video_channel()) {
- return;
+ bool has_remote_audio = false;
+ for (const auto& info : voice_channel_infos) {
+ StatsReport::Id transport_id = StatsReport::NewComponentId(
+ info.transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
+ ExtractStatsFromList(info.voice_media_info.receivers, transport_id, this,
+ StatsReport::kReceive);
+ ExtractStatsFromList(info.voice_media_info.senders, transport_id, this,
+ StatsReport::kSend);
+ if (!info.voice_media_info.receivers.empty()) {
+ has_remote_audio = true;
+ }
}
- cricket::VideoMediaInfo video_info;
- if (!pc_->video_channel()->GetStats(&video_info)) {
- RTC_LOG(LS_ERROR) << "Failed to get video channel stats.";
- return;
+ for (const auto& info : video_channel_infos) {
+ StatsReport::Id transport_id = StatsReport::NewComponentId(
+ info.transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
+ ExtractStatsFromList(info.video_media_info.receivers, transport_id, this,
+ StatsReport::kReceive);
+ ExtractStatsFromList(info.video_media_info.senders, transport_id, this,
+ StatsReport::kSend);
}
- // TODO(tommi): The above code should run on the worker thread and post the
- // results back to the signaling thread, where we can add data to the reports.
- rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
-
- StatsReport::Id transport_id =
- StatsReport::NewComponentId(pc_->video_channel()->transport_name(),
- cricket::ICE_CANDIDATE_COMPONENT_RTP);
-
- ExtractStatsFromList(video_info.receivers, transport_id, this,
- StatsReport::kReceive);
- ExtractStatsFromList(video_info.senders, transport_id, this,
- StatsReport::kSend);
+ UpdateStatsFromExistingLocalAudioTracks(has_remote_audio);
}
void StatsCollector::ExtractSenderInfo() {
diff --git a/pc/statscollector.h b/pc/statscollector.h
index c171dca..681a8f0 100644
--- a/pc/statscollector.h
+++ b/pc/statscollector.h
@@ -111,10 +111,8 @@
void ExtractDataInfo();
void ExtractSessionInfo();
void ExtractBweInfo();
- void ExtractVoiceInfo();
- void ExtractVideoInfo(PeerConnectionInterface::StatsOutputLevel level);
+ void ExtractMediaInfo();
void ExtractSenderInfo();
- void BuildSsrcToTransportId();
webrtc::StatsReport* GetReport(const StatsReport::StatsType& type,
const std::string& id,
StatsReport::Direction direction);
diff --git a/pc/test/fakepeerconnectionbase.h b/pc/test/fakepeerconnectionbase.h
index 790aa8f..b1cee6d 100644
--- a/pc/test/fakepeerconnectionbase.h
+++ b/pc/test/fakepeerconnectionbase.h
@@ -249,7 +249,7 @@
std::vector<
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>>
- GetTransceiversForTesting() const override {
+ GetTransceiversInternal() const override {
return {};
}
diff --git a/pc/test/fakepeerconnectionforstats.h b/pc/test/fakepeerconnectionforstats.h
index 989640a..d73e734 100644
--- a/pc/test/fakepeerconnectionforstats.h
+++ b/pc/test/fakepeerconnectionforstats.h
@@ -116,6 +116,10 @@
std::move(voice_media_channel), mid, kDefaultRtcpMuxRequired,
kDefaultSrtpRequired);
voice_channel_->set_transport_name_for_testing(transport_name);
+ auto transceiver = RtpTransceiverProxyWithInternal<RtpTransceiver>::Create(
+ signaling_thread_, new RtpTransceiver(cricket::MEDIA_TYPE_AUDIO));
+ transceiver->internal()->SetChannel(voice_channel_.get());
+ transceivers_.push_back(transceiver);
return voice_media_channel_ptr;
}
@@ -130,6 +134,10 @@
std::move(video_media_channel), mid, kDefaultRtcpMuxRequired,
kDefaultSrtpRequired);
video_channel_->set_transport_name_for_testing(transport_name);
+ auto transceiver = RtpTransceiverProxyWithInternal<RtpTransceiver>::Create(
+ signaling_thread_, new RtpTransceiver(cricket::MEDIA_TYPE_VIDEO));
+ transceiver->internal()->SetChannel(video_channel_.get());
+ transceivers_.push_back(transceiver);
return video_media_channel_ptr;
}
@@ -220,6 +228,12 @@
return video_channel_.get();
}
+ std::vector<
+ rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>>
+ GetTransceiversInternal() const override {
+ return transceivers_;
+ }
+
bool GetLocalTrackIdBySsrc(uint32_t ssrc, std::string* track_id) override {
auto it = local_track_id_by_ssrc_.find(ssrc);
if (it != local_track_id_by_ssrc_.end()) {
@@ -316,6 +330,9 @@
rtc::scoped_refptr<StreamCollection> local_streams_;
rtc::scoped_refptr<StreamCollection> remote_streams_;
+ std::vector<
+ rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>>
+ transceivers_;
std::vector<rtc::scoped_refptr<RtpSenderInterface>> senders_;
std::vector<rtc::scoped_refptr<RtpReceiverInterface>> receivers_;