blob: 97dd5bdba22a3555ba7cd5e4ee8b086d11427d8d [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
kjellanderb24317b2016-02-10 07:54:43 -08002 * Copyright 2012 The WebRTC project authors. All Rights Reserved.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003 *
kjellanderb24317b2016-02-10 07:54:43 -08004 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00009 */
10
Steve Anton10542f22019-01-11 09:11:00 -080011#include "pc/stats_collector.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000012
Harald Alvestrand5761e7b2021-01-29 14:45:08 +000013#include <stddef.h>
14#include <stdint.h>
15
Harald Alvestrandc24a2182022-02-23 13:44:59 +000016#include <algorithm>
Byoungchan Leeefe46b62021-11-10 11:23:56 +090017#include <cmath>
Harald Alvestrandc24a2182022-02-23 13:44:59 +000018#include <list>
Steve Anton5dfde182018-02-06 10:34:40 -080019#include <set>
henrike@webrtc.org28e20752013-07-10 00:45:36 +000020#include <utility>
21#include <vector>
22
Harald Alvestrandc24a2182022-02-23 13:44:59 +000023#include "absl/strings/string_view.h"
Harald Alvestrand5761e7b2021-01-29 14:45:08 +000024#include "absl/types/optional.h"
25#include "api/audio_codecs/audio_encoder.h"
26#include "api/candidate.h"
27#include "api/data_channel_interface.h"
Jonas Orelande62c2f22022-03-29 11:04:48 +020028#include "api/field_trials_view.h"
Harald Alvestrand5761e7b2021-01-29 14:45:08 +000029#include "api/media_types.h"
Harald Alvestrand5761e7b2021-01-29 14:45:08 +000030#include "api/rtp_sender_interface.h"
31#include "api/scoped_refptr.h"
Artem Titovd15a5752021-02-10 14:31:24 +010032#include "api/sequence_checker.h"
Harald Alvestrand5761e7b2021-01-29 14:45:08 +000033#include "api/video/video_content_type.h"
34#include "api/video/video_timing.h"
35#include "call/call.h"
36#include "media/base/media_channel.h"
37#include "modules/audio_processing/include/audio_processing_statistics.h"
38#include "p2p/base/ice_transport_internal.h"
39#include "p2p/base/p2p_constants.h"
Harald Alvestrand5761e7b2021-01-29 14:45:08 +000040#include "pc/channel_interface.h"
41#include "pc/data_channel_utils.h"
42#include "pc/rtp_receiver.h"
Harald Alvestrandc24a2182022-02-23 13:44:59 +000043#include "pc/rtp_receiver_proxy.h"
44#include "pc/rtp_sender_proxy.h"
Harald Alvestrand5761e7b2021-01-29 14:45:08 +000045#include "pc/rtp_transceiver.h"
46#include "pc/transport_stats.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020047#include "rtc_base/checks.h"
Harald Alvestrand5761e7b2021-01-29 14:45:08 +000048#include "rtc_base/ip_address.h"
49#include "rtc_base/location.h"
50#include "rtc_base/logging.h"
51#include "rtc_base/rtc_certificate.h"
52#include "rtc_base/socket_address.h"
53#include "rtc_base/ssl_stream_adapter.h"
54#include "rtc_base/string_encode.h"
Harald Alvestrand5761e7b2021-01-29 14:45:08 +000055#include "rtc_base/thread.h"
56#include "rtc_base/time_utils.h"
Markus Handell518669d2021-06-07 13:30:46 +020057#include "rtc_base/trace_event.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000058
59namespace webrtc {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000060namespace {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000061
Niels Möllerac0a4cb2019-10-09 15:01:33 +020062// Field trial which controls whether to report standard-compliant bytes
63// sent/received per stream. If enabled, padding and headers are not included
64// in bytes sent or received.
65constexpr char kUseStandardBytesStats[] = "WebRTC-UseStandardBytesStats";
66
guoweis@webrtc.org950c5182014-12-16 23:01:31 +000067// The following is the enum RTCStatsIceCandidateType from
68// http://w3c.github.io/webrtc-stats/#rtcstatsicecandidatetype-enum such that
69// our stats report for ice candidate type could conform to that.
70const char STATSREPORT_LOCAL_PORT_TYPE[] = "host";
71const char STATSREPORT_STUN_PORT_TYPE[] = "serverreflexive";
72const char STATSREPORT_PRFLX_PORT_TYPE[] = "peerreflexive";
73const char STATSREPORT_RELAY_PORT_TYPE[] = "relayed";
74
75// Strings used by the stats collector to report adapter types. This fits the
76// general stype of http://w3c.github.io/webrtc-stats than what
77// AdapterTypeToString does.
78const char* STATSREPORT_ADAPTER_TYPE_ETHERNET = "lan";
79const char* STATSREPORT_ADAPTER_TYPE_WIFI = "wlan";
80const char* STATSREPORT_ADAPTER_TYPE_WWAN = "wwan";
81const char* STATSREPORT_ADAPTER_TYPE_VPN = "vpn";
phoglund@webrtc.org006521d2015-02-12 09:23:59 +000082const char* STATSREPORT_ADAPTER_TYPE_LOOPBACK = "loopback";
Qingsi Wang01560de2018-07-26 10:44:02 -070083const char* STATSREPORT_ADAPTER_TYPE_WILDCARD = "wildcard";
guoweis@webrtc.org950c5182014-12-16 23:01:31 +000084
Yves Gerey665174f2018-06-19 15:03:05 +020085template <typename ValueType>
tommi@webrtc.orgd3900292015-03-12 16:35:55 +000086struct TypeForAdd {
tommi@webrtc.org92f40182015-03-04 15:25:19 +000087 const StatsReport::StatsValueName name;
tommi@webrtc.orgd3900292015-03-12 16:35:55 +000088 const ValueType& value;
tommi@webrtc.org92f40182015-03-04 15:25:19 +000089};
90
tommi@webrtc.orgd3900292015-03-12 16:35:55 +000091typedef TypeForAdd<bool> BoolForAdd;
92typedef TypeForAdd<float> FloatForAdd;
Peter Boström0c4e06b2015-10-07 12:23:21 +020093typedef TypeForAdd<int64_t> Int64ForAdd;
tommi@webrtc.orgd3900292015-03-12 16:35:55 +000094typedef TypeForAdd<int> IntForAdd;
tommi@webrtc.org92f40182015-03-04 15:25:19 +000095
jbauchbe24c942015-06-22 15:06:43 -070096StatsReport* AddTrackReport(StatsCollection* reports,
97 const std::string& track_id) {
xians@webrtc.org01bda202014-07-09 07:38:38 +000098 // Adds an empty track report.
tommi@webrtc.orgd3900292015-03-12 16:35:55 +000099 StatsReport::Id id(
tommi@webrtc.org4fb7e252015-01-21 11:36:18 +0000100 StatsReport::NewTypedId(StatsReport::kStatsReportTypeTrack, track_id));
tommi@webrtc.orgd3900292015-03-12 16:35:55 +0000101 StatsReport* report = reports->ReplaceOrAddNew(id);
tommi@webrtc.org92f40182015-03-04 15:25:19 +0000102 report->AddString(StatsReport::kStatsValueNameTrackId, track_id);
jbauchbe24c942015-06-22 15:06:43 -0700103 return report;
xians@webrtc.org01bda202014-07-09 07:38:38 +0000104}
105
Harald Alvestrand75ceef22018-01-04 15:26:13 +0100106template <class Track>
107void CreateTrackReport(const Track* track,
108 StatsCollection* reports,
109 TrackIdMap* track_ids) {
110 const std::string& track_id = track->id();
111 StatsReport* report = AddTrackReport(reports, track_id);
112 RTC_DCHECK(report != nullptr);
113 (*track_ids)[track_id] = report;
114}
115
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000116template <class TrackVector>
Steve Anton36b29d12017-10-30 09:57:42 -0700117void CreateTrackReports(const TrackVector& tracks,
118 StatsCollection* reports,
119 TrackIdMap* track_ids) {
jbauchbe24c942015-06-22 15:06:43 -0700120 for (const auto& track : tracks) {
Harald Alvestrand75ceef22018-01-04 15:26:13 +0100121 CreateTrackReport(track.get(), reports, track_ids);
jbauchbe24c942015-06-22 15:06:43 -0700122 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000123}
124
tommi@webrtc.org92f40182015-03-04 15:25:19 +0000125void ExtractCommonSendProperties(const cricket::MediaSenderInfo& info,
Niels Möllerac0a4cb2019-10-09 15:01:33 +0200126 StatsReport* report,
127 bool use_standard_bytes_stats) {
tommi@webrtc.org92f40182015-03-04 15:25:19 +0000128 report->AddString(StatsReport::kStatsValueNameCodecName, info.codec_name);
Niels Möllerac0a4cb2019-10-09 15:01:33 +0200129 int64_t bytes_sent = info.payload_bytes_sent;
130 if (!use_standard_bytes_stats) {
131 bytes_sent += info.header_and_padding_bytes_sent;
132 }
133 report->AddInt64(StatsReport::kStatsValueNameBytesSent, bytes_sent);
zhihuang6ba3b192016-05-13 11:46:35 -0700134 if (info.rtt_ms >= 0) {
135 report->AddInt64(StatsReport::kStatsValueNameRtt, info.rtt_ms);
136 }
tommi@webrtc.org92f40182015-03-04 15:25:19 +0000137}
138
pbosf42376c2015-08-28 07:35:32 -0700139void ExtractCommonReceiveProperties(const cricket::MediaReceiverInfo& info,
140 StatsReport* report) {
141 report->AddString(StatsReport::kStatsValueNameCodecName, info.codec_name);
142}
143
Ivo Creusen56d46092017-11-24 17:29:59 +0100144void SetAudioProcessingStats(StatsReport* report,
Ivo Creusen56d46092017-11-24 17:29:59 +0100145 const AudioProcessingStats& apm_stats) {
Ivo Creusen56d46092017-11-24 17:29:59 +0100146 if (apm_stats.delay_median_ms) {
Ivo Creusenae026092017-11-20 13:07:16 +0100147 report->AddInt(StatsReport::kStatsValueNameEchoDelayMedian,
Ivo Creusen56d46092017-11-24 17:29:59 +0100148 *apm_stats.delay_median_ms);
Ivo Creusenae026092017-11-20 13:07:16 +0100149 }
Ivo Creusen56d46092017-11-24 17:29:59 +0100150 if (apm_stats.delay_standard_deviation_ms) {
Ivo Creusenae026092017-11-20 13:07:16 +0100151 report->AddInt(StatsReport::kStatsValueNameEchoDelayStdDev,
Ivo Creusen56d46092017-11-24 17:29:59 +0100152 *apm_stats.delay_standard_deviation_ms);
zhihuang6ba3b192016-05-13 11:46:35 -0700153 }
Ivo Creusen56d46092017-11-24 17:29:59 +0100154 if (apm_stats.echo_return_loss) {
Ivo Creusenae026092017-11-20 13:07:16 +0100155 report->AddInt(StatsReport::kStatsValueNameEchoReturnLoss,
Ivo Creusen56d46092017-11-24 17:29:59 +0100156 *apm_stats.echo_return_loss);
henrik.lundin04a057b2017-01-16 23:53:59 -0800157 }
Ivo Creusen56d46092017-11-24 17:29:59 +0100158 if (apm_stats.echo_return_loss_enhancement) {
Ivo Creusenae026092017-11-20 13:07:16 +0100159 report->AddInt(StatsReport::kStatsValueNameEchoReturnLossEnhancement,
Ivo Creusen56d46092017-11-24 17:29:59 +0100160 *apm_stats.echo_return_loss_enhancement);
Ivo Creusenae026092017-11-20 13:07:16 +0100161 }
Ivo Creusen56d46092017-11-24 17:29:59 +0100162 if (apm_stats.residual_echo_likelihood) {
Ivo Creusenae026092017-11-20 13:07:16 +0100163 report->AddFloat(StatsReport::kStatsValueNameResidualEchoLikelihood,
Ivo Creusen56d46092017-11-24 17:29:59 +0100164 static_cast<float>(*apm_stats.residual_echo_likelihood));
Ivo Creusenae026092017-11-20 13:07:16 +0100165 }
Ivo Creusen56d46092017-11-24 17:29:59 +0100166 if (apm_stats.residual_echo_likelihood_recent_max) {
ivoc4e477a12017-01-15 08:29:46 -0800167 report->AddFloat(
168 StatsReport::kStatsValueNameResidualEchoLikelihoodRecentMax,
Ivo Creusen56d46092017-11-24 17:29:59 +0100169 static_cast<float>(*apm_stats.residual_echo_likelihood_recent_max));
170 }
171 if (apm_stats.divergent_filter_fraction) {
172 report->AddFloat(StatsReport::kStatsValueNameAecDivergentFilterFraction,
173 static_cast<float>(*apm_stats.divergent_filter_fraction));
ivoc8c63a822016-10-21 04:10:03 -0700174 }
tommi@webrtc.org92f40182015-03-04 15:25:19 +0000175}
176
Niels Möllerac0a4cb2019-10-09 15:01:33 +0200177void ExtractStats(const cricket::VoiceReceiverInfo& info,
178 StatsReport* report,
179 bool use_standard_bytes_stats) {
pbosf42376c2015-08-28 07:35:32 -0700180 ExtractCommonReceiveProperties(info, report);
tommi@webrtc.org92f40182015-03-04 15:25:19 +0000181 const FloatForAdd floats[] = {
Yves Gerey665174f2018-06-19 15:03:05 +0200182 {StatsReport::kStatsValueNameExpandRate, info.expand_rate},
183 {StatsReport::kStatsValueNameSecondaryDecodedRate,
184 info.secondary_decoded_rate},
185 {StatsReport::kStatsValueNameSecondaryDiscardedRate,
186 info.secondary_discarded_rate},
187 {StatsReport::kStatsValueNameSpeechExpandRate, info.speech_expand_rate},
188 {StatsReport::kStatsValueNameAccelerateRate, info.accelerate_rate},
189 {StatsReport::kStatsValueNamePreemptiveExpandRate,
190 info.preemptive_expand_rate},
191 {StatsReport::kStatsValueNameTotalAudioEnergy, info.total_output_energy},
192 {StatsReport::kStatsValueNameTotalSamplesDuration,
193 info.total_output_duration}};
tommi@webrtc.org92f40182015-03-04 15:25:19 +0000194
195 const IntForAdd ints[] = {
Yves Gerey665174f2018-06-19 15:03:05 +0200196 {StatsReport::kStatsValueNameCurrentDelayMs, info.delay_estimate_ms},
197 {StatsReport::kStatsValueNameDecodingCNG, info.decoding_cng},
198 {StatsReport::kStatsValueNameDecodingCTN, info.decoding_calls_to_neteq},
199 {StatsReport::kStatsValueNameDecodingCTSG,
200 info.decoding_calls_to_silence_generator},
201 {StatsReport::kStatsValueNameDecodingMutedOutput,
202 info.decoding_muted_output},
203 {StatsReport::kStatsValueNameDecodingNormal, info.decoding_normal},
204 {StatsReport::kStatsValueNameDecodingPLC, info.decoding_plc},
205 {StatsReport::kStatsValueNameDecodingPLCCNG, info.decoding_plc_cng},
206 {StatsReport::kStatsValueNameJitterBufferMs, info.jitter_buffer_ms},
207 {StatsReport::kStatsValueNameJitterReceived, info.jitter_ms},
208 {StatsReport::kStatsValueNamePacketsLost, info.packets_lost},
209 {StatsReport::kStatsValueNamePacketsReceived, info.packets_rcvd},
210 {StatsReport::kStatsValueNamePreferredJitterBufferMs,
211 info.jitter_buffer_preferred_ms},
tommi@webrtc.org92f40182015-03-04 15:25:19 +0000212 };
213
214 for (const auto& f : floats)
215 report->AddFloat(f.name, f.value);
216
217 for (const auto& i : ints)
218 report->AddInt(i.name, i.value);
zhihuang6ba3b192016-05-13 11:46:35 -0700219 if (info.audio_level >= 0) {
220 report->AddInt(StatsReport::kStatsValueNameAudioOutputLevel,
221 info.audio_level);
222 }
Alex Narest5b5d97c2019-08-07 18:15:08 +0200223 if (info.decoding_codec_plc)
224 report->AddInt(StatsReport::kStatsValueNameDecodingCodecPLC,
225 info.decoding_codec_plc);
tommi@webrtc.org92f40182015-03-04 15:25:19 +0000226
Niels Möllerac0a4cb2019-10-09 15:01:33 +0200227 int64_t bytes_rcvd = info.payload_bytes_rcvd;
228 if (!use_standard_bytes_stats) {
229 bytes_rcvd += info.header_and_padding_bytes_rcvd;
230 }
231 report->AddInt64(StatsReport::kStatsValueNameBytesReceived, bytes_rcvd);
zhihuang6ba3b192016-05-13 11:46:35 -0700232 if (info.capture_start_ntp_time_ms >= 0) {
233 report->AddInt64(StatsReport::kStatsValueNameCaptureStartNtpTimeMs,
234 info.capture_start_ntp_time_ms);
235 }
fippobec70ab2016-01-28 01:27:15 -0800236 report->AddString(StatsReport::kStatsValueNameMediaType, "audio");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000237}
238
Niels Möllerac0a4cb2019-10-09 15:01:33 +0200239void ExtractStats(const cricket::VoiceSenderInfo& info,
240 StatsReport* report,
241 bool use_standard_bytes_stats) {
242 ExtractCommonSendProperties(info, report, use_standard_bytes_stats);
tommi@webrtc.org92f40182015-03-04 15:25:19 +0000243
Alessio Bazzicad7fdb952022-03-18 14:21:00 +0100244 SetAudioProcessingStats(report, info.apm_statistics);
tommi@webrtc.org92f40182015-03-04 15:25:19 +0000245
zsteine76bd3a2017-07-14 12:17:49 -0700246 const FloatForAdd floats[] = {
Yves Gerey665174f2018-06-19 15:03:05 +0200247 {StatsReport::kStatsValueNameTotalAudioEnergy, info.total_input_energy},
248 {StatsReport::kStatsValueNameTotalSamplesDuration,
249 info.total_input_duration}};
zsteine76bd3a2017-07-14 12:17:49 -0700250
andrew2fe1cb02015-11-27 17:27:35 -0800251 RTC_DCHECK_GE(info.audio_level, 0);
tommi@webrtc.org92f40182015-03-04 15:25:19 +0000252 const IntForAdd ints[] = {
Yves Gerey665174f2018-06-19 15:03:05 +0200253 {StatsReport::kStatsValueNameAudioInputLevel, info.audio_level},
254 {StatsReport::kStatsValueNameJitterReceived, info.jitter_ms},
255 {StatsReport::kStatsValueNamePacketsLost, info.packets_lost},
256 {StatsReport::kStatsValueNamePacketsSent, info.packets_sent},
tommi@webrtc.org92f40182015-03-04 15:25:19 +0000257 };
258
zsteine76bd3a2017-07-14 12:17:49 -0700259 for (const auto& f : floats) {
260 report->AddFloat(f.name, f.value);
261 }
262
zhihuang6ba3b192016-05-13 11:46:35 -0700263 for (const auto& i : ints) {
264 if (i.value >= 0) {
265 report->AddInt(i.name, i.value);
266 }
267 }
fippobec70ab2016-01-28 01:27:15 -0800268 report->AddString(StatsReport::kStatsValueNameMediaType, "audio");
ivoce1198e02017-09-08 08:13:19 -0700269 if (info.ana_statistics.bitrate_action_counter) {
270 report->AddInt(StatsReport::kStatsValueNameAnaBitrateActionCounter,
271 *info.ana_statistics.bitrate_action_counter);
272 }
273 if (info.ana_statistics.channel_action_counter) {
274 report->AddInt(StatsReport::kStatsValueNameAnaChannelActionCounter,
275 *info.ana_statistics.channel_action_counter);
276 }
277 if (info.ana_statistics.dtx_action_counter) {
278 report->AddInt(StatsReport::kStatsValueNameAnaDtxActionCounter,
279 *info.ana_statistics.dtx_action_counter);
280 }
281 if (info.ana_statistics.fec_action_counter) {
282 report->AddInt(StatsReport::kStatsValueNameAnaFecActionCounter,
283 *info.ana_statistics.fec_action_counter);
284 }
ivoc0d0b9122017-09-08 13:24:21 -0700285 if (info.ana_statistics.frame_length_increase_counter) {
286 report->AddInt(StatsReport::kStatsValueNameAnaFrameLengthIncreaseCounter,
287 *info.ana_statistics.frame_length_increase_counter);
288 }
289 if (info.ana_statistics.frame_length_decrease_counter) {
290 report->AddInt(StatsReport::kStatsValueNameAnaFrameLengthDecreaseCounter,
291 *info.ana_statistics.frame_length_decrease_counter);
292 }
293 if (info.ana_statistics.uplink_packet_loss_fraction) {
294 report->AddFloat(StatsReport::kStatsValueNameAnaUplinkPacketLossFraction,
295 *info.ana_statistics.uplink_packet_loss_fraction);
ivoce1198e02017-09-08 08:13:19 -0700296 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000297}
298
Niels Möllerac0a4cb2019-10-09 15:01:33 +0200299void ExtractStats(const cricket::VideoReceiverInfo& info,
300 StatsReport* report,
301 bool use_standard_bytes_stats) {
pbosf42376c2015-08-28 07:35:32 -0700302 ExtractCommonReceiveProperties(info, report);
Peter Boströmb7d9a972015-12-18 16:01:11 +0100303 report->AddString(StatsReport::kStatsValueNameCodecImplementationName,
304 info.decoder_implementation_name);
Niels Möllerac0a4cb2019-10-09 15:01:33 +0200305 int64_t bytes_rcvd = info.payload_bytes_rcvd;
306 if (!use_standard_bytes_stats) {
307 bytes_rcvd += info.header_and_padding_bytes_rcvd;
308 }
309 report->AddInt64(StatsReport::kStatsValueNameBytesReceived, bytes_rcvd);
zhihuang6ba3b192016-05-13 11:46:35 -0700310 if (info.capture_start_ntp_time_ms >= 0) {
311 report->AddInt64(StatsReport::kStatsValueNameCaptureStartNtpTimeMs,
312 info.capture_start_ntp_time_ms);
313 }
Benjamin Wright514f0842018-12-10 09:55:17 -0800314 if (info.first_frame_received_to_decoded_ms >= 0) {
315 report->AddInt64(StatsReport::kStatsValueNameFirstFrameReceivedToDecodedMs,
316 info.first_frame_received_to_decoded_ms);
317 }
sakalcc452e12017-02-09 04:53:45 -0800318 if (info.qp_sum)
319 report->AddInt64(StatsReport::kStatsValueNameQpSum, *info.qp_sum);
320
Jakob Ivarssone54914a2021-07-01 11:16:05 +0200321 if (info.nacks_sent) {
322 report->AddInt(StatsReport::kStatsValueNameNacksSent, *info.nacks_sent);
323 }
324
tommi@webrtc.org92f40182015-03-04 15:25:19 +0000325 const IntForAdd ints[] = {
Yves Gerey665174f2018-06-19 15:03:05 +0200326 {StatsReport::kStatsValueNameCurrentDelayMs, info.current_delay_ms},
327 {StatsReport::kStatsValueNameDecodeMs, info.decode_ms},
328 {StatsReport::kStatsValueNameFirsSent, info.firs_sent},
329 {StatsReport::kStatsValueNameFrameHeightReceived, info.frame_height},
330 {StatsReport::kStatsValueNameFrameRateDecoded, info.framerate_decoded},
331 {StatsReport::kStatsValueNameFrameRateOutput, info.framerate_output},
332 {StatsReport::kStatsValueNameFrameRateReceived, info.framerate_rcvd},
333 {StatsReport::kStatsValueNameFrameWidthReceived, info.frame_width},
334 {StatsReport::kStatsValueNameJitterBufferMs, info.jitter_buffer_ms},
335 {StatsReport::kStatsValueNameMaxDecodeMs, info.max_decode_ms},
336 {StatsReport::kStatsValueNameMinPlayoutDelayMs,
337 info.min_playout_delay_ms},
Yves Gerey665174f2018-06-19 15:03:05 +0200338 {StatsReport::kStatsValueNamePacketsLost, info.packets_lost},
339 {StatsReport::kStatsValueNamePacketsReceived, info.packets_rcvd},
340 {StatsReport::kStatsValueNamePlisSent, info.plis_sent},
341 {StatsReport::kStatsValueNameRenderDelayMs, info.render_delay_ms},
342 {StatsReport::kStatsValueNameTargetDelayMs, info.target_delay_ms},
343 {StatsReport::kStatsValueNameFramesDecoded, info.frames_decoded},
Artem Titov8a3ab0e2018-07-27 14:52:57 +0000344 };
tommi@webrtc.org92f40182015-03-04 15:25:19 +0000345
346 for (const auto& i : ints)
347 report->AddInt(i.name, i.value);
fippobec70ab2016-01-28 01:27:15 -0800348 report->AddString(StatsReport::kStatsValueNameMediaType, "video");
ilnikf04afde2017-07-07 01:26:24 -0700349
ilnik2edc6842017-07-06 03:06:50 -0700350 if (info.timing_frame_info) {
351 report->AddString(StatsReport::kStatsValueNameTimingFrameInfo,
352 info.timing_frame_info->ToString());
353 }
ilnikf04afde2017-07-07 01:26:24 -0700354
ilnika79cc282017-08-23 05:24:10 -0700355 report->AddInt64(StatsReport::kStatsValueNameInterframeDelayMaxMs,
356 info.interframe_delay_max_ms);
ilnik2e1b40b2017-09-04 07:57:17 -0700357
358 report->AddString(
359 StatsReport::kStatsValueNameContentType,
360 webrtc::videocontenttypehelpers::ToString(info.content_type));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000361}
362
Niels Möllerac0a4cb2019-10-09 15:01:33 +0200363void ExtractStats(const cricket::VideoSenderInfo& info,
364 StatsReport* report,
365 bool use_standard_bytes_stats) {
366 ExtractCommonSendProperties(info, report, use_standard_bytes_stats);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000367
Peter Boströmb7d9a972015-12-18 16:01:11 +0100368 report->AddString(StatsReport::kStatsValueNameCodecImplementationName,
369 info.encoder_implementation_name);
mallinath@webrtc.org62451dc2013-12-13 12:29:34 +0000370 report->AddBoolean(StatsReport::kStatsValueNameBandwidthLimitedResolution,
371 (info.adapt_reason & 0x2) > 0);
tommi@webrtc.org92f40182015-03-04 15:25:19 +0000372 report->AddBoolean(StatsReport::kStatsValueNameCpuLimitedResolution,
373 (info.adapt_reason & 0x1) > 0);
Åsa Perssonc3ed6302017-11-16 14:04:52 +0100374 report->AddBoolean(StatsReport::kStatsValueNameHasEnteredLowResolution,
375 info.has_entered_low_resolution);
376
sakal87da4042016-10-31 06:53:47 -0700377 if (info.qp_sum)
378 report->AddInt(StatsReport::kStatsValueNameQpSum, *info.qp_sum);
tommi@webrtc.org92f40182015-03-04 15:25:19 +0000379
380 const IntForAdd ints[] = {
Ilya Nikolaevskiy70473fc2018-02-28 16:35:03 +0100381 {StatsReport::kStatsValueNameAdaptationChanges, info.adapt_changes},
382 {StatsReport::kStatsValueNameAvgEncodeMs, info.avg_encode_ms},
383 {StatsReport::kStatsValueNameEncodeUsagePercent,
384 info.encode_usage_percent},
385 {StatsReport::kStatsValueNameFirsReceived, info.firs_rcvd},
386 {StatsReport::kStatsValueNameFrameHeightSent, info.send_frame_height},
Byoungchan Leeefe46b62021-11-10 11:23:56 +0900387 {StatsReport::kStatsValueNameFrameRateInput, round(info.framerate_input)},
Ilya Nikolaevskiy70473fc2018-02-28 16:35:03 +0100388 {StatsReport::kStatsValueNameFrameRateSent, info.framerate_sent},
389 {StatsReport::kStatsValueNameFrameWidthSent, info.send_frame_width},
390 {StatsReport::kStatsValueNameNacksReceived, info.nacks_rcvd},
391 {StatsReport::kStatsValueNamePacketsLost, info.packets_lost},
392 {StatsReport::kStatsValueNamePacketsSent, info.packets_sent},
393 {StatsReport::kStatsValueNamePlisReceived, info.plis_rcvd},
394 {StatsReport::kStatsValueNameFramesEncoded, info.frames_encoded},
395 {StatsReport::kStatsValueNameHugeFramesSent, info.huge_frames_sent},
tommi@webrtc.org92f40182015-03-04 15:25:19 +0000396 };
397
398 for (const auto& i : ints)
399 report->AddInt(i.name, i.value);
fippobec70ab2016-01-28 01:27:15 -0800400 report->AddString(StatsReport::kStatsValueNameMediaType, "video");
ilnik50864a82017-09-06 12:32:35 -0700401 report->AddString(
402 StatsReport::kStatsValueNameContentType,
403 webrtc::videocontenttypehelpers::ToString(info.content_type));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000404}
405
406void ExtractStats(const cricket::BandwidthEstimationInfo& info,
407 double stats_gathering_started,
408 StatsReport* report) {
henrikg91d6ede2015-09-17 00:24:34 -0700409 RTC_DCHECK(report->type() == StatsReport::kStatsReportTypeBwe);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000410
tommi@webrtc.orgd3900292015-03-12 16:35:55 +0000411 report->set_timestamp(stats_gathering_started);
412 const IntForAdd ints[] = {
Yves Gerey665174f2018-06-19 15:03:05 +0200413 {StatsReport::kStatsValueNameAvailableSendBandwidth,
414 info.available_send_bandwidth},
415 {StatsReport::kStatsValueNameAvailableReceiveBandwidth,
416 info.available_recv_bandwidth},
417 {StatsReport::kStatsValueNameTargetEncBitrate, info.target_enc_bitrate},
418 {StatsReport::kStatsValueNameActualEncBitrate, info.actual_enc_bitrate},
419 {StatsReport::kStatsValueNameRetransmitBitrate, info.retransmit_bitrate},
420 {StatsReport::kStatsValueNameTransmitBitrate, info.transmit_bitrate},
tommi@webrtc.orgd3900292015-03-12 16:35:55 +0000421 };
422 for (const auto& i : ints)
423 report->AddInt(i.name, i.value);
424 report->AddInt64(StatsReport::kStatsValueNameBucketDelay, info.bucket_delay);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000425}
426
wu@webrtc.org97077a32013-10-25 21:18:33 +0000427void ExtractRemoteStats(const cricket::MediaSenderInfo& info,
428 StatsReport* report) {
tommi@webrtc.org8e327c42015-01-19 20:41:26 +0000429 report->set_timestamp(info.remote_stats[0].timestamp);
wu@webrtc.org97077a32013-10-25 21:18:33 +0000430 // TODO(hta): Extract some stats here.
431}
432
433void ExtractRemoteStats(const cricket::MediaReceiverInfo& info,
434 StatsReport* report) {
tommi@webrtc.org8e327c42015-01-19 20:41:26 +0000435 report->set_timestamp(info.remote_stats[0].timestamp);
wu@webrtc.org97077a32013-10-25 21:18:33 +0000436 // TODO(hta): Extract some stats here.
437}
438
Steve Antonefe4c922019-03-27 10:26:06 -0700439std::string GetTrackIdBySsrc(
440 uint32_t ssrc,
441 StatsReport::Direction direction,
442 const std::map<uint32_t, std::string>& track_id_by_ssrc) {
443 auto it = track_id_by_ssrc.find(ssrc);
444 if (it != track_id_by_ssrc.end()) {
445 return it->second;
446 }
447 if (direction == StatsReport::kReceive) {
448 // If the track ID was not found, this might be an unsignaled receive
449 // SSRC, so try looking up by the special SSRC 0.
450 it = track_id_by_ssrc.find(0);
451 if (it != track_id_by_ssrc.end()) {
452 RTC_LOG(LS_INFO) << "Assuming SSRC=" << ssrc
453 << " is an unsignalled receive stream corresponding "
454 "to the RtpReceiver with track ID \""
455 << it->second << "\".";
456 return it->second;
457 }
458 }
Steve Antonefe4c922019-03-27 10:26:06 -0700459 return "";
460}
461
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000462// Template to extract stats from a data vector.
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +0000463// In order to use the template, the functions that are called from it,
464// ExtractStats and ExtractRemoteStats, must be defined and overloaded
465// for each type.
Yves Gerey665174f2018-06-19 15:03:05 +0200466template <typename T>
Steve Antonefe4c922019-03-27 10:26:06 -0700467void ExtractStatsFromList(
468 const std::vector<T>& data,
469 const StatsReport::Id& transport_id,
470 StatsCollector* collector,
471 StatsReport::Direction direction,
472 const std::map<uint32_t, std::string>& track_id_by_ssrc) {
tommi@webrtc.org4fb7e252015-01-21 11:36:18 +0000473 for (const auto& d : data) {
Peter Boström0c4e06b2015-10-07 12:23:21 +0200474 uint32_t ssrc = d.ssrc();
Steve Antonefe4c922019-03-27 10:26:06 -0700475 std::string track_id = GetTrackIdBySsrc(ssrc, direction, track_id_by_ssrc);
xians@webrtc.org4cb01282014-06-12 14:57:05 +0000476 // Each track can have stats for both local and remote objects.
wu@webrtc.org97077a32013-10-25 21:18:33 +0000477 // TODO(hta): Handle the case of multiple SSRCs per object.
Yves Gerey665174f2018-06-19 15:03:05 +0200478 StatsReport* report =
Steve Antonefe4c922019-03-27 10:26:06 -0700479 collector->PrepareReport(true, ssrc, track_id, transport_id, direction);
xians@webrtc.org4cb01282014-06-12 14:57:05 +0000480 if (report)
Niels Möllerac0a4cb2019-10-09 15:01:33 +0200481 ExtractStats(d, report, collector->UseStandardBytesStats());
xians@webrtc.org4cb01282014-06-12 14:57:05 +0000482
tommi@webrtc.org4fb7e252015-01-21 11:36:18 +0000483 if (!d.remote_stats.empty()) {
Steve Antonefe4c922019-03-27 10:26:06 -0700484 report = collector->PrepareReport(false, ssrc, track_id, transport_id,
485 direction);
tommi@webrtc.org4fb7e252015-01-21 11:36:18 +0000486 if (report)
487 ExtractRemoteStats(d, report);
wu@webrtc.org97077a32013-10-25 21:18:33 +0000488 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000489 }
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000490}
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000491
492} // namespace
493
guoweis@webrtc.org950c5182014-12-16 23:01:31 +0000494const char* IceCandidateTypeToStatsType(const std::string& candidate_type) {
495 if (candidate_type == cricket::LOCAL_PORT_TYPE) {
496 return STATSREPORT_LOCAL_PORT_TYPE;
497 }
498 if (candidate_type == cricket::STUN_PORT_TYPE) {
499 return STATSREPORT_STUN_PORT_TYPE;
500 }
501 if (candidate_type == cricket::PRFLX_PORT_TYPE) {
502 return STATSREPORT_PRFLX_PORT_TYPE;
503 }
504 if (candidate_type == cricket::RELAY_PORT_TYPE) {
505 return STATSREPORT_RELAY_PORT_TYPE;
506 }
Artem Titovd3251962021-11-15 16:57:07 +0100507 RTC_DCHECK_NOTREACHED();
guoweis@webrtc.org950c5182014-12-16 23:01:31 +0000508 return "unknown";
509}
510
511const char* AdapterTypeToStatsType(rtc::AdapterType type) {
512 switch (type) {
513 case rtc::ADAPTER_TYPE_UNKNOWN:
514 return "unknown";
515 case rtc::ADAPTER_TYPE_ETHERNET:
516 return STATSREPORT_ADAPTER_TYPE_ETHERNET;
517 case rtc::ADAPTER_TYPE_WIFI:
518 return STATSREPORT_ADAPTER_TYPE_WIFI;
519 case rtc::ADAPTER_TYPE_CELLULAR:
Jonas Oreland08d18062020-04-02 07:19:12 +0200520 case rtc::ADAPTER_TYPE_CELLULAR_2G:
521 case rtc::ADAPTER_TYPE_CELLULAR_3G:
522 case rtc::ADAPTER_TYPE_CELLULAR_4G:
523 case rtc::ADAPTER_TYPE_CELLULAR_5G:
guoweis@webrtc.org950c5182014-12-16 23:01:31 +0000524 return STATSREPORT_ADAPTER_TYPE_WWAN;
525 case rtc::ADAPTER_TYPE_VPN:
526 return STATSREPORT_ADAPTER_TYPE_VPN;
phoglund@webrtc.org006521d2015-02-12 09:23:59 +0000527 case rtc::ADAPTER_TYPE_LOOPBACK:
528 return STATSREPORT_ADAPTER_TYPE_LOOPBACK;
Qingsi Wang01560de2018-07-26 10:44:02 -0700529 case rtc::ADAPTER_TYPE_ANY:
530 return STATSREPORT_ADAPTER_TYPE_WILDCARD;
guoweis@webrtc.org950c5182014-12-16 23:01:31 +0000531 default:
Artem Titovd3251962021-11-15 16:57:07 +0100532 RTC_DCHECK_NOTREACHED();
guoweis@webrtc.org950c5182014-12-16 23:01:31 +0000533 return "";
534 }
535}
536
Steve Anton2d8609c2018-01-23 16:38:46 -0800537StatsCollector::StatsCollector(PeerConnectionInternal* pc)
Niels Möllerac0a4cb2019-10-09 15:01:33 +0200538 : pc_(pc),
539 stats_gathering_started_(0),
540 use_standard_bytes_stats_(
Jonas Orelanded99dae2022-03-09 09:28:10 +0100541 pc->trials().IsEnabled(kUseStandardBytesStats)) {
deadbeefab9b2d12015-10-14 11:33:11 -0700542 RTC_DCHECK(pc_);
tommi@webrtc.org03505bc2014-07-14 20:15:26 +0000543}
544
545StatsCollector::~StatsCollector() {
Tomas Gunnarssone1c8a432021-04-08 15:15:28 +0200546 RTC_DCHECK_RUN_ON(pc_->signaling_thread());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000547}
548
nissecdf37a92016-09-13 23:41:47 -0700549// Wallclock time in ms.
decurtis@webrtc.org322a5642015-02-03 22:09:37 +0000550double StatsCollector::GetTimeNow() {
Minyue Li656d6092018-08-10 15:38:52 +0200551 return static_cast<double>(rtc::TimeUTCMillis());
decurtis@webrtc.org322a5642015-02-03 22:09:37 +0000552}
553
Artem Titov880fa812021-07-30 22:30:23 +0200554// Adds a MediaStream with tracks that can be used as a `selector` in a call
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000555// to GetStats.
556void StatsCollector::AddStream(MediaStreamInterface* stream) {
Tomas Gunnarssone1c8a432021-04-08 15:15:28 +0200557 RTC_DCHECK_RUN_ON(pc_->signaling_thread());
henrikg91d6ede2015-09-17 00:24:34 -0700558 RTC_DCHECK(stream != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000559
Steve Anton36b29d12017-10-30 09:57:42 -0700560 CreateTrackReports<AudioTrackVector>(stream->GetAudioTracks(), &reports_,
561 &track_ids_);
562 CreateTrackReports<VideoTrackVector>(stream->GetVideoTracks(), &reports_,
563 &track_ids_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000564}
565
Harald Alvestrand75ceef22018-01-04 15:26:13 +0100566void StatsCollector::AddTrack(MediaStreamTrackInterface* track) {
567 if (track->kind() == MediaStreamTrackInterface::kAudioKind) {
568 CreateTrackReport(static_cast<AudioTrackInterface*>(track), &reports_,
569 &track_ids_);
570 } else if (track->kind() == MediaStreamTrackInterface::kVideoKind) {
571 CreateTrackReport(static_cast<VideoTrackInterface*>(track), &reports_,
572 &track_ids_);
573 } else {
Artem Titovd3251962021-11-15 16:57:07 +0100574 RTC_DCHECK_NOTREACHED() << "Illegal track kind";
Harald Alvestrand75ceef22018-01-04 15:26:13 +0100575 }
576}
577
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000578void StatsCollector::AddLocalAudioTrack(AudioTrackInterface* audio_track,
Peter Boström0c4e06b2015-10-07 12:23:21 +0200579 uint32_t ssrc) {
Tomas Gunnarssone1c8a432021-04-08 15:15:28 +0200580 RTC_DCHECK_RUN_ON(pc_->signaling_thread());
henrikg91d6ede2015-09-17 00:24:34 -0700581 RTC_DCHECK(audio_track != NULL);
kwiberg5377bc72016-10-04 13:46:56 -0700582#if RTC_DCHECK_IS_ON
tommi@webrtc.orgd3900292015-03-12 16:35:55 +0000583 for (const auto& track : local_audio_tracks_)
henrikg91d6ede2015-09-17 00:24:34 -0700584 RTC_DCHECK(track.first != audio_track || track.second != ssrc);
tommi@webrtc.orgd3900292015-03-12 16:35:55 +0000585#endif
xians@webrtc.org01bda202014-07-09 07:38:38 +0000586
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000587 local_audio_tracks_.push_back(std::make_pair(audio_track, ssrc));
xians@webrtc.org01bda202014-07-09 07:38:38 +0000588
589 // Create the kStatsReportTypeTrack report for the new track if there is no
590 // report yet.
tommi@webrtc.orgd3900292015-03-12 16:35:55 +0000591 StatsReport::Id id(StatsReport::NewTypedId(StatsReport::kStatsReportTypeTrack,
592 audio_track->id()));
593 StatsReport* report = reports_.Find(id);
tommi@webrtc.org4fb7e252015-01-21 11:36:18 +0000594 if (!report) {
tommi@webrtc.orgd3900292015-03-12 16:35:55 +0000595 report = reports_.InsertNew(id);
tommi@webrtc.org92f40182015-03-04 15:25:19 +0000596 report->AddString(StatsReport::kStatsValueNameTrackId, audio_track->id());
tommi@webrtc.org4fb7e252015-01-21 11:36:18 +0000597 }
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000598}
599
600void StatsCollector::RemoveLocalAudioTrack(AudioTrackInterface* audio_track,
Peter Boström0c4e06b2015-10-07 12:23:21 +0200601 uint32_t ssrc) {
henrikg91d6ede2015-09-17 00:24:34 -0700602 RTC_DCHECK(audio_track != NULL);
deadbeef19b3a552017-06-16 20:19:08 -0700603 local_audio_tracks_.erase(
604 std::remove_if(
605 local_audio_tracks_.begin(), local_audio_tracks_.end(),
606 [audio_track, ssrc](const LocalAudioTrackVector::value_type& track) {
607 return track.first == audio_track && track.second == ssrc;
608 }),
609 local_audio_tracks_.end());
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000610}
611
tommi@webrtc.org5b06b062014-08-15 08:38:30 +0000612void StatsCollector::GetStats(MediaStreamTrackInterface* track,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000613 StatsReports* reports) {
Tomas Gunnarssone1c8a432021-04-08 15:15:28 +0200614 RTC_DCHECK_RUN_ON(pc_->signaling_thread());
henrikg91d6ede2015-09-17 00:24:34 -0700615 RTC_DCHECK(reports != NULL);
616 RTC_DCHECK(reports->empty());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000617
tommi@webrtc.orgd3900292015-03-12 16:35:55 +0000618 rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
619
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000620 if (!track) {
tommi@webrtc.org4fb7e252015-01-21 11:36:18 +0000621 reports->reserve(reports_.size());
622 for (auto* r : reports_)
623 reports->push_back(r);
tommi@webrtc.org5b06b062014-08-15 08:38:30 +0000624 return;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000625 }
626
tommi@webrtc.org4fb7e252015-01-21 11:36:18 +0000627 StatsReport* report = reports_.Find(StatsReport::NewTypedId(
Steve Anton978b8762017-09-29 12:15:02 -0700628 StatsReport::kStatsReportTypeSession, pc_->session_id()));
tommi@webrtc.org5b06b062014-08-15 08:38:30 +0000629 if (report)
630 reports->push_back(report);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000631
Yves Gerey665174f2018-06-19 15:03:05 +0200632 report = reports_.Find(
633 StatsReport::NewTypedId(StatsReport::kStatsReportTypeTrack, track->id()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000634
tommi@webrtc.org5b06b062014-08-15 08:38:30 +0000635 if (!report)
636 return;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000637
tommi@webrtc.org5b06b062014-08-15 08:38:30 +0000638 reports->push_back(report);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000639
640 std::string track_id;
tommi@webrtc.org4fb7e252015-01-21 11:36:18 +0000641 for (const auto* r : reports_) {
642 if (r->type() != StatsReport::kStatsReportTypeSsrc)
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000643 continue;
tommi@webrtc.org5b06b062014-08-15 08:38:30 +0000644
tommi@webrtc.org4fb7e252015-01-21 11:36:18 +0000645 const StatsReport::Value* v =
646 r->FindValue(StatsReport::kStatsValueNameTrackId);
tommi@webrtc.orgd3900292015-03-12 16:35:55 +0000647 if (v && v->string_val() == track->id())
tommi@webrtc.org4fb7e252015-01-21 11:36:18 +0000648 reports->push_back(r);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000649 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000650}
651
Yves Gerey665174f2018-06-19 15:03:05 +0200652void StatsCollector::UpdateStats(
653 PeerConnectionInterface::StatsOutputLevel level) {
Tomas Gunnarssone1c8a432021-04-08 15:15:28 +0200654 RTC_DCHECK_RUN_ON(pc_->signaling_thread());
Taylor Brandstetter80d661c2021-02-10 14:11:57 -0800655 // Calls to UpdateStats() that occur less than kMinGatherStatsPeriodMs apart
656 // will be ignored. Using a monotonic clock specifically for this, while using
657 // a UTC clock for the reports themselves.
658 const int64_t kMinGatherStatsPeriodMs = 50;
659 int64_t cache_now_ms = rtc::TimeMillis();
660 if (cache_timestamp_ms_ != 0 &&
661 cache_timestamp_ms_ + kMinGatherStatsPeriodMs > cache_now_ms) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000662 return;
663 }
Taylor Brandstetter80d661c2021-02-10 14:11:57 -0800664 cache_timestamp_ms_ = cache_now_ms;
665 stats_gathering_started_ = GetTimeNow();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000666
Tomas Gunnarssone1c8a432021-04-08 15:15:28 +0200667 // TODO(tommi): ExtractSessionInfo now has a single hop to the network thread
668 // to fetch stats, then applies them on the signaling thread. See if we need
669 // to do this synchronously or if updating the stats without blocking is safe.
670 std::map<std::string, std::string> transport_names_by_mid =
671 ExtractSessionInfo();
672
Steve Anton75737c02017-11-06 10:37:17 -0800673 // TODO(tommi): All of these hop over to the worker thread to fetch
Niels Möller572f50f2021-03-29 09:49:49 +0200674 // information. We could post a task to run all of these and post
Steve Anton75737c02017-11-06 10:37:17 -0800675 // the information back to the signaling thread where we can create and
676 // update stats reports. That would also clean up the threading story a bit
677 // since we'd be creating/updating the stats report objects consistently on
678 // the same thread (this class has no locks right now).
Steve Anton75737c02017-11-06 10:37:17 -0800679 ExtractBweInfo();
Tomas Gunnarssone1c8a432021-04-08 15:15:28 +0200680 ExtractMediaInfo(transport_names_by_mid);
Steve Anton75737c02017-11-06 10:37:17 -0800681 ExtractSenderInfo();
682 ExtractDataInfo();
683 UpdateTrackReports();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000684}
685
Yves Gerey665174f2018-06-19 15:03:05 +0200686StatsReport* StatsCollector::PrepareReport(bool local,
687 uint32_t ssrc,
Steve Antonefe4c922019-03-27 10:26:06 -0700688 const std::string& track_id,
Yves Gerey665174f2018-06-19 15:03:05 +0200689 const StatsReport::Id& transport_id,
690 StatsReport::Direction direction) {
Tomas Gunnarssone1c8a432021-04-08 15:15:28 +0200691 RTC_DCHECK_RUN_ON(pc_->signaling_thread());
tommi@webrtc.orgd3900292015-03-12 16:35:55 +0000692 StatsReport::Id id(StatsReport::NewIdWithDirection(
Peter Boström0c4e06b2015-10-07 12:23:21 +0200693 local ? StatsReport::kStatsReportTypeSsrc
694 : StatsReport::kStatsReportTypeRemoteSsrc,
Jonas Olsson6b1985d2018-07-05 11:59:48 +0200695 rtc::ToString(ssrc), direction));
tommi@webrtc.orgd3900292015-03-12 16:35:55 +0000696 StatsReport* report = reports_.Find(id);
Steve Antona41959e2018-11-28 11:15:33 -0800697 if (!report) {
tommi@webrtc.orgd3900292015-03-12 16:35:55 +0000698 report = reports_.InsertNew(id);
Steve Antona41959e2018-11-28 11:15:33 -0800699 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000700
tommi@webrtc.org4fb7e252015-01-21 11:36:18 +0000701 // FYI - for remote reports, the timestamp will be overwritten later.
tommi@webrtc.org8e327c42015-01-19 20:41:26 +0000702 report->set_timestamp(stats_gathering_started_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000703
tommi@webrtc.orgd3900292015-03-12 16:35:55 +0000704 report->AddInt64(StatsReport::kStatsValueNameSsrc, ssrc);
Taylor Brandstettera4653442018-06-19 09:44:26 -0700705 if (!track_id.empty()) {
Steve Antonefe4c922019-03-27 10:26:06 -0700706 report->AddString(StatsReport::kStatsValueNameTrackId, track_id);
Taylor Brandstettera4653442018-06-19 09:44:26 -0700707 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000708 // Add the mapping of SSRC to transport.
tommi@webrtc.orgd3900292015-03-12 16:35:55 +0000709 report->AddId(StatsReport::kStatsValueNameTransportId, transport_id);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000710 return report;
711}
712
Alex Narestbbeb1092019-08-16 11:49:04 +0200713StatsReport* StatsCollector::PrepareADMReport() {
Tomas Gunnarssone1c8a432021-04-08 15:15:28 +0200714 RTC_DCHECK_RUN_ON(pc_->signaling_thread());
Alex Narestbbeb1092019-08-16 11:49:04 +0200715 StatsReport::Id id(StatsReport::NewTypedId(
716 StatsReport::kStatsReportTypeSession, pc_->session_id()));
717 StatsReport* report = reports_.FindOrAddNew(id);
718 return report;
719}
720
zhihuange9e94c32016-11-04 11:38:15 -0700721bool StatsCollector::IsValidTrack(const std::string& track_id) {
722 return reports_.Find(StatsReport::NewTypedId(
723 StatsReport::kStatsReportTypeTrack, track_id)) != nullptr;
724}
725
tommi@webrtc.orgd3900292015-03-12 16:35:55 +0000726StatsReport* StatsCollector::AddCertificateReports(
Taylor Brandstetterc3928662018-02-23 13:04:51 -0800727 std::unique_ptr<rtc::SSLCertificateStats> cert_stats) {
Tomas Gunnarssone1c8a432021-04-08 15:15:28 +0200728 RTC_DCHECK_RUN_ON(pc_->signaling_thread());
wu@webrtc.org4551b792013-10-09 15:37:36 +0000729
hbose29352b2016-08-25 03:52:38 -0700730 StatsReport* first_report = nullptr;
731 StatsReport* prev_report = nullptr;
Taylor Brandstetterc3928662018-02-23 13:04:51 -0800732 for (rtc::SSLCertificateStats* stats = cert_stats.get(); stats;
hbose29352b2016-08-25 03:52:38 -0700733 stats = stats->issuer.get()) {
734 StatsReport::Id id(StatsReport::NewTypedId(
735 StatsReport::kStatsReportTypeCertificate, stats->fingerprint));
736
737 StatsReport* report = reports_.ReplaceOrAddNew(id);
738 report->set_timestamp(stats_gathering_started_);
739 report->AddString(StatsReport::kStatsValueNameFingerprint,
740 stats->fingerprint);
741 report->AddString(StatsReport::kStatsValueNameFingerprintAlgorithm,
742 stats->fingerprint_algorithm);
743 report->AddString(StatsReport::kStatsValueNameDer,
744 stats->base64_certificate);
745 if (!first_report)
746 first_report = report;
747 else
748 prev_report->AddId(StatsReport::kStatsValueNameIssuerId, id);
749 prev_report = report;
wu@webrtc.org4551b792013-10-09 15:37:36 +0000750 }
hbose29352b2016-08-25 03:52:38 -0700751 return first_report;
wu@webrtc.org4551b792013-10-09 15:37:36 +0000752}
753
tommi@webrtc.orgd3900292015-03-12 16:35:55 +0000754StatsReport* StatsCollector::AddConnectionInfoReport(
Yves Gerey665174f2018-06-19 15:03:05 +0200755 const std::string& content_name,
756 int component,
757 int connection_id,
tommi@webrtc.orgd3900292015-03-12 16:35:55 +0000758 const StatsReport::Id& channel_report_id,
759 const cricket::ConnectionInfo& info) {
Yves Gerey665174f2018-06-19 15:03:05 +0200760 StatsReport::Id id(
761 StatsReport::NewCandidatePairId(content_name, component, connection_id));
tommi@webrtc.orgd3900292015-03-12 16:35:55 +0000762 StatsReport* report = reports_.ReplaceOrAddNew(id);
763 report->set_timestamp(stats_gathering_started_);
764
765 const BoolForAdd bools[] = {
Yves Gerey665174f2018-06-19 15:03:05 +0200766 {StatsReport::kStatsValueNameActiveConnection, info.best_connection},
767 {StatsReport::kStatsValueNameReceiving, info.receiving},
768 {StatsReport::kStatsValueNameWritable, info.writable},
tommi@webrtc.orgd3900292015-03-12 16:35:55 +0000769 };
770 for (const auto& b : bools)
771 report->AddBoolean(b.name, b.value);
772
773 report->AddId(StatsReport::kStatsValueNameChannelId, channel_report_id);
Qingsi Wang72a43a12018-02-20 16:03:18 -0800774 cricket::CandidateStats local_candidate_stats(info.local_candidate);
775 cricket::CandidateStats remote_candidate_stats(info.remote_candidate);
tommi@webrtc.orgd3900292015-03-12 16:35:55 +0000776 report->AddId(StatsReport::kStatsValueNameLocalCandidateId,
Qingsi Wang72a43a12018-02-20 16:03:18 -0800777 AddCandidateReport(local_candidate_stats, true)->id());
tommi@webrtc.orgd3900292015-03-12 16:35:55 +0000778 report->AddId(StatsReport::kStatsValueNameRemoteCandidateId,
Qingsi Wang72a43a12018-02-20 16:03:18 -0800779 AddCandidateReport(remote_candidate_stats, false)->id());
tommi@webrtc.orgd3900292015-03-12 16:35:55 +0000780
781 const Int64ForAdd int64s[] = {
zhihuang5ecf16c2016-06-01 17:09:15 -0700782 {StatsReport::kStatsValueNameBytesReceived, info.recv_total_bytes},
783 {StatsReport::kStatsValueNameBytesSent, info.sent_total_bytes},
784 {StatsReport::kStatsValueNamePacketsSent, info.sent_total_packets},
785 {StatsReport::kStatsValueNameRtt, info.rtt},
786 {StatsReport::kStatsValueNameSendPacketsDiscarded,
787 info.sent_discarded_packets},
788 {StatsReport::kStatsValueNameSentPingRequestsTotal,
789 info.sent_ping_requests_total},
790 {StatsReport::kStatsValueNameSentPingRequestsBeforeFirstResponse,
791 info.sent_ping_requests_before_first_response},
792 {StatsReport::kStatsValueNameSentPingResponses, info.sent_ping_responses},
793 {StatsReport::kStatsValueNameRecvPingRequests, info.recv_ping_requests},
794 {StatsReport::kStatsValueNameRecvPingResponses, info.recv_ping_responses},
tommi@webrtc.orgd3900292015-03-12 16:35:55 +0000795 };
796 for (const auto& i : int64s)
797 report->AddInt64(i.name, i.value);
798
799 report->AddString(StatsReport::kStatsValueNameLocalAddress,
800 info.local_candidate.address().ToString());
801 report->AddString(StatsReport::kStatsValueNameLocalCandidateType,
802 info.local_candidate.type());
803 report->AddString(StatsReport::kStatsValueNameRemoteAddress,
804 info.remote_candidate.address().ToString());
805 report->AddString(StatsReport::kStatsValueNameRemoteCandidateType,
806 info.remote_candidate.type());
807 report->AddString(StatsReport::kStatsValueNameTransportType,
808 info.local_candidate.protocol());
Jonas Oreland0ee44222021-12-02 10:48:45 +0100809 report->AddString(StatsReport::kStatsValueNameLocalCandidateRelayProtocol,
810 info.local_candidate.relay_protocol());
tommi@webrtc.orgd3900292015-03-12 16:35:55 +0000811
812 return report;
813}
814
815StatsReport* StatsCollector::AddCandidateReport(
Qingsi Wang72a43a12018-02-20 16:03:18 -0800816 const cricket::CandidateStats& candidate_stats,
tommi@webrtc.org4fb7e252015-01-21 11:36:18 +0000817 bool local) {
Tommi2e154682021-06-07 21:16:38 +0200818 const auto& candidate = candidate_stats.candidate();
tommi@webrtc.orgd3900292015-03-12 16:35:55 +0000819 StatsReport::Id id(StatsReport::NewCandidateId(local, candidate.id()));
820 StatsReport* report = reports_.Find(id);
guoweis@webrtc.org950c5182014-12-16 23:01:31 +0000821 if (!report) {
tommi@webrtc.orgd3900292015-03-12 16:35:55 +0000822 report = reports_.InsertNew(id);
tommi@webrtc.org4fb7e252015-01-21 11:36:18 +0000823 report->set_timestamp(stats_gathering_started_);
824 if (local) {
tommi@webrtc.org92f40182015-03-04 15:25:19 +0000825 report->AddString(StatsReport::kStatsValueNameCandidateNetworkType,
826 AdapterTypeToStatsType(candidate.network_type()));
guoweis@webrtc.org950c5182014-12-16 23:01:31 +0000827 }
tommi@webrtc.org92f40182015-03-04 15:25:19 +0000828 report->AddString(StatsReport::kStatsValueNameCandidateIPAddress,
829 candidate.address().ipaddr().ToString());
830 report->AddString(StatsReport::kStatsValueNameCandidatePortNumber,
831 candidate.address().PortAsString());
832 report->AddInt(StatsReport::kStatsValueNameCandidatePriority,
833 candidate.priority());
834 report->AddString(StatsReport::kStatsValueNameCandidateType,
835 IceCandidateTypeToStatsType(candidate.type()));
836 report->AddString(StatsReport::kStatsValueNameCandidateTransportType,
837 candidate.protocol());
guoweis@webrtc.org950c5182014-12-16 23:01:31 +0000838 }
Philipp Hanckefe0b4992019-03-22 09:00:50 +0100839 report->set_timestamp(stats_gathering_started_);
guoweis@webrtc.org950c5182014-12-16 23:01:31 +0000840
Tommi2e154682021-06-07 21:16:38 +0200841 if (local && candidate_stats.stun_stats().has_value()) {
842 const auto& stun_stats = candidate_stats.stun_stats().value();
Qingsi Wang4ff54432018-03-01 18:25:20 -0800843 report->AddInt64(StatsReport::kStatsValueNameSentStunKeepaliveRequests,
844 stun_stats.stun_binding_requests_sent);
845 report->AddInt64(StatsReport::kStatsValueNameRecvStunKeepaliveResponses,
846 stun_stats.stun_binding_responses_received);
847 report->AddFloat(StatsReport::kStatsValueNameStunKeepaliveRttTotal,
848 stun_stats.stun_binding_rtt_ms_total);
849 report->AddFloat(StatsReport::kStatsValueNameStunKeepaliveRttSquaredTotal,
850 stun_stats.stun_binding_rtt_ms_squared_total);
851 }
852
tommi@webrtc.orgd3900292015-03-12 16:35:55 +0000853 return report;
guoweis@webrtc.org950c5182014-12-16 23:01:31 +0000854}
855
Tomas Gunnarssone1c8a432021-04-08 15:15:28 +0200856std::map<std::string, std::string> StatsCollector::ExtractSessionInfo() {
Markus Handell518669d2021-06-07 13:30:46 +0200857 TRACE_EVENT0("webrtc", "StatsCollector::ExtractSessionInfo");
Tomas Gunnarssone1c8a432021-04-08 15:15:28 +0200858 RTC_DCHECK_RUN_ON(pc_->signaling_thread());
tommi@webrtc.orgd3900292015-03-12 16:35:55 +0000859
Tomas Gunnarssone1c8a432021-04-08 15:15:28 +0200860 SessionStats stats;
Tomas Gunnarssonbfd9ba82021-04-18 11:55:57 +0200861 auto transceivers = pc_->GetTransceiversInternal();
Tomas Gunnarssone1c8a432021-04-08 15:15:28 +0200862 pc_->network_thread()->Invoke<void>(
Tomas Gunnarssonbfd9ba82021-04-18 11:55:57 +0200863 RTC_FROM_HERE, [&, sctp_transport_name = pc_->sctp_transport_name(),
864 sctp_mid = pc_->sctp_mid()]() mutable {
865 stats = ExtractSessionInfo_n(
866 transceivers, std::move(sctp_transport_name), std::move(sctp_mid));
867 });
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000868
Tomas Gunnarssone1c8a432021-04-08 15:15:28 +0200869 ExtractSessionInfo_s(stats);
Qingsi Wang72a43a12018-02-20 16:03:18 -0800870
Tomas Gunnarssone1c8a432021-04-08 15:15:28 +0200871 return std::move(stats.transport_names_by_mid);
872}
873
Tomas Gunnarssonbfd9ba82021-04-18 11:55:57 +0200874StatsCollector::SessionStats StatsCollector::ExtractSessionInfo_n(
875 const std::vector<rtc::scoped_refptr<
876 RtpTransceiverProxyWithInternal<RtpTransceiver>>>& transceivers,
877 absl::optional<std::string> sctp_transport_name,
878 absl::optional<std::string> sctp_mid) {
Markus Handell518669d2021-06-07 13:30:46 +0200879 TRACE_EVENT0("webrtc", "StatsCollector::ExtractSessionInfo_n");
Tomas Gunnarssone1c8a432021-04-08 15:15:28 +0200880 RTC_DCHECK_RUN_ON(pc_->network_thread());
881 rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
882 SessionStats stats;
883 stats.candidate_stats = pc_->GetPooledCandidateStats();
Tomas Gunnarssonbfd9ba82021-04-18 11:55:57 +0200884 for (auto& transceiver : transceivers) {
885 cricket::ChannelInterface* channel = transceiver->internal()->channel();
886 if (channel) {
Tomas Gunnarsson5411b172022-01-24 08:45:26 +0100887 stats.transport_names_by_mid[channel->mid()] =
Tomas Gunnarsson94f01942022-01-03 14:59:12 +0000888 std::string(channel->transport_name());
Tomas Gunnarssonbfd9ba82021-04-18 11:55:57 +0200889 }
890 }
891
892 if (sctp_transport_name) {
893 RTC_DCHECK(sctp_mid);
894 stats.transport_names_by_mid[*sctp_mid] = *sctp_transport_name;
895 }
Qingsi Wang72a43a12018-02-20 16:03:18 -0800896
Steve Anton5dfde182018-02-06 10:34:40 -0800897 std::set<std::string> transport_names;
Tomas Gunnarssone1c8a432021-04-08 15:15:28 +0200898 for (const auto& entry : stats.transport_names_by_mid) {
Steve Anton5dfde182018-02-06 10:34:40 -0800899 transport_names.insert(entry.second);
pthatcher@webrtc.orgc04a97f2015-03-16 19:31:40 +0000900 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000901
Steve Anton5dfde182018-02-06 10:34:40 -0800902 std::map<std::string, cricket::TransportStats> transport_stats_by_name =
903 pc_->GetTransportStatsByNames(transport_names);
904
Tomas Gunnarssone1c8a432021-04-08 15:15:28 +0200905 for (auto& entry : transport_stats_by_name) {
906 stats.transport_stats.emplace_back(entry.first, std::move(entry.second));
907 TransportStats& transport = stats.transport_stats.back();
Steve Anton5dfde182018-02-06 10:34:40 -0800908
pthatcher@webrtc.orgc04a97f2015-03-16 19:31:40 +0000909 // Attempt to get a copy of the certificates from the transport and
910 // expose them in stats reports. All channels in a transport share the
911 // same local and remote certificates.
912 //
pthatcher@webrtc.orgc04a97f2015-03-16 19:31:40 +0000913 StatsReport::Id local_cert_report_id, remote_cert_report_id;
Henrik Boströmd8281982015-08-27 10:12:24 +0200914 rtc::scoped_refptr<rtc::RTCCertificate> certificate;
Tomas Gunnarssone1c8a432021-04-08 15:15:28 +0200915 if (pc_->GetLocalCertificate(transport.name, &certificate)) {
916 transport.local_cert_stats =
917 certificate->GetSSLCertificateChain().GetStats();
918 }
919
920 std::unique_ptr<rtc::SSLCertChain> remote_cert_chain =
921 pc_->GetRemoteSSLCertChain(transport.name);
922 if (remote_cert_chain) {
923 transport.remote_cert_stats = remote_cert_chain->GetStats();
924 }
925 }
926
927 return stats;
928}
929
930void StatsCollector::ExtractSessionInfo_s(SessionStats& session_stats) {
931 RTC_DCHECK_RUN_ON(pc_->signaling_thread());
932 rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
933
934 StatsReport::Id id(StatsReport::NewTypedId(
935 StatsReport::kStatsReportTypeSession, pc_->session_id()));
936 StatsReport* report = reports_.ReplaceOrAddNew(id);
937 report->set_timestamp(stats_gathering_started_);
938 report->AddBoolean(StatsReport::kStatsValueNameInitiator,
939 pc_->initial_offerer());
940
941 for (const cricket::CandidateStats& stats : session_stats.candidate_stats) {
942 AddCandidateReport(stats, true);
943 }
944
945 for (auto& transport : session_stats.transport_stats) {
946 // Attempt to get a copy of the certificates from the transport and
947 // expose them in stats reports. All channels in a transport share the
948 // same local and remote certificates.
949 //
950 StatsReport::Id local_cert_report_id, remote_cert_report_id;
951 if (transport.local_cert_stats) {
952 StatsReport* r =
953 AddCertificateReports(std::move(transport.local_cert_stats));
pthatcher@webrtc.orgc04a97f2015-03-16 19:31:40 +0000954 if (r)
955 local_cert_report_id = r->id();
956 }
957
Tomas Gunnarssone1c8a432021-04-08 15:15:28 +0200958 if (transport.remote_cert_stats) {
959 StatsReport* r =
960 AddCertificateReports(std::move(transport.remote_cert_stats));
pthatcher@webrtc.orgc04a97f2015-03-16 19:31:40 +0000961 if (r)
962 remote_cert_report_id = r->id();
963 }
964
Tomas Gunnarssone1c8a432021-04-08 15:15:28 +0200965 for (const auto& channel_iter : transport.stats.channel_stats) {
Mirko Bonadei54c90f22021-10-03 11:26:11 +0200966 StatsReport::Id channel_stats_id(
Tomas Gunnarssone1c8a432021-04-08 15:15:28 +0200967 StatsReport::NewComponentId(transport.name, channel_iter.component));
Mirko Bonadei54c90f22021-10-03 11:26:11 +0200968 StatsReport* channel_report = reports_.ReplaceOrAddNew(channel_stats_id);
pthatcher@webrtc.orgc04a97f2015-03-16 19:31:40 +0000969 channel_report->set_timestamp(stats_gathering_started_);
970 channel_report->AddInt(StatsReport::kStatsValueNameComponent,
971 channel_iter.component);
972 if (local_cert_report_id.get()) {
973 channel_report->AddId(StatsReport::kStatsValueNameLocalCertificateId,
974 local_cert_report_id);
975 }
976 if (remote_cert_report_id.get()) {
977 channel_report->AddId(StatsReport::kStatsValueNameRemoteCertificateId,
978 remote_cert_report_id);
979 }
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800980 int srtp_crypto_suite = channel_iter.srtp_crypto_suite;
Mirko Bonadei7750d802021-07-26 17:27:42 +0200981 if (srtp_crypto_suite != rtc::kSrtpInvalidCryptoSuite &&
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800982 rtc::SrtpCryptoSuiteToName(srtp_crypto_suite).length()) {
983 channel_report->AddString(
984 StatsReport::kStatsValueNameSrtpCipher,
985 rtc::SrtpCryptoSuiteToName(srtp_crypto_suite));
pthatcher@webrtc.orgc04a97f2015-03-16 19:31:40 +0000986 }
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800987 int ssl_cipher_suite = channel_iter.ssl_cipher_suite;
Mirko Bonadei7750d802021-07-26 17:27:42 +0200988 if (ssl_cipher_suite != rtc::kTlsNullWithNullNull &&
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800989 rtc::SSLStreamAdapter::SslCipherSuiteToName(ssl_cipher_suite)
990 .length()) {
Guo-wei Shieh456696a2015-09-30 21:48:54 -0700991 channel_report->AddString(
992 StatsReport::kStatsValueNameDtlsCipher,
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800993 rtc::SSLStreamAdapter::SslCipherSuiteToName(ssl_cipher_suite));
wu@webrtc.org4551b792013-10-09 15:37:36 +0000994 }
jiayl@webrtc.org06b04ec2014-07-24 20:41:20 +0000995
Qingsi Wang72a43a12018-02-20 16:03:18 -0800996 // Collect stats for non-pooled candidates. Note that the reports
997 // generated here supersedes the candidate reports generated in
998 // AddConnectionInfoReport below, and they may report candidates that are
999 // not paired. Also, the candidate report generated in
1000 // AddConnectionInfoReport do not report port stats like StunStats.
1001 for (const cricket::CandidateStats& stats :
Jonas Oreland149dc722019-08-28 08:10:27 +02001002 channel_iter.ice_transport_stats.candidate_stats_list) {
Qingsi Wang72a43a12018-02-20 16:03:18 -08001003 AddCandidateReport(stats, true);
1004 }
1005
pthatcher@webrtc.orgc04a97f2015-03-16 19:31:40 +00001006 int connection_id = 0;
1007 for (const cricket::ConnectionInfo& info :
Jonas Oreland149dc722019-08-28 08:10:27 +02001008 channel_iter.ice_transport_stats.connection_infos) {
pthatcher@webrtc.orgc04a97f2015-03-16 19:31:40 +00001009 StatsReport* connection_report = AddConnectionInfoReport(
Tomas Gunnarssone1c8a432021-04-08 15:15:28 +02001010 transport.name, channel_iter.component, connection_id++,
pthatcher@webrtc.orgc04a97f2015-03-16 19:31:40 +00001011 channel_report->id(), info);
1012 if (info.best_connection) {
1013 channel_report->AddId(
1014 StatsReport::kStatsValueNameSelectedCandidatePairId,
1015 connection_report->id());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001016 }
1017 }
1018 }
1019 }
1020}
1021
stefanf79ade12017-06-02 06:44:03 -07001022void StatsCollector::ExtractBweInfo() {
Tomas Gunnarssone1c8a432021-04-08 15:15:28 +02001023 RTC_DCHECK_RUN_ON(pc_->signaling_thread());
stefanf79ade12017-06-02 06:44:03 -07001024
Steve Anton978b8762017-09-29 12:15:02 -07001025 if (pc_->signaling_state() == PeerConnectionInterface::kClosed)
stefanf79ade12017-06-02 06:44:03 -07001026 return;
1027
Steve Anton978b8762017-09-29 12:15:02 -07001028 webrtc::Call::Stats call_stats = pc_->GetCallStats();
stefanf79ade12017-06-02 06:44:03 -07001029 cricket::BandwidthEstimationInfo bwe_info;
1030 bwe_info.available_send_bandwidth = call_stats.send_bandwidth_bps;
1031 bwe_info.available_recv_bandwidth = call_stats.recv_bandwidth_bps;
1032 bwe_info.bucket_delay = call_stats.pacer_delay_ms;
Steve Antonafb0bb72018-02-20 11:35:37 -08001033
stefanf79ade12017-06-02 06:44:03 -07001034 // Fill in target encoder bitrate, actual encoder bitrate, rtx bitrate, etc.
1035 // TODO(holmer): Also fill this in for audio.
Tomas Gunnarsson788d8052021-05-03 16:23:08 +02001036 auto transceivers = pc_->GetTransceiversInternal();
Harald Alvestrand9a743172022-04-29 16:47:37 +00001037 std::vector<cricket::VideoMediaChannel*> video_media_channels;
Tomas Gunnarsson788d8052021-05-03 16:23:08 +02001038 for (const auto& transceiver : transceivers) {
Steve Antonafb0bb72018-02-20 11:35:37 -08001039 if (transceiver->media_type() != cricket::MEDIA_TYPE_VIDEO) {
1040 continue;
1041 }
Harald Alvestrand9a743172022-04-29 16:47:37 +00001042 auto* video_channel = transceiver->internal()->channel();
Tomas Gunnarsson788d8052021-05-03 16:23:08 +02001043 if (video_channel) {
Harald Alvestrand9a743172022-04-29 16:47:37 +00001044 video_media_channels.push_back(static_cast<cricket::VideoMediaChannel*>(
1045 video_channel->media_channel()));
Steve Antonafb0bb72018-02-20 11:35:37 -08001046 }
Tomas Gunnarsson788d8052021-05-03 16:23:08 +02001047 }
1048
Harald Alvestrand9a743172022-04-29 16:47:37 +00001049 if (!video_media_channels.empty()) {
Tomas Gunnarsson788d8052021-05-03 16:23:08 +02001050 pc_->worker_thread()->Invoke<void>(RTC_FROM_HERE, [&] {
Harald Alvestrand9a743172022-04-29 16:47:37 +00001051 for (const auto& channel : video_media_channels) {
Tomas Gunnarsson788d8052021-05-03 16:23:08 +02001052 channel->FillBitrateInfo(&bwe_info);
1053 }
1054 });
stefanf79ade12017-06-02 06:44:03 -07001055 }
Steve Antonafb0bb72018-02-20 11:35:37 -08001056
stefanf79ade12017-06-02 06:44:03 -07001057 StatsReport::Id report_id(StatsReport::NewBandwidthEstimationId());
1058 StatsReport* report = reports_.FindOrAddNew(report_id);
1059 ExtractStats(bwe_info, stats_gathering_started_, report);
1060}
1061
Steve Antonb8867112018-02-13 10:07:54 -08001062namespace {
tommi@webrtc.org69bc5a32014-12-15 09:44:48 +00001063
Steve Antonefe4c922019-03-27 10:26:06 -07001064class MediaChannelStatsGatherer {
1065 public:
1066 virtual ~MediaChannelStatsGatherer() = default;
1067
1068 virtual bool GetStatsOnWorkerThread() = 0;
1069
1070 virtual void ExtractStats(StatsCollector* collector) const = 0;
1071
1072 virtual bool HasRemoteAudio() const = 0;
1073
1074 std::string mid;
Steve Antonb8867112018-02-13 10:07:54 -08001075 std::string transport_name;
Steve Antonefe4c922019-03-27 10:26:06 -07001076 std::map<uint32_t, std::string> sender_track_id_by_ssrc;
1077 std::map<uint32_t, std::string> receiver_track_id_by_ssrc;
1078
1079 protected:
1080 template <typename ReceiverT, typename SenderT>
1081 void ExtractSenderReceiverStats(
1082 StatsCollector* collector,
1083 const std::vector<ReceiverT>& receiver_data,
1084 const std::vector<SenderT>& sender_data) const {
1085 RTC_DCHECK(collector);
1086 StatsReport::Id transport_id = StatsReport::NewComponentId(
1087 transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
1088 ExtractStatsFromList(receiver_data, transport_id, collector,
1089 StatsReport::kReceive, receiver_track_id_by_ssrc);
1090 ExtractStatsFromList(sender_data, transport_id, collector,
1091 StatsReport::kSend, sender_track_id_by_ssrc);
1092 }
1093};
1094
1095class VoiceMediaChannelStatsGatherer final : public MediaChannelStatsGatherer {
1096 public:
1097 VoiceMediaChannelStatsGatherer(
1098 cricket::VoiceMediaChannel* voice_media_channel)
1099 : voice_media_channel_(voice_media_channel) {
1100 RTC_DCHECK(voice_media_channel_);
1101 }
1102
1103 bool GetStatsOnWorkerThread() override {
Niels Möller6b4d9622020-09-14 10:47:50 +02001104 return voice_media_channel_->GetStats(&voice_media_info,
1105 /*get_and_clear_legacy_stats=*/true);
Steve Antonefe4c922019-03-27 10:26:06 -07001106 }
1107
1108 void ExtractStats(StatsCollector* collector) const override {
1109 ExtractSenderReceiverStats(collector, voice_media_info.receivers,
1110 voice_media_info.senders);
Alex Narestbbeb1092019-08-16 11:49:04 +02001111 if (voice_media_info.device_underrun_count == -2 ||
1112 voice_media_info.device_underrun_count > 0) {
1113 StatsReport* report = collector->PrepareADMReport();
1114 report->AddInt(StatsReport::kStatsValueNameAudioDeviceUnderrunCounter,
1115 voice_media_info.device_underrun_count);
1116 }
Steve Antonefe4c922019-03-27 10:26:06 -07001117 }
1118
1119 bool HasRemoteAudio() const override {
1120 return !voice_media_info.receivers.empty();
1121 }
1122
1123 private:
1124 cricket::VoiceMediaChannel* voice_media_channel_;
Steve Antonb8867112018-02-13 10:07:54 -08001125 cricket::VoiceMediaInfo voice_media_info;
1126};
1127
Steve Antonefe4c922019-03-27 10:26:06 -07001128class VideoMediaChannelStatsGatherer final : public MediaChannelStatsGatherer {
1129 public:
1130 VideoMediaChannelStatsGatherer(
1131 cricket::VideoMediaChannel* video_media_channel)
1132 : video_media_channel_(video_media_channel) {
1133 RTC_DCHECK(video_media_channel_);
1134 }
1135
1136 bool GetStatsOnWorkerThread() override {
1137 return video_media_channel_->GetStats(&video_media_info);
1138 }
1139
1140 void ExtractStats(StatsCollector* collector) const override {
1141 ExtractSenderReceiverStats(collector, video_media_info.receivers,
Henrik Boströma0ff50c2020-05-05 15:54:46 +02001142 video_media_info.aggregated_senders);
Steve Antonefe4c922019-03-27 10:26:06 -07001143 }
1144
1145 bool HasRemoteAudio() const override { return false; }
1146
1147 private:
1148 cricket::VideoMediaChannel* video_media_channel_;
Steve Antonb8867112018-02-13 10:07:54 -08001149 cricket::VideoMediaInfo video_media_info;
1150};
1151
Steve Antonefe4c922019-03-27 10:26:06 -07001152std::unique_ptr<MediaChannelStatsGatherer> CreateMediaChannelStatsGatherer(
1153 cricket::MediaChannel* channel) {
1154 RTC_DCHECK(channel);
1155 if (channel->media_type() == cricket::MEDIA_TYPE_AUDIO) {
Mirko Bonadei317a1f02019-09-17 17:06:18 +02001156 return std::make_unique<VoiceMediaChannelStatsGatherer>(
Steve Antonefe4c922019-03-27 10:26:06 -07001157 static_cast<cricket::VoiceMediaChannel*>(channel));
1158 } else {
1159 RTC_DCHECK_EQ(channel->media_type(), cricket::MEDIA_TYPE_VIDEO);
Mirko Bonadei317a1f02019-09-17 17:06:18 +02001160 return std::make_unique<VideoMediaChannelStatsGatherer>(
Steve Antonefe4c922019-03-27 10:26:06 -07001161 static_cast<cricket::VideoMediaChannel*>(channel));
1162 }
1163}
1164
Steve Antonb8867112018-02-13 10:07:54 -08001165} // namespace
1166
Tomas Gunnarssone1c8a432021-04-08 15:15:28 +02001167void StatsCollector::ExtractMediaInfo(
1168 const std::map<std::string, std::string>& transport_names_by_mid) {
Steve Antonb8867112018-02-13 10:07:54 -08001169 RTC_DCHECK_RUN_ON(pc_->signaling_thread());
1170
Steve Antonefe4c922019-03-27 10:26:06 -07001171 std::vector<std::unique_ptr<MediaChannelStatsGatherer>> gatherers;
Steve Antonb8867112018-02-13 10:07:54 -08001172
Tommi4ccdf932021-05-17 14:50:10 +02001173 auto transceivers = pc_->GetTransceiversInternal();
Steve Antonb8867112018-02-13 10:07:54 -08001174 {
1175 rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
Tommi4ccdf932021-05-17 14:50:10 +02001176 for (const auto& transceiver : transceivers) {
Steve Antonefe4c922019-03-27 10:26:06 -07001177 cricket::ChannelInterface* channel = transceiver->internal()->channel();
1178 if (!channel) {
Steve Antonb8867112018-02-13 10:07:54 -08001179 continue;
1180 }
Steve Antonefe4c922019-03-27 10:26:06 -07001181 std::unique_ptr<MediaChannelStatsGatherer> gatherer =
1182 CreateMediaChannelStatsGatherer(channel->media_channel());
Tomas Gunnarsson5411b172022-01-24 08:45:26 +01001183 gatherer->mid = channel->mid();
Tomas Gunnarssone1c8a432021-04-08 15:15:28 +02001184 gatherer->transport_name = transport_names_by_mid.at(gatherer->mid);
1185
Steve Antonefe4c922019-03-27 10:26:06 -07001186 for (const auto& sender : transceiver->internal()->senders()) {
Tommi4ccdf932021-05-17 14:50:10 +02001187 auto track = sender->track();
1188 std::string track_id = (track ? track->id() : "");
Steve Antonefe4c922019-03-27 10:26:06 -07001189 gatherer->sender_track_id_by_ssrc.insert(
1190 std::make_pair(sender->ssrc(), track_id));
Steve Antonb8867112018-02-13 10:07:54 -08001191 }
Tommi4ccdf932021-05-17 14:50:10 +02001192
1193 // Populating `receiver_track_id_by_ssrc` will be done on the worker
1194 // thread as the `ssrc` property of the receiver needs to be accessed
1195 // there.
1196
Steve Antonefe4c922019-03-27 10:26:06 -07001197 gatherers.push_back(std::move(gatherer));
Steve Antonb8867112018-02-13 10:07:54 -08001198 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001199 }
tommi@webrtc.orgd3900292015-03-12 16:35:55 +00001200
Steve Antonb8867112018-02-13 10:07:54 -08001201 pc_->worker_thread()->Invoke<void>(RTC_FROM_HERE, [&] {
1202 rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
Tommi4ccdf932021-05-17 14:50:10 +02001203 // Populate `receiver_track_id_by_ssrc` for the gatherers.
1204 int i = 0;
1205 for (const auto& transceiver : transceivers) {
1206 cricket::ChannelInterface* channel = transceiver->internal()->channel();
1207 if (!channel)
1208 continue;
1209 MediaChannelStatsGatherer* gatherer = gatherers[i++].get();
Tomas Gunnarsson5411b172022-01-24 08:45:26 +01001210 RTC_DCHECK_EQ(gatherer->mid, channel->mid());
Tommi4ccdf932021-05-17 14:50:10 +02001211
1212 for (const auto& receiver : transceiver->internal()->receivers()) {
1213 gatherer->receiver_track_id_by_ssrc.insert(std::make_pair(
1214 receiver->internal()->ssrc(), receiver->track()->id()));
1215 }
1216 }
1217
Steve Antonefe4c922019-03-27 10:26:06 -07001218 for (auto it = gatherers.begin(); it != gatherers.end();
Steve Antonb8867112018-02-13 10:07:54 -08001219 /* incremented manually */) {
Steve Antonefe4c922019-03-27 10:26:06 -07001220 MediaChannelStatsGatherer* gatherer = it->get();
1221 if (!gatherer->GetStatsOnWorkerThread()) {
1222 RTC_LOG(LS_ERROR) << "Failed to get media channel stats for mid="
1223 << gatherer->mid;
1224 it = gatherers.erase(it);
Steve Antonb8867112018-02-13 10:07:54 -08001225 continue;
1226 }
1227 ++it;
1228 }
1229 });
1230
tommi@webrtc.orgd3900292015-03-12 16:35:55 +00001231 rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
1232
Steve Antonb8867112018-02-13 10:07:54 -08001233 bool has_remote_audio = false;
Steve Antonefe4c922019-03-27 10:26:06 -07001234 for (const auto& gatherer : gatherers) {
1235 gatherer->ExtractStats(this);
1236 has_remote_audio |= gatherer->HasRemoteAudio();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001237 }
tommi@webrtc.orgd3900292015-03-12 16:35:55 +00001238
Steve Antonb8867112018-02-13 10:07:54 -08001239 UpdateStatsFromExistingLocalAudioTracks(has_remote_audio);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001240}
1241
nissefcc640f2016-04-01 01:10:42 -07001242void StatsCollector::ExtractSenderInfo() {
Tomas Gunnarssone1c8a432021-04-08 15:15:28 +02001243 RTC_DCHECK_RUN_ON(pc_->signaling_thread());
nissefcc640f2016-04-01 01:10:42 -07001244
1245 for (const auto& sender : pc_->GetSenders()) {
1246 // TODO(nisse): SSRC == 0 currently means none. Delete check when
1247 // that is fixed.
1248 if (!sender->ssrc()) {
1249 continue;
1250 }
1251 const rtc::scoped_refptr<MediaStreamTrackInterface> track(sender->track());
1252 if (!track || track->kind() != MediaStreamTrackInterface::kVideoKind) {
1253 continue;
1254 }
1255 // Safe, because kind() == kVideoKind implies a subclass of
1256 // VideoTrackInterface; see mediastreaminterface.h.
1257 VideoTrackSourceInterface* source =
1258 static_cast<VideoTrackInterface*>(track.get())->GetSource();
1259
1260 VideoTrackSourceInterface::Stats stats;
1261 if (!source->GetStats(&stats)) {
1262 continue;
1263 }
1264 const StatsReport::Id stats_id = StatsReport::NewIdWithDirection(
Jonas Olsson6b1985d2018-07-05 11:59:48 +02001265 StatsReport::kStatsReportTypeSsrc, rtc::ToString(sender->ssrc()),
1266 StatsReport::kSend);
nissefcc640f2016-04-01 01:10:42 -07001267 StatsReport* report = reports_.FindOrAddNew(stats_id);
1268 report->AddInt(StatsReport::kStatsValueNameFrameWidthInput,
1269 stats.input_width);
1270 report->AddInt(StatsReport::kStatsValueNameFrameHeightInput,
1271 stats.input_height);
1272 }
1273}
1274
decurtis@webrtc.org487a4442015-01-15 22:55:07 +00001275void StatsCollector::ExtractDataInfo() {
Tomas Gunnarssone1c8a432021-04-08 15:15:28 +02001276 RTC_DCHECK_RUN_ON(pc_->signaling_thread());
decurtis@webrtc.org487a4442015-01-15 22:55:07 +00001277
tommi@webrtc.orgd3900292015-03-12 16:35:55 +00001278 rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
1279
Taylor Brandstetter3a034e12020-07-09 15:32:34 -07001280 std::vector<DataChannelStats> data_stats = pc_->GetDataChannelStats();
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +02001281 for (const auto& stats : data_stats) {
tommi@webrtc.orgd3900292015-03-12 16:35:55 +00001282 StatsReport::Id id(StatsReport::NewTypedIntId(
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +02001283 StatsReport::kStatsReportTypeDataChannel, stats.id));
tommi@webrtc.orgd3900292015-03-12 16:35:55 +00001284 StatsReport* report = reports_.ReplaceOrAddNew(id);
decurtis@webrtc.org322a5642015-02-03 22:09:37 +00001285 report->set_timestamp(stats_gathering_started_);
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +02001286 report->AddString(StatsReport::kStatsValueNameLabel, stats.label);
zhihuang6ba3b192016-05-13 11:46:35 -07001287 // Filter out the initial id (-1).
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +02001288 if (stats.id >= 0) {
1289 report->AddInt(StatsReport::kStatsValueNameDataChannelId, stats.id);
zhihuang6ba3b192016-05-13 11:46:35 -07001290 }
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +02001291 report->AddString(StatsReport::kStatsValueNameProtocol, stats.protocol);
tommi@webrtc.org92f40182015-03-04 15:25:19 +00001292 report->AddString(StatsReport::kStatsValueNameState,
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +02001293 DataChannelInterface::DataStateString(stats.state));
decurtis@webrtc.org487a4442015-01-15 22:55:07 +00001294 }
1295}
1296
tommi@webrtc.org4fb7e252015-01-21 11:36:18 +00001297StatsReport* StatsCollector::GetReport(const StatsReport::StatsType& type,
xians@webrtc.org4cb01282014-06-12 14:57:05 +00001298 const std::string& id,
tommi@webrtc.org4fb7e252015-01-21 11:36:18 +00001299 StatsReport::Direction direction) {
Tomas Gunnarssone1c8a432021-04-08 15:15:28 +02001300 RTC_DCHECK_RUN_ON(pc_->signaling_thread());
henrikg91d6ede2015-09-17 00:24:34 -07001301 RTC_DCHECK(type == StatsReport::kStatsReportTypeSsrc ||
1302 type == StatsReport::kStatsReportTypeRemoteSsrc);
tommi@webrtc.org4fb7e252015-01-21 11:36:18 +00001303 return reports_.Find(StatsReport::NewIdWithDirection(type, id, direction));
henrike@webrtc.org40b3b682014-03-03 18:30:11 +00001304}
1305
Ivo Creusenae026092017-11-20 13:07:16 +01001306void StatsCollector::UpdateStatsFromExistingLocalAudioTracks(
1307 bool has_remote_tracks) {
Tomas Gunnarssone1c8a432021-04-08 15:15:28 +02001308 RTC_DCHECK_RUN_ON(pc_->signaling_thread());
henrike@webrtc.org40b3b682014-03-03 18:30:11 +00001309 // Loop through the existing local audio tracks.
tommi@webrtc.orgd3900292015-03-12 16:35:55 +00001310 for (const auto& it : local_audio_tracks_) {
1311 AudioTrackInterface* track = it.first;
Peter Boström0c4e06b2015-10-07 12:23:21 +02001312 uint32_t ssrc = it.second;
Jonas Olsson6b1985d2018-07-05 11:59:48 +02001313 StatsReport* report = GetReport(StatsReport::kStatsReportTypeSsrc,
1314 rtc::ToString(ssrc), StatsReport::kSend);
henrike@webrtc.orgd3d6bce2014-03-10 20:41:22 +00001315 if (report == NULL) {
1316 // This can happen if a local audio track is added to a stream on the
1317 // fly and the report has not been set up yet. Do nothing in this case.
Mirko Bonadei675513b2017-11-09 11:09:25 +01001318 RTC_LOG(LS_ERROR) << "Stats report does not exist for ssrc " << ssrc;
henrike@webrtc.orgd3d6bce2014-03-10 20:41:22 +00001319 continue;
1320 }
henrike@webrtc.org40b3b682014-03-03 18:30:11 +00001321
1322 // The same ssrc can be used by both local and remote audio tracks.
tommi@webrtc.org4fb7e252015-01-21 11:36:18 +00001323 const StatsReport::Value* v =
1324 report->FindValue(StatsReport::kStatsValueNameTrackId);
tommi@webrtc.orgd3900292015-03-12 16:35:55 +00001325 if (!v || v->string_val() != track->id())
henrike@webrtc.org40b3b682014-03-03 18:30:11 +00001326 continue;
henrike@webrtc.org40b3b682014-03-03 18:30:11 +00001327
jbauchbe24c942015-06-22 15:06:43 -07001328 report->set_timestamp(stats_gathering_started_);
Ivo Creusenae026092017-11-20 13:07:16 +01001329 UpdateReportFromAudioTrack(track, report, has_remote_tracks);
henrike@webrtc.org40b3b682014-03-03 18:30:11 +00001330 }
1331}
1332
1333void StatsCollector::UpdateReportFromAudioTrack(AudioTrackInterface* track,
Ivo Creusenae026092017-11-20 13:07:16 +01001334 StatsReport* report,
1335 bool has_remote_tracks) {
Tomas Gunnarssone1c8a432021-04-08 15:15:28 +02001336 RTC_DCHECK_RUN_ON(pc_->signaling_thread());
henrikg91d6ede2015-09-17 00:24:34 -07001337 RTC_DCHECK(track != NULL);
henrike@webrtc.org40b3b682014-03-03 18:30:11 +00001338
andrew2fe1cb02015-11-27 17:27:35 -08001339 // Don't overwrite report values if they're not available.
1340 int signal_level;
1341 if (track->GetSignalLevel(&signal_level)) {
1342 RTC_DCHECK_GE(signal_level, 0);
1343 report->AddInt(StatsReport::kStatsValueNameAudioInputLevel, signal_level);
1344 }
henrike@webrtc.org40b3b682014-03-03 18:30:11 +00001345
andrew2fe1cb02015-11-27 17:27:35 -08001346 auto audio_processor(track->GetAudioProcessor());
henrike@webrtc.org40b3b682014-03-03 18:30:11 +00001347
andrew2fe1cb02015-11-27 17:27:35 -08001348 if (audio_processor.get()) {
Ivo Creusenae026092017-11-20 13:07:16 +01001349 AudioProcessorInterface::AudioProcessorStatistics stats =
1350 audio_processor->GetStats(has_remote_tracks);
tommi@webrtc.org92f40182015-03-04 15:25:19 +00001351
Alessio Bazzicad7fdb952022-03-18 14:21:00 +01001352 SetAudioProcessingStats(report, stats.apm_statistics);
andrew2fe1cb02015-11-27 17:27:35 -08001353 }
henrike@webrtc.org40b3b682014-03-03 18:30:11 +00001354}
1355
jbauchbe24c942015-06-22 15:06:43 -07001356void StatsCollector::UpdateTrackReports() {
Tomas Gunnarssone1c8a432021-04-08 15:15:28 +02001357 RTC_DCHECK_RUN_ON(pc_->signaling_thread());
jbauchbe24c942015-06-22 15:06:43 -07001358
1359 rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
1360
1361 for (const auto& entry : track_ids_) {
1362 StatsReport* report = entry.second;
1363 report->set_timestamp(stats_gathering_started_);
1364 }
jbauchbe24c942015-06-22 15:06:43 -07001365}
1366
Tommic811ab52022-01-11 16:33:23 +01001367void StatsCollector::InvalidateCache() {
1368 RTC_DCHECK_RUN_ON(pc_->signaling_thread());
Taylor Brandstetter80d661c2021-02-10 14:11:57 -08001369 cache_timestamp_ms_ = 0;
xians@webrtc.org01bda202014-07-09 07:38:38 +00001370}
1371
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001372} // namespace webrtc