xref: /aosp_15_r20/external/webrtc/pc/legacy_stats_collector.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright 2012 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/legacy_stats_collector.h"
12*d9f75844SAndroid Build Coastguard Worker 
13*d9f75844SAndroid Build Coastguard Worker #include <stddef.h>
14*d9f75844SAndroid Build Coastguard Worker #include <stdint.h>
15*d9f75844SAndroid Build Coastguard Worker 
16*d9f75844SAndroid Build Coastguard Worker #include <algorithm>
17*d9f75844SAndroid Build Coastguard Worker #include <cmath>
18*d9f75844SAndroid Build Coastguard Worker #include <list>
19*d9f75844SAndroid Build Coastguard Worker #include <set>
20*d9f75844SAndroid Build Coastguard Worker #include <utility>
21*d9f75844SAndroid Build Coastguard Worker #include <vector>
22*d9f75844SAndroid Build Coastguard Worker 
23*d9f75844SAndroid Build Coastguard Worker #include "absl/strings/string_view.h"
24*d9f75844SAndroid Build Coastguard Worker #include "absl/types/optional.h"
25*d9f75844SAndroid Build Coastguard Worker #include "api/audio_codecs/audio_encoder.h"
26*d9f75844SAndroid Build Coastguard Worker #include "api/candidate.h"
27*d9f75844SAndroid Build Coastguard Worker #include "api/data_channel_interface.h"
28*d9f75844SAndroid Build Coastguard Worker #include "api/field_trials_view.h"
29*d9f75844SAndroid Build Coastguard Worker #include "api/media_types.h"
30*d9f75844SAndroid Build Coastguard Worker #include "api/rtp_sender_interface.h"
31*d9f75844SAndroid Build Coastguard Worker #include "api/scoped_refptr.h"
32*d9f75844SAndroid Build Coastguard Worker #include "api/sequence_checker.h"
33*d9f75844SAndroid Build Coastguard Worker #include "api/video/video_content_type.h"
34*d9f75844SAndroid Build Coastguard Worker #include "api/video/video_timing.h"
35*d9f75844SAndroid Build Coastguard Worker #include "call/call.h"
36*d9f75844SAndroid Build Coastguard Worker #include "media/base/media_channel.h"
37*d9f75844SAndroid Build Coastguard Worker #include "modules/audio_processing/include/audio_processing_statistics.h"
38*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/ice_transport_internal.h"
39*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/p2p_constants.h"
40*d9f75844SAndroid Build Coastguard Worker #include "pc/channel_interface.h"
41*d9f75844SAndroid Build Coastguard Worker #include "pc/data_channel_utils.h"
42*d9f75844SAndroid Build Coastguard Worker #include "pc/rtp_receiver.h"
43*d9f75844SAndroid Build Coastguard Worker #include "pc/rtp_receiver_proxy.h"
44*d9f75844SAndroid Build Coastguard Worker #include "pc/rtp_sender_proxy.h"
45*d9f75844SAndroid Build Coastguard Worker #include "pc/rtp_transceiver.h"
46*d9f75844SAndroid Build Coastguard Worker #include "pc/transport_stats.h"
47*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
48*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/ip_address.h"
49*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/logging.h"
50*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/rtc_certificate.h"
51*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/socket_address.h"
52*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/ssl_stream_adapter.h"
53*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/string_encode.h"
54*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/thread.h"
55*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/time_utils.h"
56*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/trace_event.h"
57*d9f75844SAndroid Build Coastguard Worker 
58*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
59*d9f75844SAndroid Build Coastguard Worker namespace {
60*d9f75844SAndroid Build Coastguard Worker 
61*d9f75844SAndroid Build Coastguard Worker // Field trial which controls whether to report standard-compliant bytes
62*d9f75844SAndroid Build Coastguard Worker // sent/received per stream.  If enabled, padding and headers are not included
63*d9f75844SAndroid Build Coastguard Worker // in bytes sent or received.
64*d9f75844SAndroid Build Coastguard Worker constexpr char kUseStandardBytesStats[] = "WebRTC-UseStandardBytesStats";
65*d9f75844SAndroid Build Coastguard Worker 
66*d9f75844SAndroid Build Coastguard Worker // The following is the enum RTCStatsIceCandidateType from
67*d9f75844SAndroid Build Coastguard Worker // http://w3c.github.io/webrtc-stats/#rtcstatsicecandidatetype-enum such that
68*d9f75844SAndroid Build Coastguard Worker // our stats report for ice candidate type could conform to that.
69*d9f75844SAndroid Build Coastguard Worker const char STATSREPORT_LOCAL_PORT_TYPE[] = "host";
70*d9f75844SAndroid Build Coastguard Worker const char STATSREPORT_STUN_PORT_TYPE[] = "serverreflexive";
71*d9f75844SAndroid Build Coastguard Worker const char STATSREPORT_PRFLX_PORT_TYPE[] = "peerreflexive";
72*d9f75844SAndroid Build Coastguard Worker const char STATSREPORT_RELAY_PORT_TYPE[] = "relayed";
73*d9f75844SAndroid Build Coastguard Worker 
74*d9f75844SAndroid Build Coastguard Worker // Strings used by the stats collector to report adapter types. This fits the
75*d9f75844SAndroid Build Coastguard Worker // general stype of http://w3c.github.io/webrtc-stats than what
76*d9f75844SAndroid Build Coastguard Worker // AdapterTypeToString does.
77*d9f75844SAndroid Build Coastguard Worker const char* STATSREPORT_ADAPTER_TYPE_ETHERNET = "lan";
78*d9f75844SAndroid Build Coastguard Worker const char* STATSREPORT_ADAPTER_TYPE_WIFI = "wlan";
79*d9f75844SAndroid Build Coastguard Worker const char* STATSREPORT_ADAPTER_TYPE_WWAN = "wwan";
80*d9f75844SAndroid Build Coastguard Worker const char* STATSREPORT_ADAPTER_TYPE_VPN = "vpn";
81*d9f75844SAndroid Build Coastguard Worker const char* STATSREPORT_ADAPTER_TYPE_LOOPBACK = "loopback";
82*d9f75844SAndroid Build Coastguard Worker const char* STATSREPORT_ADAPTER_TYPE_WILDCARD = "wildcard";
83*d9f75844SAndroid Build Coastguard Worker 
84*d9f75844SAndroid Build Coastguard Worker template <typename ValueType>
85*d9f75844SAndroid Build Coastguard Worker struct TypeForAdd {
86*d9f75844SAndroid Build Coastguard Worker   const StatsReport::StatsValueName name;
87*d9f75844SAndroid Build Coastguard Worker   const ValueType& value;
88*d9f75844SAndroid Build Coastguard Worker };
89*d9f75844SAndroid Build Coastguard Worker 
90*d9f75844SAndroid Build Coastguard Worker typedef TypeForAdd<bool> BoolForAdd;
91*d9f75844SAndroid Build Coastguard Worker typedef TypeForAdd<float> FloatForAdd;
92*d9f75844SAndroid Build Coastguard Worker typedef TypeForAdd<int64_t> Int64ForAdd;
93*d9f75844SAndroid Build Coastguard Worker typedef TypeForAdd<int> IntForAdd;
94*d9f75844SAndroid Build Coastguard Worker 
AddTrackReport(StatsCollection * reports,const std::string & track_id)95*d9f75844SAndroid Build Coastguard Worker StatsReport* AddTrackReport(StatsCollection* reports,
96*d9f75844SAndroid Build Coastguard Worker                             const std::string& track_id) {
97*d9f75844SAndroid Build Coastguard Worker   // Adds an empty track report.
98*d9f75844SAndroid Build Coastguard Worker   StatsReport::Id id(
99*d9f75844SAndroid Build Coastguard Worker       StatsReport::NewTypedId(StatsReport::kStatsReportTypeTrack, track_id));
100*d9f75844SAndroid Build Coastguard Worker   StatsReport* report = reports->ReplaceOrAddNew(id);
101*d9f75844SAndroid Build Coastguard Worker   report->AddString(StatsReport::kStatsValueNameTrackId, track_id);
102*d9f75844SAndroid Build Coastguard Worker   return report;
103*d9f75844SAndroid Build Coastguard Worker }
104*d9f75844SAndroid Build Coastguard Worker 
105*d9f75844SAndroid Build Coastguard Worker template <class Track>
CreateTrackReport(const Track * track,StatsCollection * reports,TrackIdMap * track_ids)106*d9f75844SAndroid Build Coastguard Worker void CreateTrackReport(const Track* track,
107*d9f75844SAndroid Build Coastguard Worker                        StatsCollection* reports,
108*d9f75844SAndroid Build Coastguard Worker                        TrackIdMap* track_ids) {
109*d9f75844SAndroid Build Coastguard Worker   const std::string& track_id = track->id();
110*d9f75844SAndroid Build Coastguard Worker   StatsReport* report = AddTrackReport(reports, track_id);
111*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(report != nullptr);
112*d9f75844SAndroid Build Coastguard Worker   (*track_ids)[track_id] = report;
113*d9f75844SAndroid Build Coastguard Worker }
114*d9f75844SAndroid Build Coastguard Worker 
115*d9f75844SAndroid Build Coastguard Worker template <class TrackVector>
CreateTrackReports(const TrackVector & tracks,StatsCollection * reports,TrackIdMap * track_ids)116*d9f75844SAndroid Build Coastguard Worker void CreateTrackReports(const TrackVector& tracks,
117*d9f75844SAndroid Build Coastguard Worker                         StatsCollection* reports,
118*d9f75844SAndroid Build Coastguard Worker                         TrackIdMap* track_ids) {
119*d9f75844SAndroid Build Coastguard Worker   for (const auto& track : tracks) {
120*d9f75844SAndroid Build Coastguard Worker     CreateTrackReport(track.get(), reports, track_ids);
121*d9f75844SAndroid Build Coastguard Worker   }
122*d9f75844SAndroid Build Coastguard Worker }
123*d9f75844SAndroid Build Coastguard Worker 
ExtractCommonSendProperties(const cricket::MediaSenderInfo & info,StatsReport * report,bool use_standard_bytes_stats)124*d9f75844SAndroid Build Coastguard Worker void ExtractCommonSendProperties(const cricket::MediaSenderInfo& info,
125*d9f75844SAndroid Build Coastguard Worker                                  StatsReport* report,
126*d9f75844SAndroid Build Coastguard Worker                                  bool use_standard_bytes_stats) {
127*d9f75844SAndroid Build Coastguard Worker   report->AddString(StatsReport::kStatsValueNameCodecName, info.codec_name);
128*d9f75844SAndroid Build Coastguard Worker   int64_t bytes_sent = info.payload_bytes_sent;
129*d9f75844SAndroid Build Coastguard Worker   if (!use_standard_bytes_stats) {
130*d9f75844SAndroid Build Coastguard Worker     bytes_sent += info.header_and_padding_bytes_sent;
131*d9f75844SAndroid Build Coastguard Worker   }
132*d9f75844SAndroid Build Coastguard Worker   report->AddInt64(StatsReport::kStatsValueNameBytesSent, bytes_sent);
133*d9f75844SAndroid Build Coastguard Worker   if (info.rtt_ms >= 0) {
134*d9f75844SAndroid Build Coastguard Worker     report->AddInt64(StatsReport::kStatsValueNameRtt, info.rtt_ms);
135*d9f75844SAndroid Build Coastguard Worker   }
136*d9f75844SAndroid Build Coastguard Worker }
137*d9f75844SAndroid Build Coastguard Worker 
ExtractCommonReceiveProperties(const cricket::MediaReceiverInfo & info,StatsReport * report)138*d9f75844SAndroid Build Coastguard Worker void ExtractCommonReceiveProperties(const cricket::MediaReceiverInfo& info,
139*d9f75844SAndroid Build Coastguard Worker                                     StatsReport* report) {
140*d9f75844SAndroid Build Coastguard Worker   report->AddString(StatsReport::kStatsValueNameCodecName, info.codec_name);
141*d9f75844SAndroid Build Coastguard Worker }
142*d9f75844SAndroid Build Coastguard Worker 
SetAudioProcessingStats(StatsReport * report,const AudioProcessingStats & apm_stats)143*d9f75844SAndroid Build Coastguard Worker void SetAudioProcessingStats(StatsReport* report,
144*d9f75844SAndroid Build Coastguard Worker                              const AudioProcessingStats& apm_stats) {
145*d9f75844SAndroid Build Coastguard Worker   if (apm_stats.delay_median_ms) {
146*d9f75844SAndroid Build Coastguard Worker     report->AddInt(StatsReport::kStatsValueNameEchoDelayMedian,
147*d9f75844SAndroid Build Coastguard Worker                    *apm_stats.delay_median_ms);
148*d9f75844SAndroid Build Coastguard Worker   }
149*d9f75844SAndroid Build Coastguard Worker   if (apm_stats.delay_standard_deviation_ms) {
150*d9f75844SAndroid Build Coastguard Worker     report->AddInt(StatsReport::kStatsValueNameEchoDelayStdDev,
151*d9f75844SAndroid Build Coastguard Worker                    *apm_stats.delay_standard_deviation_ms);
152*d9f75844SAndroid Build Coastguard Worker   }
153*d9f75844SAndroid Build Coastguard Worker   if (apm_stats.echo_return_loss) {
154*d9f75844SAndroid Build Coastguard Worker     report->AddInt(StatsReport::kStatsValueNameEchoReturnLoss,
155*d9f75844SAndroid Build Coastguard Worker                    *apm_stats.echo_return_loss);
156*d9f75844SAndroid Build Coastguard Worker   }
157*d9f75844SAndroid Build Coastguard Worker   if (apm_stats.echo_return_loss_enhancement) {
158*d9f75844SAndroid Build Coastguard Worker     report->AddInt(StatsReport::kStatsValueNameEchoReturnLossEnhancement,
159*d9f75844SAndroid Build Coastguard Worker                    *apm_stats.echo_return_loss_enhancement);
160*d9f75844SAndroid Build Coastguard Worker   }
161*d9f75844SAndroid Build Coastguard Worker   if (apm_stats.residual_echo_likelihood) {
162*d9f75844SAndroid Build Coastguard Worker     report->AddFloat(StatsReport::kStatsValueNameResidualEchoLikelihood,
163*d9f75844SAndroid Build Coastguard Worker                      static_cast<float>(*apm_stats.residual_echo_likelihood));
164*d9f75844SAndroid Build Coastguard Worker   }
165*d9f75844SAndroid Build Coastguard Worker   if (apm_stats.residual_echo_likelihood_recent_max) {
166*d9f75844SAndroid Build Coastguard Worker     report->AddFloat(
167*d9f75844SAndroid Build Coastguard Worker         StatsReport::kStatsValueNameResidualEchoLikelihoodRecentMax,
168*d9f75844SAndroid Build Coastguard Worker         static_cast<float>(*apm_stats.residual_echo_likelihood_recent_max));
169*d9f75844SAndroid Build Coastguard Worker   }
170*d9f75844SAndroid Build Coastguard Worker   if (apm_stats.divergent_filter_fraction) {
171*d9f75844SAndroid Build Coastguard Worker     report->AddFloat(StatsReport::kStatsValueNameAecDivergentFilterFraction,
172*d9f75844SAndroid Build Coastguard Worker                      static_cast<float>(*apm_stats.divergent_filter_fraction));
173*d9f75844SAndroid Build Coastguard Worker   }
174*d9f75844SAndroid Build Coastguard Worker }
175*d9f75844SAndroid Build Coastguard Worker 
ExtractStats(const cricket::VoiceReceiverInfo & info,StatsReport * report,bool use_standard_bytes_stats)176*d9f75844SAndroid Build Coastguard Worker void ExtractStats(const cricket::VoiceReceiverInfo& info,
177*d9f75844SAndroid Build Coastguard Worker                   StatsReport* report,
178*d9f75844SAndroid Build Coastguard Worker                   bool use_standard_bytes_stats) {
179*d9f75844SAndroid Build Coastguard Worker   ExtractCommonReceiveProperties(info, report);
180*d9f75844SAndroid Build Coastguard Worker   const FloatForAdd floats[] = {
181*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameExpandRate, info.expand_rate},
182*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameSecondaryDecodedRate,
183*d9f75844SAndroid Build Coastguard Worker        info.secondary_decoded_rate},
184*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameSecondaryDiscardedRate,
185*d9f75844SAndroid Build Coastguard Worker        info.secondary_discarded_rate},
186*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameSpeechExpandRate, info.speech_expand_rate},
187*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameAccelerateRate, info.accelerate_rate},
188*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNamePreemptiveExpandRate,
189*d9f75844SAndroid Build Coastguard Worker        info.preemptive_expand_rate},
190*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameTotalAudioEnergy,
191*d9f75844SAndroid Build Coastguard Worker        static_cast<float>(info.total_output_energy)},
192*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameTotalSamplesDuration,
193*d9f75844SAndroid Build Coastguard Worker        static_cast<float>(info.total_output_duration)}};
194*d9f75844SAndroid Build Coastguard Worker 
195*d9f75844SAndroid Build Coastguard Worker   const IntForAdd ints[] = {
196*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameCurrentDelayMs, info.delay_estimate_ms},
197*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameDecodingCNG, info.decoding_cng},
198*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameDecodingCTN, info.decoding_calls_to_neteq},
199*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameDecodingCTSG,
200*d9f75844SAndroid Build Coastguard Worker        info.decoding_calls_to_silence_generator},
201*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameDecodingMutedOutput,
202*d9f75844SAndroid Build Coastguard Worker        info.decoding_muted_output},
203*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameDecodingNormal, info.decoding_normal},
204*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameDecodingPLC, info.decoding_plc},
205*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameDecodingPLCCNG, info.decoding_plc_cng},
206*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameJitterBufferMs, info.jitter_buffer_ms},
207*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameJitterReceived, info.jitter_ms},
208*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNamePacketsLost, info.packets_lost},
209*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNamePacketsReceived, info.packets_rcvd},
210*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNamePreferredJitterBufferMs,
211*d9f75844SAndroid Build Coastguard Worker        info.jitter_buffer_preferred_ms},
212*d9f75844SAndroid Build Coastguard Worker   };
213*d9f75844SAndroid Build Coastguard Worker 
214*d9f75844SAndroid Build Coastguard Worker   for (const auto& f : floats)
215*d9f75844SAndroid Build Coastguard Worker     report->AddFloat(f.name, f.value);
216*d9f75844SAndroid Build Coastguard Worker 
217*d9f75844SAndroid Build Coastguard Worker   for (const auto& i : ints)
218*d9f75844SAndroid Build Coastguard Worker     report->AddInt(i.name, i.value);
219*d9f75844SAndroid Build Coastguard Worker   if (info.audio_level >= 0) {
220*d9f75844SAndroid Build Coastguard Worker     report->AddInt(StatsReport::kStatsValueNameAudioOutputLevel,
221*d9f75844SAndroid Build Coastguard Worker                    info.audio_level);
222*d9f75844SAndroid Build Coastguard Worker   }
223*d9f75844SAndroid Build Coastguard Worker   if (info.decoding_codec_plc)
224*d9f75844SAndroid Build Coastguard Worker     report->AddInt(StatsReport::kStatsValueNameDecodingCodecPLC,
225*d9f75844SAndroid Build Coastguard Worker                    info.decoding_codec_plc);
226*d9f75844SAndroid Build Coastguard Worker 
227*d9f75844SAndroid Build Coastguard Worker   int64_t bytes_rcvd = info.payload_bytes_rcvd;
228*d9f75844SAndroid Build Coastguard Worker   if (!use_standard_bytes_stats) {
229*d9f75844SAndroid Build Coastguard Worker     bytes_rcvd += info.header_and_padding_bytes_rcvd;
230*d9f75844SAndroid Build Coastguard Worker   }
231*d9f75844SAndroid Build Coastguard Worker   report->AddInt64(StatsReport::kStatsValueNameBytesReceived, bytes_rcvd);
232*d9f75844SAndroid Build Coastguard Worker   if (info.capture_start_ntp_time_ms >= 0) {
233*d9f75844SAndroid Build Coastguard Worker     report->AddInt64(StatsReport::kStatsValueNameCaptureStartNtpTimeMs,
234*d9f75844SAndroid Build Coastguard Worker                      info.capture_start_ntp_time_ms);
235*d9f75844SAndroid Build Coastguard Worker   }
236*d9f75844SAndroid Build Coastguard Worker   report->AddString(StatsReport::kStatsValueNameMediaType, "audio");
237*d9f75844SAndroid Build Coastguard Worker }
238*d9f75844SAndroid Build Coastguard Worker 
ExtractStats(const cricket::VoiceSenderInfo & info,StatsReport * report,bool use_standard_bytes_stats)239*d9f75844SAndroid Build Coastguard Worker void ExtractStats(const cricket::VoiceSenderInfo& info,
240*d9f75844SAndroid Build Coastguard Worker                   StatsReport* report,
241*d9f75844SAndroid Build Coastguard Worker                   bool use_standard_bytes_stats) {
242*d9f75844SAndroid Build Coastguard Worker   ExtractCommonSendProperties(info, report, use_standard_bytes_stats);
243*d9f75844SAndroid Build Coastguard Worker 
244*d9f75844SAndroid Build Coastguard Worker   SetAudioProcessingStats(report, info.apm_statistics);
245*d9f75844SAndroid Build Coastguard Worker 
246*d9f75844SAndroid Build Coastguard Worker   const FloatForAdd floats[] = {
247*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameTotalAudioEnergy,
248*d9f75844SAndroid Build Coastguard Worker        static_cast<float>(info.total_input_energy)},
249*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameTotalSamplesDuration,
250*d9f75844SAndroid Build Coastguard Worker        static_cast<float>(info.total_input_duration)}};
251*d9f75844SAndroid Build Coastguard Worker 
252*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_GE(info.audio_level, 0);
253*d9f75844SAndroid Build Coastguard Worker   const IntForAdd ints[] = {
254*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameAudioInputLevel, info.audio_level},
255*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameJitterReceived, info.jitter_ms},
256*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNamePacketsLost, info.packets_lost},
257*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNamePacketsSent, info.packets_sent},
258*d9f75844SAndroid Build Coastguard Worker   };
259*d9f75844SAndroid Build Coastguard Worker 
260*d9f75844SAndroid Build Coastguard Worker   for (const auto& f : floats) {
261*d9f75844SAndroid Build Coastguard Worker     report->AddFloat(f.name, f.value);
262*d9f75844SAndroid Build Coastguard Worker   }
263*d9f75844SAndroid Build Coastguard Worker 
264*d9f75844SAndroid Build Coastguard Worker   for (const auto& i : ints) {
265*d9f75844SAndroid Build Coastguard Worker     if (i.value >= 0) {
266*d9f75844SAndroid Build Coastguard Worker       report->AddInt(i.name, i.value);
267*d9f75844SAndroid Build Coastguard Worker     }
268*d9f75844SAndroid Build Coastguard Worker   }
269*d9f75844SAndroid Build Coastguard Worker   report->AddString(StatsReport::kStatsValueNameMediaType, "audio");
270*d9f75844SAndroid Build Coastguard Worker   if (info.ana_statistics.bitrate_action_counter) {
271*d9f75844SAndroid Build Coastguard Worker     report->AddInt(StatsReport::kStatsValueNameAnaBitrateActionCounter,
272*d9f75844SAndroid Build Coastguard Worker                    *info.ana_statistics.bitrate_action_counter);
273*d9f75844SAndroid Build Coastguard Worker   }
274*d9f75844SAndroid Build Coastguard Worker   if (info.ana_statistics.channel_action_counter) {
275*d9f75844SAndroid Build Coastguard Worker     report->AddInt(StatsReport::kStatsValueNameAnaChannelActionCounter,
276*d9f75844SAndroid Build Coastguard Worker                    *info.ana_statistics.channel_action_counter);
277*d9f75844SAndroid Build Coastguard Worker   }
278*d9f75844SAndroid Build Coastguard Worker   if (info.ana_statistics.dtx_action_counter) {
279*d9f75844SAndroid Build Coastguard Worker     report->AddInt(StatsReport::kStatsValueNameAnaDtxActionCounter,
280*d9f75844SAndroid Build Coastguard Worker                    *info.ana_statistics.dtx_action_counter);
281*d9f75844SAndroid Build Coastguard Worker   }
282*d9f75844SAndroid Build Coastguard Worker   if (info.ana_statistics.fec_action_counter) {
283*d9f75844SAndroid Build Coastguard Worker     report->AddInt(StatsReport::kStatsValueNameAnaFecActionCounter,
284*d9f75844SAndroid Build Coastguard Worker                    *info.ana_statistics.fec_action_counter);
285*d9f75844SAndroid Build Coastguard Worker   }
286*d9f75844SAndroid Build Coastguard Worker   if (info.ana_statistics.frame_length_increase_counter) {
287*d9f75844SAndroid Build Coastguard Worker     report->AddInt(StatsReport::kStatsValueNameAnaFrameLengthIncreaseCounter,
288*d9f75844SAndroid Build Coastguard Worker                    *info.ana_statistics.frame_length_increase_counter);
289*d9f75844SAndroid Build Coastguard Worker   }
290*d9f75844SAndroid Build Coastguard Worker   if (info.ana_statistics.frame_length_decrease_counter) {
291*d9f75844SAndroid Build Coastguard Worker     report->AddInt(StatsReport::kStatsValueNameAnaFrameLengthDecreaseCounter,
292*d9f75844SAndroid Build Coastguard Worker                    *info.ana_statistics.frame_length_decrease_counter);
293*d9f75844SAndroid Build Coastguard Worker   }
294*d9f75844SAndroid Build Coastguard Worker   if (info.ana_statistics.uplink_packet_loss_fraction) {
295*d9f75844SAndroid Build Coastguard Worker     report->AddFloat(StatsReport::kStatsValueNameAnaUplinkPacketLossFraction,
296*d9f75844SAndroid Build Coastguard Worker                      *info.ana_statistics.uplink_packet_loss_fraction);
297*d9f75844SAndroid Build Coastguard Worker   }
298*d9f75844SAndroid Build Coastguard Worker }
299*d9f75844SAndroid Build Coastguard Worker 
ExtractStats(const cricket::VideoReceiverInfo & info,StatsReport * report,bool use_standard_bytes_stats)300*d9f75844SAndroid Build Coastguard Worker void ExtractStats(const cricket::VideoReceiverInfo& info,
301*d9f75844SAndroid Build Coastguard Worker                   StatsReport* report,
302*d9f75844SAndroid Build Coastguard Worker                   bool use_standard_bytes_stats) {
303*d9f75844SAndroid Build Coastguard Worker   ExtractCommonReceiveProperties(info, report);
304*d9f75844SAndroid Build Coastguard Worker   report->AddString(StatsReport::kStatsValueNameCodecImplementationName,
305*d9f75844SAndroid Build Coastguard Worker                     info.decoder_implementation_name);
306*d9f75844SAndroid Build Coastguard Worker   int64_t bytes_rcvd = info.payload_bytes_rcvd;
307*d9f75844SAndroid Build Coastguard Worker   if (!use_standard_bytes_stats) {
308*d9f75844SAndroid Build Coastguard Worker     bytes_rcvd += info.header_and_padding_bytes_rcvd;
309*d9f75844SAndroid Build Coastguard Worker   }
310*d9f75844SAndroid Build Coastguard Worker   report->AddInt64(StatsReport::kStatsValueNameBytesReceived, bytes_rcvd);
311*d9f75844SAndroid Build Coastguard Worker   if (info.capture_start_ntp_time_ms >= 0) {
312*d9f75844SAndroid Build Coastguard Worker     report->AddInt64(StatsReport::kStatsValueNameCaptureStartNtpTimeMs,
313*d9f75844SAndroid Build Coastguard Worker                      info.capture_start_ntp_time_ms);
314*d9f75844SAndroid Build Coastguard Worker   }
315*d9f75844SAndroid Build Coastguard Worker   if (info.first_frame_received_to_decoded_ms >= 0) {
316*d9f75844SAndroid Build Coastguard Worker     report->AddInt64(StatsReport::kStatsValueNameFirstFrameReceivedToDecodedMs,
317*d9f75844SAndroid Build Coastguard Worker                      info.first_frame_received_to_decoded_ms);
318*d9f75844SAndroid Build Coastguard Worker   }
319*d9f75844SAndroid Build Coastguard Worker   if (info.qp_sum)
320*d9f75844SAndroid Build Coastguard Worker     report->AddInt64(StatsReport::kStatsValueNameQpSum, *info.qp_sum);
321*d9f75844SAndroid Build Coastguard Worker 
322*d9f75844SAndroid Build Coastguard Worker   if (info.nacks_sent) {
323*d9f75844SAndroid Build Coastguard Worker     report->AddInt(StatsReport::kStatsValueNameNacksSent, *info.nacks_sent);
324*d9f75844SAndroid Build Coastguard Worker   }
325*d9f75844SAndroid Build Coastguard Worker 
326*d9f75844SAndroid Build Coastguard Worker   const IntForAdd ints[] = {
327*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameCurrentDelayMs, info.current_delay_ms},
328*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameDecodeMs, info.decode_ms},
329*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameFirsSent, info.firs_sent},
330*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameFrameHeightReceived, info.frame_height},
331*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameFrameRateDecoded, info.framerate_decoded},
332*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameFrameRateOutput, info.framerate_output},
333*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameFrameRateReceived, info.framerate_rcvd},
334*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameFrameWidthReceived, info.frame_width},
335*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameJitterBufferMs, info.jitter_buffer_ms},
336*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameMaxDecodeMs, info.max_decode_ms},
337*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameMinPlayoutDelayMs,
338*d9f75844SAndroid Build Coastguard Worker        info.min_playout_delay_ms},
339*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNamePacketsLost, info.packets_lost},
340*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNamePacketsReceived, info.packets_rcvd},
341*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNamePlisSent, info.plis_sent},
342*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameRenderDelayMs, info.render_delay_ms},
343*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameTargetDelayMs, info.target_delay_ms},
344*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameFramesDecoded,
345*d9f75844SAndroid Build Coastguard Worker        static_cast<int>(info.frames_decoded)},
346*d9f75844SAndroid Build Coastguard Worker   };
347*d9f75844SAndroid Build Coastguard Worker 
348*d9f75844SAndroid Build Coastguard Worker   for (const auto& i : ints)
349*d9f75844SAndroid Build Coastguard Worker     report->AddInt(i.name, i.value);
350*d9f75844SAndroid Build Coastguard Worker   report->AddString(StatsReport::kStatsValueNameMediaType, "video");
351*d9f75844SAndroid Build Coastguard Worker 
352*d9f75844SAndroid Build Coastguard Worker   if (info.timing_frame_info) {
353*d9f75844SAndroid Build Coastguard Worker     report->AddString(StatsReport::kStatsValueNameTimingFrameInfo,
354*d9f75844SAndroid Build Coastguard Worker                       info.timing_frame_info->ToString());
355*d9f75844SAndroid Build Coastguard Worker   }
356*d9f75844SAndroid Build Coastguard Worker 
357*d9f75844SAndroid Build Coastguard Worker   report->AddInt64(StatsReport::kStatsValueNameInterframeDelayMaxMs,
358*d9f75844SAndroid Build Coastguard Worker                    info.interframe_delay_max_ms);
359*d9f75844SAndroid Build Coastguard Worker 
360*d9f75844SAndroid Build Coastguard Worker   report->AddString(
361*d9f75844SAndroid Build Coastguard Worker       StatsReport::kStatsValueNameContentType,
362*d9f75844SAndroid Build Coastguard Worker       webrtc::videocontenttypehelpers::ToString(info.content_type));
363*d9f75844SAndroid Build Coastguard Worker }
364*d9f75844SAndroid Build Coastguard Worker 
ExtractStats(const cricket::VideoSenderInfo & info,StatsReport * report,bool use_standard_bytes_stats)365*d9f75844SAndroid Build Coastguard Worker void ExtractStats(const cricket::VideoSenderInfo& info,
366*d9f75844SAndroid Build Coastguard Worker                   StatsReport* report,
367*d9f75844SAndroid Build Coastguard Worker                   bool use_standard_bytes_stats) {
368*d9f75844SAndroid Build Coastguard Worker   ExtractCommonSendProperties(info, report, use_standard_bytes_stats);
369*d9f75844SAndroid Build Coastguard Worker 
370*d9f75844SAndroid Build Coastguard Worker   report->AddString(StatsReport::kStatsValueNameCodecImplementationName,
371*d9f75844SAndroid Build Coastguard Worker                     info.encoder_implementation_name);
372*d9f75844SAndroid Build Coastguard Worker   report->AddBoolean(StatsReport::kStatsValueNameBandwidthLimitedResolution,
373*d9f75844SAndroid Build Coastguard Worker                      (info.adapt_reason & 0x2) > 0);
374*d9f75844SAndroid Build Coastguard Worker   report->AddBoolean(StatsReport::kStatsValueNameCpuLimitedResolution,
375*d9f75844SAndroid Build Coastguard Worker                      (info.adapt_reason & 0x1) > 0);
376*d9f75844SAndroid Build Coastguard Worker   report->AddBoolean(StatsReport::kStatsValueNameHasEnteredLowResolution,
377*d9f75844SAndroid Build Coastguard Worker                      info.has_entered_low_resolution);
378*d9f75844SAndroid Build Coastguard Worker 
379*d9f75844SAndroid Build Coastguard Worker   if (info.qp_sum)
380*d9f75844SAndroid Build Coastguard Worker     report->AddInt(StatsReport::kStatsValueNameQpSum, *info.qp_sum);
381*d9f75844SAndroid Build Coastguard Worker 
382*d9f75844SAndroid Build Coastguard Worker   const IntForAdd ints[] = {
383*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameAdaptationChanges, info.adapt_changes},
384*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameAvgEncodeMs, info.avg_encode_ms},
385*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameEncodeUsagePercent,
386*d9f75844SAndroid Build Coastguard Worker        info.encode_usage_percent},
387*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameFirsReceived, info.firs_rcvd},
388*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameFrameHeightSent, info.send_frame_height},
389*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameFrameRateInput,
390*d9f75844SAndroid Build Coastguard Worker        static_cast<int>(round(info.framerate_input))},
391*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameFrameRateSent, info.framerate_sent},
392*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameFrameWidthSent, info.send_frame_width},
393*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameNacksReceived,
394*d9f75844SAndroid Build Coastguard Worker        static_cast<int>(info.nacks_rcvd)},
395*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNamePacketsLost, info.packets_lost},
396*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNamePacketsSent, info.packets_sent},
397*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNamePlisReceived, info.plis_rcvd},
398*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameFramesEncoded,
399*d9f75844SAndroid Build Coastguard Worker        static_cast<int>(info.frames_encoded)},
400*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameHugeFramesSent,
401*d9f75844SAndroid Build Coastguard Worker        static_cast<int>(info.huge_frames_sent)},
402*d9f75844SAndroid Build Coastguard Worker   };
403*d9f75844SAndroid Build Coastguard Worker 
404*d9f75844SAndroid Build Coastguard Worker   for (const auto& i : ints)
405*d9f75844SAndroid Build Coastguard Worker     report->AddInt(i.name, i.value);
406*d9f75844SAndroid Build Coastguard Worker   report->AddString(StatsReport::kStatsValueNameMediaType, "video");
407*d9f75844SAndroid Build Coastguard Worker   report->AddString(
408*d9f75844SAndroid Build Coastguard Worker       StatsReport::kStatsValueNameContentType,
409*d9f75844SAndroid Build Coastguard Worker       webrtc::videocontenttypehelpers::ToString(info.content_type));
410*d9f75844SAndroid Build Coastguard Worker }
411*d9f75844SAndroid Build Coastguard Worker 
ExtractStats(const cricket::BandwidthEstimationInfo & info,double stats_gathering_started,StatsReport * report)412*d9f75844SAndroid Build Coastguard Worker void ExtractStats(const cricket::BandwidthEstimationInfo& info,
413*d9f75844SAndroid Build Coastguard Worker                   double stats_gathering_started,
414*d9f75844SAndroid Build Coastguard Worker                   StatsReport* report) {
415*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(report->type() == StatsReport::kStatsReportTypeBwe);
416*d9f75844SAndroid Build Coastguard Worker 
417*d9f75844SAndroid Build Coastguard Worker   report->set_timestamp(stats_gathering_started);
418*d9f75844SAndroid Build Coastguard Worker   const IntForAdd ints[] = {
419*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameAvailableSendBandwidth,
420*d9f75844SAndroid Build Coastguard Worker        info.available_send_bandwidth},
421*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameAvailableReceiveBandwidth,
422*d9f75844SAndroid Build Coastguard Worker        info.available_recv_bandwidth},
423*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameTargetEncBitrate, info.target_enc_bitrate},
424*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameActualEncBitrate, info.actual_enc_bitrate},
425*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameRetransmitBitrate, info.retransmit_bitrate},
426*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameTransmitBitrate, info.transmit_bitrate},
427*d9f75844SAndroid Build Coastguard Worker   };
428*d9f75844SAndroid Build Coastguard Worker   for (const auto& i : ints)
429*d9f75844SAndroid Build Coastguard Worker     report->AddInt(i.name, i.value);
430*d9f75844SAndroid Build Coastguard Worker   report->AddInt64(StatsReport::kStatsValueNameBucketDelay, info.bucket_delay);
431*d9f75844SAndroid Build Coastguard Worker }
432*d9f75844SAndroid Build Coastguard Worker 
ExtractRemoteStats(const cricket::MediaSenderInfo & info,StatsReport * report)433*d9f75844SAndroid Build Coastguard Worker void ExtractRemoteStats(const cricket::MediaSenderInfo& info,
434*d9f75844SAndroid Build Coastguard Worker                         StatsReport* report) {
435*d9f75844SAndroid Build Coastguard Worker   report->set_timestamp(info.remote_stats[0].timestamp);
436*d9f75844SAndroid Build Coastguard Worker   // TODO(hta): Extract some stats here.
437*d9f75844SAndroid Build Coastguard Worker }
438*d9f75844SAndroid Build Coastguard Worker 
ExtractRemoteStats(const cricket::MediaReceiverInfo & info,StatsReport * report)439*d9f75844SAndroid Build Coastguard Worker void ExtractRemoteStats(const cricket::MediaReceiverInfo& info,
440*d9f75844SAndroid Build Coastguard Worker                         StatsReport* report) {
441*d9f75844SAndroid Build Coastguard Worker   report->set_timestamp(info.remote_stats[0].timestamp);
442*d9f75844SAndroid Build Coastguard Worker   // TODO(hta): Extract some stats here.
443*d9f75844SAndroid Build Coastguard Worker }
444*d9f75844SAndroid Build Coastguard Worker 
GetTrackIdBySsrc(uint32_t ssrc,StatsReport::Direction direction,const std::map<uint32_t,std::string> & track_id_by_ssrc)445*d9f75844SAndroid Build Coastguard Worker std::string GetTrackIdBySsrc(
446*d9f75844SAndroid Build Coastguard Worker     uint32_t ssrc,
447*d9f75844SAndroid Build Coastguard Worker     StatsReport::Direction direction,
448*d9f75844SAndroid Build Coastguard Worker     const std::map<uint32_t, std::string>& track_id_by_ssrc) {
449*d9f75844SAndroid Build Coastguard Worker   auto it = track_id_by_ssrc.find(ssrc);
450*d9f75844SAndroid Build Coastguard Worker   if (it != track_id_by_ssrc.end()) {
451*d9f75844SAndroid Build Coastguard Worker     return it->second;
452*d9f75844SAndroid Build Coastguard Worker   }
453*d9f75844SAndroid Build Coastguard Worker   if (direction == StatsReport::kReceive) {
454*d9f75844SAndroid Build Coastguard Worker     // If the track ID was not found, this might be an unsignaled receive
455*d9f75844SAndroid Build Coastguard Worker     // SSRC, so try looking up by the special SSRC 0.
456*d9f75844SAndroid Build Coastguard Worker     it = track_id_by_ssrc.find(0);
457*d9f75844SAndroid Build Coastguard Worker     if (it != track_id_by_ssrc.end()) {
458*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_INFO) << "Assuming SSRC=" << ssrc
459*d9f75844SAndroid Build Coastguard Worker                        << " is an unsignalled receive stream corresponding "
460*d9f75844SAndroid Build Coastguard Worker                           "to the RtpReceiver with track ID \""
461*d9f75844SAndroid Build Coastguard Worker                        << it->second << "\".";
462*d9f75844SAndroid Build Coastguard Worker       return it->second;
463*d9f75844SAndroid Build Coastguard Worker     }
464*d9f75844SAndroid Build Coastguard Worker   }
465*d9f75844SAndroid Build Coastguard Worker   return "";
466*d9f75844SAndroid Build Coastguard Worker }
467*d9f75844SAndroid Build Coastguard Worker 
468*d9f75844SAndroid Build Coastguard Worker // Template to extract stats from a data vector.
469*d9f75844SAndroid Build Coastguard Worker // In order to use the template, the functions that are called from it,
470*d9f75844SAndroid Build Coastguard Worker // ExtractStats and ExtractRemoteStats, must be defined and overloaded
471*d9f75844SAndroid Build Coastguard Worker // for each type.
472*d9f75844SAndroid Build Coastguard Worker template <typename T>
ExtractStatsFromList(const std::vector<T> & data,const StatsReport::Id & transport_id,LegacyStatsCollector * collector,StatsReport::Direction direction,const std::map<uint32_t,std::string> & track_id_by_ssrc)473*d9f75844SAndroid Build Coastguard Worker void ExtractStatsFromList(
474*d9f75844SAndroid Build Coastguard Worker     const std::vector<T>& data,
475*d9f75844SAndroid Build Coastguard Worker     const StatsReport::Id& transport_id,
476*d9f75844SAndroid Build Coastguard Worker     LegacyStatsCollector* collector,
477*d9f75844SAndroid Build Coastguard Worker     StatsReport::Direction direction,
478*d9f75844SAndroid Build Coastguard Worker     const std::map<uint32_t, std::string>& track_id_by_ssrc) {
479*d9f75844SAndroid Build Coastguard Worker   for (const auto& d : data) {
480*d9f75844SAndroid Build Coastguard Worker     uint32_t ssrc = d.ssrc();
481*d9f75844SAndroid Build Coastguard Worker     std::string track_id = GetTrackIdBySsrc(ssrc, direction, track_id_by_ssrc);
482*d9f75844SAndroid Build Coastguard Worker     // Each track can have stats for both local and remote objects.
483*d9f75844SAndroid Build Coastguard Worker     // TODO(hta): Handle the case of multiple SSRCs per object.
484*d9f75844SAndroid Build Coastguard Worker     StatsReport* report =
485*d9f75844SAndroid Build Coastguard Worker         collector->PrepareReport(true, ssrc, track_id, transport_id, direction);
486*d9f75844SAndroid Build Coastguard Worker     if (report)
487*d9f75844SAndroid Build Coastguard Worker       ExtractStats(d, report, collector->UseStandardBytesStats());
488*d9f75844SAndroid Build Coastguard Worker 
489*d9f75844SAndroid Build Coastguard Worker     if (!d.remote_stats.empty()) {
490*d9f75844SAndroid Build Coastguard Worker       report = collector->PrepareReport(false, ssrc, track_id, transport_id,
491*d9f75844SAndroid Build Coastguard Worker                                         direction);
492*d9f75844SAndroid Build Coastguard Worker       if (report)
493*d9f75844SAndroid Build Coastguard Worker         ExtractRemoteStats(d, report);
494*d9f75844SAndroid Build Coastguard Worker     }
495*d9f75844SAndroid Build Coastguard Worker   }
496*d9f75844SAndroid Build Coastguard Worker }
497*d9f75844SAndroid Build Coastguard Worker 
498*d9f75844SAndroid Build Coastguard Worker }  // namespace
499*d9f75844SAndroid Build Coastguard Worker 
IceCandidateTypeToStatsType(const std::string & candidate_type)500*d9f75844SAndroid Build Coastguard Worker const char* IceCandidateTypeToStatsType(const std::string& candidate_type) {
501*d9f75844SAndroid Build Coastguard Worker   if (candidate_type == cricket::LOCAL_PORT_TYPE) {
502*d9f75844SAndroid Build Coastguard Worker     return STATSREPORT_LOCAL_PORT_TYPE;
503*d9f75844SAndroid Build Coastguard Worker   }
504*d9f75844SAndroid Build Coastguard Worker   if (candidate_type == cricket::STUN_PORT_TYPE) {
505*d9f75844SAndroid Build Coastguard Worker     return STATSREPORT_STUN_PORT_TYPE;
506*d9f75844SAndroid Build Coastguard Worker   }
507*d9f75844SAndroid Build Coastguard Worker   if (candidate_type == cricket::PRFLX_PORT_TYPE) {
508*d9f75844SAndroid Build Coastguard Worker     return STATSREPORT_PRFLX_PORT_TYPE;
509*d9f75844SAndroid Build Coastguard Worker   }
510*d9f75844SAndroid Build Coastguard Worker   if (candidate_type == cricket::RELAY_PORT_TYPE) {
511*d9f75844SAndroid Build Coastguard Worker     return STATSREPORT_RELAY_PORT_TYPE;
512*d9f75844SAndroid Build Coastguard Worker   }
513*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_NOTREACHED();
514*d9f75844SAndroid Build Coastguard Worker   return "unknown";
515*d9f75844SAndroid Build Coastguard Worker }
516*d9f75844SAndroid Build Coastguard Worker 
AdapterTypeToStatsType(rtc::AdapterType type)517*d9f75844SAndroid Build Coastguard Worker const char* AdapterTypeToStatsType(rtc::AdapterType type) {
518*d9f75844SAndroid Build Coastguard Worker   switch (type) {
519*d9f75844SAndroid Build Coastguard Worker     case rtc::ADAPTER_TYPE_UNKNOWN:
520*d9f75844SAndroid Build Coastguard Worker       return "unknown";
521*d9f75844SAndroid Build Coastguard Worker     case rtc::ADAPTER_TYPE_ETHERNET:
522*d9f75844SAndroid Build Coastguard Worker       return STATSREPORT_ADAPTER_TYPE_ETHERNET;
523*d9f75844SAndroid Build Coastguard Worker     case rtc::ADAPTER_TYPE_WIFI:
524*d9f75844SAndroid Build Coastguard Worker       return STATSREPORT_ADAPTER_TYPE_WIFI;
525*d9f75844SAndroid Build Coastguard Worker     case rtc::ADAPTER_TYPE_CELLULAR:
526*d9f75844SAndroid Build Coastguard Worker     case rtc::ADAPTER_TYPE_CELLULAR_2G:
527*d9f75844SAndroid Build Coastguard Worker     case rtc::ADAPTER_TYPE_CELLULAR_3G:
528*d9f75844SAndroid Build Coastguard Worker     case rtc::ADAPTER_TYPE_CELLULAR_4G:
529*d9f75844SAndroid Build Coastguard Worker     case rtc::ADAPTER_TYPE_CELLULAR_5G:
530*d9f75844SAndroid Build Coastguard Worker       return STATSREPORT_ADAPTER_TYPE_WWAN;
531*d9f75844SAndroid Build Coastguard Worker     case rtc::ADAPTER_TYPE_VPN:
532*d9f75844SAndroid Build Coastguard Worker       return STATSREPORT_ADAPTER_TYPE_VPN;
533*d9f75844SAndroid Build Coastguard Worker     case rtc::ADAPTER_TYPE_LOOPBACK:
534*d9f75844SAndroid Build Coastguard Worker       return STATSREPORT_ADAPTER_TYPE_LOOPBACK;
535*d9f75844SAndroid Build Coastguard Worker     case rtc::ADAPTER_TYPE_ANY:
536*d9f75844SAndroid Build Coastguard Worker       return STATSREPORT_ADAPTER_TYPE_WILDCARD;
537*d9f75844SAndroid Build Coastguard Worker     default:
538*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK_NOTREACHED();
539*d9f75844SAndroid Build Coastguard Worker       return "";
540*d9f75844SAndroid Build Coastguard Worker   }
541*d9f75844SAndroid Build Coastguard Worker }
542*d9f75844SAndroid Build Coastguard Worker 
LegacyStatsCollector(PeerConnectionInternal * pc)543*d9f75844SAndroid Build Coastguard Worker LegacyStatsCollector::LegacyStatsCollector(PeerConnectionInternal* pc)
544*d9f75844SAndroid Build Coastguard Worker     : pc_(pc),
545*d9f75844SAndroid Build Coastguard Worker       stats_gathering_started_(0),
546*d9f75844SAndroid Build Coastguard Worker       use_standard_bytes_stats_(
547*d9f75844SAndroid Build Coastguard Worker           pc->trials().IsEnabled(kUseStandardBytesStats)) {
548*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(pc_);
549*d9f75844SAndroid Build Coastguard Worker }
550*d9f75844SAndroid Build Coastguard Worker 
~LegacyStatsCollector()551*d9f75844SAndroid Build Coastguard Worker LegacyStatsCollector::~LegacyStatsCollector() {
552*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(pc_->signaling_thread());
553*d9f75844SAndroid Build Coastguard Worker }
554*d9f75844SAndroid Build Coastguard Worker 
555*d9f75844SAndroid Build Coastguard Worker // Wallclock time in ms.
GetTimeNow()556*d9f75844SAndroid Build Coastguard Worker double LegacyStatsCollector::GetTimeNow() {
557*d9f75844SAndroid Build Coastguard Worker   return static_cast<double>(rtc::TimeUTCMillis());
558*d9f75844SAndroid Build Coastguard Worker }
559*d9f75844SAndroid Build Coastguard Worker 
560*d9f75844SAndroid Build Coastguard Worker // Adds a MediaStream with tracks that can be used as a `selector` in a call
561*d9f75844SAndroid Build Coastguard Worker // to GetStats.
AddStream(MediaStreamInterface * stream)562*d9f75844SAndroid Build Coastguard Worker void LegacyStatsCollector::AddStream(MediaStreamInterface* stream) {
563*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(pc_->signaling_thread());
564*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(stream != NULL);
565*d9f75844SAndroid Build Coastguard Worker 
566*d9f75844SAndroid Build Coastguard Worker   CreateTrackReports<AudioTrackVector>(stream->GetAudioTracks(), &reports_,
567*d9f75844SAndroid Build Coastguard Worker                                        &track_ids_);
568*d9f75844SAndroid Build Coastguard Worker   CreateTrackReports<VideoTrackVector>(stream->GetVideoTracks(), &reports_,
569*d9f75844SAndroid Build Coastguard Worker                                        &track_ids_);
570*d9f75844SAndroid Build Coastguard Worker }
571*d9f75844SAndroid Build Coastguard Worker 
AddTrack(MediaStreamTrackInterface * track)572*d9f75844SAndroid Build Coastguard Worker void LegacyStatsCollector::AddTrack(MediaStreamTrackInterface* track) {
573*d9f75844SAndroid Build Coastguard Worker   if (track->kind() == MediaStreamTrackInterface::kAudioKind) {
574*d9f75844SAndroid Build Coastguard Worker     CreateTrackReport(static_cast<AudioTrackInterface*>(track), &reports_,
575*d9f75844SAndroid Build Coastguard Worker                       &track_ids_);
576*d9f75844SAndroid Build Coastguard Worker   } else if (track->kind() == MediaStreamTrackInterface::kVideoKind) {
577*d9f75844SAndroid Build Coastguard Worker     CreateTrackReport(static_cast<VideoTrackInterface*>(track), &reports_,
578*d9f75844SAndroid Build Coastguard Worker                       &track_ids_);
579*d9f75844SAndroid Build Coastguard Worker   } else {
580*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK_NOTREACHED() << "Illegal track kind";
581*d9f75844SAndroid Build Coastguard Worker   }
582*d9f75844SAndroid Build Coastguard Worker }
583*d9f75844SAndroid Build Coastguard Worker 
AddLocalAudioTrack(AudioTrackInterface * audio_track,uint32_t ssrc)584*d9f75844SAndroid Build Coastguard Worker void LegacyStatsCollector::AddLocalAudioTrack(AudioTrackInterface* audio_track,
585*d9f75844SAndroid Build Coastguard Worker                                               uint32_t ssrc) {
586*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(pc_->signaling_thread());
587*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(audio_track != NULL);
588*d9f75844SAndroid Build Coastguard Worker #if RTC_DCHECK_IS_ON
589*d9f75844SAndroid Build Coastguard Worker   for (const auto& track : local_audio_tracks_)
590*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(track.first != audio_track || track.second != ssrc);
591*d9f75844SAndroid Build Coastguard Worker #endif
592*d9f75844SAndroid Build Coastguard Worker 
593*d9f75844SAndroid Build Coastguard Worker   local_audio_tracks_.push_back(std::make_pair(audio_track, ssrc));
594*d9f75844SAndroid Build Coastguard Worker 
595*d9f75844SAndroid Build Coastguard Worker   // Create the kStatsReportTypeTrack report for the new track if there is no
596*d9f75844SAndroid Build Coastguard Worker   // report yet.
597*d9f75844SAndroid Build Coastguard Worker   StatsReport::Id id(StatsReport::NewTypedId(StatsReport::kStatsReportTypeTrack,
598*d9f75844SAndroid Build Coastguard Worker                                              audio_track->id()));
599*d9f75844SAndroid Build Coastguard Worker   StatsReport* report = reports_.Find(id);
600*d9f75844SAndroid Build Coastguard Worker   if (!report) {
601*d9f75844SAndroid Build Coastguard Worker     report = reports_.InsertNew(id);
602*d9f75844SAndroid Build Coastguard Worker     report->AddString(StatsReport::kStatsValueNameTrackId, audio_track->id());
603*d9f75844SAndroid Build Coastguard Worker   }
604*d9f75844SAndroid Build Coastguard Worker }
605*d9f75844SAndroid Build Coastguard Worker 
RemoveLocalAudioTrack(AudioTrackInterface * audio_track,uint32_t ssrc)606*d9f75844SAndroid Build Coastguard Worker void LegacyStatsCollector::RemoveLocalAudioTrack(
607*d9f75844SAndroid Build Coastguard Worker     AudioTrackInterface* audio_track,
608*d9f75844SAndroid Build Coastguard Worker     uint32_t ssrc) {
609*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(audio_track != NULL);
610*d9f75844SAndroid Build Coastguard Worker   local_audio_tracks_.erase(
611*d9f75844SAndroid Build Coastguard Worker       std::remove_if(
612*d9f75844SAndroid Build Coastguard Worker           local_audio_tracks_.begin(), local_audio_tracks_.end(),
613*d9f75844SAndroid Build Coastguard Worker           [audio_track, ssrc](const LocalAudioTrackVector::value_type& track) {
614*d9f75844SAndroid Build Coastguard Worker             return track.first == audio_track && track.second == ssrc;
615*d9f75844SAndroid Build Coastguard Worker           }),
616*d9f75844SAndroid Build Coastguard Worker       local_audio_tracks_.end());
617*d9f75844SAndroid Build Coastguard Worker }
618*d9f75844SAndroid Build Coastguard Worker 
GetStats(MediaStreamTrackInterface * track,StatsReports * reports)619*d9f75844SAndroid Build Coastguard Worker void LegacyStatsCollector::GetStats(MediaStreamTrackInterface* track,
620*d9f75844SAndroid Build Coastguard Worker                                     StatsReports* reports) {
621*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(pc_->signaling_thread());
622*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(reports != NULL);
623*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(reports->empty());
624*d9f75844SAndroid Build Coastguard Worker 
625*d9f75844SAndroid Build Coastguard Worker   rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
626*d9f75844SAndroid Build Coastguard Worker 
627*d9f75844SAndroid Build Coastguard Worker   if (!track) {
628*d9f75844SAndroid Build Coastguard Worker     reports->reserve(reports_.size());
629*d9f75844SAndroid Build Coastguard Worker     for (auto* r : reports_)
630*d9f75844SAndroid Build Coastguard Worker       reports->push_back(r);
631*d9f75844SAndroid Build Coastguard Worker     return;
632*d9f75844SAndroid Build Coastguard Worker   }
633*d9f75844SAndroid Build Coastguard Worker 
634*d9f75844SAndroid Build Coastguard Worker   StatsReport* report = reports_.Find(StatsReport::NewTypedId(
635*d9f75844SAndroid Build Coastguard Worker       StatsReport::kStatsReportTypeSession, pc_->session_id()));
636*d9f75844SAndroid Build Coastguard Worker   if (report)
637*d9f75844SAndroid Build Coastguard Worker     reports->push_back(report);
638*d9f75844SAndroid Build Coastguard Worker 
639*d9f75844SAndroid Build Coastguard Worker   report = reports_.Find(
640*d9f75844SAndroid Build Coastguard Worker       StatsReport::NewTypedId(StatsReport::kStatsReportTypeTrack, track->id()));
641*d9f75844SAndroid Build Coastguard Worker 
642*d9f75844SAndroid Build Coastguard Worker   if (!report)
643*d9f75844SAndroid Build Coastguard Worker     return;
644*d9f75844SAndroid Build Coastguard Worker 
645*d9f75844SAndroid Build Coastguard Worker   reports->push_back(report);
646*d9f75844SAndroid Build Coastguard Worker 
647*d9f75844SAndroid Build Coastguard Worker   std::string track_id;
648*d9f75844SAndroid Build Coastguard Worker   for (const auto* r : reports_) {
649*d9f75844SAndroid Build Coastguard Worker     if (r->type() != StatsReport::kStatsReportTypeSsrc)
650*d9f75844SAndroid Build Coastguard Worker       continue;
651*d9f75844SAndroid Build Coastguard Worker 
652*d9f75844SAndroid Build Coastguard Worker     const StatsReport::Value* v =
653*d9f75844SAndroid Build Coastguard Worker         r->FindValue(StatsReport::kStatsValueNameTrackId);
654*d9f75844SAndroid Build Coastguard Worker     if (v && v->string_val() == track->id())
655*d9f75844SAndroid Build Coastguard Worker       reports->push_back(r);
656*d9f75844SAndroid Build Coastguard Worker   }
657*d9f75844SAndroid Build Coastguard Worker }
658*d9f75844SAndroid Build Coastguard Worker 
UpdateStats(PeerConnectionInterface::StatsOutputLevel level)659*d9f75844SAndroid Build Coastguard Worker void LegacyStatsCollector::UpdateStats(
660*d9f75844SAndroid Build Coastguard Worker     PeerConnectionInterface::StatsOutputLevel level) {
661*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(pc_->signaling_thread());
662*d9f75844SAndroid Build Coastguard Worker   // Calls to UpdateStats() that occur less than kMinGatherStatsPeriodMs apart
663*d9f75844SAndroid Build Coastguard Worker   // will be ignored. Using a monotonic clock specifically for this, while using
664*d9f75844SAndroid Build Coastguard Worker   // a UTC clock for the reports themselves.
665*d9f75844SAndroid Build Coastguard Worker   const int64_t kMinGatherStatsPeriodMs = 50;
666*d9f75844SAndroid Build Coastguard Worker   int64_t cache_now_ms = rtc::TimeMillis();
667*d9f75844SAndroid Build Coastguard Worker   if (cache_timestamp_ms_ != 0 &&
668*d9f75844SAndroid Build Coastguard Worker       cache_timestamp_ms_ + kMinGatherStatsPeriodMs > cache_now_ms) {
669*d9f75844SAndroid Build Coastguard Worker     return;
670*d9f75844SAndroid Build Coastguard Worker   }
671*d9f75844SAndroid Build Coastguard Worker   cache_timestamp_ms_ = cache_now_ms;
672*d9f75844SAndroid Build Coastguard Worker   stats_gathering_started_ = GetTimeNow();
673*d9f75844SAndroid Build Coastguard Worker 
674*d9f75844SAndroid Build Coastguard Worker   // TODO(tommi): ExtractSessionInfo now has a single hop to the network thread
675*d9f75844SAndroid Build Coastguard Worker   // to fetch stats, then applies them on the signaling thread. See if we need
676*d9f75844SAndroid Build Coastguard Worker   // to do this synchronously or if updating the stats without blocking is safe.
677*d9f75844SAndroid Build Coastguard Worker   std::map<std::string, std::string> transport_names_by_mid =
678*d9f75844SAndroid Build Coastguard Worker       ExtractSessionInfo();
679*d9f75844SAndroid Build Coastguard Worker 
680*d9f75844SAndroid Build Coastguard Worker   // TODO(tommi): All of these hop over to the worker thread to fetch
681*d9f75844SAndroid Build Coastguard Worker   // information.  We could post a task to run all of these and post
682*d9f75844SAndroid Build Coastguard Worker   // the information back to the signaling thread where we can create and
683*d9f75844SAndroid Build Coastguard Worker   // update stats reports.  That would also clean up the threading story a bit
684*d9f75844SAndroid Build Coastguard Worker   // since we'd be creating/updating the stats report objects consistently on
685*d9f75844SAndroid Build Coastguard Worker   // the same thread (this class has no locks right now).
686*d9f75844SAndroid Build Coastguard Worker   ExtractBweInfo();
687*d9f75844SAndroid Build Coastguard Worker   ExtractMediaInfo(transport_names_by_mid);
688*d9f75844SAndroid Build Coastguard Worker   ExtractSenderInfo();
689*d9f75844SAndroid Build Coastguard Worker   ExtractDataInfo();
690*d9f75844SAndroid Build Coastguard Worker   UpdateTrackReports();
691*d9f75844SAndroid Build Coastguard Worker }
692*d9f75844SAndroid Build Coastguard Worker 
PrepareReport(bool local,uint32_t ssrc,const std::string & track_id,const StatsReport::Id & transport_id,StatsReport::Direction direction)693*d9f75844SAndroid Build Coastguard Worker StatsReport* LegacyStatsCollector::PrepareReport(
694*d9f75844SAndroid Build Coastguard Worker     bool local,
695*d9f75844SAndroid Build Coastguard Worker     uint32_t ssrc,
696*d9f75844SAndroid Build Coastguard Worker     const std::string& track_id,
697*d9f75844SAndroid Build Coastguard Worker     const StatsReport::Id& transport_id,
698*d9f75844SAndroid Build Coastguard Worker     StatsReport::Direction direction) {
699*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(pc_->signaling_thread());
700*d9f75844SAndroid Build Coastguard Worker   StatsReport::Id id(StatsReport::NewIdWithDirection(
701*d9f75844SAndroid Build Coastguard Worker       local ? StatsReport::kStatsReportTypeSsrc
702*d9f75844SAndroid Build Coastguard Worker             : StatsReport::kStatsReportTypeRemoteSsrc,
703*d9f75844SAndroid Build Coastguard Worker       rtc::ToString(ssrc), direction));
704*d9f75844SAndroid Build Coastguard Worker   StatsReport* report = reports_.Find(id);
705*d9f75844SAndroid Build Coastguard Worker   if (!report) {
706*d9f75844SAndroid Build Coastguard Worker     report = reports_.InsertNew(id);
707*d9f75844SAndroid Build Coastguard Worker   }
708*d9f75844SAndroid Build Coastguard Worker 
709*d9f75844SAndroid Build Coastguard Worker   // FYI - for remote reports, the timestamp will be overwritten later.
710*d9f75844SAndroid Build Coastguard Worker   report->set_timestamp(stats_gathering_started_);
711*d9f75844SAndroid Build Coastguard Worker 
712*d9f75844SAndroid Build Coastguard Worker   report->AddInt64(StatsReport::kStatsValueNameSsrc, ssrc);
713*d9f75844SAndroid Build Coastguard Worker   if (!track_id.empty()) {
714*d9f75844SAndroid Build Coastguard Worker     report->AddString(StatsReport::kStatsValueNameTrackId, track_id);
715*d9f75844SAndroid Build Coastguard Worker   }
716*d9f75844SAndroid Build Coastguard Worker   // Add the mapping of SSRC to transport.
717*d9f75844SAndroid Build Coastguard Worker   report->AddId(StatsReport::kStatsValueNameTransportId, transport_id);
718*d9f75844SAndroid Build Coastguard Worker   return report;
719*d9f75844SAndroid Build Coastguard Worker }
720*d9f75844SAndroid Build Coastguard Worker 
PrepareADMReport()721*d9f75844SAndroid Build Coastguard Worker StatsReport* LegacyStatsCollector::PrepareADMReport() {
722*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(pc_->signaling_thread());
723*d9f75844SAndroid Build Coastguard Worker   StatsReport::Id id(StatsReport::NewTypedId(
724*d9f75844SAndroid Build Coastguard Worker       StatsReport::kStatsReportTypeSession, pc_->session_id()));
725*d9f75844SAndroid Build Coastguard Worker   StatsReport* report = reports_.FindOrAddNew(id);
726*d9f75844SAndroid Build Coastguard Worker   return report;
727*d9f75844SAndroid Build Coastguard Worker }
728*d9f75844SAndroid Build Coastguard Worker 
IsValidTrack(const std::string & track_id)729*d9f75844SAndroid Build Coastguard Worker bool LegacyStatsCollector::IsValidTrack(const std::string& track_id) {
730*d9f75844SAndroid Build Coastguard Worker   return reports_.Find(StatsReport::NewTypedId(
731*d9f75844SAndroid Build Coastguard Worker              StatsReport::kStatsReportTypeTrack, track_id)) != nullptr;
732*d9f75844SAndroid Build Coastguard Worker }
733*d9f75844SAndroid Build Coastguard Worker 
AddCertificateReports(std::unique_ptr<rtc::SSLCertificateStats> cert_stats)734*d9f75844SAndroid Build Coastguard Worker StatsReport* LegacyStatsCollector::AddCertificateReports(
735*d9f75844SAndroid Build Coastguard Worker     std::unique_ptr<rtc::SSLCertificateStats> cert_stats) {
736*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(pc_->signaling_thread());
737*d9f75844SAndroid Build Coastguard Worker 
738*d9f75844SAndroid Build Coastguard Worker   StatsReport* first_report = nullptr;
739*d9f75844SAndroid Build Coastguard Worker   StatsReport* prev_report = nullptr;
740*d9f75844SAndroid Build Coastguard Worker   for (rtc::SSLCertificateStats* stats = cert_stats.get(); stats;
741*d9f75844SAndroid Build Coastguard Worker        stats = stats->issuer.get()) {
742*d9f75844SAndroid Build Coastguard Worker     StatsReport::Id id(StatsReport::NewTypedId(
743*d9f75844SAndroid Build Coastguard Worker         StatsReport::kStatsReportTypeCertificate, stats->fingerprint));
744*d9f75844SAndroid Build Coastguard Worker 
745*d9f75844SAndroid Build Coastguard Worker     StatsReport* report = reports_.ReplaceOrAddNew(id);
746*d9f75844SAndroid Build Coastguard Worker     report->set_timestamp(stats_gathering_started_);
747*d9f75844SAndroid Build Coastguard Worker     report->AddString(StatsReport::kStatsValueNameFingerprint,
748*d9f75844SAndroid Build Coastguard Worker                       stats->fingerprint);
749*d9f75844SAndroid Build Coastguard Worker     report->AddString(StatsReport::kStatsValueNameFingerprintAlgorithm,
750*d9f75844SAndroid Build Coastguard Worker                       stats->fingerprint_algorithm);
751*d9f75844SAndroid Build Coastguard Worker     report->AddString(StatsReport::kStatsValueNameDer,
752*d9f75844SAndroid Build Coastguard Worker                       stats->base64_certificate);
753*d9f75844SAndroid Build Coastguard Worker     if (!first_report)
754*d9f75844SAndroid Build Coastguard Worker       first_report = report;
755*d9f75844SAndroid Build Coastguard Worker     else
756*d9f75844SAndroid Build Coastguard Worker       prev_report->AddId(StatsReport::kStatsValueNameIssuerId, id);
757*d9f75844SAndroid Build Coastguard Worker     prev_report = report;
758*d9f75844SAndroid Build Coastguard Worker   }
759*d9f75844SAndroid Build Coastguard Worker   return first_report;
760*d9f75844SAndroid Build Coastguard Worker }
761*d9f75844SAndroid Build Coastguard Worker 
AddConnectionInfoReport(const std::string & content_name,int component,int connection_id,const StatsReport::Id & channel_report_id,const cricket::ConnectionInfo & info)762*d9f75844SAndroid Build Coastguard Worker StatsReport* LegacyStatsCollector::AddConnectionInfoReport(
763*d9f75844SAndroid Build Coastguard Worker     const std::string& content_name,
764*d9f75844SAndroid Build Coastguard Worker     int component,
765*d9f75844SAndroid Build Coastguard Worker     int connection_id,
766*d9f75844SAndroid Build Coastguard Worker     const StatsReport::Id& channel_report_id,
767*d9f75844SAndroid Build Coastguard Worker     const cricket::ConnectionInfo& info) {
768*d9f75844SAndroid Build Coastguard Worker   StatsReport::Id id(
769*d9f75844SAndroid Build Coastguard Worker       StatsReport::NewCandidatePairId(content_name, component, connection_id));
770*d9f75844SAndroid Build Coastguard Worker   StatsReport* report = reports_.ReplaceOrAddNew(id);
771*d9f75844SAndroid Build Coastguard Worker   report->set_timestamp(stats_gathering_started_);
772*d9f75844SAndroid Build Coastguard Worker 
773*d9f75844SAndroid Build Coastguard Worker   const BoolForAdd bools[] = {
774*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameActiveConnection, info.best_connection},
775*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameReceiving, info.receiving},
776*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameWritable, info.writable},
777*d9f75844SAndroid Build Coastguard Worker   };
778*d9f75844SAndroid Build Coastguard Worker   for (const auto& b : bools)
779*d9f75844SAndroid Build Coastguard Worker     report->AddBoolean(b.name, b.value);
780*d9f75844SAndroid Build Coastguard Worker 
781*d9f75844SAndroid Build Coastguard Worker   report->AddId(StatsReport::kStatsValueNameChannelId, channel_report_id);
782*d9f75844SAndroid Build Coastguard Worker   cricket::CandidateStats local_candidate_stats(info.local_candidate);
783*d9f75844SAndroid Build Coastguard Worker   cricket::CandidateStats remote_candidate_stats(info.remote_candidate);
784*d9f75844SAndroid Build Coastguard Worker   report->AddId(StatsReport::kStatsValueNameLocalCandidateId,
785*d9f75844SAndroid Build Coastguard Worker                 AddCandidateReport(local_candidate_stats, true)->id());
786*d9f75844SAndroid Build Coastguard Worker   report->AddId(StatsReport::kStatsValueNameRemoteCandidateId,
787*d9f75844SAndroid Build Coastguard Worker                 AddCandidateReport(remote_candidate_stats, false)->id());
788*d9f75844SAndroid Build Coastguard Worker 
789*d9f75844SAndroid Build Coastguard Worker   const Int64ForAdd int64s[] = {
790*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameBytesReceived,
791*d9f75844SAndroid Build Coastguard Worker        static_cast<int64_t>(info.recv_total_bytes)},
792*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameBytesSent,
793*d9f75844SAndroid Build Coastguard Worker        static_cast<int64_t>(info.sent_total_bytes)},
794*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNamePacketsSent,
795*d9f75844SAndroid Build Coastguard Worker        static_cast<int64_t>(info.sent_total_packets)},
796*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameRtt, static_cast<int64_t>(info.rtt)},
797*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameSendPacketsDiscarded,
798*d9f75844SAndroid Build Coastguard Worker        static_cast<int64_t>(info.sent_discarded_packets)},
799*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameSentPingRequestsTotal,
800*d9f75844SAndroid Build Coastguard Worker        static_cast<int64_t>(info.sent_ping_requests_total)},
801*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameSentPingRequestsBeforeFirstResponse,
802*d9f75844SAndroid Build Coastguard Worker        static_cast<int64_t>(info.sent_ping_requests_before_first_response)},
803*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameSentPingResponses,
804*d9f75844SAndroid Build Coastguard Worker        static_cast<int64_t>(info.sent_ping_responses)},
805*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameRecvPingRequests,
806*d9f75844SAndroid Build Coastguard Worker        static_cast<int64_t>(info.recv_ping_requests)},
807*d9f75844SAndroid Build Coastguard Worker       {StatsReport::kStatsValueNameRecvPingResponses,
808*d9f75844SAndroid Build Coastguard Worker        static_cast<int64_t>(info.recv_ping_responses)},
809*d9f75844SAndroid Build Coastguard Worker   };
810*d9f75844SAndroid Build Coastguard Worker   for (const auto& i : int64s)
811*d9f75844SAndroid Build Coastguard Worker     report->AddInt64(i.name, i.value);
812*d9f75844SAndroid Build Coastguard Worker 
813*d9f75844SAndroid Build Coastguard Worker   report->AddString(StatsReport::kStatsValueNameLocalAddress,
814*d9f75844SAndroid Build Coastguard Worker                     info.local_candidate.address().ToString());
815*d9f75844SAndroid Build Coastguard Worker   report->AddString(StatsReport::kStatsValueNameLocalCandidateType,
816*d9f75844SAndroid Build Coastguard Worker                     info.local_candidate.type());
817*d9f75844SAndroid Build Coastguard Worker   report->AddString(StatsReport::kStatsValueNameRemoteAddress,
818*d9f75844SAndroid Build Coastguard Worker                     info.remote_candidate.address().ToString());
819*d9f75844SAndroid Build Coastguard Worker   report->AddString(StatsReport::kStatsValueNameRemoteCandidateType,
820*d9f75844SAndroid Build Coastguard Worker                     info.remote_candidate.type());
821*d9f75844SAndroid Build Coastguard Worker   report->AddString(StatsReport::kStatsValueNameTransportType,
822*d9f75844SAndroid Build Coastguard Worker                     info.local_candidate.protocol());
823*d9f75844SAndroid Build Coastguard Worker   report->AddString(StatsReport::kStatsValueNameLocalCandidateRelayProtocol,
824*d9f75844SAndroid Build Coastguard Worker                     info.local_candidate.relay_protocol());
825*d9f75844SAndroid Build Coastguard Worker 
826*d9f75844SAndroid Build Coastguard Worker   return report;
827*d9f75844SAndroid Build Coastguard Worker }
828*d9f75844SAndroid Build Coastguard Worker 
AddCandidateReport(const cricket::CandidateStats & candidate_stats,bool local)829*d9f75844SAndroid Build Coastguard Worker StatsReport* LegacyStatsCollector::AddCandidateReport(
830*d9f75844SAndroid Build Coastguard Worker     const cricket::CandidateStats& candidate_stats,
831*d9f75844SAndroid Build Coastguard Worker     bool local) {
832*d9f75844SAndroid Build Coastguard Worker   const auto& candidate = candidate_stats.candidate();
833*d9f75844SAndroid Build Coastguard Worker   StatsReport::Id id(StatsReport::NewCandidateId(local, candidate.id()));
834*d9f75844SAndroid Build Coastguard Worker   StatsReport* report = reports_.Find(id);
835*d9f75844SAndroid Build Coastguard Worker   if (!report) {
836*d9f75844SAndroid Build Coastguard Worker     report = reports_.InsertNew(id);
837*d9f75844SAndroid Build Coastguard Worker     report->set_timestamp(stats_gathering_started_);
838*d9f75844SAndroid Build Coastguard Worker     if (local) {
839*d9f75844SAndroid Build Coastguard Worker       report->AddString(StatsReport::kStatsValueNameCandidateNetworkType,
840*d9f75844SAndroid Build Coastguard Worker                         AdapterTypeToStatsType(candidate.network_type()));
841*d9f75844SAndroid Build Coastguard Worker     }
842*d9f75844SAndroid Build Coastguard Worker     report->AddString(StatsReport::kStatsValueNameCandidateIPAddress,
843*d9f75844SAndroid Build Coastguard Worker                       candidate.address().ipaddr().ToString());
844*d9f75844SAndroid Build Coastguard Worker     report->AddString(StatsReport::kStatsValueNameCandidatePortNumber,
845*d9f75844SAndroid Build Coastguard Worker                       candidate.address().PortAsString());
846*d9f75844SAndroid Build Coastguard Worker     report->AddInt(StatsReport::kStatsValueNameCandidatePriority,
847*d9f75844SAndroid Build Coastguard Worker                    candidate.priority());
848*d9f75844SAndroid Build Coastguard Worker     report->AddString(StatsReport::kStatsValueNameCandidateType,
849*d9f75844SAndroid Build Coastguard Worker                       IceCandidateTypeToStatsType(candidate.type()));
850*d9f75844SAndroid Build Coastguard Worker     report->AddString(StatsReport::kStatsValueNameCandidateTransportType,
851*d9f75844SAndroid Build Coastguard Worker                       candidate.protocol());
852*d9f75844SAndroid Build Coastguard Worker   }
853*d9f75844SAndroid Build Coastguard Worker   report->set_timestamp(stats_gathering_started_);
854*d9f75844SAndroid Build Coastguard Worker 
855*d9f75844SAndroid Build Coastguard Worker   if (local && candidate_stats.stun_stats().has_value()) {
856*d9f75844SAndroid Build Coastguard Worker     const auto& stun_stats = candidate_stats.stun_stats().value();
857*d9f75844SAndroid Build Coastguard Worker     report->AddInt64(StatsReport::kStatsValueNameSentStunKeepaliveRequests,
858*d9f75844SAndroid Build Coastguard Worker                      stun_stats.stun_binding_requests_sent);
859*d9f75844SAndroid Build Coastguard Worker     report->AddInt64(StatsReport::kStatsValueNameRecvStunKeepaliveResponses,
860*d9f75844SAndroid Build Coastguard Worker                      stun_stats.stun_binding_responses_received);
861*d9f75844SAndroid Build Coastguard Worker     report->AddFloat(StatsReport::kStatsValueNameStunKeepaliveRttTotal,
862*d9f75844SAndroid Build Coastguard Worker                      stun_stats.stun_binding_rtt_ms_total);
863*d9f75844SAndroid Build Coastguard Worker     report->AddFloat(StatsReport::kStatsValueNameStunKeepaliveRttSquaredTotal,
864*d9f75844SAndroid Build Coastguard Worker                      stun_stats.stun_binding_rtt_ms_squared_total);
865*d9f75844SAndroid Build Coastguard Worker   }
866*d9f75844SAndroid Build Coastguard Worker 
867*d9f75844SAndroid Build Coastguard Worker   return report;
868*d9f75844SAndroid Build Coastguard Worker }
869*d9f75844SAndroid Build Coastguard Worker 
ExtractSessionInfo()870*d9f75844SAndroid Build Coastguard Worker std::map<std::string, std::string> LegacyStatsCollector::ExtractSessionInfo() {
871*d9f75844SAndroid Build Coastguard Worker   TRACE_EVENT0("webrtc", "LegacyStatsCollector::ExtractSessionInfo");
872*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(pc_->signaling_thread());
873*d9f75844SAndroid Build Coastguard Worker 
874*d9f75844SAndroid Build Coastguard Worker   SessionStats stats;
875*d9f75844SAndroid Build Coastguard Worker   auto transceivers = pc_->GetTransceiversInternal();
876*d9f75844SAndroid Build Coastguard Worker   pc_->network_thread()->BlockingCall(
877*d9f75844SAndroid Build Coastguard Worker       [&, sctp_transport_name = pc_->sctp_transport_name(),
878*d9f75844SAndroid Build Coastguard Worker        sctp_mid = pc_->sctp_mid()]() mutable {
879*d9f75844SAndroid Build Coastguard Worker         stats = ExtractSessionInfo_n(
880*d9f75844SAndroid Build Coastguard Worker             transceivers, std::move(sctp_transport_name), std::move(sctp_mid));
881*d9f75844SAndroid Build Coastguard Worker       });
882*d9f75844SAndroid Build Coastguard Worker 
883*d9f75844SAndroid Build Coastguard Worker   ExtractSessionInfo_s(stats);
884*d9f75844SAndroid Build Coastguard Worker 
885*d9f75844SAndroid Build Coastguard Worker   return std::move(stats.transport_names_by_mid);
886*d9f75844SAndroid Build Coastguard Worker }
887*d9f75844SAndroid Build Coastguard Worker 
ExtractSessionInfo_n(const std::vector<rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>> & transceivers,absl::optional<std::string> sctp_transport_name,absl::optional<std::string> sctp_mid)888*d9f75844SAndroid Build Coastguard Worker LegacyStatsCollector::SessionStats LegacyStatsCollector::ExtractSessionInfo_n(
889*d9f75844SAndroid Build Coastguard Worker     const std::vector<rtc::scoped_refptr<
890*d9f75844SAndroid Build Coastguard Worker         RtpTransceiverProxyWithInternal<RtpTransceiver>>>& transceivers,
891*d9f75844SAndroid Build Coastguard Worker     absl::optional<std::string> sctp_transport_name,
892*d9f75844SAndroid Build Coastguard Worker     absl::optional<std::string> sctp_mid) {
893*d9f75844SAndroid Build Coastguard Worker   TRACE_EVENT0("webrtc", "LegacyStatsCollector::ExtractSessionInfo_n");
894*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(pc_->network_thread());
895*d9f75844SAndroid Build Coastguard Worker   rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
896*d9f75844SAndroid Build Coastguard Worker   SessionStats stats;
897*d9f75844SAndroid Build Coastguard Worker   stats.candidate_stats = pc_->GetPooledCandidateStats();
898*d9f75844SAndroid Build Coastguard Worker   for (auto& transceiver : transceivers) {
899*d9f75844SAndroid Build Coastguard Worker     cricket::ChannelInterface* channel = transceiver->internal()->channel();
900*d9f75844SAndroid Build Coastguard Worker     if (channel) {
901*d9f75844SAndroid Build Coastguard Worker       stats.transport_names_by_mid[channel->mid()] =
902*d9f75844SAndroid Build Coastguard Worker           std::string(channel->transport_name());
903*d9f75844SAndroid Build Coastguard Worker     }
904*d9f75844SAndroid Build Coastguard Worker   }
905*d9f75844SAndroid Build Coastguard Worker 
906*d9f75844SAndroid Build Coastguard Worker   if (sctp_transport_name) {
907*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(sctp_mid);
908*d9f75844SAndroid Build Coastguard Worker     stats.transport_names_by_mid[*sctp_mid] = *sctp_transport_name;
909*d9f75844SAndroid Build Coastguard Worker   }
910*d9f75844SAndroid Build Coastguard Worker 
911*d9f75844SAndroid Build Coastguard Worker   std::set<std::string> transport_names;
912*d9f75844SAndroid Build Coastguard Worker   for (const auto& entry : stats.transport_names_by_mid) {
913*d9f75844SAndroid Build Coastguard Worker     transport_names.insert(entry.second);
914*d9f75844SAndroid Build Coastguard Worker   }
915*d9f75844SAndroid Build Coastguard Worker 
916*d9f75844SAndroid Build Coastguard Worker   std::map<std::string, cricket::TransportStats> transport_stats_by_name =
917*d9f75844SAndroid Build Coastguard Worker       pc_->GetTransportStatsByNames(transport_names);
918*d9f75844SAndroid Build Coastguard Worker 
919*d9f75844SAndroid Build Coastguard Worker   for (auto& entry : transport_stats_by_name) {
920*d9f75844SAndroid Build Coastguard Worker     stats.transport_stats.emplace_back(entry.first, std::move(entry.second));
921*d9f75844SAndroid Build Coastguard Worker     TransportStats& transport = stats.transport_stats.back();
922*d9f75844SAndroid Build Coastguard Worker 
923*d9f75844SAndroid Build Coastguard Worker     // Attempt to get a copy of the certificates from the transport and
924*d9f75844SAndroid Build Coastguard Worker     // expose them in stats reports.  All channels in a transport share the
925*d9f75844SAndroid Build Coastguard Worker     // same local and remote certificates.
926*d9f75844SAndroid Build Coastguard Worker     //
927*d9f75844SAndroid Build Coastguard Worker     StatsReport::Id local_cert_report_id, remote_cert_report_id;
928*d9f75844SAndroid Build Coastguard Worker     rtc::scoped_refptr<rtc::RTCCertificate> certificate;
929*d9f75844SAndroid Build Coastguard Worker     if (pc_->GetLocalCertificate(transport.name, &certificate)) {
930*d9f75844SAndroid Build Coastguard Worker       transport.local_cert_stats =
931*d9f75844SAndroid Build Coastguard Worker           certificate->GetSSLCertificateChain().GetStats();
932*d9f75844SAndroid Build Coastguard Worker     }
933*d9f75844SAndroid Build Coastguard Worker 
934*d9f75844SAndroid Build Coastguard Worker     std::unique_ptr<rtc::SSLCertChain> remote_cert_chain =
935*d9f75844SAndroid Build Coastguard Worker         pc_->GetRemoteSSLCertChain(transport.name);
936*d9f75844SAndroid Build Coastguard Worker     if (remote_cert_chain) {
937*d9f75844SAndroid Build Coastguard Worker       transport.remote_cert_stats = remote_cert_chain->GetStats();
938*d9f75844SAndroid Build Coastguard Worker     }
939*d9f75844SAndroid Build Coastguard Worker   }
940*d9f75844SAndroid Build Coastguard Worker 
941*d9f75844SAndroid Build Coastguard Worker   return stats;
942*d9f75844SAndroid Build Coastguard Worker }
943*d9f75844SAndroid Build Coastguard Worker 
ExtractSessionInfo_s(SessionStats & session_stats)944*d9f75844SAndroid Build Coastguard Worker void LegacyStatsCollector::ExtractSessionInfo_s(SessionStats& session_stats) {
945*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(pc_->signaling_thread());
946*d9f75844SAndroid Build Coastguard Worker   rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
947*d9f75844SAndroid Build Coastguard Worker 
948*d9f75844SAndroid Build Coastguard Worker   StatsReport::Id id(StatsReport::NewTypedId(
949*d9f75844SAndroid Build Coastguard Worker       StatsReport::kStatsReportTypeSession, pc_->session_id()));
950*d9f75844SAndroid Build Coastguard Worker   StatsReport* report = reports_.ReplaceOrAddNew(id);
951*d9f75844SAndroid Build Coastguard Worker   report->set_timestamp(stats_gathering_started_);
952*d9f75844SAndroid Build Coastguard Worker   report->AddBoolean(StatsReport::kStatsValueNameInitiator,
953*d9f75844SAndroid Build Coastguard Worker                      pc_->initial_offerer());
954*d9f75844SAndroid Build Coastguard Worker 
955*d9f75844SAndroid Build Coastguard Worker   for (const cricket::CandidateStats& stats : session_stats.candidate_stats) {
956*d9f75844SAndroid Build Coastguard Worker     AddCandidateReport(stats, true);
957*d9f75844SAndroid Build Coastguard Worker   }
958*d9f75844SAndroid Build Coastguard Worker 
959*d9f75844SAndroid Build Coastguard Worker   for (auto& transport : session_stats.transport_stats) {
960*d9f75844SAndroid Build Coastguard Worker     // Attempt to get a copy of the certificates from the transport and
961*d9f75844SAndroid Build Coastguard Worker     // expose them in stats reports.  All channels in a transport share the
962*d9f75844SAndroid Build Coastguard Worker     // same local and remote certificates.
963*d9f75844SAndroid Build Coastguard Worker     //
964*d9f75844SAndroid Build Coastguard Worker     StatsReport::Id local_cert_report_id, remote_cert_report_id;
965*d9f75844SAndroid Build Coastguard Worker     if (transport.local_cert_stats) {
966*d9f75844SAndroid Build Coastguard Worker       StatsReport* r =
967*d9f75844SAndroid Build Coastguard Worker           AddCertificateReports(std::move(transport.local_cert_stats));
968*d9f75844SAndroid Build Coastguard Worker       if (r)
969*d9f75844SAndroid Build Coastguard Worker         local_cert_report_id = r->id();
970*d9f75844SAndroid Build Coastguard Worker     }
971*d9f75844SAndroid Build Coastguard Worker 
972*d9f75844SAndroid Build Coastguard Worker     if (transport.remote_cert_stats) {
973*d9f75844SAndroid Build Coastguard Worker       StatsReport* r =
974*d9f75844SAndroid Build Coastguard Worker           AddCertificateReports(std::move(transport.remote_cert_stats));
975*d9f75844SAndroid Build Coastguard Worker       if (r)
976*d9f75844SAndroid Build Coastguard Worker         remote_cert_report_id = r->id();
977*d9f75844SAndroid Build Coastguard Worker     }
978*d9f75844SAndroid Build Coastguard Worker 
979*d9f75844SAndroid Build Coastguard Worker     for (const auto& channel_iter : transport.stats.channel_stats) {
980*d9f75844SAndroid Build Coastguard Worker       StatsReport::Id channel_stats_id(
981*d9f75844SAndroid Build Coastguard Worker           StatsReport::NewComponentId(transport.name, channel_iter.component));
982*d9f75844SAndroid Build Coastguard Worker       StatsReport* channel_report = reports_.ReplaceOrAddNew(channel_stats_id);
983*d9f75844SAndroid Build Coastguard Worker       channel_report->set_timestamp(stats_gathering_started_);
984*d9f75844SAndroid Build Coastguard Worker       channel_report->AddInt(StatsReport::kStatsValueNameComponent,
985*d9f75844SAndroid Build Coastguard Worker                              channel_iter.component);
986*d9f75844SAndroid Build Coastguard Worker       if (local_cert_report_id.get()) {
987*d9f75844SAndroid Build Coastguard Worker         channel_report->AddId(StatsReport::kStatsValueNameLocalCertificateId,
988*d9f75844SAndroid Build Coastguard Worker                               local_cert_report_id);
989*d9f75844SAndroid Build Coastguard Worker       }
990*d9f75844SAndroid Build Coastguard Worker       if (remote_cert_report_id.get()) {
991*d9f75844SAndroid Build Coastguard Worker         channel_report->AddId(StatsReport::kStatsValueNameRemoteCertificateId,
992*d9f75844SAndroid Build Coastguard Worker                               remote_cert_report_id);
993*d9f75844SAndroid Build Coastguard Worker       }
994*d9f75844SAndroid Build Coastguard Worker       int srtp_crypto_suite = channel_iter.srtp_crypto_suite;
995*d9f75844SAndroid Build Coastguard Worker       if (srtp_crypto_suite != rtc::kSrtpInvalidCryptoSuite &&
996*d9f75844SAndroid Build Coastguard Worker           rtc::SrtpCryptoSuiteToName(srtp_crypto_suite).length()) {
997*d9f75844SAndroid Build Coastguard Worker         channel_report->AddString(
998*d9f75844SAndroid Build Coastguard Worker             StatsReport::kStatsValueNameSrtpCipher,
999*d9f75844SAndroid Build Coastguard Worker             rtc::SrtpCryptoSuiteToName(srtp_crypto_suite));
1000*d9f75844SAndroid Build Coastguard Worker       }
1001*d9f75844SAndroid Build Coastguard Worker       int ssl_cipher_suite = channel_iter.ssl_cipher_suite;
1002*d9f75844SAndroid Build Coastguard Worker       if (ssl_cipher_suite != rtc::kTlsNullWithNullNull &&
1003*d9f75844SAndroid Build Coastguard Worker           rtc::SSLStreamAdapter::SslCipherSuiteToName(ssl_cipher_suite)
1004*d9f75844SAndroid Build Coastguard Worker               .length()) {
1005*d9f75844SAndroid Build Coastguard Worker         channel_report->AddString(
1006*d9f75844SAndroid Build Coastguard Worker             StatsReport::kStatsValueNameDtlsCipher,
1007*d9f75844SAndroid Build Coastguard Worker             rtc::SSLStreamAdapter::SslCipherSuiteToName(ssl_cipher_suite));
1008*d9f75844SAndroid Build Coastguard Worker       }
1009*d9f75844SAndroid Build Coastguard Worker 
1010*d9f75844SAndroid Build Coastguard Worker       // Collect stats for non-pooled candidates. Note that the reports
1011*d9f75844SAndroid Build Coastguard Worker       // generated here supersedes the candidate reports generated in
1012*d9f75844SAndroid Build Coastguard Worker       // AddConnectionInfoReport below, and they may report candidates that are
1013*d9f75844SAndroid Build Coastguard Worker       // not paired. Also, the candidate report generated in
1014*d9f75844SAndroid Build Coastguard Worker       // AddConnectionInfoReport do not report port stats like StunStats.
1015*d9f75844SAndroid Build Coastguard Worker       for (const cricket::CandidateStats& stats :
1016*d9f75844SAndroid Build Coastguard Worker            channel_iter.ice_transport_stats.candidate_stats_list) {
1017*d9f75844SAndroid Build Coastguard Worker         AddCandidateReport(stats, true);
1018*d9f75844SAndroid Build Coastguard Worker       }
1019*d9f75844SAndroid Build Coastguard Worker 
1020*d9f75844SAndroid Build Coastguard Worker       int connection_id = 0;
1021*d9f75844SAndroid Build Coastguard Worker       for (const cricket::ConnectionInfo& info :
1022*d9f75844SAndroid Build Coastguard Worker            channel_iter.ice_transport_stats.connection_infos) {
1023*d9f75844SAndroid Build Coastguard Worker         StatsReport* connection_report = AddConnectionInfoReport(
1024*d9f75844SAndroid Build Coastguard Worker             transport.name, channel_iter.component, connection_id++,
1025*d9f75844SAndroid Build Coastguard Worker             channel_report->id(), info);
1026*d9f75844SAndroid Build Coastguard Worker         if (info.best_connection) {
1027*d9f75844SAndroid Build Coastguard Worker           channel_report->AddId(
1028*d9f75844SAndroid Build Coastguard Worker               StatsReport::kStatsValueNameSelectedCandidatePairId,
1029*d9f75844SAndroid Build Coastguard Worker               connection_report->id());
1030*d9f75844SAndroid Build Coastguard Worker         }
1031*d9f75844SAndroid Build Coastguard Worker       }
1032*d9f75844SAndroid Build Coastguard Worker     }
1033*d9f75844SAndroid Build Coastguard Worker   }
1034*d9f75844SAndroid Build Coastguard Worker }
1035*d9f75844SAndroid Build Coastguard Worker 
ExtractBweInfo()1036*d9f75844SAndroid Build Coastguard Worker void LegacyStatsCollector::ExtractBweInfo() {
1037*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(pc_->signaling_thread());
1038*d9f75844SAndroid Build Coastguard Worker 
1039*d9f75844SAndroid Build Coastguard Worker   if (pc_->signaling_state() == PeerConnectionInterface::kClosed)
1040*d9f75844SAndroid Build Coastguard Worker     return;
1041*d9f75844SAndroid Build Coastguard Worker 
1042*d9f75844SAndroid Build Coastguard Worker   webrtc::Call::Stats call_stats = pc_->GetCallStats();
1043*d9f75844SAndroid Build Coastguard Worker   cricket::BandwidthEstimationInfo bwe_info;
1044*d9f75844SAndroid Build Coastguard Worker   bwe_info.available_send_bandwidth = call_stats.send_bandwidth_bps;
1045*d9f75844SAndroid Build Coastguard Worker   bwe_info.available_recv_bandwidth = call_stats.recv_bandwidth_bps;
1046*d9f75844SAndroid Build Coastguard Worker   bwe_info.bucket_delay = call_stats.pacer_delay_ms;
1047*d9f75844SAndroid Build Coastguard Worker 
1048*d9f75844SAndroid Build Coastguard Worker   // Fill in target encoder bitrate, actual encoder bitrate, rtx bitrate, etc.
1049*d9f75844SAndroid Build Coastguard Worker   // TODO(holmer): Also fill this in for audio.
1050*d9f75844SAndroid Build Coastguard Worker   auto transceivers = pc_->GetTransceiversInternal();
1051*d9f75844SAndroid Build Coastguard Worker   std::vector<cricket::VideoMediaChannel*> video_media_channels;
1052*d9f75844SAndroid Build Coastguard Worker   for (const auto& transceiver : transceivers) {
1053*d9f75844SAndroid Build Coastguard Worker     if (transceiver->media_type() != cricket::MEDIA_TYPE_VIDEO) {
1054*d9f75844SAndroid Build Coastguard Worker       continue;
1055*d9f75844SAndroid Build Coastguard Worker     }
1056*d9f75844SAndroid Build Coastguard Worker     auto* video_channel = transceiver->internal()->channel();
1057*d9f75844SAndroid Build Coastguard Worker     if (video_channel) {
1058*d9f75844SAndroid Build Coastguard Worker       video_media_channels.push_back(static_cast<cricket::VideoMediaChannel*>(
1059*d9f75844SAndroid Build Coastguard Worker           video_channel->media_channel()));
1060*d9f75844SAndroid Build Coastguard Worker     }
1061*d9f75844SAndroid Build Coastguard Worker   }
1062*d9f75844SAndroid Build Coastguard Worker 
1063*d9f75844SAndroid Build Coastguard Worker   if (!video_media_channels.empty()) {
1064*d9f75844SAndroid Build Coastguard Worker     pc_->worker_thread()->BlockingCall([&] {
1065*d9f75844SAndroid Build Coastguard Worker       for (const auto& channel : video_media_channels) {
1066*d9f75844SAndroid Build Coastguard Worker         channel->FillBitrateInfo(&bwe_info);
1067*d9f75844SAndroid Build Coastguard Worker       }
1068*d9f75844SAndroid Build Coastguard Worker     });
1069*d9f75844SAndroid Build Coastguard Worker   }
1070*d9f75844SAndroid Build Coastguard Worker 
1071*d9f75844SAndroid Build Coastguard Worker   StatsReport::Id report_id(StatsReport::NewBandwidthEstimationId());
1072*d9f75844SAndroid Build Coastguard Worker   StatsReport* report = reports_.FindOrAddNew(report_id);
1073*d9f75844SAndroid Build Coastguard Worker   ExtractStats(bwe_info, stats_gathering_started_, report);
1074*d9f75844SAndroid Build Coastguard Worker }
1075*d9f75844SAndroid Build Coastguard Worker 
1076*d9f75844SAndroid Build Coastguard Worker namespace {
1077*d9f75844SAndroid Build Coastguard Worker 
1078*d9f75844SAndroid Build Coastguard Worker class MediaChannelStatsGatherer {
1079*d9f75844SAndroid Build Coastguard Worker  public:
1080*d9f75844SAndroid Build Coastguard Worker   virtual ~MediaChannelStatsGatherer() = default;
1081*d9f75844SAndroid Build Coastguard Worker 
1082*d9f75844SAndroid Build Coastguard Worker   virtual bool GetStatsOnWorkerThread() = 0;
1083*d9f75844SAndroid Build Coastguard Worker 
1084*d9f75844SAndroid Build Coastguard Worker   virtual void ExtractStats(LegacyStatsCollector* collector) const = 0;
1085*d9f75844SAndroid Build Coastguard Worker 
1086*d9f75844SAndroid Build Coastguard Worker   virtual bool HasRemoteAudio() const = 0;
1087*d9f75844SAndroid Build Coastguard Worker 
1088*d9f75844SAndroid Build Coastguard Worker   std::string mid;
1089*d9f75844SAndroid Build Coastguard Worker   std::string transport_name;
1090*d9f75844SAndroid Build Coastguard Worker   std::map<uint32_t, std::string> sender_track_id_by_ssrc;
1091*d9f75844SAndroid Build Coastguard Worker   std::map<uint32_t, std::string> receiver_track_id_by_ssrc;
1092*d9f75844SAndroid Build Coastguard Worker 
1093*d9f75844SAndroid Build Coastguard Worker  protected:
1094*d9f75844SAndroid Build Coastguard Worker   template <typename ReceiverT, typename SenderT>
ExtractSenderReceiverStats(LegacyStatsCollector * collector,const std::vector<ReceiverT> & receiver_data,const std::vector<SenderT> & sender_data) const1095*d9f75844SAndroid Build Coastguard Worker   void ExtractSenderReceiverStats(
1096*d9f75844SAndroid Build Coastguard Worker       LegacyStatsCollector* collector,
1097*d9f75844SAndroid Build Coastguard Worker       const std::vector<ReceiverT>& receiver_data,
1098*d9f75844SAndroid Build Coastguard Worker       const std::vector<SenderT>& sender_data) const {
1099*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(collector);
1100*d9f75844SAndroid Build Coastguard Worker     StatsReport::Id transport_id = StatsReport::NewComponentId(
1101*d9f75844SAndroid Build Coastguard Worker         transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
1102*d9f75844SAndroid Build Coastguard Worker     ExtractStatsFromList(receiver_data, transport_id, collector,
1103*d9f75844SAndroid Build Coastguard Worker                          StatsReport::kReceive, receiver_track_id_by_ssrc);
1104*d9f75844SAndroid Build Coastguard Worker     ExtractStatsFromList(sender_data, transport_id, collector,
1105*d9f75844SAndroid Build Coastguard Worker                          StatsReport::kSend, sender_track_id_by_ssrc);
1106*d9f75844SAndroid Build Coastguard Worker   }
1107*d9f75844SAndroid Build Coastguard Worker };
1108*d9f75844SAndroid Build Coastguard Worker 
1109*d9f75844SAndroid Build Coastguard Worker class VoiceMediaChannelStatsGatherer final : public MediaChannelStatsGatherer {
1110*d9f75844SAndroid Build Coastguard Worker  public:
VoiceMediaChannelStatsGatherer(cricket::VoiceMediaChannel * voice_media_channel)1111*d9f75844SAndroid Build Coastguard Worker   VoiceMediaChannelStatsGatherer(
1112*d9f75844SAndroid Build Coastguard Worker       cricket::VoiceMediaChannel* voice_media_channel)
1113*d9f75844SAndroid Build Coastguard Worker       : voice_media_channel_(voice_media_channel) {
1114*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(voice_media_channel_);
1115*d9f75844SAndroid Build Coastguard Worker   }
1116*d9f75844SAndroid Build Coastguard Worker 
GetStatsOnWorkerThread()1117*d9f75844SAndroid Build Coastguard Worker   bool GetStatsOnWorkerThread() override {
1118*d9f75844SAndroid Build Coastguard Worker     return voice_media_channel_->GetStats(&voice_media_info,
1119*d9f75844SAndroid Build Coastguard Worker                                           /*get_and_clear_legacy_stats=*/true);
1120*d9f75844SAndroid Build Coastguard Worker   }
1121*d9f75844SAndroid Build Coastguard Worker 
ExtractStats(LegacyStatsCollector * collector) const1122*d9f75844SAndroid Build Coastguard Worker   void ExtractStats(LegacyStatsCollector* collector) const override {
1123*d9f75844SAndroid Build Coastguard Worker     ExtractSenderReceiverStats(collector, voice_media_info.receivers,
1124*d9f75844SAndroid Build Coastguard Worker                                voice_media_info.senders);
1125*d9f75844SAndroid Build Coastguard Worker     if (voice_media_info.device_underrun_count == -2 ||
1126*d9f75844SAndroid Build Coastguard Worker         voice_media_info.device_underrun_count > 0) {
1127*d9f75844SAndroid Build Coastguard Worker       StatsReport* report = collector->PrepareADMReport();
1128*d9f75844SAndroid Build Coastguard Worker       report->AddInt(StatsReport::kStatsValueNameAudioDeviceUnderrunCounter,
1129*d9f75844SAndroid Build Coastguard Worker                      voice_media_info.device_underrun_count);
1130*d9f75844SAndroid Build Coastguard Worker     }
1131*d9f75844SAndroid Build Coastguard Worker   }
1132*d9f75844SAndroid Build Coastguard Worker 
HasRemoteAudio() const1133*d9f75844SAndroid Build Coastguard Worker   bool HasRemoteAudio() const override {
1134*d9f75844SAndroid Build Coastguard Worker     return !voice_media_info.receivers.empty();
1135*d9f75844SAndroid Build Coastguard Worker   }
1136*d9f75844SAndroid Build Coastguard Worker 
1137*d9f75844SAndroid Build Coastguard Worker  private:
1138*d9f75844SAndroid Build Coastguard Worker   cricket::VoiceMediaChannel* voice_media_channel_;
1139*d9f75844SAndroid Build Coastguard Worker   cricket::VoiceMediaInfo voice_media_info;
1140*d9f75844SAndroid Build Coastguard Worker };
1141*d9f75844SAndroid Build Coastguard Worker 
1142*d9f75844SAndroid Build Coastguard Worker class VideoMediaChannelStatsGatherer final : public MediaChannelStatsGatherer {
1143*d9f75844SAndroid Build Coastguard Worker  public:
VideoMediaChannelStatsGatherer(cricket::VideoMediaChannel * video_media_channel)1144*d9f75844SAndroid Build Coastguard Worker   VideoMediaChannelStatsGatherer(
1145*d9f75844SAndroid Build Coastguard Worker       cricket::VideoMediaChannel* video_media_channel)
1146*d9f75844SAndroid Build Coastguard Worker       : video_media_channel_(video_media_channel) {
1147*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(video_media_channel_);
1148*d9f75844SAndroid Build Coastguard Worker   }
1149*d9f75844SAndroid Build Coastguard Worker 
GetStatsOnWorkerThread()1150*d9f75844SAndroid Build Coastguard Worker   bool GetStatsOnWorkerThread() override {
1151*d9f75844SAndroid Build Coastguard Worker     return video_media_channel_->GetStats(&video_media_info);
1152*d9f75844SAndroid Build Coastguard Worker   }
1153*d9f75844SAndroid Build Coastguard Worker 
ExtractStats(LegacyStatsCollector * collector) const1154*d9f75844SAndroid Build Coastguard Worker   void ExtractStats(LegacyStatsCollector* collector) const override {
1155*d9f75844SAndroid Build Coastguard Worker     ExtractSenderReceiverStats(collector, video_media_info.receivers,
1156*d9f75844SAndroid Build Coastguard Worker                                video_media_info.aggregated_senders);
1157*d9f75844SAndroid Build Coastguard Worker   }
1158*d9f75844SAndroid Build Coastguard Worker 
HasRemoteAudio() const1159*d9f75844SAndroid Build Coastguard Worker   bool HasRemoteAudio() const override { return false; }
1160*d9f75844SAndroid Build Coastguard Worker 
1161*d9f75844SAndroid Build Coastguard Worker  private:
1162*d9f75844SAndroid Build Coastguard Worker   cricket::VideoMediaChannel* video_media_channel_;
1163*d9f75844SAndroid Build Coastguard Worker   cricket::VideoMediaInfo video_media_info;
1164*d9f75844SAndroid Build Coastguard Worker };
1165*d9f75844SAndroid Build Coastguard Worker 
CreateMediaChannelStatsGatherer(cricket::MediaChannel * channel)1166*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<MediaChannelStatsGatherer> CreateMediaChannelStatsGatherer(
1167*d9f75844SAndroid Build Coastguard Worker     cricket::MediaChannel* channel) {
1168*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(channel);
1169*d9f75844SAndroid Build Coastguard Worker   if (channel->media_type() == cricket::MEDIA_TYPE_AUDIO) {
1170*d9f75844SAndroid Build Coastguard Worker     return std::make_unique<VoiceMediaChannelStatsGatherer>(
1171*d9f75844SAndroid Build Coastguard Worker         static_cast<cricket::VoiceMediaChannel*>(channel));
1172*d9f75844SAndroid Build Coastguard Worker   } else {
1173*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK_EQ(channel->media_type(), cricket::MEDIA_TYPE_VIDEO);
1174*d9f75844SAndroid Build Coastguard Worker     return std::make_unique<VideoMediaChannelStatsGatherer>(
1175*d9f75844SAndroid Build Coastguard Worker         static_cast<cricket::VideoMediaChannel*>(channel));
1176*d9f75844SAndroid Build Coastguard Worker   }
1177*d9f75844SAndroid Build Coastguard Worker }
1178*d9f75844SAndroid Build Coastguard Worker 
1179*d9f75844SAndroid Build Coastguard Worker }  // namespace
1180*d9f75844SAndroid Build Coastguard Worker 
ExtractMediaInfo(const std::map<std::string,std::string> & transport_names_by_mid)1181*d9f75844SAndroid Build Coastguard Worker void LegacyStatsCollector::ExtractMediaInfo(
1182*d9f75844SAndroid Build Coastguard Worker     const std::map<std::string, std::string>& transport_names_by_mid) {
1183*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(pc_->signaling_thread());
1184*d9f75844SAndroid Build Coastguard Worker 
1185*d9f75844SAndroid Build Coastguard Worker   std::vector<std::unique_ptr<MediaChannelStatsGatherer>> gatherers;
1186*d9f75844SAndroid Build Coastguard Worker 
1187*d9f75844SAndroid Build Coastguard Worker   auto transceivers = pc_->GetTransceiversInternal();
1188*d9f75844SAndroid Build Coastguard Worker   {
1189*d9f75844SAndroid Build Coastguard Worker     rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
1190*d9f75844SAndroid Build Coastguard Worker     for (const auto& transceiver : transceivers) {
1191*d9f75844SAndroid Build Coastguard Worker       cricket::ChannelInterface* channel = transceiver->internal()->channel();
1192*d9f75844SAndroid Build Coastguard Worker       if (!channel) {
1193*d9f75844SAndroid Build Coastguard Worker         continue;
1194*d9f75844SAndroid Build Coastguard Worker       }
1195*d9f75844SAndroid Build Coastguard Worker       std::unique_ptr<MediaChannelStatsGatherer> gatherer =
1196*d9f75844SAndroid Build Coastguard Worker           CreateMediaChannelStatsGatherer(channel->media_channel());
1197*d9f75844SAndroid Build Coastguard Worker       gatherer->mid = channel->mid();
1198*d9f75844SAndroid Build Coastguard Worker       gatherer->transport_name = transport_names_by_mid.at(gatherer->mid);
1199*d9f75844SAndroid Build Coastguard Worker 
1200*d9f75844SAndroid Build Coastguard Worker       for (const auto& sender : transceiver->internal()->senders()) {
1201*d9f75844SAndroid Build Coastguard Worker         auto track = sender->track();
1202*d9f75844SAndroid Build Coastguard Worker         std::string track_id = (track ? track->id() : "");
1203*d9f75844SAndroid Build Coastguard Worker         gatherer->sender_track_id_by_ssrc.insert(
1204*d9f75844SAndroid Build Coastguard Worker             std::make_pair(sender->ssrc(), track_id));
1205*d9f75844SAndroid Build Coastguard Worker       }
1206*d9f75844SAndroid Build Coastguard Worker 
1207*d9f75844SAndroid Build Coastguard Worker       // Populating `receiver_track_id_by_ssrc` will be done on the worker
1208*d9f75844SAndroid Build Coastguard Worker       // thread as the `ssrc` property of the receiver needs to be accessed
1209*d9f75844SAndroid Build Coastguard Worker       // there.
1210*d9f75844SAndroid Build Coastguard Worker 
1211*d9f75844SAndroid Build Coastguard Worker       gatherers.push_back(std::move(gatherer));
1212*d9f75844SAndroid Build Coastguard Worker     }
1213*d9f75844SAndroid Build Coastguard Worker   }
1214*d9f75844SAndroid Build Coastguard Worker 
1215*d9f75844SAndroid Build Coastguard Worker   pc_->worker_thread()->BlockingCall([&] {
1216*d9f75844SAndroid Build Coastguard Worker     rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
1217*d9f75844SAndroid Build Coastguard Worker     // Populate `receiver_track_id_by_ssrc` for the gatherers.
1218*d9f75844SAndroid Build Coastguard Worker     int i = 0;
1219*d9f75844SAndroid Build Coastguard Worker     for (const auto& transceiver : transceivers) {
1220*d9f75844SAndroid Build Coastguard Worker       cricket::ChannelInterface* channel = transceiver->internal()->channel();
1221*d9f75844SAndroid Build Coastguard Worker       if (!channel)
1222*d9f75844SAndroid Build Coastguard Worker         continue;
1223*d9f75844SAndroid Build Coastguard Worker       MediaChannelStatsGatherer* gatherer = gatherers[i++].get();
1224*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK_EQ(gatherer->mid, channel->mid());
1225*d9f75844SAndroid Build Coastguard Worker 
1226*d9f75844SAndroid Build Coastguard Worker       for (const auto& receiver : transceiver->internal()->receivers()) {
1227*d9f75844SAndroid Build Coastguard Worker         gatherer->receiver_track_id_by_ssrc.insert(std::make_pair(
1228*d9f75844SAndroid Build Coastguard Worker             receiver->internal()->ssrc(), receiver->track()->id()));
1229*d9f75844SAndroid Build Coastguard Worker       }
1230*d9f75844SAndroid Build Coastguard Worker     }
1231*d9f75844SAndroid Build Coastguard Worker 
1232*d9f75844SAndroid Build Coastguard Worker     for (auto it = gatherers.begin(); it != gatherers.end();
1233*d9f75844SAndroid Build Coastguard Worker          /* incremented manually */) {
1234*d9f75844SAndroid Build Coastguard Worker       MediaChannelStatsGatherer* gatherer = it->get();
1235*d9f75844SAndroid Build Coastguard Worker       if (!gatherer->GetStatsOnWorkerThread()) {
1236*d9f75844SAndroid Build Coastguard Worker         RTC_LOG(LS_ERROR) << "Failed to get media channel stats for mid="
1237*d9f75844SAndroid Build Coastguard Worker                           << gatherer->mid;
1238*d9f75844SAndroid Build Coastguard Worker         it = gatherers.erase(it);
1239*d9f75844SAndroid Build Coastguard Worker         continue;
1240*d9f75844SAndroid Build Coastguard Worker       }
1241*d9f75844SAndroid Build Coastguard Worker       ++it;
1242*d9f75844SAndroid Build Coastguard Worker     }
1243*d9f75844SAndroid Build Coastguard Worker   });
1244*d9f75844SAndroid Build Coastguard Worker 
1245*d9f75844SAndroid Build Coastguard Worker   rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
1246*d9f75844SAndroid Build Coastguard Worker 
1247*d9f75844SAndroid Build Coastguard Worker   bool has_remote_audio = false;
1248*d9f75844SAndroid Build Coastguard Worker   for (const auto& gatherer : gatherers) {
1249*d9f75844SAndroid Build Coastguard Worker     gatherer->ExtractStats(this);
1250*d9f75844SAndroid Build Coastguard Worker     has_remote_audio |= gatherer->HasRemoteAudio();
1251*d9f75844SAndroid Build Coastguard Worker   }
1252*d9f75844SAndroid Build Coastguard Worker 
1253*d9f75844SAndroid Build Coastguard Worker   UpdateStatsFromExistingLocalAudioTracks(has_remote_audio);
1254*d9f75844SAndroid Build Coastguard Worker }
1255*d9f75844SAndroid Build Coastguard Worker 
ExtractSenderInfo()1256*d9f75844SAndroid Build Coastguard Worker void LegacyStatsCollector::ExtractSenderInfo() {
1257*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(pc_->signaling_thread());
1258*d9f75844SAndroid Build Coastguard Worker 
1259*d9f75844SAndroid Build Coastguard Worker   for (const auto& sender : pc_->GetSenders()) {
1260*d9f75844SAndroid Build Coastguard Worker     // TODO(bugs.webrtc.org/8694): SSRC == 0 currently means none. Delete check
1261*d9f75844SAndroid Build Coastguard Worker     // when that is fixed.
1262*d9f75844SAndroid Build Coastguard Worker     if (!sender->ssrc()) {
1263*d9f75844SAndroid Build Coastguard Worker       continue;
1264*d9f75844SAndroid Build Coastguard Worker     }
1265*d9f75844SAndroid Build Coastguard Worker     const rtc::scoped_refptr<MediaStreamTrackInterface> track(sender->track());
1266*d9f75844SAndroid Build Coastguard Worker     if (!track || track->kind() != MediaStreamTrackInterface::kVideoKind) {
1267*d9f75844SAndroid Build Coastguard Worker       continue;
1268*d9f75844SAndroid Build Coastguard Worker     }
1269*d9f75844SAndroid Build Coastguard Worker     // Safe, because kind() == kVideoKind implies a subclass of
1270*d9f75844SAndroid Build Coastguard Worker     // VideoTrackInterface; see mediastreaminterface.h.
1271*d9f75844SAndroid Build Coastguard Worker     VideoTrackSourceInterface* source =
1272*d9f75844SAndroid Build Coastguard Worker         static_cast<VideoTrackInterface*>(track.get())->GetSource();
1273*d9f75844SAndroid Build Coastguard Worker 
1274*d9f75844SAndroid Build Coastguard Worker     VideoTrackSourceInterface::Stats stats;
1275*d9f75844SAndroid Build Coastguard Worker     if (!source->GetStats(&stats)) {
1276*d9f75844SAndroid Build Coastguard Worker       continue;
1277*d9f75844SAndroid Build Coastguard Worker     }
1278*d9f75844SAndroid Build Coastguard Worker     const StatsReport::Id stats_id = StatsReport::NewIdWithDirection(
1279*d9f75844SAndroid Build Coastguard Worker         StatsReport::kStatsReportTypeSsrc, rtc::ToString(sender->ssrc()),
1280*d9f75844SAndroid Build Coastguard Worker         StatsReport::kSend);
1281*d9f75844SAndroid Build Coastguard Worker     StatsReport* report = reports_.FindOrAddNew(stats_id);
1282*d9f75844SAndroid Build Coastguard Worker     report->AddInt(StatsReport::kStatsValueNameFrameWidthInput,
1283*d9f75844SAndroid Build Coastguard Worker                    stats.input_width);
1284*d9f75844SAndroid Build Coastguard Worker     report->AddInt(StatsReport::kStatsValueNameFrameHeightInput,
1285*d9f75844SAndroid Build Coastguard Worker                    stats.input_height);
1286*d9f75844SAndroid Build Coastguard Worker   }
1287*d9f75844SAndroid Build Coastguard Worker }
1288*d9f75844SAndroid Build Coastguard Worker 
ExtractDataInfo()1289*d9f75844SAndroid Build Coastguard Worker void LegacyStatsCollector::ExtractDataInfo() {
1290*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(pc_->signaling_thread());
1291*d9f75844SAndroid Build Coastguard Worker 
1292*d9f75844SAndroid Build Coastguard Worker   rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
1293*d9f75844SAndroid Build Coastguard Worker 
1294*d9f75844SAndroid Build Coastguard Worker   std::vector<DataChannelStats> data_stats = pc_->GetDataChannelStats();
1295*d9f75844SAndroid Build Coastguard Worker   for (const auto& stats : data_stats) {
1296*d9f75844SAndroid Build Coastguard Worker     StatsReport::Id id(StatsReport::NewTypedIntId(
1297*d9f75844SAndroid Build Coastguard Worker         StatsReport::kStatsReportTypeDataChannel, stats.id));
1298*d9f75844SAndroid Build Coastguard Worker     StatsReport* report = reports_.ReplaceOrAddNew(id);
1299*d9f75844SAndroid Build Coastguard Worker     report->set_timestamp(stats_gathering_started_);
1300*d9f75844SAndroid Build Coastguard Worker     report->AddString(StatsReport::kStatsValueNameLabel, stats.label);
1301*d9f75844SAndroid Build Coastguard Worker     // Filter out the initial id (-1).
1302*d9f75844SAndroid Build Coastguard Worker     if (stats.id >= 0) {
1303*d9f75844SAndroid Build Coastguard Worker       report->AddInt(StatsReport::kStatsValueNameDataChannelId, stats.id);
1304*d9f75844SAndroid Build Coastguard Worker     }
1305*d9f75844SAndroid Build Coastguard Worker     report->AddString(StatsReport::kStatsValueNameProtocol, stats.protocol);
1306*d9f75844SAndroid Build Coastguard Worker     report->AddString(StatsReport::kStatsValueNameState,
1307*d9f75844SAndroid Build Coastguard Worker                       DataChannelInterface::DataStateString(stats.state));
1308*d9f75844SAndroid Build Coastguard Worker   }
1309*d9f75844SAndroid Build Coastguard Worker }
1310*d9f75844SAndroid Build Coastguard Worker 
GetReport(const StatsReport::StatsType & type,const std::string & id,StatsReport::Direction direction)1311*d9f75844SAndroid Build Coastguard Worker StatsReport* LegacyStatsCollector::GetReport(const StatsReport::StatsType& type,
1312*d9f75844SAndroid Build Coastguard Worker                                              const std::string& id,
1313*d9f75844SAndroid Build Coastguard Worker                                              StatsReport::Direction direction) {
1314*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(pc_->signaling_thread());
1315*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(type == StatsReport::kStatsReportTypeSsrc ||
1316*d9f75844SAndroid Build Coastguard Worker              type == StatsReport::kStatsReportTypeRemoteSsrc);
1317*d9f75844SAndroid Build Coastguard Worker   return reports_.Find(StatsReport::NewIdWithDirection(type, id, direction));
1318*d9f75844SAndroid Build Coastguard Worker }
1319*d9f75844SAndroid Build Coastguard Worker 
UpdateStatsFromExistingLocalAudioTracks(bool has_remote_tracks)1320*d9f75844SAndroid Build Coastguard Worker void LegacyStatsCollector::UpdateStatsFromExistingLocalAudioTracks(
1321*d9f75844SAndroid Build Coastguard Worker     bool has_remote_tracks) {
1322*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(pc_->signaling_thread());
1323*d9f75844SAndroid Build Coastguard Worker   // Loop through the existing local audio tracks.
1324*d9f75844SAndroid Build Coastguard Worker   for (const auto& it : local_audio_tracks_) {
1325*d9f75844SAndroid Build Coastguard Worker     AudioTrackInterface* track = it.first;
1326*d9f75844SAndroid Build Coastguard Worker     uint32_t ssrc = it.second;
1327*d9f75844SAndroid Build Coastguard Worker     StatsReport* report = GetReport(StatsReport::kStatsReportTypeSsrc,
1328*d9f75844SAndroid Build Coastguard Worker                                     rtc::ToString(ssrc), StatsReport::kSend);
1329*d9f75844SAndroid Build Coastguard Worker     if (report == NULL) {
1330*d9f75844SAndroid Build Coastguard Worker       // This can happen if a local audio track is added to a stream on the
1331*d9f75844SAndroid Build Coastguard Worker       // fly and the report has not been set up yet. Do nothing in this case.
1332*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_ERROR) << "Stats report does not exist for ssrc " << ssrc;
1333*d9f75844SAndroid Build Coastguard Worker       continue;
1334*d9f75844SAndroid Build Coastguard Worker     }
1335*d9f75844SAndroid Build Coastguard Worker 
1336*d9f75844SAndroid Build Coastguard Worker     // The same ssrc can be used by both local and remote audio tracks.
1337*d9f75844SAndroid Build Coastguard Worker     const StatsReport::Value* v =
1338*d9f75844SAndroid Build Coastguard Worker         report->FindValue(StatsReport::kStatsValueNameTrackId);
1339*d9f75844SAndroid Build Coastguard Worker     if (!v || v->string_val() != track->id())
1340*d9f75844SAndroid Build Coastguard Worker       continue;
1341*d9f75844SAndroid Build Coastguard Worker 
1342*d9f75844SAndroid Build Coastguard Worker     report->set_timestamp(stats_gathering_started_);
1343*d9f75844SAndroid Build Coastguard Worker     UpdateReportFromAudioTrack(track, report, has_remote_tracks);
1344*d9f75844SAndroid Build Coastguard Worker   }
1345*d9f75844SAndroid Build Coastguard Worker }
1346*d9f75844SAndroid Build Coastguard Worker 
UpdateReportFromAudioTrack(AudioTrackInterface * track,StatsReport * report,bool has_remote_tracks)1347*d9f75844SAndroid Build Coastguard Worker void LegacyStatsCollector::UpdateReportFromAudioTrack(
1348*d9f75844SAndroid Build Coastguard Worker     AudioTrackInterface* track,
1349*d9f75844SAndroid Build Coastguard Worker     StatsReport* report,
1350*d9f75844SAndroid Build Coastguard Worker     bool has_remote_tracks) {
1351*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(pc_->signaling_thread());
1352*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(track != NULL);
1353*d9f75844SAndroid Build Coastguard Worker 
1354*d9f75844SAndroid Build Coastguard Worker   // Don't overwrite report values if they're not available.
1355*d9f75844SAndroid Build Coastguard Worker   int signal_level;
1356*d9f75844SAndroid Build Coastguard Worker   if (track->GetSignalLevel(&signal_level)) {
1357*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK_GE(signal_level, 0);
1358*d9f75844SAndroid Build Coastguard Worker     report->AddInt(StatsReport::kStatsValueNameAudioInputLevel, signal_level);
1359*d9f75844SAndroid Build Coastguard Worker   }
1360*d9f75844SAndroid Build Coastguard Worker 
1361*d9f75844SAndroid Build Coastguard Worker   auto audio_processor(track->GetAudioProcessor());
1362*d9f75844SAndroid Build Coastguard Worker 
1363*d9f75844SAndroid Build Coastguard Worker   if (audio_processor.get()) {
1364*d9f75844SAndroid Build Coastguard Worker     AudioProcessorInterface::AudioProcessorStatistics stats =
1365*d9f75844SAndroid Build Coastguard Worker         audio_processor->GetStats(has_remote_tracks);
1366*d9f75844SAndroid Build Coastguard Worker 
1367*d9f75844SAndroid Build Coastguard Worker     SetAudioProcessingStats(report, stats.apm_statistics);
1368*d9f75844SAndroid Build Coastguard Worker   }
1369*d9f75844SAndroid Build Coastguard Worker }
1370*d9f75844SAndroid Build Coastguard Worker 
UpdateTrackReports()1371*d9f75844SAndroid Build Coastguard Worker void LegacyStatsCollector::UpdateTrackReports() {
1372*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(pc_->signaling_thread());
1373*d9f75844SAndroid Build Coastguard Worker 
1374*d9f75844SAndroid Build Coastguard Worker   rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
1375*d9f75844SAndroid Build Coastguard Worker 
1376*d9f75844SAndroid Build Coastguard Worker   for (const auto& entry : track_ids_) {
1377*d9f75844SAndroid Build Coastguard Worker     StatsReport* report = entry.second;
1378*d9f75844SAndroid Build Coastguard Worker     report->set_timestamp(stats_gathering_started_);
1379*d9f75844SAndroid Build Coastguard Worker   }
1380*d9f75844SAndroid Build Coastguard Worker }
1381*d9f75844SAndroid Build Coastguard Worker 
InvalidateCache()1382*d9f75844SAndroid Build Coastguard Worker void LegacyStatsCollector::InvalidateCache() {
1383*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(pc_->signaling_thread());
1384*d9f75844SAndroid Build Coastguard Worker   cache_timestamp_ms_ = 0;
1385*d9f75844SAndroid Build Coastguard Worker }
1386*d9f75844SAndroid Build Coastguard Worker 
1387*d9f75844SAndroid Build Coastguard Worker }  // namespace webrtc
1388