xref: /aosp_15_r20/external/webrtc/pc/rtc_stats_collector.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright 2016 The WebRTC Project Authors. All rights reserved.
3*d9f75844SAndroid Build Coastguard Worker  *
4*d9f75844SAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker  */
10*d9f75844SAndroid Build Coastguard Worker 
11*d9f75844SAndroid Build Coastguard Worker #include "pc/rtc_stats_collector.h"
12*d9f75844SAndroid Build Coastguard Worker 
13*d9f75844SAndroid Build Coastguard Worker #include <stdint.h>
14*d9f75844SAndroid Build Coastguard Worker #include <stdio.h>
15*d9f75844SAndroid Build Coastguard Worker 
16*d9f75844SAndroid Build Coastguard Worker #include <cstdint>
17*d9f75844SAndroid Build Coastguard Worker #include <map>
18*d9f75844SAndroid Build Coastguard Worker #include <memory>
19*d9f75844SAndroid Build Coastguard Worker #include <string>
20*d9f75844SAndroid Build Coastguard Worker #include <type_traits>
21*d9f75844SAndroid Build Coastguard Worker #include <utility>
22*d9f75844SAndroid Build Coastguard Worker #include <vector>
23*d9f75844SAndroid Build Coastguard Worker 
24*d9f75844SAndroid Build Coastguard Worker #include "absl/functional/bind_front.h"
25*d9f75844SAndroid Build Coastguard Worker #include "absl/strings/string_view.h"
26*d9f75844SAndroid Build Coastguard Worker #include "api/array_view.h"
27*d9f75844SAndroid Build Coastguard Worker #include "api/candidate.h"
28*d9f75844SAndroid Build Coastguard Worker #include "api/dtls_transport_interface.h"
29*d9f75844SAndroid Build Coastguard Worker #include "api/media_stream_interface.h"
30*d9f75844SAndroid Build Coastguard Worker #include "api/rtp_parameters.h"
31*d9f75844SAndroid Build Coastguard Worker #include "api/sequence_checker.h"
32*d9f75844SAndroid Build Coastguard Worker #include "api/stats/rtc_stats.h"
33*d9f75844SAndroid Build Coastguard Worker #include "api/stats/rtcstats_objects.h"
34*d9f75844SAndroid Build Coastguard Worker #include "api/units/time_delta.h"
35*d9f75844SAndroid Build Coastguard Worker #include "api/video/video_content_type.h"
36*d9f75844SAndroid Build Coastguard Worker #include "common_video/include/quality_limitation_reason.h"
37*d9f75844SAndroid Build Coastguard Worker #include "media/base/media_channel.h"
38*d9f75844SAndroid Build Coastguard Worker #include "modules/audio_processing/include/audio_processing_statistics.h"
39*d9f75844SAndroid Build Coastguard Worker #include "modules/rtp_rtcp/include/report_block_data.h"
40*d9f75844SAndroid Build Coastguard Worker #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
41*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/connection_info.h"
42*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/ice_transport_internal.h"
43*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/p2p_constants.h"
44*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/port.h"
45*d9f75844SAndroid Build Coastguard Worker #include "pc/channel_interface.h"
46*d9f75844SAndroid Build Coastguard Worker #include "pc/data_channel_utils.h"
47*d9f75844SAndroid Build Coastguard Worker #include "pc/rtc_stats_traversal.h"
48*d9f75844SAndroid Build Coastguard Worker #include "pc/rtp_receiver_proxy.h"
49*d9f75844SAndroid Build Coastguard Worker #include "pc/rtp_sender_proxy.h"
50*d9f75844SAndroid Build Coastguard Worker #include "pc/webrtc_sdp.h"
51*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
52*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/ip_address.h"
53*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/logging.h"
54*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/network_constants.h"
55*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/rtc_certificate.h"
56*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/socket_address.h"
57*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/ssl_stream_adapter.h"
58*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/string_encode.h"
59*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/strings/string_builder.h"
60*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/time_utils.h"
61*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/trace_event.h"
62*d9f75844SAndroid Build Coastguard Worker 
63*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
64*d9f75844SAndroid Build Coastguard Worker 
65*d9f75844SAndroid Build Coastguard Worker namespace {
66*d9f75844SAndroid Build Coastguard Worker 
67*d9f75844SAndroid Build Coastguard Worker const char kDirectionInbound = 'I';
68*d9f75844SAndroid Build Coastguard Worker const char kDirectionOutbound = 'O';
69*d9f75844SAndroid Build Coastguard Worker 
70*d9f75844SAndroid Build Coastguard Worker // TODO(https://crbug.com/webrtc/10656): Consider making IDs less predictable.
RTCCertificateIDFromFingerprint(const std::string & fingerprint)71*d9f75844SAndroid Build Coastguard Worker std::string RTCCertificateIDFromFingerprint(const std::string& fingerprint) {
72*d9f75844SAndroid Build Coastguard Worker   return "CF" + fingerprint;
73*d9f75844SAndroid Build Coastguard Worker }
74*d9f75844SAndroid Build Coastguard Worker 
75*d9f75844SAndroid Build Coastguard Worker // `direction` is either kDirectionInbound or kDirectionOutbound.
RTCCodecStatsIDFromTransportAndCodecParameters(const char direction,const std::string & transport_id,const RtpCodecParameters & codec_params)76*d9f75844SAndroid Build Coastguard Worker std::string RTCCodecStatsIDFromTransportAndCodecParameters(
77*d9f75844SAndroid Build Coastguard Worker     const char direction,
78*d9f75844SAndroid Build Coastguard Worker     const std::string& transport_id,
79*d9f75844SAndroid Build Coastguard Worker     const RtpCodecParameters& codec_params) {
80*d9f75844SAndroid Build Coastguard Worker   char buf[1024];
81*d9f75844SAndroid Build Coastguard Worker   rtc::SimpleStringBuilder sb(buf);
82*d9f75844SAndroid Build Coastguard Worker   sb << 'C' << direction << transport_id << '_' << codec_params.payload_type;
83*d9f75844SAndroid Build Coastguard Worker   // TODO(https://crbug.com/webrtc/14420): If we stop supporting different FMTP
84*d9f75844SAndroid Build Coastguard Worker   // lines for the same PT and transport, which should be illegal SDP, then we
85*d9f75844SAndroid Build Coastguard Worker   // wouldn't need `fmtp` to be part of the ID here.
86*d9f75844SAndroid Build Coastguard Worker   rtc::StringBuilder fmtp;
87*d9f75844SAndroid Build Coastguard Worker   if (WriteFmtpParameters(codec_params.parameters, &fmtp)) {
88*d9f75844SAndroid Build Coastguard Worker     sb << '_' << fmtp.Release();
89*d9f75844SAndroid Build Coastguard Worker   }
90*d9f75844SAndroid Build Coastguard Worker   return sb.str();
91*d9f75844SAndroid Build Coastguard Worker }
92*d9f75844SAndroid Build Coastguard Worker 
RTCIceCandidatePairStatsIDFromConnectionInfo(const cricket::ConnectionInfo & info)93*d9f75844SAndroid Build Coastguard Worker std::string RTCIceCandidatePairStatsIDFromConnectionInfo(
94*d9f75844SAndroid Build Coastguard Worker     const cricket::ConnectionInfo& info) {
95*d9f75844SAndroid Build Coastguard Worker   char buf[4096];
96*d9f75844SAndroid Build Coastguard Worker   rtc::SimpleStringBuilder sb(buf);
97*d9f75844SAndroid Build Coastguard Worker   sb << "CP" << info.local_candidate.id() << "_" << info.remote_candidate.id();
98*d9f75844SAndroid Build Coastguard Worker   return sb.str();
99*d9f75844SAndroid Build Coastguard Worker }
100*d9f75844SAndroid Build Coastguard Worker 
101*d9f75844SAndroid Build Coastguard Worker // `direction` is either kDirectionInbound or kDirectionOutbound.
DEPRECATED_RTCMediaStreamTrackStatsIDFromDirectionAndAttachment(const char direction,int attachment_id)102*d9f75844SAndroid Build Coastguard Worker std::string DEPRECATED_RTCMediaStreamTrackStatsIDFromDirectionAndAttachment(
103*d9f75844SAndroid Build Coastguard Worker     const char direction,
104*d9f75844SAndroid Build Coastguard Worker     int attachment_id) {
105*d9f75844SAndroid Build Coastguard Worker   char buf[1024];
106*d9f75844SAndroid Build Coastguard Worker   rtc::SimpleStringBuilder sb(buf);
107*d9f75844SAndroid Build Coastguard Worker   sb << "DEPRECATED_T" << direction << attachment_id;
108*d9f75844SAndroid Build Coastguard Worker   return sb.str();
109*d9f75844SAndroid Build Coastguard Worker }
110*d9f75844SAndroid Build Coastguard Worker 
RTCTransportStatsIDFromTransportChannel(const std::string & transport_name,int channel_component)111*d9f75844SAndroid Build Coastguard Worker std::string RTCTransportStatsIDFromTransportChannel(
112*d9f75844SAndroid Build Coastguard Worker     const std::string& transport_name,
113*d9f75844SAndroid Build Coastguard Worker     int channel_component) {
114*d9f75844SAndroid Build Coastguard Worker   char buf[1024];
115*d9f75844SAndroid Build Coastguard Worker   rtc::SimpleStringBuilder sb(buf);
116*d9f75844SAndroid Build Coastguard Worker   sb << 'T' << transport_name << channel_component;
117*d9f75844SAndroid Build Coastguard Worker   return sb.str();
118*d9f75844SAndroid Build Coastguard Worker }
119*d9f75844SAndroid Build Coastguard Worker 
RTCInboundRTPStreamStatsIDFromSSRC(const std::string & transport_id,cricket::MediaType media_type,uint32_t ssrc)120*d9f75844SAndroid Build Coastguard Worker std::string RTCInboundRTPStreamStatsIDFromSSRC(const std::string& transport_id,
121*d9f75844SAndroid Build Coastguard Worker                                                cricket::MediaType media_type,
122*d9f75844SAndroid Build Coastguard Worker                                                uint32_t ssrc) {
123*d9f75844SAndroid Build Coastguard Worker   char buf[1024];
124*d9f75844SAndroid Build Coastguard Worker   rtc::SimpleStringBuilder sb(buf);
125*d9f75844SAndroid Build Coastguard Worker   sb << 'I' << transport_id
126*d9f75844SAndroid Build Coastguard Worker      << (media_type == cricket::MEDIA_TYPE_AUDIO ? 'A' : 'V') << ssrc;
127*d9f75844SAndroid Build Coastguard Worker   return sb.str();
128*d9f75844SAndroid Build Coastguard Worker }
129*d9f75844SAndroid Build Coastguard Worker 
RTCOutboundRTPStreamStatsIDFromSSRC(const std::string & transport_id,cricket::MediaType media_type,uint32_t ssrc)130*d9f75844SAndroid Build Coastguard Worker std::string RTCOutboundRTPStreamStatsIDFromSSRC(const std::string& transport_id,
131*d9f75844SAndroid Build Coastguard Worker                                                 cricket::MediaType media_type,
132*d9f75844SAndroid Build Coastguard Worker                                                 uint32_t ssrc) {
133*d9f75844SAndroid Build Coastguard Worker   char buf[1024];
134*d9f75844SAndroid Build Coastguard Worker   rtc::SimpleStringBuilder sb(buf);
135*d9f75844SAndroid Build Coastguard Worker   sb << 'O' << transport_id
136*d9f75844SAndroid Build Coastguard Worker      << (media_type == cricket::MEDIA_TYPE_AUDIO ? 'A' : 'V') << ssrc;
137*d9f75844SAndroid Build Coastguard Worker   return sb.str();
138*d9f75844SAndroid Build Coastguard Worker }
139*d9f75844SAndroid Build Coastguard Worker 
RTCRemoteInboundRtpStreamStatsIdFromSourceSsrc(cricket::MediaType media_type,uint32_t source_ssrc)140*d9f75844SAndroid Build Coastguard Worker std::string RTCRemoteInboundRtpStreamStatsIdFromSourceSsrc(
141*d9f75844SAndroid Build Coastguard Worker     cricket::MediaType media_type,
142*d9f75844SAndroid Build Coastguard Worker     uint32_t source_ssrc) {
143*d9f75844SAndroid Build Coastguard Worker   char buf[1024];
144*d9f75844SAndroid Build Coastguard Worker   rtc::SimpleStringBuilder sb(buf);
145*d9f75844SAndroid Build Coastguard Worker   sb << "RI" << (media_type == cricket::MEDIA_TYPE_AUDIO ? 'A' : 'V')
146*d9f75844SAndroid Build Coastguard Worker      << source_ssrc;
147*d9f75844SAndroid Build Coastguard Worker   return sb.str();
148*d9f75844SAndroid Build Coastguard Worker }
149*d9f75844SAndroid Build Coastguard Worker 
RTCRemoteOutboundRTPStreamStatsIDFromSSRC(cricket::MediaType media_type,uint32_t source_ssrc)150*d9f75844SAndroid Build Coastguard Worker std::string RTCRemoteOutboundRTPStreamStatsIDFromSSRC(
151*d9f75844SAndroid Build Coastguard Worker     cricket::MediaType media_type,
152*d9f75844SAndroid Build Coastguard Worker     uint32_t source_ssrc) {
153*d9f75844SAndroid Build Coastguard Worker   char buf[1024];
154*d9f75844SAndroid Build Coastguard Worker   rtc::SimpleStringBuilder sb(buf);
155*d9f75844SAndroid Build Coastguard Worker   sb << "RO" << (media_type == cricket::MEDIA_TYPE_AUDIO ? 'A' : 'V')
156*d9f75844SAndroid Build Coastguard Worker      << source_ssrc;
157*d9f75844SAndroid Build Coastguard Worker   return sb.str();
158*d9f75844SAndroid Build Coastguard Worker }
159*d9f75844SAndroid Build Coastguard Worker 
RTCMediaSourceStatsIDFromKindAndAttachment(cricket::MediaType media_type,int attachment_id)160*d9f75844SAndroid Build Coastguard Worker std::string RTCMediaSourceStatsIDFromKindAndAttachment(
161*d9f75844SAndroid Build Coastguard Worker     cricket::MediaType media_type,
162*d9f75844SAndroid Build Coastguard Worker     int attachment_id) {
163*d9f75844SAndroid Build Coastguard Worker   char buf[1024];
164*d9f75844SAndroid Build Coastguard Worker   rtc::SimpleStringBuilder sb(buf);
165*d9f75844SAndroid Build Coastguard Worker   sb << 'S' << (media_type == cricket::MEDIA_TYPE_AUDIO ? 'A' : 'V')
166*d9f75844SAndroid Build Coastguard Worker      << attachment_id;
167*d9f75844SAndroid Build Coastguard Worker   return sb.str();
168*d9f75844SAndroid Build Coastguard Worker }
169*d9f75844SAndroid Build Coastguard Worker 
CandidateTypeToRTCIceCandidateType(const std::string & type)170*d9f75844SAndroid Build Coastguard Worker const char* CandidateTypeToRTCIceCandidateType(const std::string& type) {
171*d9f75844SAndroid Build Coastguard Worker   if (type == cricket::LOCAL_PORT_TYPE)
172*d9f75844SAndroid Build Coastguard Worker     return RTCIceCandidateType::kHost;
173*d9f75844SAndroid Build Coastguard Worker   if (type == cricket::STUN_PORT_TYPE)
174*d9f75844SAndroid Build Coastguard Worker     return RTCIceCandidateType::kSrflx;
175*d9f75844SAndroid Build Coastguard Worker   if (type == cricket::PRFLX_PORT_TYPE)
176*d9f75844SAndroid Build Coastguard Worker     return RTCIceCandidateType::kPrflx;
177*d9f75844SAndroid Build Coastguard Worker   if (type == cricket::RELAY_PORT_TYPE)
178*d9f75844SAndroid Build Coastguard Worker     return RTCIceCandidateType::kRelay;
179*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_NOTREACHED();
180*d9f75844SAndroid Build Coastguard Worker   return nullptr;
181*d9f75844SAndroid Build Coastguard Worker }
182*d9f75844SAndroid Build Coastguard Worker 
DataStateToRTCDataChannelState(DataChannelInterface::DataState state)183*d9f75844SAndroid Build Coastguard Worker const char* DataStateToRTCDataChannelState(
184*d9f75844SAndroid Build Coastguard Worker     DataChannelInterface::DataState state) {
185*d9f75844SAndroid Build Coastguard Worker   switch (state) {
186*d9f75844SAndroid Build Coastguard Worker     case DataChannelInterface::kConnecting:
187*d9f75844SAndroid Build Coastguard Worker       return RTCDataChannelState::kConnecting;
188*d9f75844SAndroid Build Coastguard Worker     case DataChannelInterface::kOpen:
189*d9f75844SAndroid Build Coastguard Worker       return RTCDataChannelState::kOpen;
190*d9f75844SAndroid Build Coastguard Worker     case DataChannelInterface::kClosing:
191*d9f75844SAndroid Build Coastguard Worker       return RTCDataChannelState::kClosing;
192*d9f75844SAndroid Build Coastguard Worker     case DataChannelInterface::kClosed:
193*d9f75844SAndroid Build Coastguard Worker       return RTCDataChannelState::kClosed;
194*d9f75844SAndroid Build Coastguard Worker     default:
195*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK_NOTREACHED();
196*d9f75844SAndroid Build Coastguard Worker       return nullptr;
197*d9f75844SAndroid Build Coastguard Worker   }
198*d9f75844SAndroid Build Coastguard Worker }
199*d9f75844SAndroid Build Coastguard Worker 
IceCandidatePairStateToRTCStatsIceCandidatePairState(cricket::IceCandidatePairState state)200*d9f75844SAndroid Build Coastguard Worker const char* IceCandidatePairStateToRTCStatsIceCandidatePairState(
201*d9f75844SAndroid Build Coastguard Worker     cricket::IceCandidatePairState state) {
202*d9f75844SAndroid Build Coastguard Worker   switch (state) {
203*d9f75844SAndroid Build Coastguard Worker     case cricket::IceCandidatePairState::WAITING:
204*d9f75844SAndroid Build Coastguard Worker       return RTCStatsIceCandidatePairState::kWaiting;
205*d9f75844SAndroid Build Coastguard Worker     case cricket::IceCandidatePairState::IN_PROGRESS:
206*d9f75844SAndroid Build Coastguard Worker       return RTCStatsIceCandidatePairState::kInProgress;
207*d9f75844SAndroid Build Coastguard Worker     case cricket::IceCandidatePairState::SUCCEEDED:
208*d9f75844SAndroid Build Coastguard Worker       return RTCStatsIceCandidatePairState::kSucceeded;
209*d9f75844SAndroid Build Coastguard Worker     case cricket::IceCandidatePairState::FAILED:
210*d9f75844SAndroid Build Coastguard Worker       return RTCStatsIceCandidatePairState::kFailed;
211*d9f75844SAndroid Build Coastguard Worker     default:
212*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK_NOTREACHED();
213*d9f75844SAndroid Build Coastguard Worker       return nullptr;
214*d9f75844SAndroid Build Coastguard Worker   }
215*d9f75844SAndroid Build Coastguard Worker }
216*d9f75844SAndroid Build Coastguard Worker 
IceRoleToRTCIceRole(cricket::IceRole role)217*d9f75844SAndroid Build Coastguard Worker const char* IceRoleToRTCIceRole(cricket::IceRole role) {
218*d9f75844SAndroid Build Coastguard Worker   switch (role) {
219*d9f75844SAndroid Build Coastguard Worker     case cricket::IceRole::ICEROLE_UNKNOWN:
220*d9f75844SAndroid Build Coastguard Worker       return RTCIceRole::kUnknown;
221*d9f75844SAndroid Build Coastguard Worker     case cricket::IceRole::ICEROLE_CONTROLLED:
222*d9f75844SAndroid Build Coastguard Worker       return RTCIceRole::kControlled;
223*d9f75844SAndroid Build Coastguard Worker     case cricket::IceRole::ICEROLE_CONTROLLING:
224*d9f75844SAndroid Build Coastguard Worker       return RTCIceRole::kControlling;
225*d9f75844SAndroid Build Coastguard Worker     default:
226*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK_NOTREACHED();
227*d9f75844SAndroid Build Coastguard Worker       return nullptr;
228*d9f75844SAndroid Build Coastguard Worker   }
229*d9f75844SAndroid Build Coastguard Worker }
230*d9f75844SAndroid Build Coastguard Worker 
DtlsTransportStateToRTCDtlsTransportState(DtlsTransportState state)231*d9f75844SAndroid Build Coastguard Worker const char* DtlsTransportStateToRTCDtlsTransportState(
232*d9f75844SAndroid Build Coastguard Worker     DtlsTransportState state) {
233*d9f75844SAndroid Build Coastguard Worker   switch (state) {
234*d9f75844SAndroid Build Coastguard Worker     case DtlsTransportState::kNew:
235*d9f75844SAndroid Build Coastguard Worker       return RTCDtlsTransportState::kNew;
236*d9f75844SAndroid Build Coastguard Worker     case DtlsTransportState::kConnecting:
237*d9f75844SAndroid Build Coastguard Worker       return RTCDtlsTransportState::kConnecting;
238*d9f75844SAndroid Build Coastguard Worker     case DtlsTransportState::kConnected:
239*d9f75844SAndroid Build Coastguard Worker       return RTCDtlsTransportState::kConnected;
240*d9f75844SAndroid Build Coastguard Worker     case DtlsTransportState::kClosed:
241*d9f75844SAndroid Build Coastguard Worker       return RTCDtlsTransportState::kClosed;
242*d9f75844SAndroid Build Coastguard Worker     case DtlsTransportState::kFailed:
243*d9f75844SAndroid Build Coastguard Worker       return RTCDtlsTransportState::kFailed;
244*d9f75844SAndroid Build Coastguard Worker     default:
245*d9f75844SAndroid Build Coastguard Worker       RTC_CHECK_NOTREACHED();
246*d9f75844SAndroid Build Coastguard Worker       return nullptr;
247*d9f75844SAndroid Build Coastguard Worker   }
248*d9f75844SAndroid Build Coastguard Worker }
249*d9f75844SAndroid Build Coastguard Worker 
IceTransportStateToRTCIceTransportState(IceTransportState state)250*d9f75844SAndroid Build Coastguard Worker const char* IceTransportStateToRTCIceTransportState(IceTransportState state) {
251*d9f75844SAndroid Build Coastguard Worker   switch (state) {
252*d9f75844SAndroid Build Coastguard Worker     case IceTransportState::kNew:
253*d9f75844SAndroid Build Coastguard Worker       return RTCIceTransportState::kNew;
254*d9f75844SAndroid Build Coastguard Worker     case IceTransportState::kChecking:
255*d9f75844SAndroid Build Coastguard Worker       return RTCIceTransportState::kChecking;
256*d9f75844SAndroid Build Coastguard Worker     case IceTransportState::kConnected:
257*d9f75844SAndroid Build Coastguard Worker       return RTCIceTransportState::kConnected;
258*d9f75844SAndroid Build Coastguard Worker     case IceTransportState::kCompleted:
259*d9f75844SAndroid Build Coastguard Worker       return RTCIceTransportState::kCompleted;
260*d9f75844SAndroid Build Coastguard Worker     case IceTransportState::kFailed:
261*d9f75844SAndroid Build Coastguard Worker       return RTCIceTransportState::kFailed;
262*d9f75844SAndroid Build Coastguard Worker     case IceTransportState::kDisconnected:
263*d9f75844SAndroid Build Coastguard Worker       return RTCIceTransportState::kDisconnected;
264*d9f75844SAndroid Build Coastguard Worker     case IceTransportState::kClosed:
265*d9f75844SAndroid Build Coastguard Worker       return RTCIceTransportState::kClosed;
266*d9f75844SAndroid Build Coastguard Worker     default:
267*d9f75844SAndroid Build Coastguard Worker       RTC_CHECK_NOTREACHED();
268*d9f75844SAndroid Build Coastguard Worker       return nullptr;
269*d9f75844SAndroid Build Coastguard Worker   }
270*d9f75844SAndroid Build Coastguard Worker }
271*d9f75844SAndroid Build Coastguard Worker 
NetworkTypeToStatsType(rtc::AdapterType type)272*d9f75844SAndroid Build Coastguard Worker const char* NetworkTypeToStatsType(rtc::AdapterType type) {
273*d9f75844SAndroid Build Coastguard Worker   switch (type) {
274*d9f75844SAndroid Build Coastguard Worker     case rtc::ADAPTER_TYPE_CELLULAR:
275*d9f75844SAndroid Build Coastguard Worker     case rtc::ADAPTER_TYPE_CELLULAR_2G:
276*d9f75844SAndroid Build Coastguard Worker     case rtc::ADAPTER_TYPE_CELLULAR_3G:
277*d9f75844SAndroid Build Coastguard Worker     case rtc::ADAPTER_TYPE_CELLULAR_4G:
278*d9f75844SAndroid Build Coastguard Worker     case rtc::ADAPTER_TYPE_CELLULAR_5G:
279*d9f75844SAndroid Build Coastguard Worker       return RTCNetworkType::kCellular;
280*d9f75844SAndroid Build Coastguard Worker     case rtc::ADAPTER_TYPE_ETHERNET:
281*d9f75844SAndroid Build Coastguard Worker       return RTCNetworkType::kEthernet;
282*d9f75844SAndroid Build Coastguard Worker     case rtc::ADAPTER_TYPE_WIFI:
283*d9f75844SAndroid Build Coastguard Worker       return RTCNetworkType::kWifi;
284*d9f75844SAndroid Build Coastguard Worker     case rtc::ADAPTER_TYPE_VPN:
285*d9f75844SAndroid Build Coastguard Worker       return RTCNetworkType::kVpn;
286*d9f75844SAndroid Build Coastguard Worker     case rtc::ADAPTER_TYPE_UNKNOWN:
287*d9f75844SAndroid Build Coastguard Worker     case rtc::ADAPTER_TYPE_LOOPBACK:
288*d9f75844SAndroid Build Coastguard Worker     case rtc::ADAPTER_TYPE_ANY:
289*d9f75844SAndroid Build Coastguard Worker       return RTCNetworkType::kUnknown;
290*d9f75844SAndroid Build Coastguard Worker   }
291*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_NOTREACHED();
292*d9f75844SAndroid Build Coastguard Worker   return nullptr;
293*d9f75844SAndroid Build Coastguard Worker }
294*d9f75844SAndroid Build Coastguard Worker 
NetworkTypeToStatsNetworkAdapterType(rtc::AdapterType type)295*d9f75844SAndroid Build Coastguard Worker absl::string_view NetworkTypeToStatsNetworkAdapterType(rtc::AdapterType type) {
296*d9f75844SAndroid Build Coastguard Worker   switch (type) {
297*d9f75844SAndroid Build Coastguard Worker     case rtc::ADAPTER_TYPE_CELLULAR:
298*d9f75844SAndroid Build Coastguard Worker       return RTCNetworkAdapterType::kCellular;
299*d9f75844SAndroid Build Coastguard Worker     case rtc::ADAPTER_TYPE_CELLULAR_2G:
300*d9f75844SAndroid Build Coastguard Worker       return RTCNetworkAdapterType::kCellular2g;
301*d9f75844SAndroid Build Coastguard Worker     case rtc::ADAPTER_TYPE_CELLULAR_3G:
302*d9f75844SAndroid Build Coastguard Worker       return RTCNetworkAdapterType::kCellular3g;
303*d9f75844SAndroid Build Coastguard Worker     case rtc::ADAPTER_TYPE_CELLULAR_4G:
304*d9f75844SAndroid Build Coastguard Worker       return RTCNetworkAdapterType::kCellular4g;
305*d9f75844SAndroid Build Coastguard Worker     case rtc::ADAPTER_TYPE_CELLULAR_5G:
306*d9f75844SAndroid Build Coastguard Worker       return RTCNetworkAdapterType::kCellular5g;
307*d9f75844SAndroid Build Coastguard Worker     case rtc::ADAPTER_TYPE_ETHERNET:
308*d9f75844SAndroid Build Coastguard Worker       return RTCNetworkAdapterType::kEthernet;
309*d9f75844SAndroid Build Coastguard Worker     case rtc::ADAPTER_TYPE_WIFI:
310*d9f75844SAndroid Build Coastguard Worker       return RTCNetworkAdapterType::kWifi;
311*d9f75844SAndroid Build Coastguard Worker     case rtc::ADAPTER_TYPE_UNKNOWN:
312*d9f75844SAndroid Build Coastguard Worker       return RTCNetworkAdapterType::kUnknown;
313*d9f75844SAndroid Build Coastguard Worker     case rtc::ADAPTER_TYPE_LOOPBACK:
314*d9f75844SAndroid Build Coastguard Worker       return RTCNetworkAdapterType::kLoopback;
315*d9f75844SAndroid Build Coastguard Worker     case rtc::ADAPTER_TYPE_ANY:
316*d9f75844SAndroid Build Coastguard Worker       return RTCNetworkAdapterType::kAny;
317*d9f75844SAndroid Build Coastguard Worker     case rtc::ADAPTER_TYPE_VPN:
318*d9f75844SAndroid Build Coastguard Worker       /* should not be handled here. Vpn is modelled as a bool */
319*d9f75844SAndroid Build Coastguard Worker       break;
320*d9f75844SAndroid Build Coastguard Worker   }
321*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_NOTREACHED();
322*d9f75844SAndroid Build Coastguard Worker   return {};
323*d9f75844SAndroid Build Coastguard Worker }
324*d9f75844SAndroid Build Coastguard Worker 
QualityLimitationReasonToRTCQualityLimitationReason(QualityLimitationReason reason)325*d9f75844SAndroid Build Coastguard Worker const char* QualityLimitationReasonToRTCQualityLimitationReason(
326*d9f75844SAndroid Build Coastguard Worker     QualityLimitationReason reason) {
327*d9f75844SAndroid Build Coastguard Worker   switch (reason) {
328*d9f75844SAndroid Build Coastguard Worker     case QualityLimitationReason::kNone:
329*d9f75844SAndroid Build Coastguard Worker       return RTCQualityLimitationReason::kNone;
330*d9f75844SAndroid Build Coastguard Worker     case QualityLimitationReason::kCpu:
331*d9f75844SAndroid Build Coastguard Worker       return RTCQualityLimitationReason::kCpu;
332*d9f75844SAndroid Build Coastguard Worker     case QualityLimitationReason::kBandwidth:
333*d9f75844SAndroid Build Coastguard Worker       return RTCQualityLimitationReason::kBandwidth;
334*d9f75844SAndroid Build Coastguard Worker     case QualityLimitationReason::kOther:
335*d9f75844SAndroid Build Coastguard Worker       return RTCQualityLimitationReason::kOther;
336*d9f75844SAndroid Build Coastguard Worker   }
337*d9f75844SAndroid Build Coastguard Worker   RTC_CHECK_NOTREACHED();
338*d9f75844SAndroid Build Coastguard Worker }
339*d9f75844SAndroid Build Coastguard Worker 
340*d9f75844SAndroid Build Coastguard Worker std::map<std::string, double>
QualityLimitationDurationToRTCQualityLimitationDuration(std::map<webrtc::QualityLimitationReason,int64_t> durations_ms)341*d9f75844SAndroid Build Coastguard Worker QualityLimitationDurationToRTCQualityLimitationDuration(
342*d9f75844SAndroid Build Coastguard Worker     std::map<webrtc::QualityLimitationReason, int64_t> durations_ms) {
343*d9f75844SAndroid Build Coastguard Worker   std::map<std::string, double> result;
344*d9f75844SAndroid Build Coastguard Worker   // The internal duration is defined in milliseconds while the spec defines
345*d9f75844SAndroid Build Coastguard Worker   // the value in seconds:
346*d9f75844SAndroid Build Coastguard Worker   // https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-qualitylimitationdurations
347*d9f75844SAndroid Build Coastguard Worker   for (const auto& elem : durations_ms) {
348*d9f75844SAndroid Build Coastguard Worker     result[QualityLimitationReasonToRTCQualityLimitationReason(elem.first)] =
349*d9f75844SAndroid Build Coastguard Worker         elem.second / static_cast<double>(rtc::kNumMillisecsPerSec);
350*d9f75844SAndroid Build Coastguard Worker   }
351*d9f75844SAndroid Build Coastguard Worker   return result;
352*d9f75844SAndroid Build Coastguard Worker }
353*d9f75844SAndroid Build Coastguard Worker 
DoubleAudioLevelFromIntAudioLevel(int audio_level)354*d9f75844SAndroid Build Coastguard Worker double DoubleAudioLevelFromIntAudioLevel(int audio_level) {
355*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_GE(audio_level, 0);
356*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_LE(audio_level, 32767);
357*d9f75844SAndroid Build Coastguard Worker   return audio_level / 32767.0;
358*d9f75844SAndroid Build Coastguard Worker }
359*d9f75844SAndroid Build Coastguard Worker 
360*d9f75844SAndroid Build Coastguard Worker // Gets the `codecId` identified by `transport_id` and `codec_params`. If no
361*d9f75844SAndroid Build Coastguard Worker // such `RTCCodecStats` exist yet, create it and add it to `report`.
GetCodecIdAndMaybeCreateCodecStats(uint64_t timestamp_us,const char direction,const std::string & transport_id,const RtpCodecParameters & codec_params,RTCStatsReport * report)362*d9f75844SAndroid Build Coastguard Worker std::string GetCodecIdAndMaybeCreateCodecStats(
363*d9f75844SAndroid Build Coastguard Worker     uint64_t timestamp_us,
364*d9f75844SAndroid Build Coastguard Worker     const char direction,
365*d9f75844SAndroid Build Coastguard Worker     const std::string& transport_id,
366*d9f75844SAndroid Build Coastguard Worker     const RtpCodecParameters& codec_params,
367*d9f75844SAndroid Build Coastguard Worker     RTCStatsReport* report) {
368*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_GE(codec_params.payload_type, 0);
369*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_LE(codec_params.payload_type, 127);
370*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(codec_params.clock_rate);
371*d9f75844SAndroid Build Coastguard Worker   uint32_t payload_type = static_cast<uint32_t>(codec_params.payload_type);
372*d9f75844SAndroid Build Coastguard Worker   std::string codec_id = RTCCodecStatsIDFromTransportAndCodecParameters(
373*d9f75844SAndroid Build Coastguard Worker       direction, transport_id, codec_params);
374*d9f75844SAndroid Build Coastguard Worker   if (report->Get(codec_id) != nullptr) {
375*d9f75844SAndroid Build Coastguard Worker     // The `RTCCodecStats` already exists.
376*d9f75844SAndroid Build Coastguard Worker     return codec_id;
377*d9f75844SAndroid Build Coastguard Worker   }
378*d9f75844SAndroid Build Coastguard Worker   // Create the `RTCCodecStats` that we want to reference.
379*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<RTCCodecStats> codec_stats(
380*d9f75844SAndroid Build Coastguard Worker       std::make_unique<RTCCodecStats>(codec_id, timestamp_us));
381*d9f75844SAndroid Build Coastguard Worker   codec_stats->payload_type = payload_type;
382*d9f75844SAndroid Build Coastguard Worker   codec_stats->mime_type = codec_params.mime_type();
383*d9f75844SAndroid Build Coastguard Worker   if (codec_params.clock_rate.has_value()) {
384*d9f75844SAndroid Build Coastguard Worker     codec_stats->clock_rate = static_cast<uint32_t>(*codec_params.clock_rate);
385*d9f75844SAndroid Build Coastguard Worker   }
386*d9f75844SAndroid Build Coastguard Worker   if (codec_params.num_channels) {
387*d9f75844SAndroid Build Coastguard Worker     codec_stats->channels = *codec_params.num_channels;
388*d9f75844SAndroid Build Coastguard Worker   }
389*d9f75844SAndroid Build Coastguard Worker 
390*d9f75844SAndroid Build Coastguard Worker   rtc::StringBuilder fmtp;
391*d9f75844SAndroid Build Coastguard Worker   if (WriteFmtpParameters(codec_params.parameters, &fmtp)) {
392*d9f75844SAndroid Build Coastguard Worker     codec_stats->sdp_fmtp_line = fmtp.Release();
393*d9f75844SAndroid Build Coastguard Worker   }
394*d9f75844SAndroid Build Coastguard Worker   codec_stats->transport_id = transport_id;
395*d9f75844SAndroid Build Coastguard Worker   report->AddStats(std::move(codec_stats));
396*d9f75844SAndroid Build Coastguard Worker   return codec_id;
397*d9f75844SAndroid Build Coastguard Worker }
398*d9f75844SAndroid Build Coastguard Worker 
SetMediaStreamTrackStatsFromMediaStreamTrackInterface(const MediaStreamTrackInterface & track,DEPRECATED_RTCMediaStreamTrackStats * track_stats)399*d9f75844SAndroid Build Coastguard Worker void SetMediaStreamTrackStatsFromMediaStreamTrackInterface(
400*d9f75844SAndroid Build Coastguard Worker     const MediaStreamTrackInterface& track,
401*d9f75844SAndroid Build Coastguard Worker     DEPRECATED_RTCMediaStreamTrackStats* track_stats) {
402*d9f75844SAndroid Build Coastguard Worker   track_stats->track_identifier = track.id();
403*d9f75844SAndroid Build Coastguard Worker   track_stats->ended = (track.state() == MediaStreamTrackInterface::kEnded);
404*d9f75844SAndroid Build Coastguard Worker }
405*d9f75844SAndroid Build Coastguard Worker 
406*d9f75844SAndroid Build Coastguard Worker // Provides the media independent counters (both audio and video).
SetInboundRTPStreamStatsFromMediaReceiverInfo(const cricket::MediaReceiverInfo & media_receiver_info,RTCInboundRTPStreamStats * inbound_stats)407*d9f75844SAndroid Build Coastguard Worker void SetInboundRTPStreamStatsFromMediaReceiverInfo(
408*d9f75844SAndroid Build Coastguard Worker     const cricket::MediaReceiverInfo& media_receiver_info,
409*d9f75844SAndroid Build Coastguard Worker     RTCInboundRTPStreamStats* inbound_stats) {
410*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(inbound_stats);
411*d9f75844SAndroid Build Coastguard Worker   inbound_stats->ssrc = media_receiver_info.ssrc();
412*d9f75844SAndroid Build Coastguard Worker   inbound_stats->packets_received =
413*d9f75844SAndroid Build Coastguard Worker       static_cast<uint32_t>(media_receiver_info.packets_rcvd);
414*d9f75844SAndroid Build Coastguard Worker   inbound_stats->bytes_received =
415*d9f75844SAndroid Build Coastguard Worker       static_cast<uint64_t>(media_receiver_info.payload_bytes_rcvd);
416*d9f75844SAndroid Build Coastguard Worker   inbound_stats->header_bytes_received =
417*d9f75844SAndroid Build Coastguard Worker       static_cast<uint64_t>(media_receiver_info.header_and_padding_bytes_rcvd);
418*d9f75844SAndroid Build Coastguard Worker   inbound_stats->packets_lost =
419*d9f75844SAndroid Build Coastguard Worker       static_cast<int32_t>(media_receiver_info.packets_lost);
420*d9f75844SAndroid Build Coastguard Worker   inbound_stats->jitter_buffer_delay =
421*d9f75844SAndroid Build Coastguard Worker       media_receiver_info.jitter_buffer_delay_seconds;
422*d9f75844SAndroid Build Coastguard Worker   if (media_receiver_info.jitter_buffer_target_delay_seconds.has_value()) {
423*d9f75844SAndroid Build Coastguard Worker     inbound_stats->jitter_buffer_target_delay =
424*d9f75844SAndroid Build Coastguard Worker         *media_receiver_info.jitter_buffer_target_delay_seconds;
425*d9f75844SAndroid Build Coastguard Worker   }
426*d9f75844SAndroid Build Coastguard Worker   if (media_receiver_info.jitter_buffer_minimum_delay_seconds.has_value()) {
427*d9f75844SAndroid Build Coastguard Worker     inbound_stats->jitter_buffer_minimum_delay =
428*d9f75844SAndroid Build Coastguard Worker         *media_receiver_info.jitter_buffer_minimum_delay_seconds;
429*d9f75844SAndroid Build Coastguard Worker   }
430*d9f75844SAndroid Build Coastguard Worker   inbound_stats->jitter_buffer_emitted_count =
431*d9f75844SAndroid Build Coastguard Worker       media_receiver_info.jitter_buffer_emitted_count;
432*d9f75844SAndroid Build Coastguard Worker   if (media_receiver_info.nacks_sent.has_value()) {
433*d9f75844SAndroid Build Coastguard Worker     inbound_stats->nack_count = *media_receiver_info.nacks_sent;
434*d9f75844SAndroid Build Coastguard Worker   }
435*d9f75844SAndroid Build Coastguard Worker }
436*d9f75844SAndroid Build Coastguard Worker 
CreateInboundAudioStreamStats(const cricket::VoiceMediaInfo & voice_media_info,const cricket::VoiceReceiverInfo & voice_receiver_info,const std::string & transport_id,const std::string & mid,int64_t timestamp_us,RTCStatsReport * report)437*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<RTCInboundRTPStreamStats> CreateInboundAudioStreamStats(
438*d9f75844SAndroid Build Coastguard Worker     const cricket::VoiceMediaInfo& voice_media_info,
439*d9f75844SAndroid Build Coastguard Worker     const cricket::VoiceReceiverInfo& voice_receiver_info,
440*d9f75844SAndroid Build Coastguard Worker     const std::string& transport_id,
441*d9f75844SAndroid Build Coastguard Worker     const std::string& mid,
442*d9f75844SAndroid Build Coastguard Worker     int64_t timestamp_us,
443*d9f75844SAndroid Build Coastguard Worker     RTCStatsReport* report) {
444*d9f75844SAndroid Build Coastguard Worker   auto inbound_audio = std::make_unique<RTCInboundRTPStreamStats>(
445*d9f75844SAndroid Build Coastguard Worker       /*id=*/RTCInboundRTPStreamStatsIDFromSSRC(
446*d9f75844SAndroid Build Coastguard Worker           transport_id, cricket::MEDIA_TYPE_AUDIO, voice_receiver_info.ssrc()),
447*d9f75844SAndroid Build Coastguard Worker       timestamp_us);
448*d9f75844SAndroid Build Coastguard Worker   SetInboundRTPStreamStatsFromMediaReceiverInfo(voice_receiver_info,
449*d9f75844SAndroid Build Coastguard Worker                                                 inbound_audio.get());
450*d9f75844SAndroid Build Coastguard Worker   inbound_audio->transport_id = transport_id;
451*d9f75844SAndroid Build Coastguard Worker   inbound_audio->mid = mid;
452*d9f75844SAndroid Build Coastguard Worker   inbound_audio->media_type = "audio";
453*d9f75844SAndroid Build Coastguard Worker   inbound_audio->kind = "audio";
454*d9f75844SAndroid Build Coastguard Worker   if (voice_receiver_info.codec_payload_type.has_value()) {
455*d9f75844SAndroid Build Coastguard Worker     auto codec_param_it = voice_media_info.receive_codecs.find(
456*d9f75844SAndroid Build Coastguard Worker         voice_receiver_info.codec_payload_type.value());
457*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(codec_param_it != voice_media_info.receive_codecs.end());
458*d9f75844SAndroid Build Coastguard Worker     if (codec_param_it != voice_media_info.receive_codecs.end()) {
459*d9f75844SAndroid Build Coastguard Worker       inbound_audio->codec_id = GetCodecIdAndMaybeCreateCodecStats(
460*d9f75844SAndroid Build Coastguard Worker           inbound_audio->timestamp_us(), kDirectionInbound, transport_id,
461*d9f75844SAndroid Build Coastguard Worker           codec_param_it->second, report);
462*d9f75844SAndroid Build Coastguard Worker     }
463*d9f75844SAndroid Build Coastguard Worker   }
464*d9f75844SAndroid Build Coastguard Worker   inbound_audio->jitter = static_cast<double>(voice_receiver_info.jitter_ms) /
465*d9f75844SAndroid Build Coastguard Worker                           rtc::kNumMillisecsPerSec;
466*d9f75844SAndroid Build Coastguard Worker   inbound_audio->total_samples_received =
467*d9f75844SAndroid Build Coastguard Worker       voice_receiver_info.total_samples_received;
468*d9f75844SAndroid Build Coastguard Worker   inbound_audio->concealed_samples = voice_receiver_info.concealed_samples;
469*d9f75844SAndroid Build Coastguard Worker   inbound_audio->silent_concealed_samples =
470*d9f75844SAndroid Build Coastguard Worker       voice_receiver_info.silent_concealed_samples;
471*d9f75844SAndroid Build Coastguard Worker   inbound_audio->concealment_events = voice_receiver_info.concealment_events;
472*d9f75844SAndroid Build Coastguard Worker   inbound_audio->inserted_samples_for_deceleration =
473*d9f75844SAndroid Build Coastguard Worker       voice_receiver_info.inserted_samples_for_deceleration;
474*d9f75844SAndroid Build Coastguard Worker   inbound_audio->removed_samples_for_acceleration =
475*d9f75844SAndroid Build Coastguard Worker       voice_receiver_info.removed_samples_for_acceleration;
476*d9f75844SAndroid Build Coastguard Worker   if (voice_receiver_info.audio_level >= 0) {
477*d9f75844SAndroid Build Coastguard Worker     inbound_audio->audio_level =
478*d9f75844SAndroid Build Coastguard Worker         DoubleAudioLevelFromIntAudioLevel(voice_receiver_info.audio_level);
479*d9f75844SAndroid Build Coastguard Worker   }
480*d9f75844SAndroid Build Coastguard Worker   inbound_audio->total_audio_energy = voice_receiver_info.total_output_energy;
481*d9f75844SAndroid Build Coastguard Worker   inbound_audio->total_samples_duration =
482*d9f75844SAndroid Build Coastguard Worker       voice_receiver_info.total_output_duration;
483*d9f75844SAndroid Build Coastguard Worker   // `fir_count`, `pli_count` and `sli_count` are only valid for video and are
484*d9f75844SAndroid Build Coastguard Worker   // purposefully left undefined for audio.
485*d9f75844SAndroid Build Coastguard Worker   if (voice_receiver_info.last_packet_received_timestamp_ms.has_value()) {
486*d9f75844SAndroid Build Coastguard Worker     inbound_audio->last_packet_received_timestamp = static_cast<double>(
487*d9f75844SAndroid Build Coastguard Worker         *voice_receiver_info.last_packet_received_timestamp_ms);
488*d9f75844SAndroid Build Coastguard Worker   }
489*d9f75844SAndroid Build Coastguard Worker   if (voice_receiver_info.estimated_playout_ntp_timestamp_ms.has_value()) {
490*d9f75844SAndroid Build Coastguard Worker     // TODO(bugs.webrtc.org/10529): Fix time origin.
491*d9f75844SAndroid Build Coastguard Worker     inbound_audio->estimated_playout_timestamp = static_cast<double>(
492*d9f75844SAndroid Build Coastguard Worker         *voice_receiver_info.estimated_playout_ntp_timestamp_ms);
493*d9f75844SAndroid Build Coastguard Worker   }
494*d9f75844SAndroid Build Coastguard Worker   inbound_audio->fec_packets_received =
495*d9f75844SAndroid Build Coastguard Worker       voice_receiver_info.fec_packets_received;
496*d9f75844SAndroid Build Coastguard Worker   inbound_audio->fec_packets_discarded =
497*d9f75844SAndroid Build Coastguard Worker       voice_receiver_info.fec_packets_discarded;
498*d9f75844SAndroid Build Coastguard Worker   inbound_audio->packets_discarded = voice_receiver_info.packets_discarded;
499*d9f75844SAndroid Build Coastguard Worker   inbound_audio->jitter_buffer_flushes =
500*d9f75844SAndroid Build Coastguard Worker       voice_receiver_info.jitter_buffer_flushes;
501*d9f75844SAndroid Build Coastguard Worker   inbound_audio->delayed_packet_outage_samples =
502*d9f75844SAndroid Build Coastguard Worker       voice_receiver_info.delayed_packet_outage_samples;
503*d9f75844SAndroid Build Coastguard Worker   inbound_audio->relative_packet_arrival_delay =
504*d9f75844SAndroid Build Coastguard Worker       voice_receiver_info.relative_packet_arrival_delay_seconds;
505*d9f75844SAndroid Build Coastguard Worker   inbound_audio->interruption_count =
506*d9f75844SAndroid Build Coastguard Worker       voice_receiver_info.interruption_count >= 0
507*d9f75844SAndroid Build Coastguard Worker           ? voice_receiver_info.interruption_count
508*d9f75844SAndroid Build Coastguard Worker           : 0;
509*d9f75844SAndroid Build Coastguard Worker   inbound_audio->total_interruption_duration =
510*d9f75844SAndroid Build Coastguard Worker       static_cast<double>(voice_receiver_info.total_interruption_duration_ms) /
511*d9f75844SAndroid Build Coastguard Worker       rtc::kNumMillisecsPerSec;
512*d9f75844SAndroid Build Coastguard Worker   return inbound_audio;
513*d9f75844SAndroid Build Coastguard Worker }
514*d9f75844SAndroid Build Coastguard Worker 
515*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<RTCRemoteOutboundRtpStreamStats>
CreateRemoteOutboundAudioStreamStats(const cricket::VoiceReceiverInfo & voice_receiver_info,const std::string & mid,const RTCInboundRTPStreamStats & inbound_audio_stats,const std::string & transport_id)516*d9f75844SAndroid Build Coastguard Worker CreateRemoteOutboundAudioStreamStats(
517*d9f75844SAndroid Build Coastguard Worker     const cricket::VoiceReceiverInfo& voice_receiver_info,
518*d9f75844SAndroid Build Coastguard Worker     const std::string& mid,
519*d9f75844SAndroid Build Coastguard Worker     const RTCInboundRTPStreamStats& inbound_audio_stats,
520*d9f75844SAndroid Build Coastguard Worker     const std::string& transport_id) {
521*d9f75844SAndroid Build Coastguard Worker   if (!voice_receiver_info.last_sender_report_timestamp_ms.has_value()) {
522*d9f75844SAndroid Build Coastguard Worker     // Cannot create `RTCRemoteOutboundRtpStreamStats` when the RTCP SR arrival
523*d9f75844SAndroid Build Coastguard Worker     // timestamp is not available - i.e., until the first sender report is
524*d9f75844SAndroid Build Coastguard Worker     // received.
525*d9f75844SAndroid Build Coastguard Worker     return nullptr;
526*d9f75844SAndroid Build Coastguard Worker   }
527*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_GT(voice_receiver_info.sender_reports_reports_count, 0);
528*d9f75844SAndroid Build Coastguard Worker 
529*d9f75844SAndroid Build Coastguard Worker   // Create.
530*d9f75844SAndroid Build Coastguard Worker   auto stats = std::make_unique<RTCRemoteOutboundRtpStreamStats>(
531*d9f75844SAndroid Build Coastguard Worker       /*id=*/RTCRemoteOutboundRTPStreamStatsIDFromSSRC(
532*d9f75844SAndroid Build Coastguard Worker           cricket::MEDIA_TYPE_AUDIO, voice_receiver_info.ssrc()),
533*d9f75844SAndroid Build Coastguard Worker       /*timestamp_us=*/rtc::kNumMicrosecsPerMillisec *
534*d9f75844SAndroid Build Coastguard Worker           voice_receiver_info.last_sender_report_timestamp_ms.value());
535*d9f75844SAndroid Build Coastguard Worker 
536*d9f75844SAndroid Build Coastguard Worker   // Populate.
537*d9f75844SAndroid Build Coastguard Worker   // - RTCRtpStreamStats.
538*d9f75844SAndroid Build Coastguard Worker   stats->ssrc = voice_receiver_info.ssrc();
539*d9f75844SAndroid Build Coastguard Worker   stats->kind = "audio";
540*d9f75844SAndroid Build Coastguard Worker   stats->transport_id = transport_id;
541*d9f75844SAndroid Build Coastguard Worker   if (inbound_audio_stats.codec_id.is_defined()) {
542*d9f75844SAndroid Build Coastguard Worker     stats->codec_id = *inbound_audio_stats.codec_id;
543*d9f75844SAndroid Build Coastguard Worker   }
544*d9f75844SAndroid Build Coastguard Worker   // - RTCSentRtpStreamStats.
545*d9f75844SAndroid Build Coastguard Worker   stats->packets_sent = voice_receiver_info.sender_reports_packets_sent;
546*d9f75844SAndroid Build Coastguard Worker   stats->bytes_sent = voice_receiver_info.sender_reports_bytes_sent;
547*d9f75844SAndroid Build Coastguard Worker   // - RTCRemoteOutboundRtpStreamStats.
548*d9f75844SAndroid Build Coastguard Worker   stats->local_id = inbound_audio_stats.id();
549*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(
550*d9f75844SAndroid Build Coastguard Worker       voice_receiver_info.last_sender_report_remote_timestamp_ms.has_value());
551*d9f75844SAndroid Build Coastguard Worker   stats->remote_timestamp = static_cast<double>(
552*d9f75844SAndroid Build Coastguard Worker       voice_receiver_info.last_sender_report_remote_timestamp_ms.value());
553*d9f75844SAndroid Build Coastguard Worker   stats->reports_sent = voice_receiver_info.sender_reports_reports_count;
554*d9f75844SAndroid Build Coastguard Worker   if (voice_receiver_info.round_trip_time.has_value()) {
555*d9f75844SAndroid Build Coastguard Worker     stats->round_trip_time =
556*d9f75844SAndroid Build Coastguard Worker         voice_receiver_info.round_trip_time->seconds<double>();
557*d9f75844SAndroid Build Coastguard Worker   }
558*d9f75844SAndroid Build Coastguard Worker   stats->round_trip_time_measurements =
559*d9f75844SAndroid Build Coastguard Worker       voice_receiver_info.round_trip_time_measurements;
560*d9f75844SAndroid Build Coastguard Worker   stats->total_round_trip_time =
561*d9f75844SAndroid Build Coastguard Worker       voice_receiver_info.total_round_trip_time.seconds<double>();
562*d9f75844SAndroid Build Coastguard Worker 
563*d9f75844SAndroid Build Coastguard Worker   return stats;
564*d9f75844SAndroid Build Coastguard Worker }
565*d9f75844SAndroid Build Coastguard Worker 
SetInboundRTPStreamStatsFromVideoReceiverInfo(const std::string & transport_id,const std::string & mid,const cricket::VideoMediaInfo & video_media_info,const cricket::VideoReceiverInfo & video_receiver_info,RTCInboundRTPStreamStats * inbound_video,RTCStatsReport * report)566*d9f75844SAndroid Build Coastguard Worker void SetInboundRTPStreamStatsFromVideoReceiverInfo(
567*d9f75844SAndroid Build Coastguard Worker     const std::string& transport_id,
568*d9f75844SAndroid Build Coastguard Worker     const std::string& mid,
569*d9f75844SAndroid Build Coastguard Worker     const cricket::VideoMediaInfo& video_media_info,
570*d9f75844SAndroid Build Coastguard Worker     const cricket::VideoReceiverInfo& video_receiver_info,
571*d9f75844SAndroid Build Coastguard Worker     RTCInboundRTPStreamStats* inbound_video,
572*d9f75844SAndroid Build Coastguard Worker     RTCStatsReport* report) {
573*d9f75844SAndroid Build Coastguard Worker   SetInboundRTPStreamStatsFromMediaReceiverInfo(video_receiver_info,
574*d9f75844SAndroid Build Coastguard Worker                                                 inbound_video);
575*d9f75844SAndroid Build Coastguard Worker   inbound_video->transport_id = transport_id;
576*d9f75844SAndroid Build Coastguard Worker   inbound_video->mid = mid;
577*d9f75844SAndroid Build Coastguard Worker   inbound_video->media_type = "video";
578*d9f75844SAndroid Build Coastguard Worker   inbound_video->kind = "video";
579*d9f75844SAndroid Build Coastguard Worker   if (video_receiver_info.codec_payload_type.has_value()) {
580*d9f75844SAndroid Build Coastguard Worker     auto codec_param_it = video_media_info.receive_codecs.find(
581*d9f75844SAndroid Build Coastguard Worker         video_receiver_info.codec_payload_type.value());
582*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(codec_param_it != video_media_info.receive_codecs.end());
583*d9f75844SAndroid Build Coastguard Worker     if (codec_param_it != video_media_info.receive_codecs.end()) {
584*d9f75844SAndroid Build Coastguard Worker       inbound_video->codec_id = GetCodecIdAndMaybeCreateCodecStats(
585*d9f75844SAndroid Build Coastguard Worker           inbound_video->timestamp_us(), kDirectionInbound, transport_id,
586*d9f75844SAndroid Build Coastguard Worker           codec_param_it->second, report);
587*d9f75844SAndroid Build Coastguard Worker     }
588*d9f75844SAndroid Build Coastguard Worker   }
589*d9f75844SAndroid Build Coastguard Worker   inbound_video->jitter = static_cast<double>(video_receiver_info.jitter_ms) /
590*d9f75844SAndroid Build Coastguard Worker                           rtc::kNumMillisecsPerSec;
591*d9f75844SAndroid Build Coastguard Worker   inbound_video->fir_count =
592*d9f75844SAndroid Build Coastguard Worker       static_cast<uint32_t>(video_receiver_info.firs_sent);
593*d9f75844SAndroid Build Coastguard Worker   inbound_video->pli_count =
594*d9f75844SAndroid Build Coastguard Worker       static_cast<uint32_t>(video_receiver_info.plis_sent);
595*d9f75844SAndroid Build Coastguard Worker   inbound_video->frames_received = video_receiver_info.frames_received;
596*d9f75844SAndroid Build Coastguard Worker   inbound_video->frames_decoded = video_receiver_info.frames_decoded;
597*d9f75844SAndroid Build Coastguard Worker   inbound_video->frames_dropped = video_receiver_info.frames_dropped;
598*d9f75844SAndroid Build Coastguard Worker   inbound_video->key_frames_decoded = video_receiver_info.key_frames_decoded;
599*d9f75844SAndroid Build Coastguard Worker   if (video_receiver_info.frame_width > 0) {
600*d9f75844SAndroid Build Coastguard Worker     inbound_video->frame_width =
601*d9f75844SAndroid Build Coastguard Worker         static_cast<uint32_t>(video_receiver_info.frame_width);
602*d9f75844SAndroid Build Coastguard Worker   }
603*d9f75844SAndroid Build Coastguard Worker   if (video_receiver_info.frame_height > 0) {
604*d9f75844SAndroid Build Coastguard Worker     inbound_video->frame_height =
605*d9f75844SAndroid Build Coastguard Worker         static_cast<uint32_t>(video_receiver_info.frame_height);
606*d9f75844SAndroid Build Coastguard Worker   }
607*d9f75844SAndroid Build Coastguard Worker   if (video_receiver_info.framerate_decoded > 0) {
608*d9f75844SAndroid Build Coastguard Worker     inbound_video->frames_per_second = video_receiver_info.framerate_decoded;
609*d9f75844SAndroid Build Coastguard Worker   }
610*d9f75844SAndroid Build Coastguard Worker   if (video_receiver_info.qp_sum.has_value()) {
611*d9f75844SAndroid Build Coastguard Worker     inbound_video->qp_sum = *video_receiver_info.qp_sum;
612*d9f75844SAndroid Build Coastguard Worker   }
613*d9f75844SAndroid Build Coastguard Worker   if (video_receiver_info.timing_frame_info.has_value()) {
614*d9f75844SAndroid Build Coastguard Worker     inbound_video->goog_timing_frame_info =
615*d9f75844SAndroid Build Coastguard Worker         video_receiver_info.timing_frame_info->ToString();
616*d9f75844SAndroid Build Coastguard Worker   }
617*d9f75844SAndroid Build Coastguard Worker   inbound_video->total_decode_time =
618*d9f75844SAndroid Build Coastguard Worker       video_receiver_info.total_decode_time.seconds<double>();
619*d9f75844SAndroid Build Coastguard Worker   inbound_video->total_processing_delay =
620*d9f75844SAndroid Build Coastguard Worker       video_receiver_info.total_processing_delay.seconds<double>();
621*d9f75844SAndroid Build Coastguard Worker   inbound_video->total_assembly_time =
622*d9f75844SAndroid Build Coastguard Worker       video_receiver_info.total_assembly_time.seconds<double>();
623*d9f75844SAndroid Build Coastguard Worker   inbound_video->frames_assembled_from_multiple_packets =
624*d9f75844SAndroid Build Coastguard Worker       video_receiver_info.frames_assembled_from_multiple_packets;
625*d9f75844SAndroid Build Coastguard Worker   inbound_video->total_inter_frame_delay =
626*d9f75844SAndroid Build Coastguard Worker       video_receiver_info.total_inter_frame_delay;
627*d9f75844SAndroid Build Coastguard Worker   inbound_video->total_squared_inter_frame_delay =
628*d9f75844SAndroid Build Coastguard Worker       video_receiver_info.total_squared_inter_frame_delay;
629*d9f75844SAndroid Build Coastguard Worker   inbound_video->pause_count = video_receiver_info.pause_count;
630*d9f75844SAndroid Build Coastguard Worker   inbound_video->total_pauses_duration =
631*d9f75844SAndroid Build Coastguard Worker       static_cast<double>(video_receiver_info.total_pauses_duration_ms) /
632*d9f75844SAndroid Build Coastguard Worker       rtc::kNumMillisecsPerSec;
633*d9f75844SAndroid Build Coastguard Worker   inbound_video->freeze_count = video_receiver_info.freeze_count;
634*d9f75844SAndroid Build Coastguard Worker   inbound_video->total_freezes_duration =
635*d9f75844SAndroid Build Coastguard Worker       static_cast<double>(video_receiver_info.total_freezes_duration_ms) /
636*d9f75844SAndroid Build Coastguard Worker       rtc::kNumMillisecsPerSec;
637*d9f75844SAndroid Build Coastguard Worker   inbound_video->min_playout_delay =
638*d9f75844SAndroid Build Coastguard Worker       static_cast<double>(video_receiver_info.min_playout_delay_ms) /
639*d9f75844SAndroid Build Coastguard Worker       rtc::kNumMillisecsPerSec;
640*d9f75844SAndroid Build Coastguard Worker   if (video_receiver_info.last_packet_received_timestamp_ms.has_value()) {
641*d9f75844SAndroid Build Coastguard Worker     inbound_video->last_packet_received_timestamp = static_cast<double>(
642*d9f75844SAndroid Build Coastguard Worker         *video_receiver_info.last_packet_received_timestamp_ms);
643*d9f75844SAndroid Build Coastguard Worker   }
644*d9f75844SAndroid Build Coastguard Worker   if (video_receiver_info.estimated_playout_ntp_timestamp_ms.has_value()) {
645*d9f75844SAndroid Build Coastguard Worker     // TODO(bugs.webrtc.org/10529): Fix time origin if needed.
646*d9f75844SAndroid Build Coastguard Worker     inbound_video->estimated_playout_timestamp = static_cast<double>(
647*d9f75844SAndroid Build Coastguard Worker         *video_receiver_info.estimated_playout_ntp_timestamp_ms);
648*d9f75844SAndroid Build Coastguard Worker   }
649*d9f75844SAndroid Build Coastguard Worker   // TODO(bugs.webrtc.org/10529): When info's `content_info` is optional
650*d9f75844SAndroid Build Coastguard Worker   // support the "unspecified" value.
651*d9f75844SAndroid Build Coastguard Worker   if (video_receiver_info.content_type == VideoContentType::SCREENSHARE)
652*d9f75844SAndroid Build Coastguard Worker     inbound_video->content_type = RTCContentType::kScreenshare;
653*d9f75844SAndroid Build Coastguard Worker   if (!video_receiver_info.decoder_implementation_name.empty()) {
654*d9f75844SAndroid Build Coastguard Worker     inbound_video->decoder_implementation =
655*d9f75844SAndroid Build Coastguard Worker         video_receiver_info.decoder_implementation_name;
656*d9f75844SAndroid Build Coastguard Worker   }
657*d9f75844SAndroid Build Coastguard Worker   if (video_receiver_info.power_efficient_decoder.has_value()) {
658*d9f75844SAndroid Build Coastguard Worker     inbound_video->power_efficient_decoder =
659*d9f75844SAndroid Build Coastguard Worker         video_receiver_info.power_efficient_decoder.value();
660*d9f75844SAndroid Build Coastguard Worker   }
661*d9f75844SAndroid Build Coastguard Worker }
662*d9f75844SAndroid Build Coastguard Worker 
663*d9f75844SAndroid Build Coastguard Worker // Provides the media independent counters and information (both audio and
664*d9f75844SAndroid Build Coastguard Worker // video).
SetOutboundRTPStreamStatsFromMediaSenderInfo(const cricket::MediaSenderInfo & media_sender_info,RTCOutboundRTPStreamStats * outbound_stats)665*d9f75844SAndroid Build Coastguard Worker void SetOutboundRTPStreamStatsFromMediaSenderInfo(
666*d9f75844SAndroid Build Coastguard Worker     const cricket::MediaSenderInfo& media_sender_info,
667*d9f75844SAndroid Build Coastguard Worker     RTCOutboundRTPStreamStats* outbound_stats) {
668*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(outbound_stats);
669*d9f75844SAndroid Build Coastguard Worker   outbound_stats->ssrc = media_sender_info.ssrc();
670*d9f75844SAndroid Build Coastguard Worker   outbound_stats->packets_sent =
671*d9f75844SAndroid Build Coastguard Worker       static_cast<uint32_t>(media_sender_info.packets_sent);
672*d9f75844SAndroid Build Coastguard Worker   outbound_stats->total_packet_send_delay =
673*d9f75844SAndroid Build Coastguard Worker       media_sender_info.total_packet_send_delay.seconds<double>();
674*d9f75844SAndroid Build Coastguard Worker   outbound_stats->retransmitted_packets_sent =
675*d9f75844SAndroid Build Coastguard Worker       media_sender_info.retransmitted_packets_sent;
676*d9f75844SAndroid Build Coastguard Worker   outbound_stats->bytes_sent =
677*d9f75844SAndroid Build Coastguard Worker       static_cast<uint64_t>(media_sender_info.payload_bytes_sent);
678*d9f75844SAndroid Build Coastguard Worker   outbound_stats->header_bytes_sent =
679*d9f75844SAndroid Build Coastguard Worker       static_cast<uint64_t>(media_sender_info.header_and_padding_bytes_sent);
680*d9f75844SAndroid Build Coastguard Worker   outbound_stats->retransmitted_bytes_sent =
681*d9f75844SAndroid Build Coastguard Worker       media_sender_info.retransmitted_bytes_sent;
682*d9f75844SAndroid Build Coastguard Worker   outbound_stats->nack_count = media_sender_info.nacks_rcvd;
683*d9f75844SAndroid Build Coastguard Worker   if (media_sender_info.active.has_value()) {
684*d9f75844SAndroid Build Coastguard Worker     outbound_stats->active = *media_sender_info.active;
685*d9f75844SAndroid Build Coastguard Worker   }
686*d9f75844SAndroid Build Coastguard Worker }
687*d9f75844SAndroid Build Coastguard Worker 
SetOutboundRTPStreamStatsFromVoiceSenderInfo(const std::string & transport_id,const std::string & mid,const cricket::VoiceMediaInfo & voice_media_info,const cricket::VoiceSenderInfo & voice_sender_info,RTCOutboundRTPStreamStats * outbound_audio,RTCStatsReport * report)688*d9f75844SAndroid Build Coastguard Worker void SetOutboundRTPStreamStatsFromVoiceSenderInfo(
689*d9f75844SAndroid Build Coastguard Worker     const std::string& transport_id,
690*d9f75844SAndroid Build Coastguard Worker     const std::string& mid,
691*d9f75844SAndroid Build Coastguard Worker     const cricket::VoiceMediaInfo& voice_media_info,
692*d9f75844SAndroid Build Coastguard Worker     const cricket::VoiceSenderInfo& voice_sender_info,
693*d9f75844SAndroid Build Coastguard Worker     RTCOutboundRTPStreamStats* outbound_audio,
694*d9f75844SAndroid Build Coastguard Worker     RTCStatsReport* report) {
695*d9f75844SAndroid Build Coastguard Worker   SetOutboundRTPStreamStatsFromMediaSenderInfo(voice_sender_info,
696*d9f75844SAndroid Build Coastguard Worker                                                outbound_audio);
697*d9f75844SAndroid Build Coastguard Worker   outbound_audio->transport_id = transport_id;
698*d9f75844SAndroid Build Coastguard Worker   outbound_audio->mid = mid;
699*d9f75844SAndroid Build Coastguard Worker   outbound_audio->media_type = "audio";
700*d9f75844SAndroid Build Coastguard Worker   outbound_audio->kind = "audio";
701*d9f75844SAndroid Build Coastguard Worker   if (voice_sender_info.target_bitrate.has_value() &&
702*d9f75844SAndroid Build Coastguard Worker       *voice_sender_info.target_bitrate > 0) {
703*d9f75844SAndroid Build Coastguard Worker     outbound_audio->target_bitrate = *voice_sender_info.target_bitrate;
704*d9f75844SAndroid Build Coastguard Worker   }
705*d9f75844SAndroid Build Coastguard Worker   if (voice_sender_info.codec_payload_type.has_value()) {
706*d9f75844SAndroid Build Coastguard Worker     auto codec_param_it = voice_media_info.send_codecs.find(
707*d9f75844SAndroid Build Coastguard Worker         voice_sender_info.codec_payload_type.value());
708*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(codec_param_it != voice_media_info.send_codecs.end());
709*d9f75844SAndroid Build Coastguard Worker     if (codec_param_it != voice_media_info.send_codecs.end()) {
710*d9f75844SAndroid Build Coastguard Worker       outbound_audio->codec_id = GetCodecIdAndMaybeCreateCodecStats(
711*d9f75844SAndroid Build Coastguard Worker           outbound_audio->timestamp_us(), kDirectionOutbound, transport_id,
712*d9f75844SAndroid Build Coastguard Worker           codec_param_it->second, report);
713*d9f75844SAndroid Build Coastguard Worker     }
714*d9f75844SAndroid Build Coastguard Worker   }
715*d9f75844SAndroid Build Coastguard Worker   // `fir_count`, `pli_count` and `sli_count` are only valid for video and are
716*d9f75844SAndroid Build Coastguard Worker   // purposefully left undefined for audio.
717*d9f75844SAndroid Build Coastguard Worker }
718*d9f75844SAndroid Build Coastguard Worker 
SetOutboundRTPStreamStatsFromVideoSenderInfo(const std::string & transport_id,const std::string & mid,const cricket::VideoMediaInfo & video_media_info,const cricket::VideoSenderInfo & video_sender_info,RTCOutboundRTPStreamStats * outbound_video,RTCStatsReport * report)719*d9f75844SAndroid Build Coastguard Worker void SetOutboundRTPStreamStatsFromVideoSenderInfo(
720*d9f75844SAndroid Build Coastguard Worker     const std::string& transport_id,
721*d9f75844SAndroid Build Coastguard Worker     const std::string& mid,
722*d9f75844SAndroid Build Coastguard Worker     const cricket::VideoMediaInfo& video_media_info,
723*d9f75844SAndroid Build Coastguard Worker     const cricket::VideoSenderInfo& video_sender_info,
724*d9f75844SAndroid Build Coastguard Worker     RTCOutboundRTPStreamStats* outbound_video,
725*d9f75844SAndroid Build Coastguard Worker     RTCStatsReport* report) {
726*d9f75844SAndroid Build Coastguard Worker   SetOutboundRTPStreamStatsFromMediaSenderInfo(video_sender_info,
727*d9f75844SAndroid Build Coastguard Worker                                                outbound_video);
728*d9f75844SAndroid Build Coastguard Worker   outbound_video->transport_id = transport_id;
729*d9f75844SAndroid Build Coastguard Worker   outbound_video->mid = mid;
730*d9f75844SAndroid Build Coastguard Worker   outbound_video->media_type = "video";
731*d9f75844SAndroid Build Coastguard Worker   outbound_video->kind = "video";
732*d9f75844SAndroid Build Coastguard Worker   if (video_sender_info.codec_payload_type.has_value()) {
733*d9f75844SAndroid Build Coastguard Worker     auto codec_param_it = video_media_info.send_codecs.find(
734*d9f75844SAndroid Build Coastguard Worker         video_sender_info.codec_payload_type.value());
735*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(codec_param_it != video_media_info.send_codecs.end());
736*d9f75844SAndroid Build Coastguard Worker     if (codec_param_it != video_media_info.send_codecs.end()) {
737*d9f75844SAndroid Build Coastguard Worker       outbound_video->codec_id = GetCodecIdAndMaybeCreateCodecStats(
738*d9f75844SAndroid Build Coastguard Worker           outbound_video->timestamp_us(), kDirectionOutbound, transport_id,
739*d9f75844SAndroid Build Coastguard Worker           codec_param_it->second, report);
740*d9f75844SAndroid Build Coastguard Worker     }
741*d9f75844SAndroid Build Coastguard Worker   }
742*d9f75844SAndroid Build Coastguard Worker   outbound_video->fir_count =
743*d9f75844SAndroid Build Coastguard Worker       static_cast<uint32_t>(video_sender_info.firs_rcvd);
744*d9f75844SAndroid Build Coastguard Worker   outbound_video->pli_count =
745*d9f75844SAndroid Build Coastguard Worker       static_cast<uint32_t>(video_sender_info.plis_rcvd);
746*d9f75844SAndroid Build Coastguard Worker   if (video_sender_info.qp_sum.has_value())
747*d9f75844SAndroid Build Coastguard Worker     outbound_video->qp_sum = *video_sender_info.qp_sum;
748*d9f75844SAndroid Build Coastguard Worker   if (video_sender_info.target_bitrate.has_value() &&
749*d9f75844SAndroid Build Coastguard Worker       *video_sender_info.target_bitrate > 0) {
750*d9f75844SAndroid Build Coastguard Worker     outbound_video->target_bitrate = *video_sender_info.target_bitrate;
751*d9f75844SAndroid Build Coastguard Worker   }
752*d9f75844SAndroid Build Coastguard Worker   outbound_video->frames_encoded = video_sender_info.frames_encoded;
753*d9f75844SAndroid Build Coastguard Worker   outbound_video->key_frames_encoded = video_sender_info.key_frames_encoded;
754*d9f75844SAndroid Build Coastguard Worker   outbound_video->total_encode_time =
755*d9f75844SAndroid Build Coastguard Worker       static_cast<double>(video_sender_info.total_encode_time_ms) /
756*d9f75844SAndroid Build Coastguard Worker       rtc::kNumMillisecsPerSec;
757*d9f75844SAndroid Build Coastguard Worker   outbound_video->total_encoded_bytes_target =
758*d9f75844SAndroid Build Coastguard Worker       video_sender_info.total_encoded_bytes_target;
759*d9f75844SAndroid Build Coastguard Worker   if (video_sender_info.send_frame_width > 0) {
760*d9f75844SAndroid Build Coastguard Worker     outbound_video->frame_width =
761*d9f75844SAndroid Build Coastguard Worker         static_cast<uint32_t>(video_sender_info.send_frame_width);
762*d9f75844SAndroid Build Coastguard Worker   }
763*d9f75844SAndroid Build Coastguard Worker   if (video_sender_info.send_frame_height > 0) {
764*d9f75844SAndroid Build Coastguard Worker     outbound_video->frame_height =
765*d9f75844SAndroid Build Coastguard Worker         static_cast<uint32_t>(video_sender_info.send_frame_height);
766*d9f75844SAndroid Build Coastguard Worker   }
767*d9f75844SAndroid Build Coastguard Worker   if (video_sender_info.framerate_sent > 0) {
768*d9f75844SAndroid Build Coastguard Worker     outbound_video->frames_per_second = video_sender_info.framerate_sent;
769*d9f75844SAndroid Build Coastguard Worker   }
770*d9f75844SAndroid Build Coastguard Worker   outbound_video->frames_sent = video_sender_info.frames_sent;
771*d9f75844SAndroid Build Coastguard Worker   outbound_video->huge_frames_sent = video_sender_info.huge_frames_sent;
772*d9f75844SAndroid Build Coastguard Worker   outbound_video->quality_limitation_reason =
773*d9f75844SAndroid Build Coastguard Worker       QualityLimitationReasonToRTCQualityLimitationReason(
774*d9f75844SAndroid Build Coastguard Worker           video_sender_info.quality_limitation_reason);
775*d9f75844SAndroid Build Coastguard Worker   outbound_video->quality_limitation_durations =
776*d9f75844SAndroid Build Coastguard Worker       QualityLimitationDurationToRTCQualityLimitationDuration(
777*d9f75844SAndroid Build Coastguard Worker           video_sender_info.quality_limitation_durations_ms);
778*d9f75844SAndroid Build Coastguard Worker   outbound_video->quality_limitation_resolution_changes =
779*d9f75844SAndroid Build Coastguard Worker       video_sender_info.quality_limitation_resolution_changes;
780*d9f75844SAndroid Build Coastguard Worker   // TODO(https://crbug.com/webrtc/10529): When info's `content_info` is
781*d9f75844SAndroid Build Coastguard Worker   // optional, support the "unspecified" value.
782*d9f75844SAndroid Build Coastguard Worker   if (video_sender_info.content_type == VideoContentType::SCREENSHARE)
783*d9f75844SAndroid Build Coastguard Worker     outbound_video->content_type = RTCContentType::kScreenshare;
784*d9f75844SAndroid Build Coastguard Worker   if (!video_sender_info.encoder_implementation_name.empty()) {
785*d9f75844SAndroid Build Coastguard Worker     outbound_video->encoder_implementation =
786*d9f75844SAndroid Build Coastguard Worker         video_sender_info.encoder_implementation_name;
787*d9f75844SAndroid Build Coastguard Worker   }
788*d9f75844SAndroid Build Coastguard Worker   if (video_sender_info.rid.has_value()) {
789*d9f75844SAndroid Build Coastguard Worker     outbound_video->rid = *video_sender_info.rid;
790*d9f75844SAndroid Build Coastguard Worker   }
791*d9f75844SAndroid Build Coastguard Worker   if (video_sender_info.power_efficient_encoder.has_value()) {
792*d9f75844SAndroid Build Coastguard Worker     outbound_video->power_efficient_encoder =
793*d9f75844SAndroid Build Coastguard Worker         video_sender_info.power_efficient_encoder.value();
794*d9f75844SAndroid Build Coastguard Worker   }
795*d9f75844SAndroid Build Coastguard Worker }
796*d9f75844SAndroid Build Coastguard Worker 
797*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<RTCRemoteInboundRtpStreamStats>
ProduceRemoteInboundRtpStreamStatsFromReportBlockData(const std::string & transport_id,const ReportBlockData & report_block_data,cricket::MediaType media_type,const std::map<std::string,RTCOutboundRTPStreamStats * > & outbound_rtps,const RTCStatsReport & report)798*d9f75844SAndroid Build Coastguard Worker ProduceRemoteInboundRtpStreamStatsFromReportBlockData(
799*d9f75844SAndroid Build Coastguard Worker     const std::string& transport_id,
800*d9f75844SAndroid Build Coastguard Worker     const ReportBlockData& report_block_data,
801*d9f75844SAndroid Build Coastguard Worker     cricket::MediaType media_type,
802*d9f75844SAndroid Build Coastguard Worker     const std::map<std::string, RTCOutboundRTPStreamStats*>& outbound_rtps,
803*d9f75844SAndroid Build Coastguard Worker     const RTCStatsReport& report) {
804*d9f75844SAndroid Build Coastguard Worker   const auto& report_block = report_block_data.report_block();
805*d9f75844SAndroid Build Coastguard Worker   // RTCStats' timestamp generally refers to when the metric was sampled, but
806*d9f75844SAndroid Build Coastguard Worker   // for "remote-[outbound/inbound]-rtp" it refers to the local time when the
807*d9f75844SAndroid Build Coastguard Worker   // Report Block was received.
808*d9f75844SAndroid Build Coastguard Worker   auto remote_inbound = std::make_unique<RTCRemoteInboundRtpStreamStats>(
809*d9f75844SAndroid Build Coastguard Worker       RTCRemoteInboundRtpStreamStatsIdFromSourceSsrc(media_type,
810*d9f75844SAndroid Build Coastguard Worker                                                      report_block.source_ssrc),
811*d9f75844SAndroid Build Coastguard Worker       /*timestamp=*/report_block_data.report_block_timestamp_utc_us());
812*d9f75844SAndroid Build Coastguard Worker   remote_inbound->ssrc = report_block.source_ssrc;
813*d9f75844SAndroid Build Coastguard Worker   remote_inbound->kind =
814*d9f75844SAndroid Build Coastguard Worker       media_type == cricket::MEDIA_TYPE_AUDIO ? "audio" : "video";
815*d9f75844SAndroid Build Coastguard Worker   remote_inbound->packets_lost = report_block.packets_lost;
816*d9f75844SAndroid Build Coastguard Worker   remote_inbound->fraction_lost =
817*d9f75844SAndroid Build Coastguard Worker       static_cast<double>(report_block.fraction_lost) / (1 << 8);
818*d9f75844SAndroid Build Coastguard Worker   if (report_block_data.num_rtts() > 0) {
819*d9f75844SAndroid Build Coastguard Worker     remote_inbound->round_trip_time =
820*d9f75844SAndroid Build Coastguard Worker         static_cast<double>(report_block_data.last_rtt_ms()) /
821*d9f75844SAndroid Build Coastguard Worker         rtc::kNumMillisecsPerSec;
822*d9f75844SAndroid Build Coastguard Worker   }
823*d9f75844SAndroid Build Coastguard Worker   remote_inbound->total_round_trip_time =
824*d9f75844SAndroid Build Coastguard Worker       static_cast<double>(report_block_data.sum_rtt_ms()) /
825*d9f75844SAndroid Build Coastguard Worker       rtc::kNumMillisecsPerSec;
826*d9f75844SAndroid Build Coastguard Worker   remote_inbound->round_trip_time_measurements =
827*d9f75844SAndroid Build Coastguard Worker       report_block_data.num_rtts();
828*d9f75844SAndroid Build Coastguard Worker 
829*d9f75844SAndroid Build Coastguard Worker   std::string local_id = RTCOutboundRTPStreamStatsIDFromSSRC(
830*d9f75844SAndroid Build Coastguard Worker       transport_id, media_type, report_block.source_ssrc);
831*d9f75844SAndroid Build Coastguard Worker   // Look up local stat from `outbound_rtps` where the pointers are non-const.
832*d9f75844SAndroid Build Coastguard Worker   auto local_id_it = outbound_rtps.find(local_id);
833*d9f75844SAndroid Build Coastguard Worker   if (local_id_it != outbound_rtps.end()) {
834*d9f75844SAndroid Build Coastguard Worker     remote_inbound->local_id = local_id;
835*d9f75844SAndroid Build Coastguard Worker     auto& outbound_rtp = *local_id_it->second;
836*d9f75844SAndroid Build Coastguard Worker     outbound_rtp.remote_id = remote_inbound->id();
837*d9f75844SAndroid Build Coastguard Worker     // The RTP/RTCP transport is obtained from the
838*d9f75844SAndroid Build Coastguard Worker     // RTCOutboundRtpStreamStats's transport.
839*d9f75844SAndroid Build Coastguard Worker     const auto* transport_from_id = report.Get(transport_id);
840*d9f75844SAndroid Build Coastguard Worker     if (transport_from_id) {
841*d9f75844SAndroid Build Coastguard Worker       const auto& transport = transport_from_id->cast_to<RTCTransportStats>();
842*d9f75844SAndroid Build Coastguard Worker       // If RTP and RTCP are not multiplexed, there is a separate RTCP
843*d9f75844SAndroid Build Coastguard Worker       // transport paired with the RTP transport, otherwise the same
844*d9f75844SAndroid Build Coastguard Worker       // transport is used for RTCP and RTP.
845*d9f75844SAndroid Build Coastguard Worker       remote_inbound->transport_id =
846*d9f75844SAndroid Build Coastguard Worker           transport.rtcp_transport_stats_id.is_defined()
847*d9f75844SAndroid Build Coastguard Worker               ? *transport.rtcp_transport_stats_id
848*d9f75844SAndroid Build Coastguard Worker               : *outbound_rtp.transport_id;
849*d9f75844SAndroid Build Coastguard Worker     }
850*d9f75844SAndroid Build Coastguard Worker     // We're assuming the same codec is used on both ends. However if the
851*d9f75844SAndroid Build Coastguard Worker     // codec is switched out on the fly we may have received a Report Block
852*d9f75844SAndroid Build Coastguard Worker     // based on the previous codec and there is no way to tell which point in
853*d9f75844SAndroid Build Coastguard Worker     // time the codec changed for the remote end.
854*d9f75844SAndroid Build Coastguard Worker     const auto* codec_from_id = outbound_rtp.codec_id.is_defined()
855*d9f75844SAndroid Build Coastguard Worker                                     ? report.Get(*outbound_rtp.codec_id)
856*d9f75844SAndroid Build Coastguard Worker                                     : nullptr;
857*d9f75844SAndroid Build Coastguard Worker     if (codec_from_id) {
858*d9f75844SAndroid Build Coastguard Worker       remote_inbound->codec_id = *outbound_rtp.codec_id;
859*d9f75844SAndroid Build Coastguard Worker       const auto& codec = codec_from_id->cast_to<RTCCodecStats>();
860*d9f75844SAndroid Build Coastguard Worker       if (codec.clock_rate.is_defined()) {
861*d9f75844SAndroid Build Coastguard Worker         // The Report Block jitter is expressed in RTP timestamp units
862*d9f75844SAndroid Build Coastguard Worker         // (https://tools.ietf.org/html/rfc3550#section-6.4.1). To convert this
863*d9f75844SAndroid Build Coastguard Worker         // to seconds we divide by the codec's clock rate.
864*d9f75844SAndroid Build Coastguard Worker         remote_inbound->jitter =
865*d9f75844SAndroid Build Coastguard Worker             static_cast<double>(report_block.jitter) / *codec.clock_rate;
866*d9f75844SAndroid Build Coastguard Worker       }
867*d9f75844SAndroid Build Coastguard Worker     }
868*d9f75844SAndroid Build Coastguard Worker   }
869*d9f75844SAndroid Build Coastguard Worker   return remote_inbound;
870*d9f75844SAndroid Build Coastguard Worker }
871*d9f75844SAndroid Build Coastguard Worker 
ProduceCertificateStatsFromSSLCertificateStats(int64_t timestamp_us,const rtc::SSLCertificateStats & certificate_stats,RTCStatsReport * report)872*d9f75844SAndroid Build Coastguard Worker void ProduceCertificateStatsFromSSLCertificateStats(
873*d9f75844SAndroid Build Coastguard Worker     int64_t timestamp_us,
874*d9f75844SAndroid Build Coastguard Worker     const rtc::SSLCertificateStats& certificate_stats,
875*d9f75844SAndroid Build Coastguard Worker     RTCStatsReport* report) {
876*d9f75844SAndroid Build Coastguard Worker   RTCCertificateStats* prev_certificate_stats = nullptr;
877*d9f75844SAndroid Build Coastguard Worker   for (const rtc::SSLCertificateStats* s = &certificate_stats; s;
878*d9f75844SAndroid Build Coastguard Worker        s = s->issuer.get()) {
879*d9f75844SAndroid Build Coastguard Worker     std::string certificate_stats_id =
880*d9f75844SAndroid Build Coastguard Worker         RTCCertificateIDFromFingerprint(s->fingerprint);
881*d9f75844SAndroid Build Coastguard Worker     // It is possible for the same certificate to show up multiple times, e.g.
882*d9f75844SAndroid Build Coastguard Worker     // if local and remote side use the same certificate in a loopback call.
883*d9f75844SAndroid Build Coastguard Worker     // If the report already contains stats for this certificate, skip it.
884*d9f75844SAndroid Build Coastguard Worker     if (report->Get(certificate_stats_id)) {
885*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK_EQ(s, &certificate_stats);
886*d9f75844SAndroid Build Coastguard Worker       break;
887*d9f75844SAndroid Build Coastguard Worker     }
888*d9f75844SAndroid Build Coastguard Worker     RTCCertificateStats* certificate_stats =
889*d9f75844SAndroid Build Coastguard Worker         new RTCCertificateStats(certificate_stats_id, timestamp_us);
890*d9f75844SAndroid Build Coastguard Worker     certificate_stats->fingerprint = s->fingerprint;
891*d9f75844SAndroid Build Coastguard Worker     certificate_stats->fingerprint_algorithm = s->fingerprint_algorithm;
892*d9f75844SAndroid Build Coastguard Worker     certificate_stats->base64_certificate = s->base64_certificate;
893*d9f75844SAndroid Build Coastguard Worker     if (prev_certificate_stats)
894*d9f75844SAndroid Build Coastguard Worker       prev_certificate_stats->issuer_certificate_id = certificate_stats->id();
895*d9f75844SAndroid Build Coastguard Worker     report->AddStats(std::unique_ptr<RTCCertificateStats>(certificate_stats));
896*d9f75844SAndroid Build Coastguard Worker     prev_certificate_stats = certificate_stats;
897*d9f75844SAndroid Build Coastguard Worker   }
898*d9f75844SAndroid Build Coastguard Worker }
899*d9f75844SAndroid Build Coastguard Worker 
ProduceIceCandidateStats(int64_t timestamp_us,const cricket::Candidate & candidate,bool is_local,const std::string & transport_id,RTCStatsReport * report)900*d9f75844SAndroid Build Coastguard Worker const std::string& ProduceIceCandidateStats(int64_t timestamp_us,
901*d9f75844SAndroid Build Coastguard Worker                                             const cricket::Candidate& candidate,
902*d9f75844SAndroid Build Coastguard Worker                                             bool is_local,
903*d9f75844SAndroid Build Coastguard Worker                                             const std::string& transport_id,
904*d9f75844SAndroid Build Coastguard Worker                                             RTCStatsReport* report) {
905*d9f75844SAndroid Build Coastguard Worker   const std::string& id = "I" + candidate.id();
906*d9f75844SAndroid Build Coastguard Worker   const RTCStats* stats = report->Get(id);
907*d9f75844SAndroid Build Coastguard Worker   if (!stats) {
908*d9f75844SAndroid Build Coastguard Worker     std::unique_ptr<RTCIceCandidateStats> candidate_stats;
909*d9f75844SAndroid Build Coastguard Worker     if (is_local)
910*d9f75844SAndroid Build Coastguard Worker       candidate_stats =
911*d9f75844SAndroid Build Coastguard Worker           std::make_unique<RTCLocalIceCandidateStats>(id, timestamp_us);
912*d9f75844SAndroid Build Coastguard Worker     else
913*d9f75844SAndroid Build Coastguard Worker       candidate_stats =
914*d9f75844SAndroid Build Coastguard Worker           std::make_unique<RTCRemoteIceCandidateStats>(id, timestamp_us);
915*d9f75844SAndroid Build Coastguard Worker     candidate_stats->transport_id = transport_id;
916*d9f75844SAndroid Build Coastguard Worker     if (is_local) {
917*d9f75844SAndroid Build Coastguard Worker       candidate_stats->network_type =
918*d9f75844SAndroid Build Coastguard Worker           NetworkTypeToStatsType(candidate.network_type());
919*d9f75844SAndroid Build Coastguard Worker       const std::string& candidate_type = candidate.type();
920*d9f75844SAndroid Build Coastguard Worker       const std::string& relay_protocol = candidate.relay_protocol();
921*d9f75844SAndroid Build Coastguard Worker       const std::string& url = candidate.url();
922*d9f75844SAndroid Build Coastguard Worker       if (candidate_type == cricket::RELAY_PORT_TYPE ||
923*d9f75844SAndroid Build Coastguard Worker           (candidate_type == cricket::PRFLX_PORT_TYPE &&
924*d9f75844SAndroid Build Coastguard Worker            !relay_protocol.empty())) {
925*d9f75844SAndroid Build Coastguard Worker         RTC_DCHECK(relay_protocol.compare("udp") == 0 ||
926*d9f75844SAndroid Build Coastguard Worker                    relay_protocol.compare("tcp") == 0 ||
927*d9f75844SAndroid Build Coastguard Worker                    relay_protocol.compare("tls") == 0);
928*d9f75844SAndroid Build Coastguard Worker         candidate_stats->relay_protocol = relay_protocol;
929*d9f75844SAndroid Build Coastguard Worker         if (!url.empty()) {
930*d9f75844SAndroid Build Coastguard Worker           candidate_stats->url = url;
931*d9f75844SAndroid Build Coastguard Worker         }
932*d9f75844SAndroid Build Coastguard Worker       } else if (candidate_type == cricket::STUN_PORT_TYPE) {
933*d9f75844SAndroid Build Coastguard Worker         if (!url.empty()) {
934*d9f75844SAndroid Build Coastguard Worker           candidate_stats->url = url;
935*d9f75844SAndroid Build Coastguard Worker         }
936*d9f75844SAndroid Build Coastguard Worker       }
937*d9f75844SAndroid Build Coastguard Worker       if (candidate.network_type() == rtc::ADAPTER_TYPE_VPN) {
938*d9f75844SAndroid Build Coastguard Worker         candidate_stats->vpn = true;
939*d9f75844SAndroid Build Coastguard Worker         candidate_stats->network_adapter_type =
940*d9f75844SAndroid Build Coastguard Worker             std::string(NetworkTypeToStatsNetworkAdapterType(
941*d9f75844SAndroid Build Coastguard Worker                 candidate.underlying_type_for_vpn()));
942*d9f75844SAndroid Build Coastguard Worker       } else {
943*d9f75844SAndroid Build Coastguard Worker         candidate_stats->vpn = false;
944*d9f75844SAndroid Build Coastguard Worker         candidate_stats->network_adapter_type = std::string(
945*d9f75844SAndroid Build Coastguard Worker             NetworkTypeToStatsNetworkAdapterType(candidate.network_type()));
946*d9f75844SAndroid Build Coastguard Worker       }
947*d9f75844SAndroid Build Coastguard Worker     } else {
948*d9f75844SAndroid Build Coastguard Worker       // We don't expect to know the adapter type of remote candidates.
949*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK_EQ(rtc::ADAPTER_TYPE_UNKNOWN, candidate.network_type());
950*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK_EQ(0, candidate.relay_protocol().compare(""));
951*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK_EQ(rtc::ADAPTER_TYPE_UNKNOWN,
952*d9f75844SAndroid Build Coastguard Worker                     candidate.underlying_type_for_vpn());
953*d9f75844SAndroid Build Coastguard Worker     }
954*d9f75844SAndroid Build Coastguard Worker     candidate_stats->ip = candidate.address().ipaddr().ToString();
955*d9f75844SAndroid Build Coastguard Worker     candidate_stats->address = candidate.address().ipaddr().ToString();
956*d9f75844SAndroid Build Coastguard Worker     candidate_stats->port = static_cast<int32_t>(candidate.address().port());
957*d9f75844SAndroid Build Coastguard Worker     candidate_stats->protocol = candidate.protocol();
958*d9f75844SAndroid Build Coastguard Worker     candidate_stats->candidate_type =
959*d9f75844SAndroid Build Coastguard Worker         CandidateTypeToRTCIceCandidateType(candidate.type());
960*d9f75844SAndroid Build Coastguard Worker     candidate_stats->priority = static_cast<int32_t>(candidate.priority());
961*d9f75844SAndroid Build Coastguard Worker     candidate_stats->foundation = candidate.foundation();
962*d9f75844SAndroid Build Coastguard Worker     auto related_address = candidate.related_address();
963*d9f75844SAndroid Build Coastguard Worker     if (related_address.port() != 0) {
964*d9f75844SAndroid Build Coastguard Worker       candidate_stats->related_address = related_address.ipaddr().ToString();
965*d9f75844SAndroid Build Coastguard Worker       candidate_stats->related_port =
966*d9f75844SAndroid Build Coastguard Worker           static_cast<int32_t>(related_address.port());
967*d9f75844SAndroid Build Coastguard Worker     }
968*d9f75844SAndroid Build Coastguard Worker     candidate_stats->username_fragment = candidate.username();
969*d9f75844SAndroid Build Coastguard Worker     if (candidate.protocol() == "tcp") {
970*d9f75844SAndroid Build Coastguard Worker       candidate_stats->tcp_type = candidate.tcptype();
971*d9f75844SAndroid Build Coastguard Worker     }
972*d9f75844SAndroid Build Coastguard Worker 
973*d9f75844SAndroid Build Coastguard Worker     stats = candidate_stats.get();
974*d9f75844SAndroid Build Coastguard Worker     report->AddStats(std::move(candidate_stats));
975*d9f75844SAndroid Build Coastguard Worker   }
976*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_EQ(stats->type(), is_local ? RTCLocalIceCandidateStats::kType
977*d9f75844SAndroid Build Coastguard Worker                                         : RTCRemoteIceCandidateStats::kType);
978*d9f75844SAndroid Build Coastguard Worker   return stats->id();
979*d9f75844SAndroid Build Coastguard Worker }
980*d9f75844SAndroid Build Coastguard Worker 
981*d9f75844SAndroid Build Coastguard Worker template <typename StatsType>
SetAudioProcessingStats(StatsType * stats,const AudioProcessingStats & apm_stats)982*d9f75844SAndroid Build Coastguard Worker void SetAudioProcessingStats(StatsType* stats,
983*d9f75844SAndroid Build Coastguard Worker                              const AudioProcessingStats& apm_stats) {
984*d9f75844SAndroid Build Coastguard Worker   if (apm_stats.echo_return_loss.has_value()) {
985*d9f75844SAndroid Build Coastguard Worker     stats->echo_return_loss = *apm_stats.echo_return_loss;
986*d9f75844SAndroid Build Coastguard Worker   }
987*d9f75844SAndroid Build Coastguard Worker   if (apm_stats.echo_return_loss_enhancement.has_value()) {
988*d9f75844SAndroid Build Coastguard Worker     stats->echo_return_loss_enhancement =
989*d9f75844SAndroid Build Coastguard Worker         *apm_stats.echo_return_loss_enhancement;
990*d9f75844SAndroid Build Coastguard Worker   }
991*d9f75844SAndroid Build Coastguard Worker }
992*d9f75844SAndroid Build Coastguard Worker 
993*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<DEPRECATED_RTCMediaStreamTrackStats>
ProduceMediaStreamTrackStatsFromVoiceSenderInfo(int64_t timestamp_us,AudioTrackInterface & audio_track,const cricket::VoiceSenderInfo & voice_sender_info,int attachment_id)994*d9f75844SAndroid Build Coastguard Worker ProduceMediaStreamTrackStatsFromVoiceSenderInfo(
995*d9f75844SAndroid Build Coastguard Worker     int64_t timestamp_us,
996*d9f75844SAndroid Build Coastguard Worker     AudioTrackInterface& audio_track,
997*d9f75844SAndroid Build Coastguard Worker     const cricket::VoiceSenderInfo& voice_sender_info,
998*d9f75844SAndroid Build Coastguard Worker     int attachment_id) {
999*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<DEPRECATED_RTCMediaStreamTrackStats> audio_track_stats(
1000*d9f75844SAndroid Build Coastguard Worker       std::make_unique<DEPRECATED_RTCMediaStreamTrackStats>(
1001*d9f75844SAndroid Build Coastguard Worker           DEPRECATED_RTCMediaStreamTrackStatsIDFromDirectionAndAttachment(
1002*d9f75844SAndroid Build Coastguard Worker               kDirectionOutbound, attachment_id),
1003*d9f75844SAndroid Build Coastguard Worker           timestamp_us, RTCMediaStreamTrackKind::kAudio));
1004*d9f75844SAndroid Build Coastguard Worker   SetMediaStreamTrackStatsFromMediaStreamTrackInterface(
1005*d9f75844SAndroid Build Coastguard Worker       audio_track, audio_track_stats.get());
1006*d9f75844SAndroid Build Coastguard Worker   audio_track_stats->media_source_id =
1007*d9f75844SAndroid Build Coastguard Worker       RTCMediaSourceStatsIDFromKindAndAttachment(cricket::MEDIA_TYPE_AUDIO,
1008*d9f75844SAndroid Build Coastguard Worker                                                  attachment_id);
1009*d9f75844SAndroid Build Coastguard Worker   audio_track_stats->remote_source = false;
1010*d9f75844SAndroid Build Coastguard Worker   audio_track_stats->detached = false;
1011*d9f75844SAndroid Build Coastguard Worker   // Audio processor may be attached to either the track or the send
1012*d9f75844SAndroid Build Coastguard Worker   // stream, so look in both places.
1013*d9f75844SAndroid Build Coastguard Worker   SetAudioProcessingStats(audio_track_stats.get(),
1014*d9f75844SAndroid Build Coastguard Worker                           voice_sender_info.apm_statistics);
1015*d9f75844SAndroid Build Coastguard Worker   auto audio_processor(audio_track.GetAudioProcessor());
1016*d9f75844SAndroid Build Coastguard Worker   if (audio_processor.get()) {
1017*d9f75844SAndroid Build Coastguard Worker     // The `has_remote_tracks` argument is obsolete; makes no difference if it's
1018*d9f75844SAndroid Build Coastguard Worker     // set to true or false.
1019*d9f75844SAndroid Build Coastguard Worker     AudioProcessorInterface::AudioProcessorStatistics ap_stats =
1020*d9f75844SAndroid Build Coastguard Worker         audio_processor->GetStats(/*has_remote_tracks=*/false);
1021*d9f75844SAndroid Build Coastguard Worker     SetAudioProcessingStats(audio_track_stats.get(), ap_stats.apm_statistics);
1022*d9f75844SAndroid Build Coastguard Worker   }
1023*d9f75844SAndroid Build Coastguard Worker   return audio_track_stats;
1024*d9f75844SAndroid Build Coastguard Worker }
1025*d9f75844SAndroid Build Coastguard Worker 
1026*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<DEPRECATED_RTCMediaStreamTrackStats>
ProduceMediaStreamTrackStatsFromVoiceReceiverInfo(int64_t timestamp_us,const AudioTrackInterface & audio_track,const cricket::VoiceReceiverInfo & voice_receiver_info,int attachment_id)1027*d9f75844SAndroid Build Coastguard Worker ProduceMediaStreamTrackStatsFromVoiceReceiverInfo(
1028*d9f75844SAndroid Build Coastguard Worker     int64_t timestamp_us,
1029*d9f75844SAndroid Build Coastguard Worker     const AudioTrackInterface& audio_track,
1030*d9f75844SAndroid Build Coastguard Worker     const cricket::VoiceReceiverInfo& voice_receiver_info,
1031*d9f75844SAndroid Build Coastguard Worker     int attachment_id) {
1032*d9f75844SAndroid Build Coastguard Worker   // Since receiver tracks can't be reattached, we use the SSRC as
1033*d9f75844SAndroid Build Coastguard Worker   // an attachment identifier.
1034*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<DEPRECATED_RTCMediaStreamTrackStats> audio_track_stats(
1035*d9f75844SAndroid Build Coastguard Worker       std::make_unique<DEPRECATED_RTCMediaStreamTrackStats>(
1036*d9f75844SAndroid Build Coastguard Worker           DEPRECATED_RTCMediaStreamTrackStatsIDFromDirectionAndAttachment(
1037*d9f75844SAndroid Build Coastguard Worker               kDirectionInbound, attachment_id),
1038*d9f75844SAndroid Build Coastguard Worker           timestamp_us, RTCMediaStreamTrackKind::kAudio));
1039*d9f75844SAndroid Build Coastguard Worker   SetMediaStreamTrackStatsFromMediaStreamTrackInterface(
1040*d9f75844SAndroid Build Coastguard Worker       audio_track, audio_track_stats.get());
1041*d9f75844SAndroid Build Coastguard Worker   audio_track_stats->remote_source = true;
1042*d9f75844SAndroid Build Coastguard Worker   audio_track_stats->detached = false;
1043*d9f75844SAndroid Build Coastguard Worker   if (voice_receiver_info.audio_level >= 0) {
1044*d9f75844SAndroid Build Coastguard Worker     audio_track_stats->audio_level =
1045*d9f75844SAndroid Build Coastguard Worker         DoubleAudioLevelFromIntAudioLevel(voice_receiver_info.audio_level);
1046*d9f75844SAndroid Build Coastguard Worker   }
1047*d9f75844SAndroid Build Coastguard Worker   audio_track_stats->jitter_buffer_delay =
1048*d9f75844SAndroid Build Coastguard Worker       voice_receiver_info.jitter_buffer_delay_seconds;
1049*d9f75844SAndroid Build Coastguard Worker   audio_track_stats->jitter_buffer_emitted_count =
1050*d9f75844SAndroid Build Coastguard Worker       voice_receiver_info.jitter_buffer_emitted_count;
1051*d9f75844SAndroid Build Coastguard Worker   audio_track_stats->inserted_samples_for_deceleration =
1052*d9f75844SAndroid Build Coastguard Worker       voice_receiver_info.inserted_samples_for_deceleration;
1053*d9f75844SAndroid Build Coastguard Worker   audio_track_stats->removed_samples_for_acceleration =
1054*d9f75844SAndroid Build Coastguard Worker       voice_receiver_info.removed_samples_for_acceleration;
1055*d9f75844SAndroid Build Coastguard Worker   audio_track_stats->total_audio_energy =
1056*d9f75844SAndroid Build Coastguard Worker       voice_receiver_info.total_output_energy;
1057*d9f75844SAndroid Build Coastguard Worker   audio_track_stats->total_samples_received =
1058*d9f75844SAndroid Build Coastguard Worker       voice_receiver_info.total_samples_received;
1059*d9f75844SAndroid Build Coastguard Worker   audio_track_stats->total_samples_duration =
1060*d9f75844SAndroid Build Coastguard Worker       voice_receiver_info.total_output_duration;
1061*d9f75844SAndroid Build Coastguard Worker   audio_track_stats->concealed_samples = voice_receiver_info.concealed_samples;
1062*d9f75844SAndroid Build Coastguard Worker   audio_track_stats->silent_concealed_samples =
1063*d9f75844SAndroid Build Coastguard Worker       voice_receiver_info.silent_concealed_samples;
1064*d9f75844SAndroid Build Coastguard Worker   audio_track_stats->concealment_events =
1065*d9f75844SAndroid Build Coastguard Worker       voice_receiver_info.concealment_events;
1066*d9f75844SAndroid Build Coastguard Worker 
1067*d9f75844SAndroid Build Coastguard Worker   return audio_track_stats;
1068*d9f75844SAndroid Build Coastguard Worker }
1069*d9f75844SAndroid Build Coastguard Worker 
1070*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<DEPRECATED_RTCMediaStreamTrackStats>
ProduceMediaStreamTrackStatsFromVideoSenderInfo(int64_t timestamp_us,const VideoTrackInterface & video_track,const cricket::VideoSenderInfo & video_sender_info,int attachment_id)1071*d9f75844SAndroid Build Coastguard Worker ProduceMediaStreamTrackStatsFromVideoSenderInfo(
1072*d9f75844SAndroid Build Coastguard Worker     int64_t timestamp_us,
1073*d9f75844SAndroid Build Coastguard Worker     const VideoTrackInterface& video_track,
1074*d9f75844SAndroid Build Coastguard Worker     const cricket::VideoSenderInfo& video_sender_info,
1075*d9f75844SAndroid Build Coastguard Worker     int attachment_id) {
1076*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<DEPRECATED_RTCMediaStreamTrackStats> video_track_stats(
1077*d9f75844SAndroid Build Coastguard Worker       std::make_unique<DEPRECATED_RTCMediaStreamTrackStats>(
1078*d9f75844SAndroid Build Coastguard Worker           DEPRECATED_RTCMediaStreamTrackStatsIDFromDirectionAndAttachment(
1079*d9f75844SAndroid Build Coastguard Worker               kDirectionOutbound, attachment_id),
1080*d9f75844SAndroid Build Coastguard Worker           timestamp_us, RTCMediaStreamTrackKind::kVideo));
1081*d9f75844SAndroid Build Coastguard Worker   SetMediaStreamTrackStatsFromMediaStreamTrackInterface(
1082*d9f75844SAndroid Build Coastguard Worker       video_track, video_track_stats.get());
1083*d9f75844SAndroid Build Coastguard Worker   video_track_stats->media_source_id =
1084*d9f75844SAndroid Build Coastguard Worker       RTCMediaSourceStatsIDFromKindAndAttachment(cricket::MEDIA_TYPE_VIDEO,
1085*d9f75844SAndroid Build Coastguard Worker                                                  attachment_id);
1086*d9f75844SAndroid Build Coastguard Worker   video_track_stats->remote_source = false;
1087*d9f75844SAndroid Build Coastguard Worker   video_track_stats->detached = false;
1088*d9f75844SAndroid Build Coastguard Worker   video_track_stats->frame_width =
1089*d9f75844SAndroid Build Coastguard Worker       static_cast<uint32_t>(video_sender_info.send_frame_width);
1090*d9f75844SAndroid Build Coastguard Worker   video_track_stats->frame_height =
1091*d9f75844SAndroid Build Coastguard Worker       static_cast<uint32_t>(video_sender_info.send_frame_height);
1092*d9f75844SAndroid Build Coastguard Worker   // TODO(hbos): Will reduce this by frames dropped due to congestion control
1093*d9f75844SAndroid Build Coastguard Worker   // when available. https://crbug.com/659137
1094*d9f75844SAndroid Build Coastguard Worker   video_track_stats->frames_sent = video_sender_info.frames_encoded;
1095*d9f75844SAndroid Build Coastguard Worker   video_track_stats->huge_frames_sent = video_sender_info.huge_frames_sent;
1096*d9f75844SAndroid Build Coastguard Worker   return video_track_stats;
1097*d9f75844SAndroid Build Coastguard Worker }
1098*d9f75844SAndroid Build Coastguard Worker 
1099*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<DEPRECATED_RTCMediaStreamTrackStats>
ProduceMediaStreamTrackStatsFromVideoReceiverInfo(int64_t timestamp_us,const VideoTrackInterface & video_track,const cricket::VideoReceiverInfo & video_receiver_info,int attachment_id)1100*d9f75844SAndroid Build Coastguard Worker ProduceMediaStreamTrackStatsFromVideoReceiverInfo(
1101*d9f75844SAndroid Build Coastguard Worker     int64_t timestamp_us,
1102*d9f75844SAndroid Build Coastguard Worker     const VideoTrackInterface& video_track,
1103*d9f75844SAndroid Build Coastguard Worker     const cricket::VideoReceiverInfo& video_receiver_info,
1104*d9f75844SAndroid Build Coastguard Worker     int attachment_id) {
1105*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<DEPRECATED_RTCMediaStreamTrackStats> video_track_stats(
1106*d9f75844SAndroid Build Coastguard Worker       std::make_unique<DEPRECATED_RTCMediaStreamTrackStats>(
1107*d9f75844SAndroid Build Coastguard Worker           DEPRECATED_RTCMediaStreamTrackStatsIDFromDirectionAndAttachment(
1108*d9f75844SAndroid Build Coastguard Worker               kDirectionInbound, attachment_id),
1109*d9f75844SAndroid Build Coastguard Worker           timestamp_us, RTCMediaStreamTrackKind::kVideo));
1110*d9f75844SAndroid Build Coastguard Worker   SetMediaStreamTrackStatsFromMediaStreamTrackInterface(
1111*d9f75844SAndroid Build Coastguard Worker       video_track, video_track_stats.get());
1112*d9f75844SAndroid Build Coastguard Worker   video_track_stats->remote_source = true;
1113*d9f75844SAndroid Build Coastguard Worker   video_track_stats->detached = false;
1114*d9f75844SAndroid Build Coastguard Worker   if (video_receiver_info.frame_width > 0 &&
1115*d9f75844SAndroid Build Coastguard Worker       video_receiver_info.frame_height > 0) {
1116*d9f75844SAndroid Build Coastguard Worker     video_track_stats->frame_width =
1117*d9f75844SAndroid Build Coastguard Worker         static_cast<uint32_t>(video_receiver_info.frame_width);
1118*d9f75844SAndroid Build Coastguard Worker     video_track_stats->frame_height =
1119*d9f75844SAndroid Build Coastguard Worker         static_cast<uint32_t>(video_receiver_info.frame_height);
1120*d9f75844SAndroid Build Coastguard Worker   }
1121*d9f75844SAndroid Build Coastguard Worker   video_track_stats->jitter_buffer_delay =
1122*d9f75844SAndroid Build Coastguard Worker       video_receiver_info.jitter_buffer_delay_seconds;
1123*d9f75844SAndroid Build Coastguard Worker   video_track_stats->jitter_buffer_emitted_count =
1124*d9f75844SAndroid Build Coastguard Worker       video_receiver_info.jitter_buffer_emitted_count;
1125*d9f75844SAndroid Build Coastguard Worker   video_track_stats->frames_received = video_receiver_info.frames_received;
1126*d9f75844SAndroid Build Coastguard Worker   // TODO(hbos): When we support receiving simulcast, this should be the total
1127*d9f75844SAndroid Build Coastguard Worker   // number of frames correctly decoded, independent of which SSRC it was
1128*d9f75844SAndroid Build Coastguard Worker   // received from. Since we don't support that, this is correct and is the same
1129*d9f75844SAndroid Build Coastguard Worker   // value as "RTCInboundRTPStreamStats.framesDecoded". https://crbug.com/659137
1130*d9f75844SAndroid Build Coastguard Worker   video_track_stats->frames_decoded = video_receiver_info.frames_decoded;
1131*d9f75844SAndroid Build Coastguard Worker   video_track_stats->frames_dropped = video_receiver_info.frames_dropped;
1132*d9f75844SAndroid Build Coastguard Worker 
1133*d9f75844SAndroid Build Coastguard Worker   return video_track_stats;
1134*d9f75844SAndroid Build Coastguard Worker }
1135*d9f75844SAndroid Build Coastguard Worker 
ProduceSenderMediaTrackStats(int64_t timestamp_us,const TrackMediaInfoMap & track_media_info_map,std::vector<rtc::scoped_refptr<RtpSenderInternal>> senders,RTCStatsReport * report)1136*d9f75844SAndroid Build Coastguard Worker void ProduceSenderMediaTrackStats(
1137*d9f75844SAndroid Build Coastguard Worker     int64_t timestamp_us,
1138*d9f75844SAndroid Build Coastguard Worker     const TrackMediaInfoMap& track_media_info_map,
1139*d9f75844SAndroid Build Coastguard Worker     std::vector<rtc::scoped_refptr<RtpSenderInternal>> senders,
1140*d9f75844SAndroid Build Coastguard Worker     RTCStatsReport* report) {
1141*d9f75844SAndroid Build Coastguard Worker   // This function iterates over the senders to generate outgoing track stats.
1142*d9f75844SAndroid Build Coastguard Worker 
1143*d9f75844SAndroid Build Coastguard Worker   // TODO(https://crbug.com/webrtc/14175): Stop collecting "track" stats,
1144*d9f75844SAndroid Build Coastguard Worker   // they're deprecated.
1145*d9f75844SAndroid Build Coastguard Worker   for (const auto& sender : senders) {
1146*d9f75844SAndroid Build Coastguard Worker     if (sender->media_type() == cricket::MEDIA_TYPE_AUDIO) {
1147*d9f75844SAndroid Build Coastguard Worker       AudioTrackInterface* track =
1148*d9f75844SAndroid Build Coastguard Worker           static_cast<AudioTrackInterface*>(sender->track().get());
1149*d9f75844SAndroid Build Coastguard Worker       if (!track)
1150*d9f75844SAndroid Build Coastguard Worker         continue;
1151*d9f75844SAndroid Build Coastguard Worker       cricket::VoiceSenderInfo null_sender_info;
1152*d9f75844SAndroid Build Coastguard Worker       const cricket::VoiceSenderInfo* voice_sender_info = &null_sender_info;
1153*d9f75844SAndroid Build Coastguard Worker       // TODO(hta): Checking on ssrc is not proper. There should be a way
1154*d9f75844SAndroid Build Coastguard Worker       // to see from a sender whether it's connected or not.
1155*d9f75844SAndroid Build Coastguard Worker       // Related to https://crbug.com/8694 (using ssrc 0 to indicate "none")
1156*d9f75844SAndroid Build Coastguard Worker       if (sender->ssrc() != 0) {
1157*d9f75844SAndroid Build Coastguard Worker         // When pc.close is called, sender info is discarded, so
1158*d9f75844SAndroid Build Coastguard Worker         // we generate zeroes instead. Bug: It should be retained.
1159*d9f75844SAndroid Build Coastguard Worker         // https://crbug.com/807174
1160*d9f75844SAndroid Build Coastguard Worker         const cricket::VoiceSenderInfo* sender_info =
1161*d9f75844SAndroid Build Coastguard Worker             track_media_info_map.GetVoiceSenderInfoBySsrc(sender->ssrc());
1162*d9f75844SAndroid Build Coastguard Worker         if (sender_info) {
1163*d9f75844SAndroid Build Coastguard Worker           voice_sender_info = sender_info;
1164*d9f75844SAndroid Build Coastguard Worker         } else {
1165*d9f75844SAndroid Build Coastguard Worker           RTC_DLOG(LS_INFO)
1166*d9f75844SAndroid Build Coastguard Worker               << "RTCStatsCollector: No voice sender info for sender with ssrc "
1167*d9f75844SAndroid Build Coastguard Worker               << sender->ssrc();
1168*d9f75844SAndroid Build Coastguard Worker         }
1169*d9f75844SAndroid Build Coastguard Worker       }
1170*d9f75844SAndroid Build Coastguard Worker       std::unique_ptr<DEPRECATED_RTCMediaStreamTrackStats> audio_track_stats =
1171*d9f75844SAndroid Build Coastguard Worker           ProduceMediaStreamTrackStatsFromVoiceSenderInfo(
1172*d9f75844SAndroid Build Coastguard Worker               timestamp_us, *track, *voice_sender_info, sender->AttachmentId());
1173*d9f75844SAndroid Build Coastguard Worker       report->AddStats(std::move(audio_track_stats));
1174*d9f75844SAndroid Build Coastguard Worker     } else if (sender->media_type() == cricket::MEDIA_TYPE_VIDEO) {
1175*d9f75844SAndroid Build Coastguard Worker       VideoTrackInterface* track =
1176*d9f75844SAndroid Build Coastguard Worker           static_cast<VideoTrackInterface*>(sender->track().get());
1177*d9f75844SAndroid Build Coastguard Worker       if (!track)
1178*d9f75844SAndroid Build Coastguard Worker         continue;
1179*d9f75844SAndroid Build Coastguard Worker       cricket::VideoSenderInfo null_sender_info;
1180*d9f75844SAndroid Build Coastguard Worker       const cricket::VideoSenderInfo* video_sender_info = &null_sender_info;
1181*d9f75844SAndroid Build Coastguard Worker       // TODO(hta): Check on state not ssrc when state is available
1182*d9f75844SAndroid Build Coastguard Worker       // Related to https://bugs.webrtc.org/8694 (using ssrc 0 to indicate
1183*d9f75844SAndroid Build Coastguard Worker       // "none")
1184*d9f75844SAndroid Build Coastguard Worker       if (sender->ssrc() != 0) {
1185*d9f75844SAndroid Build Coastguard Worker         // When pc.close is called, sender info is discarded, so
1186*d9f75844SAndroid Build Coastguard Worker         // we generate zeroes instead. Bug: It should be retained.
1187*d9f75844SAndroid Build Coastguard Worker         // https://crbug.com/807174
1188*d9f75844SAndroid Build Coastguard Worker         const cricket::VideoSenderInfo* sender_info =
1189*d9f75844SAndroid Build Coastguard Worker             track_media_info_map.GetVideoSenderInfoBySsrc(sender->ssrc());
1190*d9f75844SAndroid Build Coastguard Worker         if (sender_info) {
1191*d9f75844SAndroid Build Coastguard Worker           video_sender_info = sender_info;
1192*d9f75844SAndroid Build Coastguard Worker         } else {
1193*d9f75844SAndroid Build Coastguard Worker           RTC_DLOG(LS_INFO)
1194*d9f75844SAndroid Build Coastguard Worker               << "No video sender info for sender with ssrc " << sender->ssrc();
1195*d9f75844SAndroid Build Coastguard Worker         }
1196*d9f75844SAndroid Build Coastguard Worker       }
1197*d9f75844SAndroid Build Coastguard Worker       std::unique_ptr<DEPRECATED_RTCMediaStreamTrackStats> video_track_stats =
1198*d9f75844SAndroid Build Coastguard Worker           ProduceMediaStreamTrackStatsFromVideoSenderInfo(
1199*d9f75844SAndroid Build Coastguard Worker               timestamp_us, *track, *video_sender_info, sender->AttachmentId());
1200*d9f75844SAndroid Build Coastguard Worker       report->AddStats(std::move(video_track_stats));
1201*d9f75844SAndroid Build Coastguard Worker     } else {
1202*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK_NOTREACHED();
1203*d9f75844SAndroid Build Coastguard Worker     }
1204*d9f75844SAndroid Build Coastguard Worker   }
1205*d9f75844SAndroid Build Coastguard Worker }
1206*d9f75844SAndroid Build Coastguard Worker 
ProduceReceiverMediaTrackStats(int64_t timestamp_us,const TrackMediaInfoMap & track_media_info_map,std::vector<rtc::scoped_refptr<RtpReceiverInternal>> receivers,RTCStatsReport * report)1207*d9f75844SAndroid Build Coastguard Worker void ProduceReceiverMediaTrackStats(
1208*d9f75844SAndroid Build Coastguard Worker     int64_t timestamp_us,
1209*d9f75844SAndroid Build Coastguard Worker     const TrackMediaInfoMap& track_media_info_map,
1210*d9f75844SAndroid Build Coastguard Worker     std::vector<rtc::scoped_refptr<RtpReceiverInternal>> receivers,
1211*d9f75844SAndroid Build Coastguard Worker     RTCStatsReport* report) {
1212*d9f75844SAndroid Build Coastguard Worker   // This function iterates over the receivers to find the remote tracks.
1213*d9f75844SAndroid Build Coastguard Worker   for (const auto& receiver : receivers) {
1214*d9f75844SAndroid Build Coastguard Worker     if (receiver->media_type() == cricket::MEDIA_TYPE_AUDIO) {
1215*d9f75844SAndroid Build Coastguard Worker       AudioTrackInterface* track =
1216*d9f75844SAndroid Build Coastguard Worker           static_cast<AudioTrackInterface*>(receiver->track().get());
1217*d9f75844SAndroid Build Coastguard Worker       const cricket::VoiceReceiverInfo* voice_receiver_info =
1218*d9f75844SAndroid Build Coastguard Worker           track_media_info_map.GetVoiceReceiverInfo(*track);
1219*d9f75844SAndroid Build Coastguard Worker       if (!voice_receiver_info) {
1220*d9f75844SAndroid Build Coastguard Worker         continue;
1221*d9f75844SAndroid Build Coastguard Worker       }
1222*d9f75844SAndroid Build Coastguard Worker       std::unique_ptr<DEPRECATED_RTCMediaStreamTrackStats> audio_track_stats =
1223*d9f75844SAndroid Build Coastguard Worker           ProduceMediaStreamTrackStatsFromVoiceReceiverInfo(
1224*d9f75844SAndroid Build Coastguard Worker               timestamp_us, *track, *voice_receiver_info,
1225*d9f75844SAndroid Build Coastguard Worker               receiver->AttachmentId());
1226*d9f75844SAndroid Build Coastguard Worker       report->AddStats(std::move(audio_track_stats));
1227*d9f75844SAndroid Build Coastguard Worker     } else if (receiver->media_type() == cricket::MEDIA_TYPE_VIDEO) {
1228*d9f75844SAndroid Build Coastguard Worker       VideoTrackInterface* track =
1229*d9f75844SAndroid Build Coastguard Worker           static_cast<VideoTrackInterface*>(receiver->track().get());
1230*d9f75844SAndroid Build Coastguard Worker       const cricket::VideoReceiverInfo* video_receiver_info =
1231*d9f75844SAndroid Build Coastguard Worker           track_media_info_map.GetVideoReceiverInfo(*track);
1232*d9f75844SAndroid Build Coastguard Worker       if (!video_receiver_info) {
1233*d9f75844SAndroid Build Coastguard Worker         continue;
1234*d9f75844SAndroid Build Coastguard Worker       }
1235*d9f75844SAndroid Build Coastguard Worker       std::unique_ptr<DEPRECATED_RTCMediaStreamTrackStats> video_track_stats =
1236*d9f75844SAndroid Build Coastguard Worker           ProduceMediaStreamTrackStatsFromVideoReceiverInfo(
1237*d9f75844SAndroid Build Coastguard Worker               timestamp_us, *track, *video_receiver_info,
1238*d9f75844SAndroid Build Coastguard Worker               receiver->AttachmentId());
1239*d9f75844SAndroid Build Coastguard Worker       report->AddStats(std::move(video_track_stats));
1240*d9f75844SAndroid Build Coastguard Worker     } else {
1241*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK_NOTREACHED();
1242*d9f75844SAndroid Build Coastguard Worker     }
1243*d9f75844SAndroid Build Coastguard Worker   }
1244*d9f75844SAndroid Build Coastguard Worker }
1245*d9f75844SAndroid Build Coastguard Worker 
CreateReportFilteredBySelector(bool filter_by_sender_selector,rtc::scoped_refptr<const RTCStatsReport> report,rtc::scoped_refptr<RtpSenderInternal> sender_selector,rtc::scoped_refptr<RtpReceiverInternal> receiver_selector)1246*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<RTCStatsReport> CreateReportFilteredBySelector(
1247*d9f75844SAndroid Build Coastguard Worker     bool filter_by_sender_selector,
1248*d9f75844SAndroid Build Coastguard Worker     rtc::scoped_refptr<const RTCStatsReport> report,
1249*d9f75844SAndroid Build Coastguard Worker     rtc::scoped_refptr<RtpSenderInternal> sender_selector,
1250*d9f75844SAndroid Build Coastguard Worker     rtc::scoped_refptr<RtpReceiverInternal> receiver_selector) {
1251*d9f75844SAndroid Build Coastguard Worker   std::vector<std::string> rtpstream_ids;
1252*d9f75844SAndroid Build Coastguard Worker   if (filter_by_sender_selector) {
1253*d9f75844SAndroid Build Coastguard Worker     // Filter mode: RTCStatsCollector::RequestInfo::kSenderSelector
1254*d9f75844SAndroid Build Coastguard Worker     if (sender_selector) {
1255*d9f75844SAndroid Build Coastguard Worker       // Find outbound-rtp(s) of the sender, i.e. the outbound-rtp(s) that
1256*d9f75844SAndroid Build Coastguard Worker       // reference the sender stats.
1257*d9f75844SAndroid Build Coastguard Worker       // Because we do not implement sender stats, we look at outbound-rtp(s)
1258*d9f75844SAndroid Build Coastguard Worker       // that reference the track attachment stats for the sender instead.
1259*d9f75844SAndroid Build Coastguard Worker       std::string track_id =
1260*d9f75844SAndroid Build Coastguard Worker           DEPRECATED_RTCMediaStreamTrackStatsIDFromDirectionAndAttachment(
1261*d9f75844SAndroid Build Coastguard Worker               kDirectionOutbound, sender_selector->AttachmentId());
1262*d9f75844SAndroid Build Coastguard Worker       for (const auto& stats : *report) {
1263*d9f75844SAndroid Build Coastguard Worker         if (stats.type() != RTCOutboundRTPStreamStats::kType)
1264*d9f75844SAndroid Build Coastguard Worker           continue;
1265*d9f75844SAndroid Build Coastguard Worker         const auto& outbound_rtp = stats.cast_to<RTCOutboundRTPStreamStats>();
1266*d9f75844SAndroid Build Coastguard Worker         if (outbound_rtp.track_id.is_defined() &&
1267*d9f75844SAndroid Build Coastguard Worker             *outbound_rtp.track_id == track_id) {
1268*d9f75844SAndroid Build Coastguard Worker           rtpstream_ids.push_back(outbound_rtp.id());
1269*d9f75844SAndroid Build Coastguard Worker         }
1270*d9f75844SAndroid Build Coastguard Worker       }
1271*d9f75844SAndroid Build Coastguard Worker     }
1272*d9f75844SAndroid Build Coastguard Worker   } else {
1273*d9f75844SAndroid Build Coastguard Worker     // Filter mode: RTCStatsCollector::RequestInfo::kReceiverSelector
1274*d9f75844SAndroid Build Coastguard Worker     if (receiver_selector) {
1275*d9f75844SAndroid Build Coastguard Worker       // Find inbound-rtp(s) of the receiver, i.e. the inbound-rtp(s) that
1276*d9f75844SAndroid Build Coastguard Worker       // reference the receiver stats.
1277*d9f75844SAndroid Build Coastguard Worker       // Because we do not implement receiver stats, we look at inbound-rtp(s)
1278*d9f75844SAndroid Build Coastguard Worker       // that reference the track attachment stats for the receiver instead.
1279*d9f75844SAndroid Build Coastguard Worker       std::string track_id =
1280*d9f75844SAndroid Build Coastguard Worker           DEPRECATED_RTCMediaStreamTrackStatsIDFromDirectionAndAttachment(
1281*d9f75844SAndroid Build Coastguard Worker               kDirectionInbound, receiver_selector->AttachmentId());
1282*d9f75844SAndroid Build Coastguard Worker       for (const auto& stats : *report) {
1283*d9f75844SAndroid Build Coastguard Worker         if (stats.type() != RTCInboundRTPStreamStats::kType)
1284*d9f75844SAndroid Build Coastguard Worker           continue;
1285*d9f75844SAndroid Build Coastguard Worker         const auto& inbound_rtp = stats.cast_to<RTCInboundRTPStreamStats>();
1286*d9f75844SAndroid Build Coastguard Worker         if (inbound_rtp.track_id.is_defined() &&
1287*d9f75844SAndroid Build Coastguard Worker             *inbound_rtp.track_id == track_id) {
1288*d9f75844SAndroid Build Coastguard Worker           rtpstream_ids.push_back(inbound_rtp.id());
1289*d9f75844SAndroid Build Coastguard Worker         }
1290*d9f75844SAndroid Build Coastguard Worker       }
1291*d9f75844SAndroid Build Coastguard Worker     }
1292*d9f75844SAndroid Build Coastguard Worker   }
1293*d9f75844SAndroid Build Coastguard Worker   if (rtpstream_ids.empty())
1294*d9f75844SAndroid Build Coastguard Worker     return RTCStatsReport::Create(report->timestamp());
1295*d9f75844SAndroid Build Coastguard Worker   return TakeReferencedStats(report->Copy(), rtpstream_ids);
1296*d9f75844SAndroid Build Coastguard Worker }
1297*d9f75844SAndroid Build Coastguard Worker 
1298*d9f75844SAndroid Build Coastguard Worker }  // namespace
1299*d9f75844SAndroid Build Coastguard Worker 
1300*d9f75844SAndroid Build Coastguard Worker RTCStatsCollector::CertificateStatsPair
Copy() const1301*d9f75844SAndroid Build Coastguard Worker RTCStatsCollector::CertificateStatsPair::Copy() const {
1302*d9f75844SAndroid Build Coastguard Worker   CertificateStatsPair copy;
1303*d9f75844SAndroid Build Coastguard Worker   copy.local = local ? local->Copy() : nullptr;
1304*d9f75844SAndroid Build Coastguard Worker   copy.remote = remote ? remote->Copy() : nullptr;
1305*d9f75844SAndroid Build Coastguard Worker   return copy;
1306*d9f75844SAndroid Build Coastguard Worker }
1307*d9f75844SAndroid Build Coastguard Worker 
RequestInfo(rtc::scoped_refptr<RTCStatsCollectorCallback> callback)1308*d9f75844SAndroid Build Coastguard Worker RTCStatsCollector::RequestInfo::RequestInfo(
1309*d9f75844SAndroid Build Coastguard Worker     rtc::scoped_refptr<RTCStatsCollectorCallback> callback)
1310*d9f75844SAndroid Build Coastguard Worker     : RequestInfo(FilterMode::kAll, std::move(callback), nullptr, nullptr) {}
1311*d9f75844SAndroid Build Coastguard Worker 
RequestInfo(rtc::scoped_refptr<RtpSenderInternal> selector,rtc::scoped_refptr<RTCStatsCollectorCallback> callback)1312*d9f75844SAndroid Build Coastguard Worker RTCStatsCollector::RequestInfo::RequestInfo(
1313*d9f75844SAndroid Build Coastguard Worker     rtc::scoped_refptr<RtpSenderInternal> selector,
1314*d9f75844SAndroid Build Coastguard Worker     rtc::scoped_refptr<RTCStatsCollectorCallback> callback)
1315*d9f75844SAndroid Build Coastguard Worker     : RequestInfo(FilterMode::kSenderSelector,
1316*d9f75844SAndroid Build Coastguard Worker                   std::move(callback),
1317*d9f75844SAndroid Build Coastguard Worker                   std::move(selector),
1318*d9f75844SAndroid Build Coastguard Worker                   nullptr) {}
1319*d9f75844SAndroid Build Coastguard Worker 
RequestInfo(rtc::scoped_refptr<RtpReceiverInternal> selector,rtc::scoped_refptr<RTCStatsCollectorCallback> callback)1320*d9f75844SAndroid Build Coastguard Worker RTCStatsCollector::RequestInfo::RequestInfo(
1321*d9f75844SAndroid Build Coastguard Worker     rtc::scoped_refptr<RtpReceiverInternal> selector,
1322*d9f75844SAndroid Build Coastguard Worker     rtc::scoped_refptr<RTCStatsCollectorCallback> callback)
1323*d9f75844SAndroid Build Coastguard Worker     : RequestInfo(FilterMode::kReceiverSelector,
1324*d9f75844SAndroid Build Coastguard Worker                   std::move(callback),
1325*d9f75844SAndroid Build Coastguard Worker                   nullptr,
1326*d9f75844SAndroid Build Coastguard Worker                   std::move(selector)) {}
1327*d9f75844SAndroid Build Coastguard Worker 
RequestInfo(RTCStatsCollector::RequestInfo::FilterMode filter_mode,rtc::scoped_refptr<RTCStatsCollectorCallback> callback,rtc::scoped_refptr<RtpSenderInternal> sender_selector,rtc::scoped_refptr<RtpReceiverInternal> receiver_selector)1328*d9f75844SAndroid Build Coastguard Worker RTCStatsCollector::RequestInfo::RequestInfo(
1329*d9f75844SAndroid Build Coastguard Worker     RTCStatsCollector::RequestInfo::FilterMode filter_mode,
1330*d9f75844SAndroid Build Coastguard Worker     rtc::scoped_refptr<RTCStatsCollectorCallback> callback,
1331*d9f75844SAndroid Build Coastguard Worker     rtc::scoped_refptr<RtpSenderInternal> sender_selector,
1332*d9f75844SAndroid Build Coastguard Worker     rtc::scoped_refptr<RtpReceiverInternal> receiver_selector)
1333*d9f75844SAndroid Build Coastguard Worker     : filter_mode_(filter_mode),
1334*d9f75844SAndroid Build Coastguard Worker       callback_(std::move(callback)),
1335*d9f75844SAndroid Build Coastguard Worker       sender_selector_(std::move(sender_selector)),
1336*d9f75844SAndroid Build Coastguard Worker       receiver_selector_(std::move(receiver_selector)) {
1337*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(callback_);
1338*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(!sender_selector_ || !receiver_selector_);
1339*d9f75844SAndroid Build Coastguard Worker }
1340*d9f75844SAndroid Build Coastguard Worker 
Create(PeerConnectionInternal * pc,int64_t cache_lifetime_us)1341*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<RTCStatsCollector> RTCStatsCollector::Create(
1342*d9f75844SAndroid Build Coastguard Worker     PeerConnectionInternal* pc,
1343*d9f75844SAndroid Build Coastguard Worker     int64_t cache_lifetime_us) {
1344*d9f75844SAndroid Build Coastguard Worker   return rtc::make_ref_counted<RTCStatsCollector>(pc, cache_lifetime_us);
1345*d9f75844SAndroid Build Coastguard Worker }
1346*d9f75844SAndroid Build Coastguard Worker 
RTCStatsCollector(PeerConnectionInternal * pc,int64_t cache_lifetime_us)1347*d9f75844SAndroid Build Coastguard Worker RTCStatsCollector::RTCStatsCollector(PeerConnectionInternal* pc,
1348*d9f75844SAndroid Build Coastguard Worker                                      int64_t cache_lifetime_us)
1349*d9f75844SAndroid Build Coastguard Worker     : pc_(pc),
1350*d9f75844SAndroid Build Coastguard Worker       signaling_thread_(pc->signaling_thread()),
1351*d9f75844SAndroid Build Coastguard Worker       worker_thread_(pc->worker_thread()),
1352*d9f75844SAndroid Build Coastguard Worker       network_thread_(pc->network_thread()),
1353*d9f75844SAndroid Build Coastguard Worker       num_pending_partial_reports_(0),
1354*d9f75844SAndroid Build Coastguard Worker       partial_report_timestamp_us_(0),
1355*d9f75844SAndroid Build Coastguard Worker       network_report_event_(true /* manual_reset */,
1356*d9f75844SAndroid Build Coastguard Worker                             true /* initially_signaled */),
1357*d9f75844SAndroid Build Coastguard Worker       cache_timestamp_us_(0),
1358*d9f75844SAndroid Build Coastguard Worker       cache_lifetime_us_(cache_lifetime_us) {
1359*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(pc_);
1360*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(signaling_thread_);
1361*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(worker_thread_);
1362*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(network_thread_);
1363*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_GE(cache_lifetime_us_, 0);
1364*d9f75844SAndroid Build Coastguard Worker   pc_->SignalSctpDataChannelCreated().connect(
1365*d9f75844SAndroid Build Coastguard Worker       this, &RTCStatsCollector::OnSctpDataChannelCreated);
1366*d9f75844SAndroid Build Coastguard Worker }
1367*d9f75844SAndroid Build Coastguard Worker 
~RTCStatsCollector()1368*d9f75844SAndroid Build Coastguard Worker RTCStatsCollector::~RTCStatsCollector() {
1369*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_EQ(num_pending_partial_reports_, 0);
1370*d9f75844SAndroid Build Coastguard Worker }
1371*d9f75844SAndroid Build Coastguard Worker 
GetStatsReport(rtc::scoped_refptr<RTCStatsCollectorCallback> callback)1372*d9f75844SAndroid Build Coastguard Worker void RTCStatsCollector::GetStatsReport(
1373*d9f75844SAndroid Build Coastguard Worker     rtc::scoped_refptr<RTCStatsCollectorCallback> callback) {
1374*d9f75844SAndroid Build Coastguard Worker   GetStatsReportInternal(RequestInfo(std::move(callback)));
1375*d9f75844SAndroid Build Coastguard Worker }
1376*d9f75844SAndroid Build Coastguard Worker 
GetStatsReport(rtc::scoped_refptr<RtpSenderInternal> selector,rtc::scoped_refptr<RTCStatsCollectorCallback> callback)1377*d9f75844SAndroid Build Coastguard Worker void RTCStatsCollector::GetStatsReport(
1378*d9f75844SAndroid Build Coastguard Worker     rtc::scoped_refptr<RtpSenderInternal> selector,
1379*d9f75844SAndroid Build Coastguard Worker     rtc::scoped_refptr<RTCStatsCollectorCallback> callback) {
1380*d9f75844SAndroid Build Coastguard Worker   GetStatsReportInternal(RequestInfo(std::move(selector), std::move(callback)));
1381*d9f75844SAndroid Build Coastguard Worker }
1382*d9f75844SAndroid Build Coastguard Worker 
GetStatsReport(rtc::scoped_refptr<RtpReceiverInternal> selector,rtc::scoped_refptr<RTCStatsCollectorCallback> callback)1383*d9f75844SAndroid Build Coastguard Worker void RTCStatsCollector::GetStatsReport(
1384*d9f75844SAndroid Build Coastguard Worker     rtc::scoped_refptr<RtpReceiverInternal> selector,
1385*d9f75844SAndroid Build Coastguard Worker     rtc::scoped_refptr<RTCStatsCollectorCallback> callback) {
1386*d9f75844SAndroid Build Coastguard Worker   GetStatsReportInternal(RequestInfo(std::move(selector), std::move(callback)));
1387*d9f75844SAndroid Build Coastguard Worker }
1388*d9f75844SAndroid Build Coastguard Worker 
GetStatsReportInternal(RTCStatsCollector::RequestInfo request)1389*d9f75844SAndroid Build Coastguard Worker void RTCStatsCollector::GetStatsReportInternal(
1390*d9f75844SAndroid Build Coastguard Worker     RTCStatsCollector::RequestInfo request) {
1391*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(signaling_thread_);
1392*d9f75844SAndroid Build Coastguard Worker   requests_.push_back(std::move(request));
1393*d9f75844SAndroid Build Coastguard Worker 
1394*d9f75844SAndroid Build Coastguard Worker   // "Now" using a monotonically increasing timer.
1395*d9f75844SAndroid Build Coastguard Worker   int64_t cache_now_us = rtc::TimeMicros();
1396*d9f75844SAndroid Build Coastguard Worker   if (cached_report_ &&
1397*d9f75844SAndroid Build Coastguard Worker       cache_now_us - cache_timestamp_us_ <= cache_lifetime_us_) {
1398*d9f75844SAndroid Build Coastguard Worker     // We have a fresh cached report to deliver. Deliver asynchronously, since
1399*d9f75844SAndroid Build Coastguard Worker     // the caller may not be expecting a synchronous callback, and it avoids
1400*d9f75844SAndroid Build Coastguard Worker     // reentrancy problems.
1401*d9f75844SAndroid Build Coastguard Worker     signaling_thread_->PostTask(
1402*d9f75844SAndroid Build Coastguard Worker         absl::bind_front(&RTCStatsCollector::DeliverCachedReport,
1403*d9f75844SAndroid Build Coastguard Worker                          rtc::scoped_refptr<RTCStatsCollector>(this),
1404*d9f75844SAndroid Build Coastguard Worker                          cached_report_, std::move(requests_)));
1405*d9f75844SAndroid Build Coastguard Worker   } else if (!num_pending_partial_reports_) {
1406*d9f75844SAndroid Build Coastguard Worker     // Only start gathering stats if we're not already gathering stats. In the
1407*d9f75844SAndroid Build Coastguard Worker     // case of already gathering stats, `callback_` will be invoked when there
1408*d9f75844SAndroid Build Coastguard Worker     // are no more pending partial reports.
1409*d9f75844SAndroid Build Coastguard Worker 
1410*d9f75844SAndroid Build Coastguard Worker     // "Now" using a system clock, relative to the UNIX epoch (Jan 1, 1970,
1411*d9f75844SAndroid Build Coastguard Worker     // UTC), in microseconds. The system clock could be modified and is not
1412*d9f75844SAndroid Build Coastguard Worker     // necessarily monotonically increasing.
1413*d9f75844SAndroid Build Coastguard Worker     int64_t timestamp_us = rtc::TimeUTCMicros();
1414*d9f75844SAndroid Build Coastguard Worker 
1415*d9f75844SAndroid Build Coastguard Worker     num_pending_partial_reports_ = 2;
1416*d9f75844SAndroid Build Coastguard Worker     partial_report_timestamp_us_ = cache_now_us;
1417*d9f75844SAndroid Build Coastguard Worker 
1418*d9f75844SAndroid Build Coastguard Worker     // Prepare `transceiver_stats_infos_` and `call_stats_` for use in
1419*d9f75844SAndroid Build Coastguard Worker     // `ProducePartialResultsOnNetworkThread` and
1420*d9f75844SAndroid Build Coastguard Worker     // `ProducePartialResultsOnSignalingThread`.
1421*d9f75844SAndroid Build Coastguard Worker     PrepareTransceiverStatsInfosAndCallStats_s_w_n();
1422*d9f75844SAndroid Build Coastguard Worker     // Don't touch `network_report_` on the signaling thread until
1423*d9f75844SAndroid Build Coastguard Worker     // ProducePartialResultsOnNetworkThread() has signaled the
1424*d9f75844SAndroid Build Coastguard Worker     // `network_report_event_`.
1425*d9f75844SAndroid Build Coastguard Worker     network_report_event_.Reset();
1426*d9f75844SAndroid Build Coastguard Worker     rtc::scoped_refptr<RTCStatsCollector> collector(this);
1427*d9f75844SAndroid Build Coastguard Worker     network_thread_->PostTask(
1428*d9f75844SAndroid Build Coastguard Worker         [collector, sctp_transport_name = pc_->sctp_transport_name(),
1429*d9f75844SAndroid Build Coastguard Worker          timestamp_us]() mutable {
1430*d9f75844SAndroid Build Coastguard Worker           collector->ProducePartialResultsOnNetworkThread(
1431*d9f75844SAndroid Build Coastguard Worker               timestamp_us, std::move(sctp_transport_name));
1432*d9f75844SAndroid Build Coastguard Worker         });
1433*d9f75844SAndroid Build Coastguard Worker     ProducePartialResultsOnSignalingThread(timestamp_us);
1434*d9f75844SAndroid Build Coastguard Worker   }
1435*d9f75844SAndroid Build Coastguard Worker }
1436*d9f75844SAndroid Build Coastguard Worker 
ClearCachedStatsReport()1437*d9f75844SAndroid Build Coastguard Worker void RTCStatsCollector::ClearCachedStatsReport() {
1438*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(signaling_thread_);
1439*d9f75844SAndroid Build Coastguard Worker   cached_report_ = nullptr;
1440*d9f75844SAndroid Build Coastguard Worker   MutexLock lock(&cached_certificates_mutex_);
1441*d9f75844SAndroid Build Coastguard Worker   cached_certificates_by_transport_.clear();
1442*d9f75844SAndroid Build Coastguard Worker }
1443*d9f75844SAndroid Build Coastguard Worker 
WaitForPendingRequest()1444*d9f75844SAndroid Build Coastguard Worker void RTCStatsCollector::WaitForPendingRequest() {
1445*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(signaling_thread_);
1446*d9f75844SAndroid Build Coastguard Worker   // If a request is pending, blocks until the `network_report_event_` is
1447*d9f75844SAndroid Build Coastguard Worker   // signaled and then delivers the result. Otherwise this is a NO-OP.
1448*d9f75844SAndroid Build Coastguard Worker   MergeNetworkReport_s();
1449*d9f75844SAndroid Build Coastguard Worker }
1450*d9f75844SAndroid Build Coastguard Worker 
ProducePartialResultsOnSignalingThread(int64_t timestamp_us)1451*d9f75844SAndroid Build Coastguard Worker void RTCStatsCollector::ProducePartialResultsOnSignalingThread(
1452*d9f75844SAndroid Build Coastguard Worker     int64_t timestamp_us) {
1453*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(signaling_thread_);
1454*d9f75844SAndroid Build Coastguard Worker   rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
1455*d9f75844SAndroid Build Coastguard Worker 
1456*d9f75844SAndroid Build Coastguard Worker   partial_report_ = RTCStatsReport::Create(Timestamp::Micros(timestamp_us));
1457*d9f75844SAndroid Build Coastguard Worker 
1458*d9f75844SAndroid Build Coastguard Worker   ProducePartialResultsOnSignalingThreadImpl(timestamp_us,
1459*d9f75844SAndroid Build Coastguard Worker                                              partial_report_.get());
1460*d9f75844SAndroid Build Coastguard Worker 
1461*d9f75844SAndroid Build Coastguard Worker   // ProducePartialResultsOnSignalingThread() is running synchronously on the
1462*d9f75844SAndroid Build Coastguard Worker   // signaling thread, so it is always the first partial result delivered on the
1463*d9f75844SAndroid Build Coastguard Worker   // signaling thread. The request is not complete until MergeNetworkReport_s()
1464*d9f75844SAndroid Build Coastguard Worker   // happens; we don't have to do anything here.
1465*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_GT(num_pending_partial_reports_, 1);
1466*d9f75844SAndroid Build Coastguard Worker   --num_pending_partial_reports_;
1467*d9f75844SAndroid Build Coastguard Worker }
1468*d9f75844SAndroid Build Coastguard Worker 
ProducePartialResultsOnSignalingThreadImpl(int64_t timestamp_us,RTCStatsReport * partial_report)1469*d9f75844SAndroid Build Coastguard Worker void RTCStatsCollector::ProducePartialResultsOnSignalingThreadImpl(
1470*d9f75844SAndroid Build Coastguard Worker     int64_t timestamp_us,
1471*d9f75844SAndroid Build Coastguard Worker     RTCStatsReport* partial_report) {
1472*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(signaling_thread_);
1473*d9f75844SAndroid Build Coastguard Worker   rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
1474*d9f75844SAndroid Build Coastguard Worker 
1475*d9f75844SAndroid Build Coastguard Worker   ProduceDataChannelStats_s(timestamp_us, partial_report);
1476*d9f75844SAndroid Build Coastguard Worker   ProduceMediaStreamStats_s(timestamp_us, partial_report);
1477*d9f75844SAndroid Build Coastguard Worker   ProduceMediaStreamTrackStats_s(timestamp_us, partial_report);
1478*d9f75844SAndroid Build Coastguard Worker   ProduceMediaSourceStats_s(timestamp_us, partial_report);
1479*d9f75844SAndroid Build Coastguard Worker   ProducePeerConnectionStats_s(timestamp_us, partial_report);
1480*d9f75844SAndroid Build Coastguard Worker }
1481*d9f75844SAndroid Build Coastguard Worker 
ProducePartialResultsOnNetworkThread(int64_t timestamp_us,absl::optional<std::string> sctp_transport_name)1482*d9f75844SAndroid Build Coastguard Worker void RTCStatsCollector::ProducePartialResultsOnNetworkThread(
1483*d9f75844SAndroid Build Coastguard Worker     int64_t timestamp_us,
1484*d9f75844SAndroid Build Coastguard Worker     absl::optional<std::string> sctp_transport_name) {
1485*d9f75844SAndroid Build Coastguard Worker   TRACE_EVENT0("webrtc",
1486*d9f75844SAndroid Build Coastguard Worker                "RTCStatsCollector::ProducePartialResultsOnNetworkThread");
1487*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(network_thread_);
1488*d9f75844SAndroid Build Coastguard Worker   rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
1489*d9f75844SAndroid Build Coastguard Worker 
1490*d9f75844SAndroid Build Coastguard Worker   // Touching `network_report_` on this thread is safe by this method because
1491*d9f75844SAndroid Build Coastguard Worker   // `network_report_event_` is reset before this method is invoked.
1492*d9f75844SAndroid Build Coastguard Worker   network_report_ = RTCStatsReport::Create(Timestamp::Micros(timestamp_us));
1493*d9f75844SAndroid Build Coastguard Worker 
1494*d9f75844SAndroid Build Coastguard Worker   std::set<std::string> transport_names;
1495*d9f75844SAndroid Build Coastguard Worker   if (sctp_transport_name) {
1496*d9f75844SAndroid Build Coastguard Worker     transport_names.emplace(std::move(*sctp_transport_name));
1497*d9f75844SAndroid Build Coastguard Worker   }
1498*d9f75844SAndroid Build Coastguard Worker 
1499*d9f75844SAndroid Build Coastguard Worker   for (const auto& info : transceiver_stats_infos_) {
1500*d9f75844SAndroid Build Coastguard Worker     if (info.transport_name)
1501*d9f75844SAndroid Build Coastguard Worker       transport_names.insert(*info.transport_name);
1502*d9f75844SAndroid Build Coastguard Worker   }
1503*d9f75844SAndroid Build Coastguard Worker 
1504*d9f75844SAndroid Build Coastguard Worker   std::map<std::string, cricket::TransportStats> transport_stats_by_name =
1505*d9f75844SAndroid Build Coastguard Worker       pc_->GetTransportStatsByNames(transport_names);
1506*d9f75844SAndroid Build Coastguard Worker   std::map<std::string, CertificateStatsPair> transport_cert_stats =
1507*d9f75844SAndroid Build Coastguard Worker       PrepareTransportCertificateStats_n(transport_stats_by_name);
1508*d9f75844SAndroid Build Coastguard Worker 
1509*d9f75844SAndroid Build Coastguard Worker   ProducePartialResultsOnNetworkThreadImpl(
1510*d9f75844SAndroid Build Coastguard Worker       timestamp_us, transport_stats_by_name, transport_cert_stats,
1511*d9f75844SAndroid Build Coastguard Worker       network_report_.get());
1512*d9f75844SAndroid Build Coastguard Worker 
1513*d9f75844SAndroid Build Coastguard Worker   // Signal that it is now safe to touch `network_report_` on the signaling
1514*d9f75844SAndroid Build Coastguard Worker   // thread, and post a task to merge it into the final results.
1515*d9f75844SAndroid Build Coastguard Worker   network_report_event_.Set();
1516*d9f75844SAndroid Build Coastguard Worker   rtc::scoped_refptr<RTCStatsCollector> collector(this);
1517*d9f75844SAndroid Build Coastguard Worker   signaling_thread_->PostTask(
1518*d9f75844SAndroid Build Coastguard Worker       [collector] { collector->MergeNetworkReport_s(); });
1519*d9f75844SAndroid Build Coastguard Worker }
1520*d9f75844SAndroid Build Coastguard Worker 
ProducePartialResultsOnNetworkThreadImpl(int64_t timestamp_us,const std::map<std::string,cricket::TransportStats> & transport_stats_by_name,const std::map<std::string,CertificateStatsPair> & transport_cert_stats,RTCStatsReport * partial_report)1521*d9f75844SAndroid Build Coastguard Worker void RTCStatsCollector::ProducePartialResultsOnNetworkThreadImpl(
1522*d9f75844SAndroid Build Coastguard Worker     int64_t timestamp_us,
1523*d9f75844SAndroid Build Coastguard Worker     const std::map<std::string, cricket::TransportStats>&
1524*d9f75844SAndroid Build Coastguard Worker         transport_stats_by_name,
1525*d9f75844SAndroid Build Coastguard Worker     const std::map<std::string, CertificateStatsPair>& transport_cert_stats,
1526*d9f75844SAndroid Build Coastguard Worker     RTCStatsReport* partial_report) {
1527*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(network_thread_);
1528*d9f75844SAndroid Build Coastguard Worker   rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
1529*d9f75844SAndroid Build Coastguard Worker 
1530*d9f75844SAndroid Build Coastguard Worker   ProduceCertificateStats_n(timestamp_us, transport_cert_stats, partial_report);
1531*d9f75844SAndroid Build Coastguard Worker   ProduceIceCandidateAndPairStats_n(timestamp_us, transport_stats_by_name,
1532*d9f75844SAndroid Build Coastguard Worker                                     call_stats_, partial_report);
1533*d9f75844SAndroid Build Coastguard Worker   ProduceTransportStats_n(timestamp_us, transport_stats_by_name,
1534*d9f75844SAndroid Build Coastguard Worker                           transport_cert_stats, partial_report);
1535*d9f75844SAndroid Build Coastguard Worker   ProduceRTPStreamStats_n(timestamp_us, transceiver_stats_infos_,
1536*d9f75844SAndroid Build Coastguard Worker                           partial_report);
1537*d9f75844SAndroid Build Coastguard Worker }
1538*d9f75844SAndroid Build Coastguard Worker 
MergeNetworkReport_s()1539*d9f75844SAndroid Build Coastguard Worker void RTCStatsCollector::MergeNetworkReport_s() {
1540*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(signaling_thread_);
1541*d9f75844SAndroid Build Coastguard Worker   // The `network_report_event_` must be signaled for it to be safe to touch
1542*d9f75844SAndroid Build Coastguard Worker   // `network_report_`. This is normally not blocking, but if
1543*d9f75844SAndroid Build Coastguard Worker   // WaitForPendingRequest() is called while a request is pending, we might have
1544*d9f75844SAndroid Build Coastguard Worker   // to wait until the network thread is done touching `network_report_`.
1545*d9f75844SAndroid Build Coastguard Worker   network_report_event_.Wait(rtc::Event::kForever);
1546*d9f75844SAndroid Build Coastguard Worker   if (!network_report_) {
1547*d9f75844SAndroid Build Coastguard Worker     // Normally, MergeNetworkReport_s() is executed because it is posted from
1548*d9f75844SAndroid Build Coastguard Worker     // the network thread. But if WaitForPendingRequest() is called while a
1549*d9f75844SAndroid Build Coastguard Worker     // request is pending, an early call to MergeNetworkReport_s() is made,
1550*d9f75844SAndroid Build Coastguard Worker     // merging the report and setting `network_report_` to null. If so, when the
1551*d9f75844SAndroid Build Coastguard Worker     // previously posted MergeNetworkReport_s() is later executed, the report is
1552*d9f75844SAndroid Build Coastguard Worker     // already null and nothing needs to be done here.
1553*d9f75844SAndroid Build Coastguard Worker     return;
1554*d9f75844SAndroid Build Coastguard Worker   }
1555*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_GT(num_pending_partial_reports_, 0);
1556*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(partial_report_);
1557*d9f75844SAndroid Build Coastguard Worker   partial_report_->TakeMembersFrom(network_report_);
1558*d9f75844SAndroid Build Coastguard Worker   network_report_ = nullptr;
1559*d9f75844SAndroid Build Coastguard Worker   --num_pending_partial_reports_;
1560*d9f75844SAndroid Build Coastguard Worker   // `network_report_` is currently the only partial report collected
1561*d9f75844SAndroid Build Coastguard Worker   // asynchronously, so `num_pending_partial_reports_` must now be 0 and we are
1562*d9f75844SAndroid Build Coastguard Worker   // ready to deliver the result.
1563*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_EQ(num_pending_partial_reports_, 0);
1564*d9f75844SAndroid Build Coastguard Worker   cache_timestamp_us_ = partial_report_timestamp_us_;
1565*d9f75844SAndroid Build Coastguard Worker   cached_report_ = partial_report_;
1566*d9f75844SAndroid Build Coastguard Worker   partial_report_ = nullptr;
1567*d9f75844SAndroid Build Coastguard Worker   transceiver_stats_infos_.clear();
1568*d9f75844SAndroid Build Coastguard Worker   // Trace WebRTC Stats when getStats is called on Javascript.
1569*d9f75844SAndroid Build Coastguard Worker   // This allows access to WebRTC stats from trace logs. To enable them,
1570*d9f75844SAndroid Build Coastguard Worker   // select the "webrtc_stats" category when recording traces.
1571*d9f75844SAndroid Build Coastguard Worker   TRACE_EVENT_INSTANT1("webrtc_stats", "webrtc_stats", "report",
1572*d9f75844SAndroid Build Coastguard Worker                        cached_report_->ToJson());
1573*d9f75844SAndroid Build Coastguard Worker 
1574*d9f75844SAndroid Build Coastguard Worker   // Deliver report and clear `requests_`.
1575*d9f75844SAndroid Build Coastguard Worker   std::vector<RequestInfo> requests;
1576*d9f75844SAndroid Build Coastguard Worker   requests.swap(requests_);
1577*d9f75844SAndroid Build Coastguard Worker   DeliverCachedReport(cached_report_, std::move(requests));
1578*d9f75844SAndroid Build Coastguard Worker }
1579*d9f75844SAndroid Build Coastguard Worker 
DeliverCachedReport(rtc::scoped_refptr<const RTCStatsReport> cached_report,std::vector<RTCStatsCollector::RequestInfo> requests)1580*d9f75844SAndroid Build Coastguard Worker void RTCStatsCollector::DeliverCachedReport(
1581*d9f75844SAndroid Build Coastguard Worker     rtc::scoped_refptr<const RTCStatsReport> cached_report,
1582*d9f75844SAndroid Build Coastguard Worker     std::vector<RTCStatsCollector::RequestInfo> requests) {
1583*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(signaling_thread_);
1584*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(!requests.empty());
1585*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(cached_report);
1586*d9f75844SAndroid Build Coastguard Worker 
1587*d9f75844SAndroid Build Coastguard Worker   for (const RequestInfo& request : requests) {
1588*d9f75844SAndroid Build Coastguard Worker     if (request.filter_mode() == RequestInfo::FilterMode::kAll) {
1589*d9f75844SAndroid Build Coastguard Worker       request.callback()->OnStatsDelivered(cached_report);
1590*d9f75844SAndroid Build Coastguard Worker     } else {
1591*d9f75844SAndroid Build Coastguard Worker       bool filter_by_sender_selector;
1592*d9f75844SAndroid Build Coastguard Worker       rtc::scoped_refptr<RtpSenderInternal> sender_selector;
1593*d9f75844SAndroid Build Coastguard Worker       rtc::scoped_refptr<RtpReceiverInternal> receiver_selector;
1594*d9f75844SAndroid Build Coastguard Worker       if (request.filter_mode() == RequestInfo::FilterMode::kSenderSelector) {
1595*d9f75844SAndroid Build Coastguard Worker         filter_by_sender_selector = true;
1596*d9f75844SAndroid Build Coastguard Worker         sender_selector = request.sender_selector();
1597*d9f75844SAndroid Build Coastguard Worker       } else {
1598*d9f75844SAndroid Build Coastguard Worker         RTC_DCHECK(request.filter_mode() ==
1599*d9f75844SAndroid Build Coastguard Worker                    RequestInfo::FilterMode::kReceiverSelector);
1600*d9f75844SAndroid Build Coastguard Worker         filter_by_sender_selector = false;
1601*d9f75844SAndroid Build Coastguard Worker         receiver_selector = request.receiver_selector();
1602*d9f75844SAndroid Build Coastguard Worker       }
1603*d9f75844SAndroid Build Coastguard Worker       request.callback()->OnStatsDelivered(CreateReportFilteredBySelector(
1604*d9f75844SAndroid Build Coastguard Worker           filter_by_sender_selector, cached_report, sender_selector,
1605*d9f75844SAndroid Build Coastguard Worker           receiver_selector));
1606*d9f75844SAndroid Build Coastguard Worker     }
1607*d9f75844SAndroid Build Coastguard Worker   }
1608*d9f75844SAndroid Build Coastguard Worker }
1609*d9f75844SAndroid Build Coastguard Worker 
ProduceCertificateStats_n(int64_t timestamp_us,const std::map<std::string,CertificateStatsPair> & transport_cert_stats,RTCStatsReport * report) const1610*d9f75844SAndroid Build Coastguard Worker void RTCStatsCollector::ProduceCertificateStats_n(
1611*d9f75844SAndroid Build Coastguard Worker     int64_t timestamp_us,
1612*d9f75844SAndroid Build Coastguard Worker     const std::map<std::string, CertificateStatsPair>& transport_cert_stats,
1613*d9f75844SAndroid Build Coastguard Worker     RTCStatsReport* report) const {
1614*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(network_thread_);
1615*d9f75844SAndroid Build Coastguard Worker   rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
1616*d9f75844SAndroid Build Coastguard Worker 
1617*d9f75844SAndroid Build Coastguard Worker   for (const auto& transport_cert_stats_pair : transport_cert_stats) {
1618*d9f75844SAndroid Build Coastguard Worker     if (transport_cert_stats_pair.second.local) {
1619*d9f75844SAndroid Build Coastguard Worker       ProduceCertificateStatsFromSSLCertificateStats(
1620*d9f75844SAndroid Build Coastguard Worker           timestamp_us, *transport_cert_stats_pair.second.local.get(), report);
1621*d9f75844SAndroid Build Coastguard Worker     }
1622*d9f75844SAndroid Build Coastguard Worker     if (transport_cert_stats_pair.second.remote) {
1623*d9f75844SAndroid Build Coastguard Worker       ProduceCertificateStatsFromSSLCertificateStats(
1624*d9f75844SAndroid Build Coastguard Worker           timestamp_us, *transport_cert_stats_pair.second.remote.get(), report);
1625*d9f75844SAndroid Build Coastguard Worker     }
1626*d9f75844SAndroid Build Coastguard Worker   }
1627*d9f75844SAndroid Build Coastguard Worker }
1628*d9f75844SAndroid Build Coastguard Worker 
ProduceDataChannelStats_s(int64_t timestamp_us,RTCStatsReport * report) const1629*d9f75844SAndroid Build Coastguard Worker void RTCStatsCollector::ProduceDataChannelStats_s(
1630*d9f75844SAndroid Build Coastguard Worker     int64_t timestamp_us,
1631*d9f75844SAndroid Build Coastguard Worker     RTCStatsReport* report) const {
1632*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(signaling_thread_);
1633*d9f75844SAndroid Build Coastguard Worker   rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
1634*d9f75844SAndroid Build Coastguard Worker   std::vector<DataChannelStats> data_stats = pc_->GetDataChannelStats();
1635*d9f75844SAndroid Build Coastguard Worker   for (const auto& stats : data_stats) {
1636*d9f75844SAndroid Build Coastguard Worker     std::unique_ptr<RTCDataChannelStats> data_channel_stats(
1637*d9f75844SAndroid Build Coastguard Worker         std::make_unique<RTCDataChannelStats>(
1638*d9f75844SAndroid Build Coastguard Worker             "D" + rtc::ToString(stats.internal_id), timestamp_us));
1639*d9f75844SAndroid Build Coastguard Worker     data_channel_stats->label = std::move(stats.label);
1640*d9f75844SAndroid Build Coastguard Worker     data_channel_stats->protocol = std::move(stats.protocol);
1641*d9f75844SAndroid Build Coastguard Worker     data_channel_stats->data_channel_identifier = stats.id;
1642*d9f75844SAndroid Build Coastguard Worker     data_channel_stats->state = DataStateToRTCDataChannelState(stats.state);
1643*d9f75844SAndroid Build Coastguard Worker     data_channel_stats->messages_sent = stats.messages_sent;
1644*d9f75844SAndroid Build Coastguard Worker     data_channel_stats->bytes_sent = stats.bytes_sent;
1645*d9f75844SAndroid Build Coastguard Worker     data_channel_stats->messages_received = stats.messages_received;
1646*d9f75844SAndroid Build Coastguard Worker     data_channel_stats->bytes_received = stats.bytes_received;
1647*d9f75844SAndroid Build Coastguard Worker     report->AddStats(std::move(data_channel_stats));
1648*d9f75844SAndroid Build Coastguard Worker   }
1649*d9f75844SAndroid Build Coastguard Worker }
1650*d9f75844SAndroid Build Coastguard Worker 
ProduceIceCandidateAndPairStats_n(int64_t timestamp_us,const std::map<std::string,cricket::TransportStats> & transport_stats_by_name,const Call::Stats & call_stats,RTCStatsReport * report) const1651*d9f75844SAndroid Build Coastguard Worker void RTCStatsCollector::ProduceIceCandidateAndPairStats_n(
1652*d9f75844SAndroid Build Coastguard Worker     int64_t timestamp_us,
1653*d9f75844SAndroid Build Coastguard Worker     const std::map<std::string, cricket::TransportStats>&
1654*d9f75844SAndroid Build Coastguard Worker         transport_stats_by_name,
1655*d9f75844SAndroid Build Coastguard Worker     const Call::Stats& call_stats,
1656*d9f75844SAndroid Build Coastguard Worker     RTCStatsReport* report) const {
1657*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(network_thread_);
1658*d9f75844SAndroid Build Coastguard Worker   rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
1659*d9f75844SAndroid Build Coastguard Worker 
1660*d9f75844SAndroid Build Coastguard Worker   for (const auto& entry : transport_stats_by_name) {
1661*d9f75844SAndroid Build Coastguard Worker     const std::string& transport_name = entry.first;
1662*d9f75844SAndroid Build Coastguard Worker     const cricket::TransportStats& transport_stats = entry.second;
1663*d9f75844SAndroid Build Coastguard Worker     for (const auto& channel_stats : transport_stats.channel_stats) {
1664*d9f75844SAndroid Build Coastguard Worker       std::string transport_id = RTCTransportStatsIDFromTransportChannel(
1665*d9f75844SAndroid Build Coastguard Worker           transport_name, channel_stats.component);
1666*d9f75844SAndroid Build Coastguard Worker       for (const auto& info :
1667*d9f75844SAndroid Build Coastguard Worker            channel_stats.ice_transport_stats.connection_infos) {
1668*d9f75844SAndroid Build Coastguard Worker         std::unique_ptr<RTCIceCandidatePairStats> candidate_pair_stats(
1669*d9f75844SAndroid Build Coastguard Worker             std::make_unique<RTCIceCandidatePairStats>(
1670*d9f75844SAndroid Build Coastguard Worker                 RTCIceCandidatePairStatsIDFromConnectionInfo(info),
1671*d9f75844SAndroid Build Coastguard Worker                 timestamp_us));
1672*d9f75844SAndroid Build Coastguard Worker 
1673*d9f75844SAndroid Build Coastguard Worker         candidate_pair_stats->transport_id = transport_id;
1674*d9f75844SAndroid Build Coastguard Worker         // TODO(hbos): There could be other candidates that are not paired with
1675*d9f75844SAndroid Build Coastguard Worker         // anything. We don't have a complete list. Local candidates come from
1676*d9f75844SAndroid Build Coastguard Worker         // Port objects, and prflx candidates (both local and remote) are only
1677*d9f75844SAndroid Build Coastguard Worker         // stored in candidate pairs. https://crbug.com/632723
1678*d9f75844SAndroid Build Coastguard Worker         candidate_pair_stats->local_candidate_id = ProduceIceCandidateStats(
1679*d9f75844SAndroid Build Coastguard Worker             timestamp_us, info.local_candidate, true, transport_id, report);
1680*d9f75844SAndroid Build Coastguard Worker         candidate_pair_stats->remote_candidate_id = ProduceIceCandidateStats(
1681*d9f75844SAndroid Build Coastguard Worker             timestamp_us, info.remote_candidate, false, transport_id, report);
1682*d9f75844SAndroid Build Coastguard Worker         candidate_pair_stats->state =
1683*d9f75844SAndroid Build Coastguard Worker             IceCandidatePairStateToRTCStatsIceCandidatePairState(info.state);
1684*d9f75844SAndroid Build Coastguard Worker         candidate_pair_stats->priority = info.priority;
1685*d9f75844SAndroid Build Coastguard Worker         candidate_pair_stats->nominated = info.nominated;
1686*d9f75844SAndroid Build Coastguard Worker         // TODO(hbos): This writable is different than the spec. It goes to
1687*d9f75844SAndroid Build Coastguard Worker         // false after a certain amount of time without a response passes.
1688*d9f75844SAndroid Build Coastguard Worker         // https://crbug.com/633550
1689*d9f75844SAndroid Build Coastguard Worker         candidate_pair_stats->writable = info.writable;
1690*d9f75844SAndroid Build Coastguard Worker         // Note that sent_total_packets includes discarded packets but
1691*d9f75844SAndroid Build Coastguard Worker         // sent_total_bytes does not.
1692*d9f75844SAndroid Build Coastguard Worker         candidate_pair_stats->packets_sent = static_cast<uint64_t>(
1693*d9f75844SAndroid Build Coastguard Worker             info.sent_total_packets - info.sent_discarded_packets);
1694*d9f75844SAndroid Build Coastguard Worker         candidate_pair_stats->packets_discarded_on_send =
1695*d9f75844SAndroid Build Coastguard Worker             static_cast<uint64_t>(info.sent_discarded_packets);
1696*d9f75844SAndroid Build Coastguard Worker         candidate_pair_stats->packets_received =
1697*d9f75844SAndroid Build Coastguard Worker             static_cast<uint64_t>(info.packets_received);
1698*d9f75844SAndroid Build Coastguard Worker         candidate_pair_stats->bytes_sent =
1699*d9f75844SAndroid Build Coastguard Worker             static_cast<uint64_t>(info.sent_total_bytes);
1700*d9f75844SAndroid Build Coastguard Worker         candidate_pair_stats->bytes_discarded_on_send =
1701*d9f75844SAndroid Build Coastguard Worker             static_cast<uint64_t>(info.sent_discarded_bytes);
1702*d9f75844SAndroid Build Coastguard Worker         candidate_pair_stats->bytes_received =
1703*d9f75844SAndroid Build Coastguard Worker             static_cast<uint64_t>(info.recv_total_bytes);
1704*d9f75844SAndroid Build Coastguard Worker         candidate_pair_stats->total_round_trip_time =
1705*d9f75844SAndroid Build Coastguard Worker             static_cast<double>(info.total_round_trip_time_ms) /
1706*d9f75844SAndroid Build Coastguard Worker             rtc::kNumMillisecsPerSec;
1707*d9f75844SAndroid Build Coastguard Worker         if (info.current_round_trip_time_ms.has_value()) {
1708*d9f75844SAndroid Build Coastguard Worker           candidate_pair_stats->current_round_trip_time =
1709*d9f75844SAndroid Build Coastguard Worker               static_cast<double>(*info.current_round_trip_time_ms) /
1710*d9f75844SAndroid Build Coastguard Worker               rtc::kNumMillisecsPerSec;
1711*d9f75844SAndroid Build Coastguard Worker         }
1712*d9f75844SAndroid Build Coastguard Worker         if (info.best_connection) {
1713*d9f75844SAndroid Build Coastguard Worker           // The bandwidth estimations we have are for the selected candidate
1714*d9f75844SAndroid Build Coastguard Worker           // pair ("info.best_connection").
1715*d9f75844SAndroid Build Coastguard Worker           RTC_DCHECK_GE(call_stats.send_bandwidth_bps, 0);
1716*d9f75844SAndroid Build Coastguard Worker           RTC_DCHECK_GE(call_stats.recv_bandwidth_bps, 0);
1717*d9f75844SAndroid Build Coastguard Worker           if (call_stats.send_bandwidth_bps > 0) {
1718*d9f75844SAndroid Build Coastguard Worker             candidate_pair_stats->available_outgoing_bitrate =
1719*d9f75844SAndroid Build Coastguard Worker                 static_cast<double>(call_stats.send_bandwidth_bps);
1720*d9f75844SAndroid Build Coastguard Worker           }
1721*d9f75844SAndroid Build Coastguard Worker           if (call_stats.recv_bandwidth_bps > 0) {
1722*d9f75844SAndroid Build Coastguard Worker             candidate_pair_stats->available_incoming_bitrate =
1723*d9f75844SAndroid Build Coastguard Worker                 static_cast<double>(call_stats.recv_bandwidth_bps);
1724*d9f75844SAndroid Build Coastguard Worker           }
1725*d9f75844SAndroid Build Coastguard Worker         }
1726*d9f75844SAndroid Build Coastguard Worker         candidate_pair_stats->requests_received =
1727*d9f75844SAndroid Build Coastguard Worker             static_cast<uint64_t>(info.recv_ping_requests);
1728*d9f75844SAndroid Build Coastguard Worker         candidate_pair_stats->requests_sent =
1729*d9f75844SAndroid Build Coastguard Worker             static_cast<uint64_t>(info.sent_ping_requests_total);
1730*d9f75844SAndroid Build Coastguard Worker         candidate_pair_stats->responses_received =
1731*d9f75844SAndroid Build Coastguard Worker             static_cast<uint64_t>(info.recv_ping_responses);
1732*d9f75844SAndroid Build Coastguard Worker         candidate_pair_stats->responses_sent =
1733*d9f75844SAndroid Build Coastguard Worker             static_cast<uint64_t>(info.sent_ping_responses);
1734*d9f75844SAndroid Build Coastguard Worker         RTC_DCHECK_GE(info.sent_ping_requests_total,
1735*d9f75844SAndroid Build Coastguard Worker                       info.sent_ping_requests_before_first_response);
1736*d9f75844SAndroid Build Coastguard Worker         candidate_pair_stats->consent_requests_sent = static_cast<uint64_t>(
1737*d9f75844SAndroid Build Coastguard Worker             info.sent_ping_requests_total -
1738*d9f75844SAndroid Build Coastguard Worker             info.sent_ping_requests_before_first_response);
1739*d9f75844SAndroid Build Coastguard Worker 
1740*d9f75844SAndroid Build Coastguard Worker         if (info.last_data_received.has_value()) {
1741*d9f75844SAndroid Build Coastguard Worker           candidate_pair_stats->last_packet_received_timestamp =
1742*d9f75844SAndroid Build Coastguard Worker               static_cast<double>(info.last_data_received->ms());
1743*d9f75844SAndroid Build Coastguard Worker         }
1744*d9f75844SAndroid Build Coastguard Worker         if (info.last_data_sent) {
1745*d9f75844SAndroid Build Coastguard Worker           candidate_pair_stats->last_packet_sent_timestamp =
1746*d9f75844SAndroid Build Coastguard Worker               static_cast<double>(info.last_data_sent->ms());
1747*d9f75844SAndroid Build Coastguard Worker         }
1748*d9f75844SAndroid Build Coastguard Worker 
1749*d9f75844SAndroid Build Coastguard Worker         report->AddStats(std::move(candidate_pair_stats));
1750*d9f75844SAndroid Build Coastguard Worker       }
1751*d9f75844SAndroid Build Coastguard Worker 
1752*d9f75844SAndroid Build Coastguard Worker       // Produce local candidate stats. If a transport exists these will already
1753*d9f75844SAndroid Build Coastguard Worker       // have been produced.
1754*d9f75844SAndroid Build Coastguard Worker       for (const auto& candidate_stats :
1755*d9f75844SAndroid Build Coastguard Worker            channel_stats.ice_transport_stats.candidate_stats_list) {
1756*d9f75844SAndroid Build Coastguard Worker         const auto& candidate = candidate_stats.candidate();
1757*d9f75844SAndroid Build Coastguard Worker         ProduceIceCandidateStats(timestamp_us, candidate, true, transport_id,
1758*d9f75844SAndroid Build Coastguard Worker                                  report);
1759*d9f75844SAndroid Build Coastguard Worker       }
1760*d9f75844SAndroid Build Coastguard Worker     }
1761*d9f75844SAndroid Build Coastguard Worker   }
1762*d9f75844SAndroid Build Coastguard Worker }
1763*d9f75844SAndroid Build Coastguard Worker 
ProduceMediaStreamStats_s(int64_t timestamp_us,RTCStatsReport * report) const1764*d9f75844SAndroid Build Coastguard Worker void RTCStatsCollector::ProduceMediaStreamStats_s(
1765*d9f75844SAndroid Build Coastguard Worker     int64_t timestamp_us,
1766*d9f75844SAndroid Build Coastguard Worker     RTCStatsReport* report) const {
1767*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(signaling_thread_);
1768*d9f75844SAndroid Build Coastguard Worker   rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
1769*d9f75844SAndroid Build Coastguard Worker 
1770*d9f75844SAndroid Build Coastguard Worker   std::map<std::string, std::vector<std::string>> track_ids;
1771*d9f75844SAndroid Build Coastguard Worker 
1772*d9f75844SAndroid Build Coastguard Worker   for (const auto& stats : transceiver_stats_infos_) {
1773*d9f75844SAndroid Build Coastguard Worker     for (const auto& sender : stats.transceiver->senders()) {
1774*d9f75844SAndroid Build Coastguard Worker       std::string track_id =
1775*d9f75844SAndroid Build Coastguard Worker           DEPRECATED_RTCMediaStreamTrackStatsIDFromDirectionAndAttachment(
1776*d9f75844SAndroid Build Coastguard Worker               kDirectionOutbound, sender->internal()->AttachmentId());
1777*d9f75844SAndroid Build Coastguard Worker       for (auto& stream_id : sender->stream_ids()) {
1778*d9f75844SAndroid Build Coastguard Worker         track_ids[stream_id].push_back(track_id);
1779*d9f75844SAndroid Build Coastguard Worker       }
1780*d9f75844SAndroid Build Coastguard Worker     }
1781*d9f75844SAndroid Build Coastguard Worker     for (const auto& receiver : stats.transceiver->receivers()) {
1782*d9f75844SAndroid Build Coastguard Worker       std::string track_id =
1783*d9f75844SAndroid Build Coastguard Worker           DEPRECATED_RTCMediaStreamTrackStatsIDFromDirectionAndAttachment(
1784*d9f75844SAndroid Build Coastguard Worker               kDirectionInbound, receiver->internal()->AttachmentId());
1785*d9f75844SAndroid Build Coastguard Worker       for (auto& stream : receiver->streams()) {
1786*d9f75844SAndroid Build Coastguard Worker         track_ids[stream->id()].push_back(track_id);
1787*d9f75844SAndroid Build Coastguard Worker       }
1788*d9f75844SAndroid Build Coastguard Worker     }
1789*d9f75844SAndroid Build Coastguard Worker   }
1790*d9f75844SAndroid Build Coastguard Worker 
1791*d9f75844SAndroid Build Coastguard Worker   // Build stats for each stream ID known.
1792*d9f75844SAndroid Build Coastguard Worker   for (auto& it : track_ids) {
1793*d9f75844SAndroid Build Coastguard Worker     std::unique_ptr<DEPRECATED_RTCMediaStreamStats> stream_stats(
1794*d9f75844SAndroid Build Coastguard Worker         std::make_unique<DEPRECATED_RTCMediaStreamStats>(
1795*d9f75844SAndroid Build Coastguard Worker             "DEPRECATED_S" + it.first, timestamp_us));
1796*d9f75844SAndroid Build Coastguard Worker     stream_stats->stream_identifier = it.first;
1797*d9f75844SAndroid Build Coastguard Worker     stream_stats->track_ids = it.second;
1798*d9f75844SAndroid Build Coastguard Worker     report->AddStats(std::move(stream_stats));
1799*d9f75844SAndroid Build Coastguard Worker   }
1800*d9f75844SAndroid Build Coastguard Worker }
1801*d9f75844SAndroid Build Coastguard Worker 
ProduceMediaStreamTrackStats_s(int64_t timestamp_us,RTCStatsReport * report) const1802*d9f75844SAndroid Build Coastguard Worker void RTCStatsCollector::ProduceMediaStreamTrackStats_s(
1803*d9f75844SAndroid Build Coastguard Worker     int64_t timestamp_us,
1804*d9f75844SAndroid Build Coastguard Worker     RTCStatsReport* report) const {
1805*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(signaling_thread_);
1806*d9f75844SAndroid Build Coastguard Worker   rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
1807*d9f75844SAndroid Build Coastguard Worker 
1808*d9f75844SAndroid Build Coastguard Worker   for (const RtpTransceiverStatsInfo& stats : transceiver_stats_infos_) {
1809*d9f75844SAndroid Build Coastguard Worker     std::vector<rtc::scoped_refptr<RtpSenderInternal>> senders;
1810*d9f75844SAndroid Build Coastguard Worker     for (const auto& sender : stats.transceiver->senders()) {
1811*d9f75844SAndroid Build Coastguard Worker       senders.push_back(
1812*d9f75844SAndroid Build Coastguard Worker           rtc::scoped_refptr<RtpSenderInternal>(sender->internal()));
1813*d9f75844SAndroid Build Coastguard Worker     }
1814*d9f75844SAndroid Build Coastguard Worker     ProduceSenderMediaTrackStats(timestamp_us, stats.track_media_info_map,
1815*d9f75844SAndroid Build Coastguard Worker                                  senders, report);
1816*d9f75844SAndroid Build Coastguard Worker 
1817*d9f75844SAndroid Build Coastguard Worker     std::vector<rtc::scoped_refptr<RtpReceiverInternal>> receivers;
1818*d9f75844SAndroid Build Coastguard Worker     for (const auto& receiver : stats.transceiver->receivers()) {
1819*d9f75844SAndroid Build Coastguard Worker       receivers.push_back(
1820*d9f75844SAndroid Build Coastguard Worker           rtc::scoped_refptr<RtpReceiverInternal>(receiver->internal()));
1821*d9f75844SAndroid Build Coastguard Worker     }
1822*d9f75844SAndroid Build Coastguard Worker     ProduceReceiverMediaTrackStats(timestamp_us, stats.track_media_info_map,
1823*d9f75844SAndroid Build Coastguard Worker                                    receivers, report);
1824*d9f75844SAndroid Build Coastguard Worker   }
1825*d9f75844SAndroid Build Coastguard Worker }
1826*d9f75844SAndroid Build Coastguard Worker 
ProduceMediaSourceStats_s(int64_t timestamp_us,RTCStatsReport * report) const1827*d9f75844SAndroid Build Coastguard Worker void RTCStatsCollector::ProduceMediaSourceStats_s(
1828*d9f75844SAndroid Build Coastguard Worker     int64_t timestamp_us,
1829*d9f75844SAndroid Build Coastguard Worker     RTCStatsReport* report) const {
1830*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(signaling_thread_);
1831*d9f75844SAndroid Build Coastguard Worker   rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
1832*d9f75844SAndroid Build Coastguard Worker 
1833*d9f75844SAndroid Build Coastguard Worker   for (const RtpTransceiverStatsInfo& transceiver_stats_info :
1834*d9f75844SAndroid Build Coastguard Worker        transceiver_stats_infos_) {
1835*d9f75844SAndroid Build Coastguard Worker     const auto& track_media_info_map =
1836*d9f75844SAndroid Build Coastguard Worker         transceiver_stats_info.track_media_info_map;
1837*d9f75844SAndroid Build Coastguard Worker     for (const auto& sender : transceiver_stats_info.transceiver->senders()) {
1838*d9f75844SAndroid Build Coastguard Worker       const auto& sender_internal = sender->internal();
1839*d9f75844SAndroid Build Coastguard Worker       const auto& track = sender_internal->track();
1840*d9f75844SAndroid Build Coastguard Worker       if (!track)
1841*d9f75844SAndroid Build Coastguard Worker         continue;
1842*d9f75844SAndroid Build Coastguard Worker       // TODO(https://crbug.com/webrtc/10771): The same track could be attached
1843*d9f75844SAndroid Build Coastguard Worker       // to multiple senders which should result in multiple senders referencing
1844*d9f75844SAndroid Build Coastguard Worker       // the same media-source stats. When all media source related metrics are
1845*d9f75844SAndroid Build Coastguard Worker       // moved to the track's source (e.g. input frame rate is moved from
1846*d9f75844SAndroid Build Coastguard Worker       // cricket::VideoSenderInfo to VideoTrackSourceInterface::Stats and audio
1847*d9f75844SAndroid Build Coastguard Worker       // levels are moved to the corresponding audio track/source object), don't
1848*d9f75844SAndroid Build Coastguard Worker       // create separate media source stats objects on a per-attachment basis.
1849*d9f75844SAndroid Build Coastguard Worker       std::unique_ptr<RTCMediaSourceStats> media_source_stats;
1850*d9f75844SAndroid Build Coastguard Worker       if (track->kind() == MediaStreamTrackInterface::kAudioKind) {
1851*d9f75844SAndroid Build Coastguard Worker         AudioTrackInterface* audio_track =
1852*d9f75844SAndroid Build Coastguard Worker             static_cast<AudioTrackInterface*>(track.get());
1853*d9f75844SAndroid Build Coastguard Worker         auto audio_source_stats = std::make_unique<RTCAudioSourceStats>(
1854*d9f75844SAndroid Build Coastguard Worker             RTCMediaSourceStatsIDFromKindAndAttachment(
1855*d9f75844SAndroid Build Coastguard Worker                 cricket::MEDIA_TYPE_AUDIO, sender_internal->AttachmentId()),
1856*d9f75844SAndroid Build Coastguard Worker             timestamp_us);
1857*d9f75844SAndroid Build Coastguard Worker         // TODO(https://crbug.com/webrtc/10771): We shouldn't need to have an
1858*d9f75844SAndroid Build Coastguard Worker         // SSRC assigned (there shouldn't need to exist a send-stream, created
1859*d9f75844SAndroid Build Coastguard Worker         // by an O/A exchange) in order to read audio media-source stats.
1860*d9f75844SAndroid Build Coastguard Worker         // TODO(https://crbug.com/webrtc/8694): SSRC 0 shouldn't be a magic
1861*d9f75844SAndroid Build Coastguard Worker         // value indicating no SSRC.
1862*d9f75844SAndroid Build Coastguard Worker         if (sender_internal->ssrc() != 0) {
1863*d9f75844SAndroid Build Coastguard Worker           auto* voice_sender_info =
1864*d9f75844SAndroid Build Coastguard Worker               track_media_info_map.GetVoiceSenderInfoBySsrc(
1865*d9f75844SAndroid Build Coastguard Worker                   sender_internal->ssrc());
1866*d9f75844SAndroid Build Coastguard Worker           if (voice_sender_info) {
1867*d9f75844SAndroid Build Coastguard Worker             audio_source_stats->audio_level = DoubleAudioLevelFromIntAudioLevel(
1868*d9f75844SAndroid Build Coastguard Worker                 voice_sender_info->audio_level);
1869*d9f75844SAndroid Build Coastguard Worker             audio_source_stats->total_audio_energy =
1870*d9f75844SAndroid Build Coastguard Worker                 voice_sender_info->total_input_energy;
1871*d9f75844SAndroid Build Coastguard Worker             audio_source_stats->total_samples_duration =
1872*d9f75844SAndroid Build Coastguard Worker                 voice_sender_info->total_input_duration;
1873*d9f75844SAndroid Build Coastguard Worker             SetAudioProcessingStats(audio_source_stats.get(),
1874*d9f75844SAndroid Build Coastguard Worker                                     voice_sender_info->apm_statistics);
1875*d9f75844SAndroid Build Coastguard Worker           }
1876*d9f75844SAndroid Build Coastguard Worker         }
1877*d9f75844SAndroid Build Coastguard Worker         // Audio processor may be attached to either the track or the send
1878*d9f75844SAndroid Build Coastguard Worker         // stream, so look in both places.
1879*d9f75844SAndroid Build Coastguard Worker         auto audio_processor(audio_track->GetAudioProcessor());
1880*d9f75844SAndroid Build Coastguard Worker         if (audio_processor.get()) {
1881*d9f75844SAndroid Build Coastguard Worker           // The `has_remote_tracks` argument is obsolete; makes no difference
1882*d9f75844SAndroid Build Coastguard Worker           // if it's set to true or false.
1883*d9f75844SAndroid Build Coastguard Worker           AudioProcessorInterface::AudioProcessorStatistics ap_stats =
1884*d9f75844SAndroid Build Coastguard Worker               audio_processor->GetStats(/*has_remote_tracks=*/false);
1885*d9f75844SAndroid Build Coastguard Worker           SetAudioProcessingStats(audio_source_stats.get(),
1886*d9f75844SAndroid Build Coastguard Worker                                   ap_stats.apm_statistics);
1887*d9f75844SAndroid Build Coastguard Worker         }
1888*d9f75844SAndroid Build Coastguard Worker         media_source_stats = std::move(audio_source_stats);
1889*d9f75844SAndroid Build Coastguard Worker       } else {
1890*d9f75844SAndroid Build Coastguard Worker         RTC_DCHECK_EQ(MediaStreamTrackInterface::kVideoKind, track->kind());
1891*d9f75844SAndroid Build Coastguard Worker         auto video_source_stats = std::make_unique<RTCVideoSourceStats>(
1892*d9f75844SAndroid Build Coastguard Worker             RTCMediaSourceStatsIDFromKindAndAttachment(
1893*d9f75844SAndroid Build Coastguard Worker                 cricket::MEDIA_TYPE_VIDEO, sender_internal->AttachmentId()),
1894*d9f75844SAndroid Build Coastguard Worker             timestamp_us);
1895*d9f75844SAndroid Build Coastguard Worker         auto* video_track = static_cast<VideoTrackInterface*>(track.get());
1896*d9f75844SAndroid Build Coastguard Worker         auto* video_source = video_track->GetSource();
1897*d9f75844SAndroid Build Coastguard Worker         VideoTrackSourceInterface::Stats source_stats;
1898*d9f75844SAndroid Build Coastguard Worker         if (video_source && video_source->GetStats(&source_stats)) {
1899*d9f75844SAndroid Build Coastguard Worker           video_source_stats->width = source_stats.input_width;
1900*d9f75844SAndroid Build Coastguard Worker           video_source_stats->height = source_stats.input_height;
1901*d9f75844SAndroid Build Coastguard Worker         }
1902*d9f75844SAndroid Build Coastguard Worker         // TODO(https://crbug.com/webrtc/10771): We shouldn't need to have an
1903*d9f75844SAndroid Build Coastguard Worker         // SSRC assigned (there shouldn't need to exist a send-stream, created
1904*d9f75844SAndroid Build Coastguard Worker         // by an O/A exchange) in order to get framesPerSecond.
1905*d9f75844SAndroid Build Coastguard Worker         // TODO(https://crbug.com/webrtc/8694): SSRC 0 shouldn't be a magic
1906*d9f75844SAndroid Build Coastguard Worker         // value indicating no SSRC.
1907*d9f75844SAndroid Build Coastguard Worker         if (sender_internal->ssrc() != 0) {
1908*d9f75844SAndroid Build Coastguard Worker           auto* video_sender_info =
1909*d9f75844SAndroid Build Coastguard Worker               track_media_info_map.GetVideoSenderInfoBySsrc(
1910*d9f75844SAndroid Build Coastguard Worker                   sender_internal->ssrc());
1911*d9f75844SAndroid Build Coastguard Worker           if (video_sender_info) {
1912*d9f75844SAndroid Build Coastguard Worker             video_source_stats->frames_per_second =
1913*d9f75844SAndroid Build Coastguard Worker                 video_sender_info->framerate_input;
1914*d9f75844SAndroid Build Coastguard Worker             video_source_stats->frames = video_sender_info->frames;
1915*d9f75844SAndroid Build Coastguard Worker           }
1916*d9f75844SAndroid Build Coastguard Worker         }
1917*d9f75844SAndroid Build Coastguard Worker         media_source_stats = std::move(video_source_stats);
1918*d9f75844SAndroid Build Coastguard Worker       }
1919*d9f75844SAndroid Build Coastguard Worker       media_source_stats->track_identifier = track->id();
1920*d9f75844SAndroid Build Coastguard Worker       media_source_stats->kind = track->kind();
1921*d9f75844SAndroid Build Coastguard Worker       report->AddStats(std::move(media_source_stats));
1922*d9f75844SAndroid Build Coastguard Worker     }
1923*d9f75844SAndroid Build Coastguard Worker   }
1924*d9f75844SAndroid Build Coastguard Worker }
1925*d9f75844SAndroid Build Coastguard Worker 
ProducePeerConnectionStats_s(int64_t timestamp_us,RTCStatsReport * report) const1926*d9f75844SAndroid Build Coastguard Worker void RTCStatsCollector::ProducePeerConnectionStats_s(
1927*d9f75844SAndroid Build Coastguard Worker     int64_t timestamp_us,
1928*d9f75844SAndroid Build Coastguard Worker     RTCStatsReport* report) const {
1929*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(signaling_thread_);
1930*d9f75844SAndroid Build Coastguard Worker   rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
1931*d9f75844SAndroid Build Coastguard Worker 
1932*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<RTCPeerConnectionStats> stats(
1933*d9f75844SAndroid Build Coastguard Worker       std::make_unique<RTCPeerConnectionStats>("P", timestamp_us));
1934*d9f75844SAndroid Build Coastguard Worker   stats->data_channels_opened = internal_record_.data_channels_opened;
1935*d9f75844SAndroid Build Coastguard Worker   stats->data_channels_closed = internal_record_.data_channels_closed;
1936*d9f75844SAndroid Build Coastguard Worker   report->AddStats(std::move(stats));
1937*d9f75844SAndroid Build Coastguard Worker }
1938*d9f75844SAndroid Build Coastguard Worker 
ProduceRTPStreamStats_n(int64_t timestamp_us,const std::vector<RtpTransceiverStatsInfo> & transceiver_stats_infos,RTCStatsReport * report) const1939*d9f75844SAndroid Build Coastguard Worker void RTCStatsCollector::ProduceRTPStreamStats_n(
1940*d9f75844SAndroid Build Coastguard Worker     int64_t timestamp_us,
1941*d9f75844SAndroid Build Coastguard Worker     const std::vector<RtpTransceiverStatsInfo>& transceiver_stats_infos,
1942*d9f75844SAndroid Build Coastguard Worker     RTCStatsReport* report) const {
1943*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(network_thread_);
1944*d9f75844SAndroid Build Coastguard Worker   rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
1945*d9f75844SAndroid Build Coastguard Worker 
1946*d9f75844SAndroid Build Coastguard Worker   for (const RtpTransceiverStatsInfo& stats : transceiver_stats_infos) {
1947*d9f75844SAndroid Build Coastguard Worker     if (stats.media_type == cricket::MEDIA_TYPE_AUDIO) {
1948*d9f75844SAndroid Build Coastguard Worker       ProduceAudioRTPStreamStats_n(timestamp_us, stats, report);
1949*d9f75844SAndroid Build Coastguard Worker     } else if (stats.media_type == cricket::MEDIA_TYPE_VIDEO) {
1950*d9f75844SAndroid Build Coastguard Worker       ProduceVideoRTPStreamStats_n(timestamp_us, stats, report);
1951*d9f75844SAndroid Build Coastguard Worker     } else {
1952*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK_NOTREACHED();
1953*d9f75844SAndroid Build Coastguard Worker     }
1954*d9f75844SAndroid Build Coastguard Worker   }
1955*d9f75844SAndroid Build Coastguard Worker }
1956*d9f75844SAndroid Build Coastguard Worker 
ProduceAudioRTPStreamStats_n(int64_t timestamp_us,const RtpTransceiverStatsInfo & stats,RTCStatsReport * report) const1957*d9f75844SAndroid Build Coastguard Worker void RTCStatsCollector::ProduceAudioRTPStreamStats_n(
1958*d9f75844SAndroid Build Coastguard Worker     int64_t timestamp_us,
1959*d9f75844SAndroid Build Coastguard Worker     const RtpTransceiverStatsInfo& stats,
1960*d9f75844SAndroid Build Coastguard Worker     RTCStatsReport* report) const {
1961*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(network_thread_);
1962*d9f75844SAndroid Build Coastguard Worker   rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
1963*d9f75844SAndroid Build Coastguard Worker 
1964*d9f75844SAndroid Build Coastguard Worker   if (!stats.mid || !stats.transport_name) {
1965*d9f75844SAndroid Build Coastguard Worker     return;
1966*d9f75844SAndroid Build Coastguard Worker   }
1967*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(stats.track_media_info_map.voice_media_info().has_value());
1968*d9f75844SAndroid Build Coastguard Worker   std::string mid = *stats.mid;
1969*d9f75844SAndroid Build Coastguard Worker   std::string transport_id = RTCTransportStatsIDFromTransportChannel(
1970*d9f75844SAndroid Build Coastguard Worker       *stats.transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
1971*d9f75844SAndroid Build Coastguard Worker   // Inbound and remote-outbound.
1972*d9f75844SAndroid Build Coastguard Worker   // The remote-outbound stats are based on RTCP sender reports sent from the
1973*d9f75844SAndroid Build Coastguard Worker   // remote endpoint providing metrics about the remote outbound streams.
1974*d9f75844SAndroid Build Coastguard Worker   for (const cricket::VoiceReceiverInfo& voice_receiver_info :
1975*d9f75844SAndroid Build Coastguard Worker        stats.track_media_info_map.voice_media_info()->receivers) {
1976*d9f75844SAndroid Build Coastguard Worker     if (!voice_receiver_info.connected())
1977*d9f75844SAndroid Build Coastguard Worker       continue;
1978*d9f75844SAndroid Build Coastguard Worker     // Inbound.
1979*d9f75844SAndroid Build Coastguard Worker     auto inbound_audio = CreateInboundAudioStreamStats(
1980*d9f75844SAndroid Build Coastguard Worker         stats.track_media_info_map.voice_media_info().value(),
1981*d9f75844SAndroid Build Coastguard Worker         voice_receiver_info, transport_id, mid, timestamp_us, report);
1982*d9f75844SAndroid Build Coastguard Worker     // TODO(hta): This lookup should look for the sender, not the track.
1983*d9f75844SAndroid Build Coastguard Worker     rtc::scoped_refptr<AudioTrackInterface> audio_track =
1984*d9f75844SAndroid Build Coastguard Worker         stats.track_media_info_map.GetAudioTrack(voice_receiver_info);
1985*d9f75844SAndroid Build Coastguard Worker     if (audio_track) {
1986*d9f75844SAndroid Build Coastguard Worker       inbound_audio->track_id =
1987*d9f75844SAndroid Build Coastguard Worker           DEPRECATED_RTCMediaStreamTrackStatsIDFromDirectionAndAttachment(
1988*d9f75844SAndroid Build Coastguard Worker               kDirectionInbound, stats.track_media_info_map
1989*d9f75844SAndroid Build Coastguard Worker                                      .GetAttachmentIdByTrack(audio_track.get())
1990*d9f75844SAndroid Build Coastguard Worker                                      .value());
1991*d9f75844SAndroid Build Coastguard Worker       inbound_audio->track_identifier = audio_track->id();
1992*d9f75844SAndroid Build Coastguard Worker     }
1993*d9f75844SAndroid Build Coastguard Worker     auto* inbound_audio_ptr = report->TryAddStats(std::move(inbound_audio));
1994*d9f75844SAndroid Build Coastguard Worker     if (!inbound_audio_ptr) {
1995*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_ERROR)
1996*d9f75844SAndroid Build Coastguard Worker           << "Unable to add audio 'inbound-rtp' to report, ID is not unique.";
1997*d9f75844SAndroid Build Coastguard Worker       continue;
1998*d9f75844SAndroid Build Coastguard Worker     }
1999*d9f75844SAndroid Build Coastguard Worker     // Remote-outbound.
2000*d9f75844SAndroid Build Coastguard Worker     auto remote_outbound_audio = CreateRemoteOutboundAudioStreamStats(
2001*d9f75844SAndroid Build Coastguard Worker         voice_receiver_info, mid, *inbound_audio_ptr, transport_id);
2002*d9f75844SAndroid Build Coastguard Worker     // Add stats.
2003*d9f75844SAndroid Build Coastguard Worker     if (remote_outbound_audio) {
2004*d9f75844SAndroid Build Coastguard Worker       // When the remote outbound stats are available, the remote ID for the
2005*d9f75844SAndroid Build Coastguard Worker       // local inbound stats is set.
2006*d9f75844SAndroid Build Coastguard Worker       auto* remote_outbound_audio_ptr =
2007*d9f75844SAndroid Build Coastguard Worker           report->TryAddStats(std::move(remote_outbound_audio));
2008*d9f75844SAndroid Build Coastguard Worker       if (remote_outbound_audio_ptr) {
2009*d9f75844SAndroid Build Coastguard Worker         inbound_audio_ptr->remote_id = remote_outbound_audio_ptr->id();
2010*d9f75844SAndroid Build Coastguard Worker       } else {
2011*d9f75844SAndroid Build Coastguard Worker         RTC_LOG(LS_ERROR) << "Unable to add audio 'remote-outbound-rtp' to "
2012*d9f75844SAndroid Build Coastguard Worker                           << "report, ID is not unique.";
2013*d9f75844SAndroid Build Coastguard Worker       }
2014*d9f75844SAndroid Build Coastguard Worker     }
2015*d9f75844SAndroid Build Coastguard Worker   }
2016*d9f75844SAndroid Build Coastguard Worker   // Outbound.
2017*d9f75844SAndroid Build Coastguard Worker   std::map<std::string, RTCOutboundRTPStreamStats*> audio_outbound_rtps;
2018*d9f75844SAndroid Build Coastguard Worker   for (const cricket::VoiceSenderInfo& voice_sender_info :
2019*d9f75844SAndroid Build Coastguard Worker        stats.track_media_info_map.voice_media_info()->senders) {
2020*d9f75844SAndroid Build Coastguard Worker     if (!voice_sender_info.connected())
2021*d9f75844SAndroid Build Coastguard Worker       continue;
2022*d9f75844SAndroid Build Coastguard Worker     auto outbound_audio = std::make_unique<RTCOutboundRTPStreamStats>(
2023*d9f75844SAndroid Build Coastguard Worker         RTCOutboundRTPStreamStatsIDFromSSRC(
2024*d9f75844SAndroid Build Coastguard Worker             transport_id, cricket::MEDIA_TYPE_AUDIO, voice_sender_info.ssrc()),
2025*d9f75844SAndroid Build Coastguard Worker         timestamp_us);
2026*d9f75844SAndroid Build Coastguard Worker     SetOutboundRTPStreamStatsFromVoiceSenderInfo(
2027*d9f75844SAndroid Build Coastguard Worker         transport_id, mid,
2028*d9f75844SAndroid Build Coastguard Worker         stats.track_media_info_map.voice_media_info().value(),
2029*d9f75844SAndroid Build Coastguard Worker         voice_sender_info, outbound_audio.get(), report);
2030*d9f75844SAndroid Build Coastguard Worker     rtc::scoped_refptr<AudioTrackInterface> audio_track =
2031*d9f75844SAndroid Build Coastguard Worker         stats.track_media_info_map.GetAudioTrack(voice_sender_info);
2032*d9f75844SAndroid Build Coastguard Worker     if (audio_track) {
2033*d9f75844SAndroid Build Coastguard Worker       int attachment_id =
2034*d9f75844SAndroid Build Coastguard Worker           stats.track_media_info_map.GetAttachmentIdByTrack(audio_track.get())
2035*d9f75844SAndroid Build Coastguard Worker               .value();
2036*d9f75844SAndroid Build Coastguard Worker       outbound_audio->track_id =
2037*d9f75844SAndroid Build Coastguard Worker           DEPRECATED_RTCMediaStreamTrackStatsIDFromDirectionAndAttachment(
2038*d9f75844SAndroid Build Coastguard Worker               kDirectionOutbound, attachment_id);
2039*d9f75844SAndroid Build Coastguard Worker       outbound_audio->media_source_id =
2040*d9f75844SAndroid Build Coastguard Worker           RTCMediaSourceStatsIDFromKindAndAttachment(cricket::MEDIA_TYPE_AUDIO,
2041*d9f75844SAndroid Build Coastguard Worker                                                      attachment_id);
2042*d9f75844SAndroid Build Coastguard Worker     }
2043*d9f75844SAndroid Build Coastguard Worker     auto audio_outbound_pair =
2044*d9f75844SAndroid Build Coastguard Worker         std::make_pair(outbound_audio->id(), outbound_audio.get());
2045*d9f75844SAndroid Build Coastguard Worker     if (report->TryAddStats(std::move(outbound_audio))) {
2046*d9f75844SAndroid Build Coastguard Worker       audio_outbound_rtps.insert(std::move(audio_outbound_pair));
2047*d9f75844SAndroid Build Coastguard Worker     } else {
2048*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_ERROR)
2049*d9f75844SAndroid Build Coastguard Worker           << "Unable to add audio 'outbound-rtp' to report, ID is not unique.";
2050*d9f75844SAndroid Build Coastguard Worker     }
2051*d9f75844SAndroid Build Coastguard Worker   }
2052*d9f75844SAndroid Build Coastguard Worker   // Remote-inbound.
2053*d9f75844SAndroid Build Coastguard Worker   // These are Report Block-based, information sent from the remote endpoint,
2054*d9f75844SAndroid Build Coastguard Worker   // providing metrics about our Outbound streams. We take advantage of the fact
2055*d9f75844SAndroid Build Coastguard Worker   // that RTCOutboundRtpStreamStats, RTCCodecStats and RTCTransport have already
2056*d9f75844SAndroid Build Coastguard Worker   // been added to the report.
2057*d9f75844SAndroid Build Coastguard Worker   for (const cricket::VoiceSenderInfo& voice_sender_info :
2058*d9f75844SAndroid Build Coastguard Worker        stats.track_media_info_map.voice_media_info()->senders) {
2059*d9f75844SAndroid Build Coastguard Worker     for (const auto& report_block_data : voice_sender_info.report_block_datas) {
2060*d9f75844SAndroid Build Coastguard Worker       report->AddStats(ProduceRemoteInboundRtpStreamStatsFromReportBlockData(
2061*d9f75844SAndroid Build Coastguard Worker           transport_id, report_block_data, cricket::MEDIA_TYPE_AUDIO,
2062*d9f75844SAndroid Build Coastguard Worker           audio_outbound_rtps, *report));
2063*d9f75844SAndroid Build Coastguard Worker     }
2064*d9f75844SAndroid Build Coastguard Worker   }
2065*d9f75844SAndroid Build Coastguard Worker }
2066*d9f75844SAndroid Build Coastguard Worker 
ProduceVideoRTPStreamStats_n(int64_t timestamp_us,const RtpTransceiverStatsInfo & stats,RTCStatsReport * report) const2067*d9f75844SAndroid Build Coastguard Worker void RTCStatsCollector::ProduceVideoRTPStreamStats_n(
2068*d9f75844SAndroid Build Coastguard Worker     int64_t timestamp_us,
2069*d9f75844SAndroid Build Coastguard Worker     const RtpTransceiverStatsInfo& stats,
2070*d9f75844SAndroid Build Coastguard Worker     RTCStatsReport* report) const {
2071*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(network_thread_);
2072*d9f75844SAndroid Build Coastguard Worker   rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
2073*d9f75844SAndroid Build Coastguard Worker 
2074*d9f75844SAndroid Build Coastguard Worker   if (!stats.mid || !stats.transport_name) {
2075*d9f75844SAndroid Build Coastguard Worker     return;
2076*d9f75844SAndroid Build Coastguard Worker   }
2077*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(stats.track_media_info_map.video_media_info().has_value());
2078*d9f75844SAndroid Build Coastguard Worker   std::string mid = *stats.mid;
2079*d9f75844SAndroid Build Coastguard Worker   std::string transport_id = RTCTransportStatsIDFromTransportChannel(
2080*d9f75844SAndroid Build Coastguard Worker       *stats.transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
2081*d9f75844SAndroid Build Coastguard Worker   // Inbound
2082*d9f75844SAndroid Build Coastguard Worker   for (const cricket::VideoReceiverInfo& video_receiver_info :
2083*d9f75844SAndroid Build Coastguard Worker        stats.track_media_info_map.video_media_info()->receivers) {
2084*d9f75844SAndroid Build Coastguard Worker     if (!video_receiver_info.connected())
2085*d9f75844SAndroid Build Coastguard Worker       continue;
2086*d9f75844SAndroid Build Coastguard Worker     auto inbound_video = std::make_unique<RTCInboundRTPStreamStats>(
2087*d9f75844SAndroid Build Coastguard Worker         RTCInboundRTPStreamStatsIDFromSSRC(transport_id,
2088*d9f75844SAndroid Build Coastguard Worker                                            cricket::MEDIA_TYPE_VIDEO,
2089*d9f75844SAndroid Build Coastguard Worker                                            video_receiver_info.ssrc()),
2090*d9f75844SAndroid Build Coastguard Worker         timestamp_us);
2091*d9f75844SAndroid Build Coastguard Worker     SetInboundRTPStreamStatsFromVideoReceiverInfo(
2092*d9f75844SAndroid Build Coastguard Worker         transport_id, mid,
2093*d9f75844SAndroid Build Coastguard Worker         stats.track_media_info_map.video_media_info().value(),
2094*d9f75844SAndroid Build Coastguard Worker         video_receiver_info, inbound_video.get(), report);
2095*d9f75844SAndroid Build Coastguard Worker     rtc::scoped_refptr<VideoTrackInterface> video_track =
2096*d9f75844SAndroid Build Coastguard Worker         stats.track_media_info_map.GetVideoTrack(video_receiver_info);
2097*d9f75844SAndroid Build Coastguard Worker     if (video_track) {
2098*d9f75844SAndroid Build Coastguard Worker       inbound_video->track_id =
2099*d9f75844SAndroid Build Coastguard Worker           DEPRECATED_RTCMediaStreamTrackStatsIDFromDirectionAndAttachment(
2100*d9f75844SAndroid Build Coastguard Worker               kDirectionInbound, stats.track_media_info_map
2101*d9f75844SAndroid Build Coastguard Worker                                      .GetAttachmentIdByTrack(video_track.get())
2102*d9f75844SAndroid Build Coastguard Worker                                      .value());
2103*d9f75844SAndroid Build Coastguard Worker       inbound_video->track_identifier = video_track->id();
2104*d9f75844SAndroid Build Coastguard Worker     }
2105*d9f75844SAndroid Build Coastguard Worker     if (!report->TryAddStats(std::move(inbound_video))) {
2106*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_ERROR)
2107*d9f75844SAndroid Build Coastguard Worker           << "Unable to add video 'inbound-rtp' to report, ID is not unique.";
2108*d9f75844SAndroid Build Coastguard Worker     }
2109*d9f75844SAndroid Build Coastguard Worker   }
2110*d9f75844SAndroid Build Coastguard Worker   // Outbound
2111*d9f75844SAndroid Build Coastguard Worker   std::map<std::string, RTCOutboundRTPStreamStats*> video_outbound_rtps;
2112*d9f75844SAndroid Build Coastguard Worker   for (const cricket::VideoSenderInfo& video_sender_info :
2113*d9f75844SAndroid Build Coastguard Worker        stats.track_media_info_map.video_media_info()->senders) {
2114*d9f75844SAndroid Build Coastguard Worker     if (!video_sender_info.connected())
2115*d9f75844SAndroid Build Coastguard Worker       continue;
2116*d9f75844SAndroid Build Coastguard Worker     auto outbound_video = std::make_unique<RTCOutboundRTPStreamStats>(
2117*d9f75844SAndroid Build Coastguard Worker         RTCOutboundRTPStreamStatsIDFromSSRC(
2118*d9f75844SAndroid Build Coastguard Worker             transport_id, cricket::MEDIA_TYPE_VIDEO, video_sender_info.ssrc()),
2119*d9f75844SAndroid Build Coastguard Worker         timestamp_us);
2120*d9f75844SAndroid Build Coastguard Worker     SetOutboundRTPStreamStatsFromVideoSenderInfo(
2121*d9f75844SAndroid Build Coastguard Worker         transport_id, mid,
2122*d9f75844SAndroid Build Coastguard Worker         stats.track_media_info_map.video_media_info().value(),
2123*d9f75844SAndroid Build Coastguard Worker         video_sender_info, outbound_video.get(), report);
2124*d9f75844SAndroid Build Coastguard Worker     rtc::scoped_refptr<VideoTrackInterface> video_track =
2125*d9f75844SAndroid Build Coastguard Worker         stats.track_media_info_map.GetVideoTrack(video_sender_info);
2126*d9f75844SAndroid Build Coastguard Worker     if (video_track) {
2127*d9f75844SAndroid Build Coastguard Worker       int attachment_id =
2128*d9f75844SAndroid Build Coastguard Worker           stats.track_media_info_map.GetAttachmentIdByTrack(video_track.get())
2129*d9f75844SAndroid Build Coastguard Worker               .value();
2130*d9f75844SAndroid Build Coastguard Worker       outbound_video->track_id =
2131*d9f75844SAndroid Build Coastguard Worker           DEPRECATED_RTCMediaStreamTrackStatsIDFromDirectionAndAttachment(
2132*d9f75844SAndroid Build Coastguard Worker               kDirectionOutbound, attachment_id);
2133*d9f75844SAndroid Build Coastguard Worker       outbound_video->media_source_id =
2134*d9f75844SAndroid Build Coastguard Worker           RTCMediaSourceStatsIDFromKindAndAttachment(cricket::MEDIA_TYPE_VIDEO,
2135*d9f75844SAndroid Build Coastguard Worker                                                      attachment_id);
2136*d9f75844SAndroid Build Coastguard Worker     }
2137*d9f75844SAndroid Build Coastguard Worker     auto video_outbound_pair =
2138*d9f75844SAndroid Build Coastguard Worker         std::make_pair(outbound_video->id(), outbound_video.get());
2139*d9f75844SAndroid Build Coastguard Worker     if (report->TryAddStats(std::move(outbound_video))) {
2140*d9f75844SAndroid Build Coastguard Worker       video_outbound_rtps.insert(std::move(video_outbound_pair));
2141*d9f75844SAndroid Build Coastguard Worker     } else {
2142*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_ERROR)
2143*d9f75844SAndroid Build Coastguard Worker           << "Unable to add video 'outbound-rtp' to report, ID is not unique.";
2144*d9f75844SAndroid Build Coastguard Worker     }
2145*d9f75844SAndroid Build Coastguard Worker   }
2146*d9f75844SAndroid Build Coastguard Worker   // Remote-inbound
2147*d9f75844SAndroid Build Coastguard Worker   // These are Report Block-based, information sent from the remote endpoint,
2148*d9f75844SAndroid Build Coastguard Worker   // providing metrics about our Outbound streams. We take advantage of the fact
2149*d9f75844SAndroid Build Coastguard Worker   // that RTCOutboundRtpStreamStats, RTCCodecStats and RTCTransport have already
2150*d9f75844SAndroid Build Coastguard Worker   // been added to the report.
2151*d9f75844SAndroid Build Coastguard Worker   for (const cricket::VideoSenderInfo& video_sender_info :
2152*d9f75844SAndroid Build Coastguard Worker        stats.track_media_info_map.video_media_info()->senders) {
2153*d9f75844SAndroid Build Coastguard Worker     for (const auto& report_block_data : video_sender_info.report_block_datas) {
2154*d9f75844SAndroid Build Coastguard Worker       report->AddStats(ProduceRemoteInboundRtpStreamStatsFromReportBlockData(
2155*d9f75844SAndroid Build Coastguard Worker           transport_id, report_block_data, cricket::MEDIA_TYPE_VIDEO,
2156*d9f75844SAndroid Build Coastguard Worker           video_outbound_rtps, *report));
2157*d9f75844SAndroid Build Coastguard Worker     }
2158*d9f75844SAndroid Build Coastguard Worker   }
2159*d9f75844SAndroid Build Coastguard Worker }
2160*d9f75844SAndroid Build Coastguard Worker 
ProduceTransportStats_n(int64_t timestamp_us,const std::map<std::string,cricket::TransportStats> & transport_stats_by_name,const std::map<std::string,CertificateStatsPair> & transport_cert_stats,RTCStatsReport * report) const2161*d9f75844SAndroid Build Coastguard Worker void RTCStatsCollector::ProduceTransportStats_n(
2162*d9f75844SAndroid Build Coastguard Worker     int64_t timestamp_us,
2163*d9f75844SAndroid Build Coastguard Worker     const std::map<std::string, cricket::TransportStats>&
2164*d9f75844SAndroid Build Coastguard Worker         transport_stats_by_name,
2165*d9f75844SAndroid Build Coastguard Worker     const std::map<std::string, CertificateStatsPair>& transport_cert_stats,
2166*d9f75844SAndroid Build Coastguard Worker     RTCStatsReport* report) const {
2167*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(network_thread_);
2168*d9f75844SAndroid Build Coastguard Worker   rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
2169*d9f75844SAndroid Build Coastguard Worker 
2170*d9f75844SAndroid Build Coastguard Worker   for (const auto& entry : transport_stats_by_name) {
2171*d9f75844SAndroid Build Coastguard Worker     const std::string& transport_name = entry.first;
2172*d9f75844SAndroid Build Coastguard Worker     const cricket::TransportStats& transport_stats = entry.second;
2173*d9f75844SAndroid Build Coastguard Worker 
2174*d9f75844SAndroid Build Coastguard Worker     // Get reference to RTCP channel, if it exists.
2175*d9f75844SAndroid Build Coastguard Worker     std::string rtcp_transport_stats_id;
2176*d9f75844SAndroid Build Coastguard Worker     for (const cricket::TransportChannelStats& channel_stats :
2177*d9f75844SAndroid Build Coastguard Worker          transport_stats.channel_stats) {
2178*d9f75844SAndroid Build Coastguard Worker       if (channel_stats.component == cricket::ICE_CANDIDATE_COMPONENT_RTCP) {
2179*d9f75844SAndroid Build Coastguard Worker         rtcp_transport_stats_id = RTCTransportStatsIDFromTransportChannel(
2180*d9f75844SAndroid Build Coastguard Worker             transport_name, channel_stats.component);
2181*d9f75844SAndroid Build Coastguard Worker         break;
2182*d9f75844SAndroid Build Coastguard Worker       }
2183*d9f75844SAndroid Build Coastguard Worker     }
2184*d9f75844SAndroid Build Coastguard Worker 
2185*d9f75844SAndroid Build Coastguard Worker     // Get reference to local and remote certificates of this transport, if they
2186*d9f75844SAndroid Build Coastguard Worker     // exist.
2187*d9f75844SAndroid Build Coastguard Worker     const auto& certificate_stats_it =
2188*d9f75844SAndroid Build Coastguard Worker         transport_cert_stats.find(transport_name);
2189*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(certificate_stats_it != transport_cert_stats.cend());
2190*d9f75844SAndroid Build Coastguard Worker     std::string local_certificate_id;
2191*d9f75844SAndroid Build Coastguard Worker     if (certificate_stats_it->second.local) {
2192*d9f75844SAndroid Build Coastguard Worker       local_certificate_id = RTCCertificateIDFromFingerprint(
2193*d9f75844SAndroid Build Coastguard Worker           certificate_stats_it->second.local->fingerprint);
2194*d9f75844SAndroid Build Coastguard Worker     }
2195*d9f75844SAndroid Build Coastguard Worker     std::string remote_certificate_id;
2196*d9f75844SAndroid Build Coastguard Worker     if (certificate_stats_it->second.remote) {
2197*d9f75844SAndroid Build Coastguard Worker       remote_certificate_id = RTCCertificateIDFromFingerprint(
2198*d9f75844SAndroid Build Coastguard Worker           certificate_stats_it->second.remote->fingerprint);
2199*d9f75844SAndroid Build Coastguard Worker     }
2200*d9f75844SAndroid Build Coastguard Worker 
2201*d9f75844SAndroid Build Coastguard Worker     // There is one transport stats for each channel.
2202*d9f75844SAndroid Build Coastguard Worker     for (const cricket::TransportChannelStats& channel_stats :
2203*d9f75844SAndroid Build Coastguard Worker          transport_stats.channel_stats) {
2204*d9f75844SAndroid Build Coastguard Worker       std::unique_ptr<RTCTransportStats> transport_stats(
2205*d9f75844SAndroid Build Coastguard Worker           std::make_unique<RTCTransportStats>(
2206*d9f75844SAndroid Build Coastguard Worker               RTCTransportStatsIDFromTransportChannel(transport_name,
2207*d9f75844SAndroid Build Coastguard Worker                                                       channel_stats.component),
2208*d9f75844SAndroid Build Coastguard Worker               timestamp_us));
2209*d9f75844SAndroid Build Coastguard Worker       transport_stats->packets_sent =
2210*d9f75844SAndroid Build Coastguard Worker           channel_stats.ice_transport_stats.packets_sent;
2211*d9f75844SAndroid Build Coastguard Worker       transport_stats->packets_received =
2212*d9f75844SAndroid Build Coastguard Worker           channel_stats.ice_transport_stats.packets_received;
2213*d9f75844SAndroid Build Coastguard Worker       transport_stats->bytes_sent =
2214*d9f75844SAndroid Build Coastguard Worker           channel_stats.ice_transport_stats.bytes_sent;
2215*d9f75844SAndroid Build Coastguard Worker       transport_stats->bytes_received =
2216*d9f75844SAndroid Build Coastguard Worker           channel_stats.ice_transport_stats.bytes_received;
2217*d9f75844SAndroid Build Coastguard Worker       transport_stats->dtls_state =
2218*d9f75844SAndroid Build Coastguard Worker           DtlsTransportStateToRTCDtlsTransportState(channel_stats.dtls_state);
2219*d9f75844SAndroid Build Coastguard Worker       transport_stats->selected_candidate_pair_changes =
2220*d9f75844SAndroid Build Coastguard Worker           channel_stats.ice_transport_stats.selected_candidate_pair_changes;
2221*d9f75844SAndroid Build Coastguard Worker       transport_stats->ice_role =
2222*d9f75844SAndroid Build Coastguard Worker           IceRoleToRTCIceRole(channel_stats.ice_transport_stats.ice_role);
2223*d9f75844SAndroid Build Coastguard Worker       transport_stats->ice_local_username_fragment =
2224*d9f75844SAndroid Build Coastguard Worker           channel_stats.ice_transport_stats.ice_local_username_fragment;
2225*d9f75844SAndroid Build Coastguard Worker       transport_stats->ice_state = IceTransportStateToRTCIceTransportState(
2226*d9f75844SAndroid Build Coastguard Worker           channel_stats.ice_transport_stats.ice_state);
2227*d9f75844SAndroid Build Coastguard Worker       for (const cricket::ConnectionInfo& info :
2228*d9f75844SAndroid Build Coastguard Worker            channel_stats.ice_transport_stats.connection_infos) {
2229*d9f75844SAndroid Build Coastguard Worker         if (info.best_connection) {
2230*d9f75844SAndroid Build Coastguard Worker           transport_stats->selected_candidate_pair_id =
2231*d9f75844SAndroid Build Coastguard Worker               RTCIceCandidatePairStatsIDFromConnectionInfo(info);
2232*d9f75844SAndroid Build Coastguard Worker         }
2233*d9f75844SAndroid Build Coastguard Worker       }
2234*d9f75844SAndroid Build Coastguard Worker       if (channel_stats.component != cricket::ICE_CANDIDATE_COMPONENT_RTCP &&
2235*d9f75844SAndroid Build Coastguard Worker           !rtcp_transport_stats_id.empty()) {
2236*d9f75844SAndroid Build Coastguard Worker         transport_stats->rtcp_transport_stats_id = rtcp_transport_stats_id;
2237*d9f75844SAndroid Build Coastguard Worker       }
2238*d9f75844SAndroid Build Coastguard Worker       if (!local_certificate_id.empty())
2239*d9f75844SAndroid Build Coastguard Worker         transport_stats->local_certificate_id = local_certificate_id;
2240*d9f75844SAndroid Build Coastguard Worker       if (!remote_certificate_id.empty())
2241*d9f75844SAndroid Build Coastguard Worker         transport_stats->remote_certificate_id = remote_certificate_id;
2242*d9f75844SAndroid Build Coastguard Worker       // Crypto information
2243*d9f75844SAndroid Build Coastguard Worker       if (channel_stats.ssl_version_bytes) {
2244*d9f75844SAndroid Build Coastguard Worker         char bytes[5];
2245*d9f75844SAndroid Build Coastguard Worker         snprintf(bytes, sizeof(bytes), "%04X", channel_stats.ssl_version_bytes);
2246*d9f75844SAndroid Build Coastguard Worker         transport_stats->tls_version = bytes;
2247*d9f75844SAndroid Build Coastguard Worker       }
2248*d9f75844SAndroid Build Coastguard Worker 
2249*d9f75844SAndroid Build Coastguard Worker       if (channel_stats.dtls_role) {
2250*d9f75844SAndroid Build Coastguard Worker         transport_stats->dtls_role = *channel_stats.dtls_role == rtc::SSL_CLIENT
2251*d9f75844SAndroid Build Coastguard Worker                                          ? webrtc::RTCDtlsRole::kClient
2252*d9f75844SAndroid Build Coastguard Worker                                          : webrtc::RTCDtlsRole::kServer;
2253*d9f75844SAndroid Build Coastguard Worker       } else {
2254*d9f75844SAndroid Build Coastguard Worker         transport_stats->dtls_role = webrtc::RTCDtlsRole::kUnknown;
2255*d9f75844SAndroid Build Coastguard Worker       }
2256*d9f75844SAndroid Build Coastguard Worker 
2257*d9f75844SAndroid Build Coastguard Worker       if (channel_stats.ssl_cipher_suite != rtc::kTlsNullWithNullNull &&
2258*d9f75844SAndroid Build Coastguard Worker           rtc::SSLStreamAdapter::SslCipherSuiteToName(
2259*d9f75844SAndroid Build Coastguard Worker               channel_stats.ssl_cipher_suite)
2260*d9f75844SAndroid Build Coastguard Worker               .length()) {
2261*d9f75844SAndroid Build Coastguard Worker         transport_stats->dtls_cipher =
2262*d9f75844SAndroid Build Coastguard Worker             rtc::SSLStreamAdapter::SslCipherSuiteToName(
2263*d9f75844SAndroid Build Coastguard Worker                 channel_stats.ssl_cipher_suite);
2264*d9f75844SAndroid Build Coastguard Worker       }
2265*d9f75844SAndroid Build Coastguard Worker       if (channel_stats.srtp_crypto_suite != rtc::kSrtpInvalidCryptoSuite &&
2266*d9f75844SAndroid Build Coastguard Worker           rtc::SrtpCryptoSuiteToName(channel_stats.srtp_crypto_suite)
2267*d9f75844SAndroid Build Coastguard Worker               .length()) {
2268*d9f75844SAndroid Build Coastguard Worker         transport_stats->srtp_cipher =
2269*d9f75844SAndroid Build Coastguard Worker             rtc::SrtpCryptoSuiteToName(channel_stats.srtp_crypto_suite);
2270*d9f75844SAndroid Build Coastguard Worker       }
2271*d9f75844SAndroid Build Coastguard Worker       report->AddStats(std::move(transport_stats));
2272*d9f75844SAndroid Build Coastguard Worker     }
2273*d9f75844SAndroid Build Coastguard Worker   }
2274*d9f75844SAndroid Build Coastguard Worker }
2275*d9f75844SAndroid Build Coastguard Worker 
2276*d9f75844SAndroid Build Coastguard Worker std::map<std::string, RTCStatsCollector::CertificateStatsPair>
PrepareTransportCertificateStats_n(const std::map<std::string,cricket::TransportStats> & transport_stats_by_name)2277*d9f75844SAndroid Build Coastguard Worker RTCStatsCollector::PrepareTransportCertificateStats_n(
2278*d9f75844SAndroid Build Coastguard Worker     const std::map<std::string, cricket::TransportStats>&
2279*d9f75844SAndroid Build Coastguard Worker         transport_stats_by_name) {
2280*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(network_thread_);
2281*d9f75844SAndroid Build Coastguard Worker   rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
2282*d9f75844SAndroid Build Coastguard Worker 
2283*d9f75844SAndroid Build Coastguard Worker   std::map<std::string, CertificateStatsPair> transport_cert_stats;
2284*d9f75844SAndroid Build Coastguard Worker   {
2285*d9f75844SAndroid Build Coastguard Worker     MutexLock lock(&cached_certificates_mutex_);
2286*d9f75844SAndroid Build Coastguard Worker     // Copy the certificate info from the cache, avoiding expensive
2287*d9f75844SAndroid Build Coastguard Worker     // rtc::SSLCertChain::GetStats() calls.
2288*d9f75844SAndroid Build Coastguard Worker     for (const auto& pair : cached_certificates_by_transport_) {
2289*d9f75844SAndroid Build Coastguard Worker       transport_cert_stats.insert(
2290*d9f75844SAndroid Build Coastguard Worker           std::make_pair(pair.first, pair.second.Copy()));
2291*d9f75844SAndroid Build Coastguard Worker     }
2292*d9f75844SAndroid Build Coastguard Worker   }
2293*d9f75844SAndroid Build Coastguard Worker   if (transport_cert_stats.empty()) {
2294*d9f75844SAndroid Build Coastguard Worker     // Collect certificate info.
2295*d9f75844SAndroid Build Coastguard Worker     for (const auto& entry : transport_stats_by_name) {
2296*d9f75844SAndroid Build Coastguard Worker       const std::string& transport_name = entry.first;
2297*d9f75844SAndroid Build Coastguard Worker 
2298*d9f75844SAndroid Build Coastguard Worker       CertificateStatsPair certificate_stats_pair;
2299*d9f75844SAndroid Build Coastguard Worker       rtc::scoped_refptr<rtc::RTCCertificate> local_certificate;
2300*d9f75844SAndroid Build Coastguard Worker       if (pc_->GetLocalCertificate(transport_name, &local_certificate)) {
2301*d9f75844SAndroid Build Coastguard Worker         certificate_stats_pair.local =
2302*d9f75844SAndroid Build Coastguard Worker             local_certificate->GetSSLCertificateChain().GetStats();
2303*d9f75844SAndroid Build Coastguard Worker       }
2304*d9f75844SAndroid Build Coastguard Worker 
2305*d9f75844SAndroid Build Coastguard Worker       std::unique_ptr<rtc::SSLCertChain> remote_cert_chain =
2306*d9f75844SAndroid Build Coastguard Worker           pc_->GetRemoteSSLCertChain(transport_name);
2307*d9f75844SAndroid Build Coastguard Worker       if (remote_cert_chain) {
2308*d9f75844SAndroid Build Coastguard Worker         certificate_stats_pair.remote = remote_cert_chain->GetStats();
2309*d9f75844SAndroid Build Coastguard Worker       }
2310*d9f75844SAndroid Build Coastguard Worker 
2311*d9f75844SAndroid Build Coastguard Worker       transport_cert_stats.insert(
2312*d9f75844SAndroid Build Coastguard Worker           std::make_pair(transport_name, std::move(certificate_stats_pair)));
2313*d9f75844SAndroid Build Coastguard Worker     }
2314*d9f75844SAndroid Build Coastguard Worker     // Copy the result into the certificate cache for future reference.
2315*d9f75844SAndroid Build Coastguard Worker     MutexLock lock(&cached_certificates_mutex_);
2316*d9f75844SAndroid Build Coastguard Worker     for (const auto& pair : transport_cert_stats) {
2317*d9f75844SAndroid Build Coastguard Worker       cached_certificates_by_transport_.insert(
2318*d9f75844SAndroid Build Coastguard Worker           std::make_pair(pair.first, pair.second.Copy()));
2319*d9f75844SAndroid Build Coastguard Worker     }
2320*d9f75844SAndroid Build Coastguard Worker   }
2321*d9f75844SAndroid Build Coastguard Worker   return transport_cert_stats;
2322*d9f75844SAndroid Build Coastguard Worker }
2323*d9f75844SAndroid Build Coastguard Worker 
PrepareTransceiverStatsInfosAndCallStats_s_w_n()2324*d9f75844SAndroid Build Coastguard Worker void RTCStatsCollector::PrepareTransceiverStatsInfosAndCallStats_s_w_n() {
2325*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(signaling_thread_);
2326*d9f75844SAndroid Build Coastguard Worker 
2327*d9f75844SAndroid Build Coastguard Worker   transceiver_stats_infos_.clear();
2328*d9f75844SAndroid Build Coastguard Worker   // These are used to invoke GetStats for all the media channels together in
2329*d9f75844SAndroid Build Coastguard Worker   // one worker thread hop.
2330*d9f75844SAndroid Build Coastguard Worker   std::map<cricket::VoiceMediaChannel*, cricket::VoiceMediaInfo> voice_stats;
2331*d9f75844SAndroid Build Coastguard Worker   std::map<cricket::VideoMediaChannel*, cricket::VideoMediaInfo> video_stats;
2332*d9f75844SAndroid Build Coastguard Worker 
2333*d9f75844SAndroid Build Coastguard Worker   auto transceivers = pc_->GetTransceiversInternal();
2334*d9f75844SAndroid Build Coastguard Worker 
2335*d9f75844SAndroid Build Coastguard Worker   // TODO(tommi): See if we can avoid synchronously blocking the signaling
2336*d9f75844SAndroid Build Coastguard Worker   // thread while we do this (or avoid the BlockingCall at all).
2337*d9f75844SAndroid Build Coastguard Worker   network_thread_->BlockingCall([this, &transceivers, &voice_stats,
2338*d9f75844SAndroid Build Coastguard Worker                                  &video_stats] {
2339*d9f75844SAndroid Build Coastguard Worker     rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
2340*d9f75844SAndroid Build Coastguard Worker 
2341*d9f75844SAndroid Build Coastguard Worker     for (const auto& transceiver_proxy : transceivers) {
2342*d9f75844SAndroid Build Coastguard Worker       RtpTransceiver* transceiver = transceiver_proxy->internal();
2343*d9f75844SAndroid Build Coastguard Worker       cricket::MediaType media_type = transceiver->media_type();
2344*d9f75844SAndroid Build Coastguard Worker 
2345*d9f75844SAndroid Build Coastguard Worker       // Prepare stats entry. The TrackMediaInfoMap will be filled in after the
2346*d9f75844SAndroid Build Coastguard Worker       // stats have been fetched on the worker thread.
2347*d9f75844SAndroid Build Coastguard Worker       transceiver_stats_infos_.emplace_back();
2348*d9f75844SAndroid Build Coastguard Worker       RtpTransceiverStatsInfo& stats = transceiver_stats_infos_.back();
2349*d9f75844SAndroid Build Coastguard Worker       stats.transceiver = transceiver;
2350*d9f75844SAndroid Build Coastguard Worker       stats.media_type = media_type;
2351*d9f75844SAndroid Build Coastguard Worker 
2352*d9f75844SAndroid Build Coastguard Worker       cricket::ChannelInterface* channel = transceiver->channel();
2353*d9f75844SAndroid Build Coastguard Worker       if (!channel) {
2354*d9f75844SAndroid Build Coastguard Worker         // The remaining fields require a BaseChannel.
2355*d9f75844SAndroid Build Coastguard Worker         continue;
2356*d9f75844SAndroid Build Coastguard Worker       }
2357*d9f75844SAndroid Build Coastguard Worker 
2358*d9f75844SAndroid Build Coastguard Worker       stats.mid = channel->mid();
2359*d9f75844SAndroid Build Coastguard Worker       stats.transport_name = std::string(channel->transport_name());
2360*d9f75844SAndroid Build Coastguard Worker 
2361*d9f75844SAndroid Build Coastguard Worker       if (media_type == cricket::MEDIA_TYPE_AUDIO) {
2362*d9f75844SAndroid Build Coastguard Worker         cricket::VoiceMediaChannel* voice_channel =
2363*d9f75844SAndroid Build Coastguard Worker             static_cast<cricket::VoiceMediaChannel*>(channel->media_channel());
2364*d9f75844SAndroid Build Coastguard Worker         RTC_DCHECK(voice_stats.find(voice_channel) == voice_stats.end());
2365*d9f75844SAndroid Build Coastguard Worker         voice_stats.insert(
2366*d9f75844SAndroid Build Coastguard Worker             std::make_pair(voice_channel, cricket::VoiceMediaInfo()));
2367*d9f75844SAndroid Build Coastguard Worker       } else if (media_type == cricket::MEDIA_TYPE_VIDEO) {
2368*d9f75844SAndroid Build Coastguard Worker         cricket::VideoMediaChannel* video_channel =
2369*d9f75844SAndroid Build Coastguard Worker             static_cast<cricket::VideoMediaChannel*>(channel->media_channel());
2370*d9f75844SAndroid Build Coastguard Worker         RTC_DCHECK(video_stats.find(video_channel) == video_stats.end());
2371*d9f75844SAndroid Build Coastguard Worker         video_stats.insert(
2372*d9f75844SAndroid Build Coastguard Worker             std::make_pair(video_channel, cricket::VideoMediaInfo()));
2373*d9f75844SAndroid Build Coastguard Worker       } else {
2374*d9f75844SAndroid Build Coastguard Worker         RTC_DCHECK_NOTREACHED();
2375*d9f75844SAndroid Build Coastguard Worker       }
2376*d9f75844SAndroid Build Coastguard Worker     }
2377*d9f75844SAndroid Build Coastguard Worker   });
2378*d9f75844SAndroid Build Coastguard Worker 
2379*d9f75844SAndroid Build Coastguard Worker   // We jump to the worker thread and call GetStats() on each media channel as
2380*d9f75844SAndroid Build Coastguard Worker   // well as GetCallStats(). At the same time we construct the
2381*d9f75844SAndroid Build Coastguard Worker   // TrackMediaInfoMaps, which also needs info from the worker thread. This
2382*d9f75844SAndroid Build Coastguard Worker   // minimizes the number of thread jumps.
2383*d9f75844SAndroid Build Coastguard Worker   worker_thread_->BlockingCall([&] {
2384*d9f75844SAndroid Build Coastguard Worker     rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
2385*d9f75844SAndroid Build Coastguard Worker 
2386*d9f75844SAndroid Build Coastguard Worker     for (auto& pair : voice_stats) {
2387*d9f75844SAndroid Build Coastguard Worker       if (!pair.first->GetStats(&pair.second,
2388*d9f75844SAndroid Build Coastguard Worker                                 /*get_and_clear_legacy_stats=*/false)) {
2389*d9f75844SAndroid Build Coastguard Worker         RTC_LOG(LS_WARNING) << "Failed to get voice stats.";
2390*d9f75844SAndroid Build Coastguard Worker       }
2391*d9f75844SAndroid Build Coastguard Worker     }
2392*d9f75844SAndroid Build Coastguard Worker     for (auto& pair : video_stats) {
2393*d9f75844SAndroid Build Coastguard Worker       if (!pair.first->GetStats(&pair.second)) {
2394*d9f75844SAndroid Build Coastguard Worker         RTC_LOG(LS_WARNING) << "Failed to get video stats.";
2395*d9f75844SAndroid Build Coastguard Worker       }
2396*d9f75844SAndroid Build Coastguard Worker     }
2397*d9f75844SAndroid Build Coastguard Worker 
2398*d9f75844SAndroid Build Coastguard Worker     // Create the TrackMediaInfoMap for each transceiver stats object.
2399*d9f75844SAndroid Build Coastguard Worker     for (auto& stats : transceiver_stats_infos_) {
2400*d9f75844SAndroid Build Coastguard Worker       auto transceiver = stats.transceiver;
2401*d9f75844SAndroid Build Coastguard Worker       absl::optional<cricket::VoiceMediaInfo> voice_media_info;
2402*d9f75844SAndroid Build Coastguard Worker       absl::optional<cricket::VideoMediaInfo> video_media_info;
2403*d9f75844SAndroid Build Coastguard Worker       auto channel = transceiver->channel();
2404*d9f75844SAndroid Build Coastguard Worker       if (channel) {
2405*d9f75844SAndroid Build Coastguard Worker         cricket::MediaType media_type = transceiver->media_type();
2406*d9f75844SAndroid Build Coastguard Worker         if (media_type == cricket::MEDIA_TYPE_AUDIO) {
2407*d9f75844SAndroid Build Coastguard Worker           cricket::VoiceMediaChannel* voice_channel =
2408*d9f75844SAndroid Build Coastguard Worker               static_cast<cricket::VoiceMediaChannel*>(
2409*d9f75844SAndroid Build Coastguard Worker                   channel->media_channel());
2410*d9f75844SAndroid Build Coastguard Worker           RTC_DCHECK(voice_stats.find(voice_channel) != voice_stats.end());
2411*d9f75844SAndroid Build Coastguard Worker           voice_media_info = std::move(voice_stats[voice_channel]);
2412*d9f75844SAndroid Build Coastguard Worker         } else if (media_type == cricket::MEDIA_TYPE_VIDEO) {
2413*d9f75844SAndroid Build Coastguard Worker           cricket::VideoMediaChannel* video_channel =
2414*d9f75844SAndroid Build Coastguard Worker               static_cast<cricket::VideoMediaChannel*>(
2415*d9f75844SAndroid Build Coastguard Worker                   channel->media_channel());
2416*d9f75844SAndroid Build Coastguard Worker           RTC_DCHECK(video_stats.find(video_channel) != video_stats.end());
2417*d9f75844SAndroid Build Coastguard Worker           video_media_info = std::move(video_stats[video_channel]);
2418*d9f75844SAndroid Build Coastguard Worker         }
2419*d9f75844SAndroid Build Coastguard Worker       }
2420*d9f75844SAndroid Build Coastguard Worker       std::vector<rtc::scoped_refptr<RtpSenderInternal>> senders;
2421*d9f75844SAndroid Build Coastguard Worker       for (const auto& sender : transceiver->senders()) {
2422*d9f75844SAndroid Build Coastguard Worker         senders.push_back(
2423*d9f75844SAndroid Build Coastguard Worker             rtc::scoped_refptr<RtpSenderInternal>(sender->internal()));
2424*d9f75844SAndroid Build Coastguard Worker       }
2425*d9f75844SAndroid Build Coastguard Worker       std::vector<rtc::scoped_refptr<RtpReceiverInternal>> receivers;
2426*d9f75844SAndroid Build Coastguard Worker       for (const auto& receiver : transceiver->receivers()) {
2427*d9f75844SAndroid Build Coastguard Worker         receivers.push_back(
2428*d9f75844SAndroid Build Coastguard Worker             rtc::scoped_refptr<RtpReceiverInternal>(receiver->internal()));
2429*d9f75844SAndroid Build Coastguard Worker       }
2430*d9f75844SAndroid Build Coastguard Worker       stats.track_media_info_map.Initialize(std::move(voice_media_info),
2431*d9f75844SAndroid Build Coastguard Worker                                             std::move(video_media_info),
2432*d9f75844SAndroid Build Coastguard Worker                                             senders, receivers);
2433*d9f75844SAndroid Build Coastguard Worker     }
2434*d9f75844SAndroid Build Coastguard Worker 
2435*d9f75844SAndroid Build Coastguard Worker     call_stats_ = pc_->GetCallStats();
2436*d9f75844SAndroid Build Coastguard Worker   });
2437*d9f75844SAndroid Build Coastguard Worker }
2438*d9f75844SAndroid Build Coastguard Worker 
OnSctpDataChannelCreated(SctpDataChannel * channel)2439*d9f75844SAndroid Build Coastguard Worker void RTCStatsCollector::OnSctpDataChannelCreated(SctpDataChannel* channel) {
2440*d9f75844SAndroid Build Coastguard Worker   channel->SignalOpened.connect(this, &RTCStatsCollector::OnDataChannelOpened);
2441*d9f75844SAndroid Build Coastguard Worker   channel->SignalClosed.connect(this, &RTCStatsCollector::OnDataChannelClosed);
2442*d9f75844SAndroid Build Coastguard Worker }
2443*d9f75844SAndroid Build Coastguard Worker 
OnDataChannelOpened(DataChannelInterface * channel)2444*d9f75844SAndroid Build Coastguard Worker void RTCStatsCollector::OnDataChannelOpened(DataChannelInterface* channel) {
2445*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(signaling_thread_);
2446*d9f75844SAndroid Build Coastguard Worker   bool result = internal_record_.opened_data_channels
2447*d9f75844SAndroid Build Coastguard Worker                     .insert(reinterpret_cast<uintptr_t>(channel))
2448*d9f75844SAndroid Build Coastguard Worker                     .second;
2449*d9f75844SAndroid Build Coastguard Worker   ++internal_record_.data_channels_opened;
2450*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(result);
2451*d9f75844SAndroid Build Coastguard Worker }
2452*d9f75844SAndroid Build Coastguard Worker 
OnDataChannelClosed(DataChannelInterface * channel)2453*d9f75844SAndroid Build Coastguard Worker void RTCStatsCollector::OnDataChannelClosed(DataChannelInterface* channel) {
2454*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(signaling_thread_);
2455*d9f75844SAndroid Build Coastguard Worker   // Only channels that have been fully opened (and have increased the
2456*d9f75844SAndroid Build Coastguard Worker   // `data_channels_opened_` counter) increase the closed counter.
2457*d9f75844SAndroid Build Coastguard Worker   if (internal_record_.opened_data_channels.erase(
2458*d9f75844SAndroid Build Coastguard Worker           reinterpret_cast<uintptr_t>(channel))) {
2459*d9f75844SAndroid Build Coastguard Worker     ++internal_record_.data_channels_closed;
2460*d9f75844SAndroid Build Coastguard Worker   }
2461*d9f75844SAndroid Build Coastguard Worker }
2462*d9f75844SAndroid Build Coastguard Worker 
CandidateTypeToRTCIceCandidateTypeForTesting(const std::string & type)2463*d9f75844SAndroid Build Coastguard Worker const char* CandidateTypeToRTCIceCandidateTypeForTesting(
2464*d9f75844SAndroid Build Coastguard Worker     const std::string& type) {
2465*d9f75844SAndroid Build Coastguard Worker   return CandidateTypeToRTCIceCandidateType(type);
2466*d9f75844SAndroid Build Coastguard Worker }
2467*d9f75844SAndroid Build Coastguard Worker 
DataStateToRTCDataChannelStateForTesting(DataChannelInterface::DataState state)2468*d9f75844SAndroid Build Coastguard Worker const char* DataStateToRTCDataChannelStateForTesting(
2469*d9f75844SAndroid Build Coastguard Worker     DataChannelInterface::DataState state) {
2470*d9f75844SAndroid Build Coastguard Worker   return DataStateToRTCDataChannelState(state);
2471*d9f75844SAndroid Build Coastguard Worker }
2472*d9f75844SAndroid Build Coastguard Worker 
2473*d9f75844SAndroid Build Coastguard Worker }  // namespace webrtc
2474