diff options
Diffstat (limited to 'third_party/libwebrtc/pc/rtc_stats_traversal.cc')
-rw-r--r-- | third_party/libwebrtc/pc/rtc_stats_traversal.cc | 152 |
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 |