xref: /aosp_15_r20/external/webrtc/pc/rtc_stats_traversal.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright 2018 The WebRTC Project Authors. All rights reserved.
3*d9f75844SAndroid Build Coastguard Worker  *
4*d9f75844SAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker  */
10*d9f75844SAndroid Build Coastguard Worker 
11*d9f75844SAndroid Build Coastguard Worker #include "pc/rtc_stats_traversal.h"
12*d9f75844SAndroid Build Coastguard Worker 
13*d9f75844SAndroid Build Coastguard Worker #include <memory>
14*d9f75844SAndroid Build Coastguard Worker #include <string>
15*d9f75844SAndroid Build Coastguard Worker #include <utility>
16*d9f75844SAndroid Build Coastguard Worker #include <vector>
17*d9f75844SAndroid Build Coastguard Worker 
18*d9f75844SAndroid Build Coastguard Worker #include "api/stats/rtcstats_objects.h"
19*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
20*d9f75844SAndroid Build Coastguard Worker 
21*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
22*d9f75844SAndroid Build Coastguard Worker 
23*d9f75844SAndroid Build Coastguard Worker namespace {
24*d9f75844SAndroid Build Coastguard Worker 
TraverseAndTakeVisitedStats(RTCStatsReport * report,RTCStatsReport * visited_report,const std::string & current_id)25*d9f75844SAndroid Build Coastguard Worker void TraverseAndTakeVisitedStats(RTCStatsReport* report,
26*d9f75844SAndroid Build Coastguard Worker                                  RTCStatsReport* visited_report,
27*d9f75844SAndroid Build Coastguard Worker                                  const std::string& current_id) {
28*d9f75844SAndroid Build Coastguard Worker   // Mark current stats object as visited by moving it `report` to
29*d9f75844SAndroid Build Coastguard Worker   // `visited_report`.
30*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<const RTCStats> current = report->Take(current_id);
31*d9f75844SAndroid Build Coastguard Worker   if (!current) {
32*d9f75844SAndroid Build Coastguard Worker     // This node has already been visited (or it is an invalid id).
33*d9f75844SAndroid Build Coastguard Worker     return;
34*d9f75844SAndroid Build Coastguard Worker   }
35*d9f75844SAndroid Build Coastguard Worker   std::vector<const std::string*> neighbor_ids =
36*d9f75844SAndroid Build Coastguard Worker       GetStatsReferencedIds(*current);
37*d9f75844SAndroid Build Coastguard Worker   visited_report->AddStats(std::move(current));
38*d9f75844SAndroid Build Coastguard Worker 
39*d9f75844SAndroid Build Coastguard Worker   // Recursively traverse all neighbors.
40*d9f75844SAndroid Build Coastguard Worker   for (const auto* neighbor_id : neighbor_ids) {
41*d9f75844SAndroid Build Coastguard Worker     TraverseAndTakeVisitedStats(report, visited_report, *neighbor_id);
42*d9f75844SAndroid Build Coastguard Worker   }
43*d9f75844SAndroid Build Coastguard Worker }
44*d9f75844SAndroid Build Coastguard Worker 
AddIdIfDefined(const RTCStatsMember<std::string> & id,std::vector<const std::string * > * neighbor_ids)45*d9f75844SAndroid Build Coastguard Worker void AddIdIfDefined(const RTCStatsMember<std::string>& id,
46*d9f75844SAndroid Build Coastguard Worker                     std::vector<const std::string*>* neighbor_ids) {
47*d9f75844SAndroid Build Coastguard Worker   if (id.is_defined())
48*d9f75844SAndroid Build Coastguard Worker     neighbor_ids->push_back(&(*id));
49*d9f75844SAndroid Build Coastguard Worker }
50*d9f75844SAndroid Build Coastguard Worker 
AddIdsIfDefined(const RTCStatsMember<std::vector<std::string>> & ids,std::vector<const std::string * > * neighbor_ids)51*d9f75844SAndroid Build Coastguard Worker void AddIdsIfDefined(const RTCStatsMember<std::vector<std::string>>& ids,
52*d9f75844SAndroid Build Coastguard Worker                      std::vector<const std::string*>* neighbor_ids) {
53*d9f75844SAndroid Build Coastguard Worker   if (ids.is_defined()) {
54*d9f75844SAndroid Build Coastguard Worker     for (const std::string& id : *ids)
55*d9f75844SAndroid Build Coastguard Worker       neighbor_ids->push_back(&id);
56*d9f75844SAndroid Build Coastguard Worker   }
57*d9f75844SAndroid Build Coastguard Worker }
58*d9f75844SAndroid Build Coastguard Worker 
59*d9f75844SAndroid Build Coastguard Worker }  // namespace
60*d9f75844SAndroid Build Coastguard Worker 
TakeReferencedStats(rtc::scoped_refptr<RTCStatsReport> report,const std::vector<std::string> & ids)61*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<RTCStatsReport> TakeReferencedStats(
62*d9f75844SAndroid Build Coastguard Worker     rtc::scoped_refptr<RTCStatsReport> report,
63*d9f75844SAndroid Build Coastguard Worker     const std::vector<std::string>& ids) {
64*d9f75844SAndroid Build Coastguard Worker   rtc::scoped_refptr<RTCStatsReport> result =
65*d9f75844SAndroid Build Coastguard Worker       RTCStatsReport::Create(report->timestamp());
66*d9f75844SAndroid Build Coastguard Worker   for (const auto& id : ids) {
67*d9f75844SAndroid Build Coastguard Worker     TraverseAndTakeVisitedStats(report.get(), result.get(), id);
68*d9f75844SAndroid Build Coastguard Worker   }
69*d9f75844SAndroid Build Coastguard Worker   return result;
70*d9f75844SAndroid Build Coastguard Worker }
71*d9f75844SAndroid Build Coastguard Worker 
GetStatsReferencedIds(const RTCStats & stats)72*d9f75844SAndroid Build Coastguard Worker std::vector<const std::string*> GetStatsReferencedIds(const RTCStats& stats) {
73*d9f75844SAndroid Build Coastguard Worker   std::vector<const std::string*> neighbor_ids;
74*d9f75844SAndroid Build Coastguard Worker   const char* type = stats.type();
75*d9f75844SAndroid Build Coastguard Worker   if (type == RTCCertificateStats::kType) {
76*d9f75844SAndroid Build Coastguard Worker     const auto& certificate = static_cast<const RTCCertificateStats&>(stats);
77*d9f75844SAndroid Build Coastguard Worker     AddIdIfDefined(certificate.issuer_certificate_id, &neighbor_ids);
78*d9f75844SAndroid Build Coastguard Worker   } else if (type == RTCCodecStats::kType) {
79*d9f75844SAndroid Build Coastguard Worker     const auto& codec = static_cast<const RTCCodecStats&>(stats);
80*d9f75844SAndroid Build Coastguard Worker     AddIdIfDefined(codec.transport_id, &neighbor_ids);
81*d9f75844SAndroid Build Coastguard Worker   } else if (type == RTCDataChannelStats::kType) {
82*d9f75844SAndroid Build Coastguard Worker     // RTCDataChannelStats does not have any neighbor references.
83*d9f75844SAndroid Build Coastguard Worker   } else if (type == RTCIceCandidatePairStats::kType) {
84*d9f75844SAndroid Build Coastguard Worker     const auto& candidate_pair =
85*d9f75844SAndroid Build Coastguard Worker         static_cast<const RTCIceCandidatePairStats&>(stats);
86*d9f75844SAndroid Build Coastguard Worker     AddIdIfDefined(candidate_pair.transport_id, &neighbor_ids);
87*d9f75844SAndroid Build Coastguard Worker     AddIdIfDefined(candidate_pair.local_candidate_id, &neighbor_ids);
88*d9f75844SAndroid Build Coastguard Worker     AddIdIfDefined(candidate_pair.remote_candidate_id, &neighbor_ids);
89*d9f75844SAndroid Build Coastguard Worker   } else if (type == RTCLocalIceCandidateStats::kType ||
90*d9f75844SAndroid Build Coastguard Worker              type == RTCRemoteIceCandidateStats::kType) {
91*d9f75844SAndroid Build Coastguard Worker     const auto& local_or_remote_candidate =
92*d9f75844SAndroid Build Coastguard Worker         static_cast<const RTCIceCandidateStats&>(stats);
93*d9f75844SAndroid Build Coastguard Worker     AddIdIfDefined(local_or_remote_candidate.transport_id, &neighbor_ids);
94*d9f75844SAndroid Build Coastguard Worker   } else if (type == DEPRECATED_RTCMediaStreamStats::kType) {
95*d9f75844SAndroid Build Coastguard Worker     const auto& stream =
96*d9f75844SAndroid Build Coastguard Worker         static_cast<const DEPRECATED_RTCMediaStreamStats&>(stats);
97*d9f75844SAndroid Build Coastguard Worker     AddIdsIfDefined(stream.track_ids, &neighbor_ids);
98*d9f75844SAndroid Build Coastguard Worker   } else if (type == DEPRECATED_RTCMediaStreamTrackStats::kType) {
99*d9f75844SAndroid Build Coastguard Worker     const auto& track =
100*d9f75844SAndroid Build Coastguard Worker         static_cast<const DEPRECATED_RTCMediaStreamTrackStats&>(stats);
101*d9f75844SAndroid Build Coastguard Worker     AddIdIfDefined(track.media_source_id, &neighbor_ids);
102*d9f75844SAndroid Build Coastguard Worker   } else if (type == RTCPeerConnectionStats::kType) {
103*d9f75844SAndroid Build Coastguard Worker     // RTCPeerConnectionStats does not have any neighbor references.
104*d9f75844SAndroid Build Coastguard Worker   } else if (type == RTCInboundRTPStreamStats::kType) {
105*d9f75844SAndroid Build Coastguard Worker     const auto& inbound_rtp =
106*d9f75844SAndroid Build Coastguard Worker         static_cast<const RTCInboundRTPStreamStats&>(stats);
107*d9f75844SAndroid Build Coastguard Worker     AddIdIfDefined(inbound_rtp.remote_id, &neighbor_ids);
108*d9f75844SAndroid Build Coastguard Worker     AddIdIfDefined(inbound_rtp.track_id, &neighbor_ids);
109*d9f75844SAndroid Build Coastguard Worker     AddIdIfDefined(inbound_rtp.transport_id, &neighbor_ids);
110*d9f75844SAndroid Build Coastguard Worker     AddIdIfDefined(inbound_rtp.codec_id, &neighbor_ids);
111*d9f75844SAndroid Build Coastguard Worker   } else if (type == RTCOutboundRTPStreamStats::kType) {
112*d9f75844SAndroid Build Coastguard Worker     const auto& outbound_rtp =
113*d9f75844SAndroid Build Coastguard Worker         static_cast<const RTCOutboundRTPStreamStats&>(stats);
114*d9f75844SAndroid Build Coastguard Worker     AddIdIfDefined(outbound_rtp.remote_id, &neighbor_ids);
115*d9f75844SAndroid Build Coastguard Worker     AddIdIfDefined(outbound_rtp.track_id, &neighbor_ids);
116*d9f75844SAndroid Build Coastguard Worker     AddIdIfDefined(outbound_rtp.transport_id, &neighbor_ids);
117*d9f75844SAndroid Build Coastguard Worker     AddIdIfDefined(outbound_rtp.codec_id, &neighbor_ids);
118*d9f75844SAndroid Build Coastguard Worker     AddIdIfDefined(outbound_rtp.media_source_id, &neighbor_ids);
119*d9f75844SAndroid Build Coastguard Worker   } else if (type == RTCRemoteInboundRtpStreamStats::kType) {
120*d9f75844SAndroid Build Coastguard Worker     const auto& remote_inbound_rtp =
121*d9f75844SAndroid Build Coastguard Worker         static_cast<const RTCRemoteInboundRtpStreamStats&>(stats);
122*d9f75844SAndroid Build Coastguard Worker     AddIdIfDefined(remote_inbound_rtp.transport_id, &neighbor_ids);
123*d9f75844SAndroid Build Coastguard Worker     AddIdIfDefined(remote_inbound_rtp.codec_id, &neighbor_ids);
124*d9f75844SAndroid Build Coastguard Worker     AddIdIfDefined(remote_inbound_rtp.local_id, &neighbor_ids);
125*d9f75844SAndroid Build Coastguard Worker   } else if (type == RTCRemoteOutboundRtpStreamStats::kType) {
126*d9f75844SAndroid Build Coastguard Worker     const auto& remote_outbound_rtp =
127*d9f75844SAndroid Build Coastguard Worker         static_cast<const RTCRemoteOutboundRtpStreamStats&>(stats);
128*d9f75844SAndroid Build Coastguard Worker     // Inherited from `RTCRTPStreamStats`.
129*d9f75844SAndroid Build Coastguard Worker     AddIdIfDefined(remote_outbound_rtp.track_id, &neighbor_ids);
130*d9f75844SAndroid Build Coastguard Worker     AddIdIfDefined(remote_outbound_rtp.transport_id, &neighbor_ids);
131*d9f75844SAndroid Build Coastguard Worker     AddIdIfDefined(remote_outbound_rtp.codec_id, &neighbor_ids);
132*d9f75844SAndroid Build Coastguard Worker     // Direct members of `RTCRemoteOutboundRtpStreamStats`.
133*d9f75844SAndroid Build Coastguard Worker     AddIdIfDefined(remote_outbound_rtp.local_id, &neighbor_ids);
134*d9f75844SAndroid Build Coastguard Worker   } else if (type == RTCAudioSourceStats::kType ||
135*d9f75844SAndroid Build Coastguard Worker              type == RTCVideoSourceStats::kType) {
136*d9f75844SAndroid Build Coastguard Worker     // RTC[Audio/Video]SourceStats does not have any neighbor references.
137*d9f75844SAndroid Build Coastguard Worker   } else if (type == RTCTransportStats::kType) {
138*d9f75844SAndroid Build Coastguard Worker     // RTCTransportStats does not have any neighbor references.
139*d9f75844SAndroid Build Coastguard Worker     const auto& transport = static_cast<const RTCTransportStats&>(stats);
140*d9f75844SAndroid Build Coastguard Worker     AddIdIfDefined(transport.rtcp_transport_stats_id, &neighbor_ids);
141*d9f75844SAndroid Build Coastguard Worker     AddIdIfDefined(transport.selected_candidate_pair_id, &neighbor_ids);
142*d9f75844SAndroid Build Coastguard Worker     AddIdIfDefined(transport.local_certificate_id, &neighbor_ids);
143*d9f75844SAndroid Build Coastguard Worker     AddIdIfDefined(transport.remote_certificate_id, &neighbor_ids);
144*d9f75844SAndroid Build Coastguard Worker   } else {
145*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK_NOTREACHED() << "Unrecognized type: " << type;
146*d9f75844SAndroid Build Coastguard Worker   }
147*d9f75844SAndroid Build Coastguard Worker   return neighbor_ids;
148*d9f75844SAndroid Build Coastguard Worker }
149*d9f75844SAndroid Build Coastguard Worker 
150*d9f75844SAndroid Build Coastguard Worker }  // namespace webrtc
151