blob: 98401126edf61c0f073cad47db8c871e4f2a4ea4 [file] [log] [blame]
Henrik Boströmb6199362018-03-12 10:27:55 +01001/*
2 * Copyright 2018 The WebRTC Project Authors. All rights reserved.
3 *
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
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Steve Anton10542f22019-01-11 09:11:00 -080011#include "pc/rtc_stats_traversal.h"
Henrik Boströmb6199362018-03-12 10:27:55 +010012
13#include <memory>
14#include <string>
15#include <utility>
16#include <vector>
17
18#include "api/stats/rtcstats_objects.h"
19#include "rtc_base/checks.h"
20
21namespace webrtc {
22
23namespace {
24
25void TraverseAndTakeVisitedStats(RTCStatsReport* report,
26 RTCStatsReport* visited_report,
27 const std::string& current_id) {
Artem Titov880fa812021-07-30 22:30:23 +020028 // Mark current stats object as visited by moving it `report` to
29 // `visited_report`.
Henrik Boströmb6199362018-03-12 10:27:55 +010030 std::unique_ptr<const RTCStats> current = report->Take(current_id);
31 if (!current) {
32 // This node has already been visited (or it is an invalid id).
33 return;
34 }
35 std::vector<const std::string*> neighbor_ids =
36 GetStatsReferencedIds(*current);
37 visited_report->AddStats(std::move(current));
38
39 // Recursively traverse all neighbors.
40 for (const auto* neighbor_id : neighbor_ids) {
41 TraverseAndTakeVisitedStats(report, visited_report, *neighbor_id);
42 }
43}
44
45void AddIdIfDefined(const RTCStatsMember<std::string>& id,
46 std::vector<const std::string*>* neighbor_ids) {
47 if (id.is_defined())
48 neighbor_ids->push_back(&(*id));
49}
50
51void AddIdsIfDefined(const RTCStatsMember<std::vector<std::string>>& ids,
52 std::vector<const std::string*>* neighbor_ids) {
53 if (ids.is_defined()) {
54 for (const std::string& id : *ids)
55 neighbor_ids->push_back(&id);
56 }
57}
58
59} // namespace
60
61rtc::scoped_refptr<RTCStatsReport> TakeReferencedStats(
62 rtc::scoped_refptr<RTCStatsReport> report,
63 const std::vector<std::string>& ids) {
Henrik Boström5b3541f2018-03-19 13:52:56 +010064 rtc::scoped_refptr<RTCStatsReport> result =
Philipp Hancke036b3fd2022-10-12 19:12:23 +020065 RTCStatsReport::Create(report->timestamp());
Henrik Boströmb6199362018-03-12 10:27:55 +010066 for (const auto& id : ids) {
67 TraverseAndTakeVisitedStats(report.get(), result.get(), id);
68 }
69 return result;
70}
71
72std::vector<const std::string*> GetStatsReferencedIds(const RTCStats& stats) {
73 std::vector<const std::string*> neighbor_ids;
74 const char* type = stats.type();
75 if (type == RTCCertificateStats::kType) {
76 const auto& certificate = static_cast<const RTCCertificateStats&>(stats);
77 AddIdIfDefined(certificate.issuer_certificate_id, &neighbor_ids);
78 } else if (type == RTCCodecStats::kType) {
Philipp Hancke95157a02020-11-16 20:08:27 +010079 const auto& codec = static_cast<const RTCCodecStats&>(stats);
80 AddIdIfDefined(codec.transport_id, &neighbor_ids);
Henrik Boströmb6199362018-03-12 10:27:55 +010081 } else if (type == RTCDataChannelStats::kType) {
82 // RTCDataChannelStats does not have any neighbor references.
83 } else if (type == RTCIceCandidatePairStats::kType) {
84 const auto& candidate_pair =
85 static_cast<const RTCIceCandidatePairStats&>(stats);
86 AddIdIfDefined(candidate_pair.transport_id, &neighbor_ids);
87 AddIdIfDefined(candidate_pair.local_candidate_id, &neighbor_ids);
88 AddIdIfDefined(candidate_pair.remote_candidate_id, &neighbor_ids);
89 } else if (type == RTCLocalIceCandidateStats::kType ||
90 type == RTCRemoteIceCandidateStats::kType) {
91 const auto& local_or_remote_candidate =
92 static_cast<const RTCIceCandidateStats&>(stats);
93 AddIdIfDefined(local_or_remote_candidate.transport_id, &neighbor_ids);
Henrik Boström15166b22022-10-19 11:06:58 +020094 } else if (type == DEPRECATED_RTCMediaStreamStats::kType) {
95 const auto& stream =
96 static_cast<const DEPRECATED_RTCMediaStreamStats&>(stats);
Henrik Boströmb6199362018-03-12 10:27:55 +010097 AddIdsIfDefined(stream.track_ids, &neighbor_ids);
Henrik Boström15166b22022-10-19 11:06:58 +020098 } else if (type == DEPRECATED_RTCMediaStreamTrackStats::kType) {
99 const auto& track =
100 static_cast<const DEPRECATED_RTCMediaStreamTrackStats&>(stats);
Henrik Boström646fda02019-05-22 15:49:42 +0200101 AddIdIfDefined(track.media_source_id, &neighbor_ids);
Henrik Boströmb6199362018-03-12 10:27:55 +0100102 } else if (type == RTCPeerConnectionStats::kType) {
103 // RTCPeerConnectionStats does not have any neighbor references.
Alessio Bazzicaf7b1b952021-03-23 17:23:04 +0100104 } else if (type == RTCInboundRTPStreamStats::kType) {
105 const auto& inbound_rtp =
106 static_cast<const RTCInboundRTPStreamStats&>(stats);
107 AddIdIfDefined(inbound_rtp.remote_id, &neighbor_ids);
108 AddIdIfDefined(inbound_rtp.track_id, &neighbor_ids);
109 AddIdIfDefined(inbound_rtp.transport_id, &neighbor_ids);
110 AddIdIfDefined(inbound_rtp.codec_id, &neighbor_ids);
Fredrik Hernqvist828de802023-01-19 15:04:54 +0100111 AddIdIfDefined(inbound_rtp.playout_id, &neighbor_ids);
Alessio Bazzicaf7b1b952021-03-23 17:23:04 +0100112 } else if (type == RTCOutboundRTPStreamStats::kType) {
113 const auto& outbound_rtp =
114 static_cast<const RTCOutboundRTPStreamStats&>(stats);
115 AddIdIfDefined(outbound_rtp.remote_id, &neighbor_ids);
116 AddIdIfDefined(outbound_rtp.track_id, &neighbor_ids);
117 AddIdIfDefined(outbound_rtp.transport_id, &neighbor_ids);
118 AddIdIfDefined(outbound_rtp.codec_id, &neighbor_ids);
119 AddIdIfDefined(outbound_rtp.media_source_id, &neighbor_ids);
Henrik Boström883eefc2019-05-27 13:40:25 +0200120 } else if (type == RTCRemoteInboundRtpStreamStats::kType) {
121 const auto& remote_inbound_rtp =
122 static_cast<const RTCRemoteInboundRtpStreamStats&>(stats);
123 AddIdIfDefined(remote_inbound_rtp.transport_id, &neighbor_ids);
124 AddIdIfDefined(remote_inbound_rtp.codec_id, &neighbor_ids);
125 AddIdIfDefined(remote_inbound_rtp.local_id, &neighbor_ids);
Alessio Bazzicaf7b1b952021-03-23 17:23:04 +0100126 } else if (type == RTCRemoteOutboundRtpStreamStats::kType) {
127 const auto& remote_outbound_rtp =
128 static_cast<const RTCRemoteOutboundRtpStreamStats&>(stats);
129 // Inherited from `RTCRTPStreamStats`.
130 AddIdIfDefined(remote_outbound_rtp.track_id, &neighbor_ids);
131 AddIdIfDefined(remote_outbound_rtp.transport_id, &neighbor_ids);
132 AddIdIfDefined(remote_outbound_rtp.codec_id, &neighbor_ids);
133 // Direct members of `RTCRemoteOutboundRtpStreamStats`.
134 AddIdIfDefined(remote_outbound_rtp.local_id, &neighbor_ids);
Henrik Boström646fda02019-05-22 15:49:42 +0200135 } else if (type == RTCAudioSourceStats::kType ||
136 type == RTCVideoSourceStats::kType) {
137 // RTC[Audio/Video]SourceStats does not have any neighbor references.
Henrik Boströmb6199362018-03-12 10:27:55 +0100138 } else if (type == RTCTransportStats::kType) {
Henrik Boströmb6199362018-03-12 10:27:55 +0100139 const auto& transport = static_cast<const RTCTransportStats&>(stats);
140 AddIdIfDefined(transport.rtcp_transport_stats_id, &neighbor_ids);
141 AddIdIfDefined(transport.selected_candidate_pair_id, &neighbor_ids);
142 AddIdIfDefined(transport.local_certificate_id, &neighbor_ids);
143 AddIdIfDefined(transport.remote_certificate_id, &neighbor_ids);
Fredrik Hernqvist828de802023-01-19 15:04:54 +0100144 } else if (type == RTCAudioPlayoutStats::kType) {
145 // RTCAudioPlayoutStats does not have any neighbor references.
Henrik Boströmb6199362018-03-12 10:27:55 +0100146 } else {
Artem Titovd3251962021-11-15 16:57:07 +0100147 RTC_DCHECK_NOTREACHED() << "Unrecognized type: " << type;
Henrik Boströmb6199362018-03-12 10:27:55 +0100148 }
149 return neighbor_ids;
150}
151
152} // namespace webrtc