summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/pc/rtc_stats_traversal.cc
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/libwebrtc/pc/rtc_stats_traversal.cc')
-rw-r--r--third_party/libwebrtc/pc/rtc_stats_traversal.cc152
1 files changed, 152 insertions, 0 deletions
diff --git a/third_party/libwebrtc/pc/rtc_stats_traversal.cc b/third_party/libwebrtc/pc/rtc_stats_traversal.cc
new file mode 100644
index 0000000000..98401126ed
--- /dev/null
+++ b/third_party/libwebrtc/pc/rtc_stats_traversal.cc
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2018 The WebRTC Project Authors. All rights reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "pc/rtc_stats_traversal.h"
+
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "api/stats/rtcstats_objects.h"
+#include "rtc_base/checks.h"
+
+namespace webrtc {
+
+namespace {
+
+void TraverseAndTakeVisitedStats(RTCStatsReport* report,
+ RTCStatsReport* visited_report,
+ const std::string& current_id) {
+ // Mark current stats object as visited by moving it `report` to
+ // `visited_report`.
+ std::unique_ptr<const RTCStats> current = report->Take(current_id);
+ if (!current) {
+ // This node has already been visited (or it is an invalid id).
+ return;
+ }
+ std::vector<const std::string*> neighbor_ids =
+ GetStatsReferencedIds(*current);
+ visited_report->AddStats(std::move(current));
+
+ // Recursively traverse all neighbors.
+ for (const auto* neighbor_id : neighbor_ids) {
+ TraverseAndTakeVisitedStats(report, visited_report, *neighbor_id);
+ }
+}
+
+void AddIdIfDefined(const RTCStatsMember<std::string>& id,
+ std::vector<const std::string*>* neighbor_ids) {
+ if (id.is_defined())
+ neighbor_ids->push_back(&(*id));
+}
+
+void AddIdsIfDefined(const RTCStatsMember<std::vector<std::string>>& ids,
+ std::vector<const std::string*>* neighbor_ids) {
+ if (ids.is_defined()) {
+ for (const std::string& id : *ids)
+ neighbor_ids->push_back(&id);
+ }
+}
+
+} // namespace
+
+rtc::scoped_refptr<RTCStatsReport> TakeReferencedStats(
+ rtc::scoped_refptr<RTCStatsReport> report,
+ const std::vector<std::string>& ids) {
+ rtc::scoped_refptr<RTCStatsReport> result =
+ RTCStatsReport::Create(report->timestamp());
+ for (const auto& id : ids) {
+ TraverseAndTakeVisitedStats(report.get(), result.get(), id);
+ }
+ return result;
+}
+
+std::vector<const std::string*> GetStatsReferencedIds(const RTCStats& stats) {
+ std::vector<const std::string*> neighbor_ids;
+ const char* type = stats.type();
+ if (type == RTCCertificateStats::kType) {
+ const auto& certificate = static_cast<const RTCCertificateStats&>(stats);
+ AddIdIfDefined(certificate.issuer_certificate_id, &neighbor_ids);
+ } else if (type == RTCCodecStats::kType) {
+ const auto& codec = static_cast<const RTCCodecStats&>(stats);
+ AddIdIfDefined(codec.transport_id, &neighbor_ids);
+ } else if (type == RTCDataChannelStats::kType) {
+ // RTCDataChannelStats does not have any neighbor references.
+ } else if (type == RTCIceCandidatePairStats::kType) {
+ const auto& candidate_pair =
+ static_cast<const RTCIceCandidatePairStats&>(stats);
+ AddIdIfDefined(candidate_pair.transport_id, &neighbor_ids);
+ AddIdIfDefined(candidate_pair.local_candidate_id, &neighbor_ids);
+ AddIdIfDefined(candidate_pair.remote_candidate_id, &neighbor_ids);
+ } else if (type == RTCLocalIceCandidateStats::kType ||
+ type == RTCRemoteIceCandidateStats::kType) {
+ const auto& local_or_remote_candidate =
+ static_cast<const RTCIceCandidateStats&>(stats);
+ AddIdIfDefined(local_or_remote_candidate.transport_id, &neighbor_ids);
+ } else if (type == DEPRECATED_RTCMediaStreamStats::kType) {
+ const auto& stream =
+ static_cast<const DEPRECATED_RTCMediaStreamStats&>(stats);
+ AddIdsIfDefined(stream.track_ids, &neighbor_ids);
+ } else if (type == DEPRECATED_RTCMediaStreamTrackStats::kType) {
+ const auto& track =
+ static_cast<const DEPRECATED_RTCMediaStreamTrackStats&>(stats);
+ AddIdIfDefined(track.media_source_id, &neighbor_ids);
+ } else if (type == RTCPeerConnectionStats::kType) {
+ // RTCPeerConnectionStats does not have any neighbor references.
+ } else if (type == RTCInboundRTPStreamStats::kType) {
+ const auto& inbound_rtp =
+ static_cast<const RTCInboundRTPStreamStats&>(stats);
+ AddIdIfDefined(inbound_rtp.remote_id, &neighbor_ids);
+ AddIdIfDefined(inbound_rtp.track_id, &neighbor_ids);
+ AddIdIfDefined(inbound_rtp.transport_id, &neighbor_ids);
+ AddIdIfDefined(inbound_rtp.codec_id, &neighbor_ids);
+ AddIdIfDefined(inbound_rtp.playout_id, &neighbor_ids);
+ } else if (type == RTCOutboundRTPStreamStats::kType) {
+ const auto& outbound_rtp =
+ static_cast<const RTCOutboundRTPStreamStats&>(stats);
+ AddIdIfDefined(outbound_rtp.remote_id, &neighbor_ids);
+ AddIdIfDefined(outbound_rtp.track_id, &neighbor_ids);
+ AddIdIfDefined(outbound_rtp.transport_id, &neighbor_ids);
+ AddIdIfDefined(outbound_rtp.codec_id, &neighbor_ids);
+ AddIdIfDefined(outbound_rtp.media_source_id, &neighbor_ids);
+ } else if (type == RTCRemoteInboundRtpStreamStats::kType) {
+ const auto& remote_inbound_rtp =
+ static_cast<const RTCRemoteInboundRtpStreamStats&>(stats);
+ AddIdIfDefined(remote_inbound_rtp.transport_id, &neighbor_ids);
+ AddIdIfDefined(remote_inbound_rtp.codec_id, &neighbor_ids);
+ AddIdIfDefined(remote_inbound_rtp.local_id, &neighbor_ids);
+ } else if (type == RTCRemoteOutboundRtpStreamStats::kType) {
+ const auto& remote_outbound_rtp =
+ static_cast<const RTCRemoteOutboundRtpStreamStats&>(stats);
+ // Inherited from `RTCRTPStreamStats`.
+ AddIdIfDefined(remote_outbound_rtp.track_id, &neighbor_ids);
+ AddIdIfDefined(remote_outbound_rtp.transport_id, &neighbor_ids);
+ AddIdIfDefined(remote_outbound_rtp.codec_id, &neighbor_ids);
+ // Direct members of `RTCRemoteOutboundRtpStreamStats`.
+ AddIdIfDefined(remote_outbound_rtp.local_id, &neighbor_ids);
+ } else if (type == RTCAudioSourceStats::kType ||
+ type == RTCVideoSourceStats::kType) {
+ // RTC[Audio/Video]SourceStats does not have any neighbor references.
+ } else if (type == RTCTransportStats::kType) {
+ const auto& transport = static_cast<const RTCTransportStats&>(stats);
+ AddIdIfDefined(transport.rtcp_transport_stats_id, &neighbor_ids);
+ AddIdIfDefined(transport.selected_candidate_pair_id, &neighbor_ids);
+ AddIdIfDefined(transport.local_certificate_id, &neighbor_ids);
+ AddIdIfDefined(transport.remote_certificate_id, &neighbor_ids);
+ } else if (type == RTCAudioPlayoutStats::kType) {
+ // RTCAudioPlayoutStats does not have any neighbor references.
+ } else {
+ RTC_DCHECK_NOTREACHED() << "Unrecognized type: " << type;
+ }
+ return neighbor_ids;
+}
+
+} // namespace webrtc