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