xref: /aosp_15_r20/external/webrtc/pc/rtc_stats_traversal.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
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 
11 #include "pc/rtc_stats_traversal.h"
12 
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 
21 namespace webrtc {
22 
23 namespace {
24 
TraverseAndTakeVisitedStats(RTCStatsReport * report,RTCStatsReport * visited_report,const std::string & current_id)25 void TraverseAndTakeVisitedStats(RTCStatsReport* report,
26                                  RTCStatsReport* visited_report,
27                                  const std::string& current_id) {
28   // Mark current stats object as visited by moving it `report` to
29   // `visited_report`.
30   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 
AddIdIfDefined(const RTCStatsMember<std::string> & id,std::vector<const std::string * > * neighbor_ids)45 void 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 
AddIdsIfDefined(const RTCStatsMember<std::vector<std::string>> & ids,std::vector<const std::string * > * neighbor_ids)51 void 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 
TakeReferencedStats(rtc::scoped_refptr<RTCStatsReport> report,const std::vector<std::string> & ids)61 rtc::scoped_refptr<RTCStatsReport> TakeReferencedStats(
62     rtc::scoped_refptr<RTCStatsReport> report,
63     const std::vector<std::string>& ids) {
64   rtc::scoped_refptr<RTCStatsReport> result =
65       RTCStatsReport::Create(report->timestamp());
66   for (const auto& id : ids) {
67     TraverseAndTakeVisitedStats(report.get(), result.get(), id);
68   }
69   return result;
70 }
71 
GetStatsReferencedIds(const RTCStats & stats)72 std::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) {
79     const auto& codec = static_cast<const RTCCodecStats&>(stats);
80     AddIdIfDefined(codec.transport_id, &neighbor_ids);
81   } 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);
94   } else if (type == DEPRECATED_RTCMediaStreamStats::kType) {
95     const auto& stream =
96         static_cast<const DEPRECATED_RTCMediaStreamStats&>(stats);
97     AddIdsIfDefined(stream.track_ids, &neighbor_ids);
98   } else if (type == DEPRECATED_RTCMediaStreamTrackStats::kType) {
99     const auto& track =
100         static_cast<const DEPRECATED_RTCMediaStreamTrackStats&>(stats);
101     AddIdIfDefined(track.media_source_id, &neighbor_ids);
102   } else if (type == RTCPeerConnectionStats::kType) {
103     // RTCPeerConnectionStats does not have any neighbor references.
104   } 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);
111   } else if (type == RTCOutboundRTPStreamStats::kType) {
112     const auto& outbound_rtp =
113         static_cast<const RTCOutboundRTPStreamStats&>(stats);
114     AddIdIfDefined(outbound_rtp.remote_id, &neighbor_ids);
115     AddIdIfDefined(outbound_rtp.track_id, &neighbor_ids);
116     AddIdIfDefined(outbound_rtp.transport_id, &neighbor_ids);
117     AddIdIfDefined(outbound_rtp.codec_id, &neighbor_ids);
118     AddIdIfDefined(outbound_rtp.media_source_id, &neighbor_ids);
119   } else if (type == RTCRemoteInboundRtpStreamStats::kType) {
120     const auto& remote_inbound_rtp =
121         static_cast<const RTCRemoteInboundRtpStreamStats&>(stats);
122     AddIdIfDefined(remote_inbound_rtp.transport_id, &neighbor_ids);
123     AddIdIfDefined(remote_inbound_rtp.codec_id, &neighbor_ids);
124     AddIdIfDefined(remote_inbound_rtp.local_id, &neighbor_ids);
125   } else if (type == RTCRemoteOutboundRtpStreamStats::kType) {
126     const auto& remote_outbound_rtp =
127         static_cast<const RTCRemoteOutboundRtpStreamStats&>(stats);
128     // Inherited from `RTCRTPStreamStats`.
129     AddIdIfDefined(remote_outbound_rtp.track_id, &neighbor_ids);
130     AddIdIfDefined(remote_outbound_rtp.transport_id, &neighbor_ids);
131     AddIdIfDefined(remote_outbound_rtp.codec_id, &neighbor_ids);
132     // Direct members of `RTCRemoteOutboundRtpStreamStats`.
133     AddIdIfDefined(remote_outbound_rtp.local_id, &neighbor_ids);
134   } else if (type == RTCAudioSourceStats::kType ||
135              type == RTCVideoSourceStats::kType) {
136     // RTC[Audio/Video]SourceStats does not have any neighbor references.
137   } else if (type == RTCTransportStats::kType) {
138     // RTCTransportStats does not have any neighbor references.
139     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);
144   } else {
145     RTC_DCHECK_NOTREACHED() << "Unrecognized type: " << type;
146   }
147   return neighbor_ids;
148 }
149 
150 }  // namespace webrtc
151