blob: 8ea13cfb5bc0b5a24db82102a0fd0498d31fbb7d [file] [log] [blame]
hbosd565b732016-08-30 21:04:351/*
2 * Copyright 2016 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Jonas Olssona4d87372019-07-05 17:08:3311#include "pc/rtc_stats_collector.h"
12
Harald Alvestrandc24a2182022-02-23 13:44:5913#include <stddef.h>
14#include <stdint.h>
Henrik Boström883eefc2019-05-27 11:40:2515
16#include <algorithm>
hbos9e302742017-01-20 10:47:1017#include <initializer_list>
hbosd565b732016-08-30 21:04:3518#include <memory>
hbosda389e32016-10-25 17:55:0819#include <ostream>
hbosd565b732016-08-30 21:04:3520#include <string>
Harald Alvestrandc24a2182022-02-23 13:44:5921#include <type_traits>
Steve Anton36b29d12017-10-30 16:57:4222#include <utility>
hbosd565b732016-08-30 21:04:3523#include <vector>
24
Steve Anton1c9c9fc2019-02-14 23:13:0925#include "absl/strings/str_replace.h"
Harald Alvestrandc24a2182022-02-23 13:44:5926#include "api/candidate.h"
Mirko Bonadei9f6808b2021-05-21 18:46:0927#include "api/dtls_transport_interface.h"
Harald Alvestrandc24a2182022-02-23 13:44:5928#include "api/media_stream_interface.h"
Harald Alvestrand9cb42c82020-10-11 13:03:4729#include "api/media_stream_track.h"
Steve Anton10542f22019-01-11 17:11:0030#include "api/rtp_parameters.h"
Harald Alvestrandc24a2182022-02-23 13:44:5931#include "api/stats/rtc_stats.h"
Steve Anton10542f22019-01-11 17:11:0032#include "api/stats/rtc_stats_report.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3133#include "api/stats/rtcstats_objects.h"
Sebastian Jansson5f83cf02018-05-08 12:52:2234#include "api/units/time_delta.h"
Harald Alvestrandc24a2182022-02-23 13:44:5935#include "api/units/timestamp.h"
36#include "api/video/recordable_encoded_frame.h"
37#include "api/video/video_content_type.h"
38#include "api/video/video_frame.h"
39#include "api/video/video_sink_interface.h"
40#include "api/video/video_source_interface.h"
41#include "common_video/include/quality_limitation_reason.h"
42#include "media/base/media_channel.h"
43#include "modules/audio_processing/include/audio_processing_statistics.h"
Henrik Boström883eefc2019-05-27 11:40:2544#include "modules/rtp_rtcp/include/report_block_data.h"
45#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
Harald Alvestrandc24a2182022-02-23 13:44:5946#include "p2p/base/connection_info.h"
47#include "p2p/base/ice_transport_internal.h"
Steve Anton10542f22019-01-11 17:11:0048#include "p2p/base/p2p_constants.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3149#include "p2p/base/port.h"
Steve Anton10542f22019-01-11 17:11:0050#include "pc/media_stream.h"
Harald Alvestrandc24a2182022-02-23 13:44:5951#include "pc/stream_collection.h"
Harald Alvestrand9e5aeb92022-05-11 09:35:3652#include "pc/test/fake_data_channel_controller.h"
Steve Anton10542f22019-01-11 17:11:0053#include "pc/test/fake_peer_connection_for_stats.h"
54#include "pc/test/mock_data_channel.h"
55#include "pc/test/mock_rtp_receiver_internal.h"
56#include "pc/test/mock_rtp_sender_internal.h"
57#include "pc/test/rtc_stats_obtainer.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3158#include "rtc_base/checks.h"
Steve Anton10542f22019-01-11 17:11:0059#include "rtc_base/fake_clock.h"
60#include "rtc_base/fake_ssl_identity.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3161#include "rtc_base/gunit.h"
Harald Alvestrandc24a2182022-02-23 13:44:5962#include "rtc_base/network_constants.h"
63#include "rtc_base/ref_counted_object.h"
64#include "rtc_base/rtc_certificate.h"
65#include "rtc_base/socket_address.h"
66#include "rtc_base/ssl_fingerprint.h"
67#include "rtc_base/ssl_identity.h"
68#include "rtc_base/ssl_stream_adapter.h"
69#include "rtc_base/string_encode.h"
Harald Alvestrand910cdc22020-01-09 11:58:2370#include "rtc_base/strings/json.h"
Markus Handell6fcd0f82020-07-07 17:08:5371#include "rtc_base/synchronization/mutex.h"
Steve Anton10542f22019-01-11 17:11:0072#include "rtc_base/time_utils.h"
Harald Alvestrandc24a2182022-02-23 13:44:5973#include "test/gmock.h"
74#include "test/gtest.h"
hbosd565b732016-08-30 21:04:3575
Alessio Bazzica049e6112021-03-18 11:55:1176using ::testing::_;
Mirko Bonadei6a489f22019-04-09 13:11:1277using ::testing::AtLeast;
78using ::testing::Invoke;
79using ::testing::Return;
hbosd565b732016-08-30 21:04:3580
81namespace webrtc {
82
Artem Titov880fa812021-07-30 20:30:2383// These are used by gtest code, such as if `EXPECT_EQ` fails.
hbosda389e32016-10-25 17:55:0884void PrintTo(const RTCCertificateStats& stats, ::std::ostream* os) {
ehmaldonado35a872c2017-07-28 14:29:1285 *os << stats.ToJson();
hbosda389e32016-10-25 17:55:0886}
87
hbos0adb8282016-11-23 10:32:0688void PrintTo(const RTCCodecStats& stats, ::std::ostream* os) {
ehmaldonado35a872c2017-07-28 14:29:1289 *os << stats.ToJson();
hbos0adb8282016-11-23 10:32:0690}
91
hbosda389e32016-10-25 17:55:0892void PrintTo(const RTCDataChannelStats& stats, ::std::ostream* os) {
ehmaldonado35a872c2017-07-28 14:29:1293 *os << stats.ToJson();
hbosda389e32016-10-25 17:55:0894}
95
96void PrintTo(const RTCIceCandidatePairStats& stats, ::std::ostream* os) {
ehmaldonado35a872c2017-07-28 14:29:1297 *os << stats.ToJson();
hbosda389e32016-10-25 17:55:0898}
99
100void PrintTo(const RTCLocalIceCandidateStats& stats, ::std::ostream* os) {
ehmaldonado35a872c2017-07-28 14:29:12101 *os << stats.ToJson();
hbosda389e32016-10-25 17:55:08102}
103
104void PrintTo(const RTCRemoteIceCandidateStats& stats, ::std::ostream* os) {
ehmaldonado35a872c2017-07-28 14:29:12105 *os << stats.ToJson();
hbosda389e32016-10-25 17:55:08106}
107
108void PrintTo(const RTCPeerConnectionStats& stats, ::std::ostream* os) {
ehmaldonado35a872c2017-07-28 14:29:12109 *os << stats.ToJson();
hbosda389e32016-10-25 17:55:08110}
111
hbos09bc1282016-11-08 14:29:22112void PrintTo(const RTCMediaStreamStats& stats, ::std::ostream* os) {
ehmaldonado35a872c2017-07-28 14:29:12113 *os << stats.ToJson();
hbos09bc1282016-11-08 14:29:22114}
115
116void PrintTo(const RTCMediaStreamTrackStats& stats, ::std::ostream* os) {
ehmaldonado35a872c2017-07-28 14:29:12117 *os << stats.ToJson();
hbos09bc1282016-11-08 14:29:22118}
119
hboseeafe942016-11-01 10:00:17120void PrintTo(const RTCInboundRTPStreamStats& stats, ::std::ostream* os) {
ehmaldonado35a872c2017-07-28 14:29:12121 *os << stats.ToJson();
hboseeafe942016-11-01 10:00:17122}
123
hbos6ded1902016-11-01 08:50:46124void PrintTo(const RTCOutboundRTPStreamStats& stats, ::std::ostream* os) {
ehmaldonado35a872c2017-07-28 14:29:12125 *os << stats.ToJson();
hbos6ded1902016-11-01 08:50:46126}
127
Henrik Boström883eefc2019-05-27 11:40:25128void PrintTo(const RTCRemoteInboundRtpStreamStats& stats, ::std::ostream* os) {
129 *os << stats.ToJson();
130}
131
Henrik Boström646fda02019-05-22 13:49:42132void PrintTo(const RTCAudioSourceStats& stats, ::std::ostream* os) {
133 *os << stats.ToJson();
134}
135
136void PrintTo(const RTCVideoSourceStats& stats, ::std::ostream* os) {
137 *os << stats.ToJson();
138}
139
hbosda389e32016-10-25 17:55:08140void PrintTo(const RTCTransportStats& stats, ::std::ostream* os) {
ehmaldonado35a872c2017-07-28 14:29:12141 *os << stats.ToJson();
hbosda389e32016-10-25 17:55:08142}
143
hbosc82f2e12016-09-05 08:36:50144namespace {
145
146const int64_t kGetStatsReportTimeoutMs = 1000;
147
Alessio Bazzicaf7b1b952021-03-23 16:23:04148// Fake data used by `SetupExampleStatsVoiceGraph()` to fill in remote outbound
149// stats.
150constexpr int64_t kRemoteOutboundStatsTimestampMs = 123;
151constexpr int64_t kRemoteOutboundStatsRemoteTimestampMs = 456;
152constexpr uint32_t kRemoteOutboundStatsPacketsSent = 7u;
153constexpr uint64_t kRemoteOutboundStatsBytesSent = 8u;
154constexpr uint64_t kRemoteOutboundStatsReportsCount = 9u;
155
hbos6ab97ce02016-10-03 21:16:56156struct CertificateInfo {
157 rtc::scoped_refptr<rtc::RTCCertificate> certificate;
158 std::vector<std::string> ders;
159 std::vector<std::string> pems;
160 std::vector<std::string> fingerprints;
161};
162
Harald Alvestranda3dab842018-01-14 08:18:58163// Return the ID for an object of the given type in a report.
164// The object must be present and be unique.
165template <typename T>
166std::string IdForType(const RTCStatsReport* report) {
167 auto stats_of_my_type = report->RTCStatsReport::GetStatsOfType<T>();
168 // We cannot use ASSERT here, since we're within a function.
Mirko Bonadeie12c1fe2018-07-03 10:53:23169 EXPECT_EQ(1U, stats_of_my_type.size())
Harald Alvestranda3dab842018-01-14 08:18:58170 << "Unexpected number of stats of this type";
171 if (stats_of_my_type.size() == 1) {
172 return stats_of_my_type[0]->id();
173 } else {
174 // Return something that is not going to be a valid stas ID.
175 return "Type not found";
176 }
177}
178
hbos6ab97ce02016-10-03 21:16:56179std::unique_ptr<CertificateInfo> CreateFakeCertificateAndInfoFromDers(
180 const std::vector<std::string>& ders) {
181 RTC_CHECK(!ders.empty());
182 std::unique_ptr<CertificateInfo> info(new CertificateInfo());
183 info->ders = ders;
184 for (const std::string& der : ders) {
185 info->pems.push_back(rtc::SSLIdentity::DerToPem(
Yves Gerey665174f2018-06-19 13:03:05186 "CERTIFICATE", reinterpret_cast<const unsigned char*>(der.c_str()),
hbos6ab97ce02016-10-03 21:16:56187 der.length()));
188 }
189 info->certificate =
190 rtc::RTCCertificate::Create(std::unique_ptr<rtc::FakeSSLIdentity>(
Taylor Brandstetterc3928662018-02-23 21:04:51191 new rtc::FakeSSLIdentity(info->pems)));
hbos6ab97ce02016-10-03 21:16:56192 // Strip header/footer and newline characters of PEM strings.
193 for (size_t i = 0; i < info->pems.size(); ++i) {
Steve Anton1c9c9fc2019-02-14 23:13:09194 absl::StrReplaceAll({{"-----BEGIN CERTIFICATE-----", ""},
195 {"-----END CERTIFICATE-----", ""},
196 {"\n", ""}},
197 &info->pems[i]);
hbos6ab97ce02016-10-03 21:16:56198 }
Taylor Brandstetterc3928662018-02-23 21:04:51199 // Fingerprints for the whole certificate chain, starting with leaf
200 // certificate.
Benjamin Wright6c6c9df2018-10-25 08:16:26201 const rtc::SSLCertChain& chain = info->certificate->GetSSLCertificateChain();
Taylor Brandstetterc3928662018-02-23 21:04:51202 std::unique_ptr<rtc::SSLFingerprint> fp;
203 for (size_t i = 0; i < chain.GetSize(); i++) {
Steve Anton4905edb2018-10-16 02:27:44204 fp = rtc::SSLFingerprint::Create("sha-1", chain.Get(i));
Taylor Brandstetterc3928662018-02-23 21:04:51205 EXPECT_TRUE(fp);
206 info->fingerprints.push_back(fp->GetRfc4572Fingerprint());
hbos6ab97ce02016-10-03 21:16:56207 }
208 EXPECT_EQ(info->ders.size(), info->fingerprints.size());
209 return info;
210}
211
hbosab9f6e42016-10-07 09:18:47212std::unique_ptr<cricket::Candidate> CreateFakeCandidate(
213 const std::string& hostname,
214 int port,
215 const std::string& protocol,
Gary Liu37e489c2017-11-21 18:49:36216 const rtc::AdapterType adapter_type,
hbosab9f6e42016-10-07 09:18:47217 const std::string& candidate_type,
Jonas Oreland0d13bbd2022-03-02 10:17:36218 uint32_t priority,
219 const rtc::AdapterType underlying_type_for_vpn =
220 rtc::ADAPTER_TYPE_UNKNOWN) {
hbosab9f6e42016-10-07 09:18:47221 std::unique_ptr<cricket::Candidate> candidate(new cricket::Candidate());
222 candidate->set_address(rtc::SocketAddress(hostname, port));
223 candidate->set_protocol(protocol);
Gary Liu37e489c2017-11-21 18:49:36224 candidate->set_network_type(adapter_type);
Jonas Oreland0d13bbd2022-03-02 10:17:36225 candidate->set_underlying_type_for_vpn(underlying_type_for_vpn);
hbosab9f6e42016-10-07 09:18:47226 candidate->set_type(candidate_type);
227 candidate->set_priority(priority);
228 return candidate;
229}
230
Taylor Brandstetter64851c02021-06-24 20:32:50231class FakeAudioProcessor : public AudioProcessorInterface {
232 public:
233 FakeAudioProcessor() {}
234 ~FakeAudioProcessor() {}
235
236 private:
237 AudioProcessorInterface::AudioProcessorStatistics GetStats(
238 bool has_recv_streams) override {
239 AudioProcessorStatistics stats;
240 stats.apm_statistics.echo_return_loss = 2.0;
241 stats.apm_statistics.echo_return_loss_enhancement = 3.0;
242 return stats;
243 }
244};
245
Yves Gerey665174f2018-06-19 13:03:05246class FakeAudioTrackForStats : public MediaStreamTrack<AudioTrackInterface> {
hbos09bc1282016-11-08 14:29:22247 public:
248 static rtc::scoped_refptr<FakeAudioTrackForStats> Create(
249 const std::string& id,
Taylor Brandstetter64851c02021-06-24 20:32:50250 MediaStreamTrackInterface::TrackState state,
251 bool create_fake_audio_processor) {
Niels Möller027c7932022-01-25 12:56:07252 auto audio_track_stats = rtc::make_ref_counted<FakeAudioTrackForStats>(id);
hbos09bc1282016-11-08 14:29:22253 audio_track_stats->set_state(state);
Taylor Brandstetter64851c02021-06-24 20:32:50254 if (create_fake_audio_processor) {
255 audio_track_stats->processor_ =
256 rtc::make_ref_counted<FakeAudioProcessor>();
257 }
hbos09bc1282016-11-08 14:29:22258 return audio_track_stats;
259 }
260
Steve Anton36b29d12017-10-30 16:57:42261 explicit FakeAudioTrackForStats(const std::string& id)
262 : MediaStreamTrack<AudioTrackInterface>(id) {}
hbos09bc1282016-11-08 14:29:22263
264 std::string kind() const override {
265 return MediaStreamTrackInterface::kAudioKind;
266 }
267 webrtc::AudioSourceInterface* GetSource() const override { return nullptr; }
268 void AddSink(webrtc::AudioTrackSinkInterface* sink) override {}
269 void RemoveSink(webrtc::AudioTrackSinkInterface* sink) override {}
hbos9e302742017-01-20 10:47:10270 bool GetSignalLevel(int* level) override { return false; }
hbos09bc1282016-11-08 14:29:22271 rtc::scoped_refptr<AudioProcessorInterface> GetAudioProcessor() override {
Taylor Brandstetter64851c02021-06-24 20:32:50272 return processor_;
hbos09bc1282016-11-08 14:29:22273 }
Taylor Brandstetter64851c02021-06-24 20:32:50274
275 private:
276 rtc::scoped_refptr<FakeAudioProcessor> processor_;
hbos09bc1282016-11-08 14:29:22277};
278
Henrik Boström646fda02019-05-22 13:49:42279class FakeVideoTrackSourceForStats : public VideoTrackSourceInterface {
280 public:
281 static rtc::scoped_refptr<FakeVideoTrackSourceForStats> Create(
282 int input_width,
283 int input_height) {
Niels Möller027c7932022-01-25 12:56:07284 return rtc::make_ref_counted<FakeVideoTrackSourceForStats>(input_width,
285 input_height);
Henrik Boström646fda02019-05-22 13:49:42286 }
287
288 FakeVideoTrackSourceForStats(int input_width, int input_height)
289 : input_width_(input_width), input_height_(input_height) {}
290 ~FakeVideoTrackSourceForStats() override {}
291
292 // VideoTrackSourceInterface
293 bool is_screencast() const override { return false; }
294 absl::optional<bool> needs_denoising() const override { return false; }
295 bool GetStats(VideoTrackSourceInterface::Stats* stats) override {
296 stats->input_width = input_width_;
297 stats->input_height = input_height_;
298 return true;
299 }
300 // MediaSourceInterface (part of VideoTrackSourceInterface)
301 MediaSourceInterface::SourceState state() const override {
302 return MediaSourceInterface::SourceState::kLive;
303 }
304 bool remote() const override { return false; }
305 // NotifierInterface (part of MediaSourceInterface)
306 void RegisterObserver(ObserverInterface* observer) override {}
307 void UnregisterObserver(ObserverInterface* observer) override {}
308 // rtc::VideoSourceInterface<VideoFrame> (part of VideoTrackSourceInterface)
309 void AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame>* sink,
310 const rtc::VideoSinkWants& wants) override {}
311 void RemoveSink(rtc::VideoSinkInterface<VideoFrame>* sink) override {}
Markus Handell6efc14b2020-05-05 18:11:13312 bool SupportsEncodedOutput() const override { return false; }
313 void GenerateKeyFrame() override {}
314 void AddEncodedSink(
315 rtc::VideoSinkInterface<RecordableEncodedFrame>* sink) override {}
316 void RemoveEncodedSink(
317 rtc::VideoSinkInterface<RecordableEncodedFrame>* sink) override {}
Henrik Boström646fda02019-05-22 13:49:42318
319 private:
320 int input_width_;
321 int input_height_;
322};
323
Yves Gerey665174f2018-06-19 13:03:05324class FakeVideoTrackForStats : public MediaStreamTrack<VideoTrackInterface> {
hbos09bc1282016-11-08 14:29:22325 public:
326 static rtc::scoped_refptr<FakeVideoTrackForStats> Create(
327 const std::string& id,
Henrik Boström646fda02019-05-22 13:49:42328 MediaStreamTrackInterface::TrackState state,
329 rtc::scoped_refptr<VideoTrackSourceInterface> source) {
Niels Möller027c7932022-01-25 12:56:07330 auto video_track =
331 rtc::make_ref_counted<FakeVideoTrackForStats>(id, std::move(source));
hbos09bc1282016-11-08 14:29:22332 video_track->set_state(state);
333 return video_track;
334 }
335
Henrik Boström646fda02019-05-22 13:49:42336 FakeVideoTrackForStats(const std::string& id,
337 rtc::scoped_refptr<VideoTrackSourceInterface> source)
338 : MediaStreamTrack<VideoTrackInterface>(id), source_(source) {}
hbos09bc1282016-11-08 14:29:22339
340 std::string kind() const override {
341 return MediaStreamTrackInterface::kVideoKind;
342 }
perkj773be362017-08-01 06:22:01343
344 void AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame>* sink,
Mirko Bonadeic4dd7302019-02-25 08:12:02345 const rtc::VideoSinkWants& wants) override {}
346 void RemoveSink(rtc::VideoSinkInterface<VideoFrame>* sink) override {}
perkj773be362017-08-01 06:22:01347
Henrik Boström646fda02019-05-22 13:49:42348 VideoTrackSourceInterface* GetSource() const override {
349 return source_.get();
350 }
351
352 private:
353 rtc::scoped_refptr<VideoTrackSourceInterface> source_;
hbos09bc1282016-11-08 14:29:22354};
355
hbos84abeb12017-01-16 14:16:44356rtc::scoped_refptr<MediaStreamTrackInterface> CreateFakeTrack(
357 cricket::MediaType media_type,
hbos9e302742017-01-20 10:47:10358 const std::string& track_id,
Taylor Brandstetter64851c02021-06-24 20:32:50359 MediaStreamTrackInterface::TrackState track_state,
360 bool create_fake_audio_processor = false) {
hbos84abeb12017-01-16 14:16:44361 if (media_type == cricket::MEDIA_TYPE_AUDIO) {
Taylor Brandstetter64851c02021-06-24 20:32:50362 return FakeAudioTrackForStats::Create(track_id, track_state,
363 create_fake_audio_processor);
hbos84abeb12017-01-16 14:16:44364 } else {
365 RTC_DCHECK_EQ(media_type, cricket::MEDIA_TYPE_VIDEO);
Henrik Boström646fda02019-05-22 13:49:42366 return FakeVideoTrackForStats::Create(track_id, track_state, nullptr);
hbos84abeb12017-01-16 14:16:44367 }
368}
369
Steve Anton57858b32018-02-15 23:19:50370rtc::scoped_refptr<MockRtpSenderInternal> CreateMockSender(
Henrik Boström646fda02019-05-22 13:49:42371 cricket::MediaType media_type,
372 rtc::scoped_refptr<MediaStreamTrackInterface> track,
Harald Alvestrandc72af932018-01-11 16:18:19373 uint32_t ssrc,
Harald Alvestranda3dab842018-01-14 08:18:58374 int attachment_id,
375 std::vector<std::string> local_stream_ids) {
Henrik Boström646fda02019-05-22 13:49:42376 RTC_DCHECK(!track ||
377 (track->kind() == MediaStreamTrackInterface::kAudioKind &&
378 media_type == cricket::MEDIA_TYPE_AUDIO) ||
379 (track->kind() == MediaStreamTrackInterface::kVideoKind &&
380 media_type == cricket::MEDIA_TYPE_VIDEO));
Niels Möller027c7932022-01-25 12:56:07381 auto sender = rtc::make_ref_counted<MockRtpSenderInternal>();
hbos9e302742017-01-20 10:47:10382 EXPECT_CALL(*sender, track()).WillRepeatedly(Return(track));
383 EXPECT_CALL(*sender, ssrc()).WillRepeatedly(Return(ssrc));
Henrik Boström646fda02019-05-22 13:49:42384 EXPECT_CALL(*sender, media_type()).WillRepeatedly(Return(media_type));
Yves Gerey665174f2018-06-19 13:03:05385 EXPECT_CALL(*sender, GetParameters()).WillRepeatedly(Invoke([ssrc]() {
386 RtpParameters params;
387 params.encodings.push_back(RtpEncodingParameters());
388 params.encodings[0].ssrc = ssrc;
389 return params;
390 }));
Harald Alvestrandc72af932018-01-11 16:18:19391 EXPECT_CALL(*sender, AttachmentId()).WillRepeatedly(Return(attachment_id));
Harald Alvestranda3dab842018-01-14 08:18:58392 EXPECT_CALL(*sender, stream_ids()).WillRepeatedly(Return(local_stream_ids));
Alessio Bazzica049e6112021-03-18 11:55:11393 EXPECT_CALL(*sender, SetTransceiverAsStopped());
hbos9e302742017-01-20 10:47:10394 return sender;
395}
396
Steve Anton57858b32018-02-15 23:19:50397rtc::scoped_refptr<MockRtpReceiverInternal> CreateMockReceiver(
Mirko Bonadeic61ce0d2017-11-21 16:04:20398 const rtc::scoped_refptr<MediaStreamTrackInterface>& track,
Harald Alvestrandc72af932018-01-11 16:18:19399 uint32_t ssrc,
400 int attachment_id) {
Niels Möller027c7932022-01-25 12:56:07401 auto receiver = rtc::make_ref_counted<MockRtpReceiverInternal>();
hbos9e302742017-01-20 10:47:10402 EXPECT_CALL(*receiver, track()).WillRepeatedly(Return(track));
Harald Alvestranda3dab842018-01-14 08:18:58403 EXPECT_CALL(*receiver, streams())
404 .WillRepeatedly(
405 Return(std::vector<rtc::scoped_refptr<MediaStreamInterface>>({})));
406
Yves Gerey665174f2018-06-19 13:03:05407 EXPECT_CALL(*receiver, media_type())
408 .WillRepeatedly(
409 Return(track->kind() == MediaStreamTrackInterface::kAudioKind
410 ? cricket::MEDIA_TYPE_AUDIO
411 : cricket::MEDIA_TYPE_VIDEO));
412 EXPECT_CALL(*receiver, GetParameters()).WillRepeatedly(Invoke([ssrc]() {
413 RtpParameters params;
414 params.encodings.push_back(RtpEncodingParameters());
415 params.encodings[0].ssrc = ssrc;
416 return params;
417 }));
Harald Alvestrandc72af932018-01-11 16:18:19418 EXPECT_CALL(*receiver, AttachmentId()).WillRepeatedly(Return(attachment_id));
Tommi6589def2022-02-17 22:36:47419 EXPECT_CALL(*receiver, Stop()).WillRepeatedly(Return());
hbos9e302742017-01-20 10:47:10420 return receiver;
421}
422
Steve Anton5b387312018-02-03 00:00:20423class RTCStatsCollectorWrapper {
hbosd565b732016-08-30 21:04:35424 public:
Steve Anton5b387312018-02-03 00:00:20425 explicit RTCStatsCollectorWrapper(
426 rtc::scoped_refptr<FakePeerConnectionForStats> pc)
427 : pc_(pc),
428 stats_collector_(
Niels Möllerafb246b2022-04-20 12:26:50429 RTCStatsCollector::Create(pc.get(),
430 50 * rtc::kNumMicrosecsPerMillisec)) {}
hbosd565b732016-08-30 21:04:35431
Steve Anton5b387312018-02-03 00:00:20432 rtc::scoped_refptr<RTCStatsCollector> stats_collector() {
433 return stats_collector_;
hbosd565b732016-08-30 21:04:35434 }
435
Henrik Boström5b3541f2018-03-19 12:52:56436 rtc::scoped_refptr<const RTCStatsReport> GetStatsReport() {
437 rtc::scoped_refptr<RTCStatsObtainer> callback = RTCStatsObtainer::Create();
438 stats_collector_->GetStatsReport(callback);
439 return WaitForReport(callback);
440 }
441
442 rtc::scoped_refptr<const RTCStatsReport> GetStatsReportWithSenderSelector(
443 rtc::scoped_refptr<RtpSenderInternal> selector) {
444 rtc::scoped_refptr<RTCStatsObtainer> callback = RTCStatsObtainer::Create();
445 stats_collector_->GetStatsReport(selector, callback);
446 return WaitForReport(callback);
447 }
448
449 rtc::scoped_refptr<const RTCStatsReport> GetStatsReportWithReceiverSelector(
450 rtc::scoped_refptr<RtpReceiverInternal> selector) {
451 rtc::scoped_refptr<RTCStatsObtainer> callback = RTCStatsObtainer::Create();
452 stats_collector_->GetStatsReport(selector, callback);
453 return WaitForReport(callback);
454 }
455
Steve Anton5b387312018-02-03 00:00:20456 rtc::scoped_refptr<const RTCStatsReport> GetFreshStatsReport() {
457 stats_collector_->ClearCachedStatsReport();
458 return GetStatsReport();
459 }
460
Henrik Boström5b3541f2018-03-19 12:52:56461 rtc::scoped_refptr<MockRtpSenderInternal> SetupLocalTrackAndSender(
462 cricket::MediaType media_type,
463 const std::string& track_id,
464 uint32_t ssrc,
Henrik Boström646fda02019-05-22 13:49:42465 bool add_stream,
466 int attachment_id) {
Harald Alvestrand89061872018-01-02 13:08:34467 rtc::scoped_refptr<MediaStream> local_stream;
468 if (add_stream) {
Seth Hampson845e8782018-03-02 19:34:10469 local_stream = MediaStream::Create("LocalStreamId");
Steve Anton5b387312018-02-03 00:00:20470 pc_->mutable_local_streams()->AddStream(local_stream);
Harald Alvestrand89061872018-01-02 13:08:34471 }
hbos84abeb12017-01-16 14:16:44472
473 rtc::scoped_refptr<MediaStreamTrackInterface> track;
474 if (media_type == cricket::MEDIA_TYPE_AUDIO) {
hbos9e302742017-01-20 10:47:10475 track = CreateFakeTrack(media_type, track_id,
476 MediaStreamTrackInterface::kLive);
Harald Alvestrand89061872018-01-02 13:08:34477 if (add_stream) {
Harald Alvestrand2f7ad282022-04-21 11:35:43478 local_stream->AddTrack(rtc::scoped_refptr<AudioTrackInterface>(
479 static_cast<AudioTrackInterface*>(track.get())));
Harald Alvestrand89061872018-01-02 13:08:34480 }
hbos84abeb12017-01-16 14:16:44481 } else {
hbos9e302742017-01-20 10:47:10482 track = CreateFakeTrack(media_type, track_id,
483 MediaStreamTrackInterface::kLive);
Harald Alvestrand89061872018-01-02 13:08:34484 if (add_stream) {
Harald Alvestrand2f7ad282022-04-21 11:35:43485 local_stream->AddTrack(rtc::scoped_refptr<VideoTrackInterface>(
486 static_cast<VideoTrackInterface*>(track.get())));
Harald Alvestrand89061872018-01-02 13:08:34487 }
hbos84abeb12017-01-16 14:16:44488 }
489
Steve Anton57858b32018-02-15 23:19:50490 rtc::scoped_refptr<MockRtpSenderInternal> sender =
Henrik Boström646fda02019-05-22 13:49:42491 CreateMockSender(media_type, track, ssrc, attachment_id, {});
Tommi6589def2022-02-17 22:36:47492 EXPECT_CALL(*sender, Stop());
493 EXPECT_CALL(*sender, SetMediaChannel(_));
Steve Anton5b387312018-02-03 00:00:20494 pc_->AddSender(sender);
Henrik Boström5b3541f2018-03-19 12:52:56495 return sender;
hbos84abeb12017-01-16 14:16:44496 }
497
Henrik Boström5b3541f2018-03-19 12:52:56498 rtc::scoped_refptr<MockRtpReceiverInternal> SetupRemoteTrackAndReceiver(
499 cricket::MediaType media_type,
500 const std::string& track_id,
501 const std::string& stream_id,
502 uint32_t ssrc) {
hbos84abeb12017-01-16 14:16:44503 rtc::scoped_refptr<MediaStream> remote_stream =
Henrik Boström5b3541f2018-03-19 12:52:56504 MediaStream::Create(stream_id);
Steve Anton5b387312018-02-03 00:00:20505 pc_->mutable_remote_streams()->AddStream(remote_stream);
hbos84abeb12017-01-16 14:16:44506
507 rtc::scoped_refptr<MediaStreamTrackInterface> track;
508 if (media_type == cricket::MEDIA_TYPE_AUDIO) {
hbos9e302742017-01-20 10:47:10509 track = CreateFakeTrack(media_type, track_id,
510 MediaStreamTrackInterface::kLive);
Harald Alvestrand2f7ad282022-04-21 11:35:43511 remote_stream->AddTrack(rtc::scoped_refptr<AudioTrackInterface>(
512 static_cast<AudioTrackInterface*>(track.get())));
hbos84abeb12017-01-16 14:16:44513 } else {
hbos9e302742017-01-20 10:47:10514 track = CreateFakeTrack(media_type, track_id,
515 MediaStreamTrackInterface::kLive);
Harald Alvestrand2f7ad282022-04-21 11:35:43516 remote_stream->AddTrack(rtc::scoped_refptr<VideoTrackInterface>(
517 static_cast<VideoTrackInterface*>(track.get())));
hbos84abeb12017-01-16 14:16:44518 }
519
Steve Anton57858b32018-02-15 23:19:50520 rtc::scoped_refptr<MockRtpReceiverInternal> receiver =
Harald Alvestrandc72af932018-01-11 16:18:19521 CreateMockReceiver(track, ssrc, 62);
Harald Alvestranda3dab842018-01-14 08:18:58522 EXPECT_CALL(*receiver, streams())
523 .WillRepeatedly(
524 Return(std::vector<rtc::scoped_refptr<MediaStreamInterface>>(
525 {remote_stream})));
Tommi6589def2022-02-17 22:36:47526 EXPECT_CALL(*receiver, SetMediaChannel(_)).WillRepeatedly(Return());
Steve Anton5b387312018-02-03 00:00:20527 pc_->AddReceiver(receiver);
Henrik Boström5b3541f2018-03-19 12:52:56528 return receiver;
hbos84abeb12017-01-16 14:16:44529 }
530
hbos9e302742017-01-20 10:47:10531 // Attaches tracks to peer connections by configuring RTP senders and RTP
532 // receivers according to the tracks' pairings with
533 // |[Voice/Video][Sender/Receiver]Info| and their SSRCs. Local tracks can be
534 // associated with multiple |[Voice/Video]SenderInfo|s, remote tracks can only
535 // be associated with one |[Voice/Video]ReceiverInfo|.
Henrik Boström646fda02019-05-22 13:49:42536 // Senders get assigned attachment ID "ssrc + 10".
hbos9e302742017-01-20 10:47:10537 void CreateMockRtpSendersReceiversAndChannels(
Harald Alvestranda3dab842018-01-14 08:18:58538 std::initializer_list<
539 std::pair<MediaStreamTrackInterface*, cricket::VoiceSenderInfo>>
540 local_audio_track_info_pairs,
541 std::initializer_list<
542 std::pair<MediaStreamTrackInterface*, cricket::VoiceReceiverInfo>>
543 remote_audio_track_info_pairs,
544 std::initializer_list<
545 std::pair<MediaStreamTrackInterface*, cricket::VideoSenderInfo>>
546 local_video_track_info_pairs,
547 std::initializer_list<
548 std::pair<MediaStreamTrackInterface*, cricket::VideoReceiverInfo>>
549 remote_video_track_info_pairs,
550 std::vector<std::string> local_stream_ids,
551 std::vector<rtc::scoped_refptr<MediaStreamInterface>> remote_streams) {
Steve Anton5b387312018-02-03 00:00:20552 cricket::VoiceMediaInfo voice_media_info;
553 cricket::VideoMediaInfo video_media_info;
554
hbos9e302742017-01-20 10:47:10555 // Local audio tracks and voice sender infos
556 for (auto& pair : local_audio_track_info_pairs) {
557 MediaStreamTrackInterface* local_audio_track = pair.first;
558 const cricket::VoiceSenderInfo& voice_sender_info = pair.second;
559 RTC_DCHECK_EQ(local_audio_track->kind(),
560 MediaStreamTrackInterface::kAudioKind);
561
Steve Anton5b387312018-02-03 00:00:20562 voice_media_info.senders.push_back(voice_sender_info);
Steve Anton57858b32018-02-15 23:19:50563 rtc::scoped_refptr<MockRtpSenderInternal> rtp_sender = CreateMockSender(
Henrik Boström646fda02019-05-22 13:49:42564 cricket::MEDIA_TYPE_AUDIO,
Harald Alvestrandc72af932018-01-11 16:18:19565 rtc::scoped_refptr<MediaStreamTrackInterface>(local_audio_track),
Henrik Boström646fda02019-05-22 13:49:42566 voice_sender_info.local_stats[0].ssrc,
567 voice_sender_info.local_stats[0].ssrc + 10, local_stream_ids);
Tomas Gunnarsson16de2162022-01-26 09:21:57568 EXPECT_CALL(*rtp_sender, SetMediaChannel(_)).WillRepeatedly(Return());
Tommi6589def2022-02-17 22:36:47569 EXPECT_CALL(*rtp_sender, Stop());
Steve Anton5b387312018-02-03 00:00:20570 pc_->AddSender(rtp_sender);
hbos9e302742017-01-20 10:47:10571 }
Steve Anton5b387312018-02-03 00:00:20572
hbos9e302742017-01-20 10:47:10573 // Remote audio tracks and voice receiver infos
574 for (auto& pair : remote_audio_track_info_pairs) {
575 MediaStreamTrackInterface* remote_audio_track = pair.first;
576 const cricket::VoiceReceiverInfo& voice_receiver_info = pair.second;
577 RTC_DCHECK_EQ(remote_audio_track->kind(),
578 MediaStreamTrackInterface::kAudioKind);
579
Steve Anton5b387312018-02-03 00:00:20580 voice_media_info.receivers.push_back(voice_receiver_info);
Steve Anton57858b32018-02-15 23:19:50581 rtc::scoped_refptr<MockRtpReceiverInternal> rtp_receiver =
582 CreateMockReceiver(
583 rtc::scoped_refptr<MediaStreamTrackInterface>(remote_audio_track),
Henrik Boström646fda02019-05-22 13:49:42584 voice_receiver_info.local_stats[0].ssrc,
585 voice_receiver_info.local_stats[0].ssrc + 10);
Harald Alvestranda3dab842018-01-14 08:18:58586 EXPECT_CALL(*rtp_receiver, streams())
587 .WillRepeatedly(Return(remote_streams));
Tommi6589def2022-02-17 22:36:47588 EXPECT_CALL(*rtp_receiver, SetMediaChannel(_)).WillRepeatedly(Return());
Steve Anton5b387312018-02-03 00:00:20589 pc_->AddReceiver(rtp_receiver);
hbos9e302742017-01-20 10:47:10590 }
Steve Anton5b387312018-02-03 00:00:20591
hbos9e302742017-01-20 10:47:10592 // Local video tracks and video sender infos
593 for (auto& pair : local_video_track_info_pairs) {
594 MediaStreamTrackInterface* local_video_track = pair.first;
595 const cricket::VideoSenderInfo& video_sender_info = pair.second;
596 RTC_DCHECK_EQ(local_video_track->kind(),
597 MediaStreamTrackInterface::kVideoKind);
598
Steve Anton5b387312018-02-03 00:00:20599 video_media_info.senders.push_back(video_sender_info);
Henrik Boströma0ff50c2020-05-05 13:54:46600 video_media_info.aggregated_senders.push_back(video_sender_info);
Steve Anton57858b32018-02-15 23:19:50601 rtc::scoped_refptr<MockRtpSenderInternal> rtp_sender = CreateMockSender(
Henrik Boström646fda02019-05-22 13:49:42602 cricket::MEDIA_TYPE_VIDEO,
Harald Alvestrandc72af932018-01-11 16:18:19603 rtc::scoped_refptr<MediaStreamTrackInterface>(local_video_track),
Henrik Boström646fda02019-05-22 13:49:42604 video_sender_info.local_stats[0].ssrc,
605 video_sender_info.local_stats[0].ssrc + 10, local_stream_ids);
Tomas Gunnarsson16de2162022-01-26 09:21:57606 EXPECT_CALL(*rtp_sender, SetMediaChannel(_)).WillRepeatedly(Return());
Tommi6589def2022-02-17 22:36:47607 EXPECT_CALL(*rtp_sender, Stop());
Steve Anton5b387312018-02-03 00:00:20608 pc_->AddSender(rtp_sender);
hbos9e302742017-01-20 10:47:10609 }
Steve Anton5b387312018-02-03 00:00:20610
hbos9e302742017-01-20 10:47:10611 // Remote video tracks and video receiver infos
612 for (auto& pair : remote_video_track_info_pairs) {
613 MediaStreamTrackInterface* remote_video_track = pair.first;
614 const cricket::VideoReceiverInfo& video_receiver_info = pair.second;
615 RTC_DCHECK_EQ(remote_video_track->kind(),
616 MediaStreamTrackInterface::kVideoKind);
617
Steve Anton5b387312018-02-03 00:00:20618 video_media_info.receivers.push_back(video_receiver_info);
Steve Anton57858b32018-02-15 23:19:50619 rtc::scoped_refptr<MockRtpReceiverInternal> rtp_receiver =
620 CreateMockReceiver(
621 rtc::scoped_refptr<MediaStreamTrackInterface>(remote_video_track),
Henrik Boström646fda02019-05-22 13:49:42622 video_receiver_info.local_stats[0].ssrc,
623 video_receiver_info.local_stats[0].ssrc + 10);
Harald Alvestranda3dab842018-01-14 08:18:58624 EXPECT_CALL(*rtp_receiver, streams())
625 .WillRepeatedly(Return(remote_streams));
Tommi6589def2022-02-17 22:36:47626 EXPECT_CALL(*rtp_receiver, SetMediaChannel(_)).WillRepeatedly(Return());
Steve Anton5b387312018-02-03 00:00:20627 pc_->AddReceiver(rtp_receiver);
hbos9e302742017-01-20 10:47:10628 }
hbos9e302742017-01-20 10:47:10629
Tommi19015512022-02-02 10:49:35630 pc_->AddVoiceChannel("audio", "transport", voice_media_info);
631 pc_->AddVideoChannel("video", "transport", video_media_info);
hbos9e302742017-01-20 10:47:10632 }
633
hbosd565b732016-08-30 21:04:35634 private:
Henrik Boström5b3541f2018-03-19 12:52:56635 rtc::scoped_refptr<const RTCStatsReport> WaitForReport(
636 rtc::scoped_refptr<RTCStatsObtainer> callback) {
Niels Möllerafb246b2022-04-20 12:26:50637 EXPECT_TRUE_WAIT(callback->report() != nullptr, kGetStatsReportTimeoutMs);
Henrik Boström5b3541f2018-03-19 12:52:56638 int64_t after = rtc::TimeUTCMicros();
639 for (const RTCStats& stats : *callback->report()) {
Alessio Bazzicaf7b1b952021-03-23 16:23:04640 if (stats.type() == RTCRemoteInboundRtpStreamStats::kType ||
641 stats.type() == RTCRemoteOutboundRtpStreamStats::kType) {
642 // Ignore remote timestamps.
643 continue;
644 }
Henrik Boström5b3541f2018-03-19 12:52:56645 EXPECT_LE(stats.timestamp_us(), after);
646 }
647 return callback->report();
648 }
649
Steve Anton5b387312018-02-03 00:00:20650 rtc::scoped_refptr<FakePeerConnectionForStats> pc_;
651 rtc::scoped_refptr<RTCStatsCollector> stats_collector_;
hbosd565b732016-08-30 21:04:35652};
653
Mirko Bonadei6a489f22019-04-09 13:11:12654class RTCStatsCollectorTest : public ::testing::Test {
hbosc82f2e12016-09-05 08:36:50655 public:
656 RTCStatsCollectorTest()
Niels Möller027c7932022-01-25 12:56:07657 : pc_(rtc::make_ref_counted<FakePeerConnectionForStats>()),
Steve Anton5b387312018-02-03 00:00:20658 stats_(new RTCStatsCollectorWrapper(pc_)) {}
hbosc82f2e12016-09-05 08:36:50659
hbos6ab97ce02016-10-03 21:16:56660 void ExpectReportContainsCertificateInfo(
661 const rtc::scoped_refptr<const RTCStatsReport>& report,
hbos23368e12016-12-21 12:29:17662 const CertificateInfo& certinfo) {
663 for (size_t i = 0; i < certinfo.fingerprints.size(); ++i) {
664 RTCCertificateStats expected_certificate_stats(
Yves Gerey665174f2018-06-19 13:03:05665 "RTCCertificate_" + certinfo.fingerprints[i], report->timestamp_us());
hbos23368e12016-12-21 12:29:17666 expected_certificate_stats.fingerprint = certinfo.fingerprints[i];
667 expected_certificate_stats.fingerprint_algorithm = "sha-1";
668 expected_certificate_stats.base64_certificate = certinfo.pems[i];
669 if (i + 1 < certinfo.fingerprints.size()) {
670 expected_certificate_stats.issuer_certificate_id =
671 "RTCCertificate_" + certinfo.fingerprints[i + 1];
hbos6ab97ce02016-10-03 21:16:56672 }
hbos23368e12016-12-21 12:29:17673 ASSERT_TRUE(report->Get(expected_certificate_stats.id()));
674 EXPECT_EQ(expected_certificate_stats,
Yves Gerey665174f2018-06-19 13:03:05675 report->Get(expected_certificate_stats.id())
676 ->cast_to<RTCCertificateStats>());
hbos6ab97ce02016-10-03 21:16:56677 }
678 }
679
Henrik Boström5b3541f2018-03-19 12:52:56680 struct ExampleStatsGraph {
681 rtc::scoped_refptr<RtpSenderInternal> sender;
682 rtc::scoped_refptr<RtpReceiverInternal> receiver;
683
684 rtc::scoped_refptr<const RTCStatsReport> full_report;
685 std::string send_codec_id;
686 std::string recv_codec_id;
687 std::string outbound_rtp_id;
688 std::string inbound_rtp_id;
Alessio Bazzicaf7b1b952021-03-23 16:23:04689 std::string remote_outbound_rtp_id;
Henrik Boström5b3541f2018-03-19 12:52:56690 std::string transport_id;
691 std::string sender_track_id;
692 std::string receiver_track_id;
693 std::string remote_stream_id;
694 std::string peer_connection_id;
Henrik Boström646fda02019-05-22 13:49:42695 std::string media_source_id;
Henrik Boström5b3541f2018-03-19 12:52:56696 };
697
Alessio Bazzicaf7b1b952021-03-23 16:23:04698 // Sets up the example stats graph (see ASCII art below) for a video only
699 // call. The graph is used for testing the stats selection algorithm (see
700 // https://w3c.github.io/webrtc-pc/#dfn-stats-selection-algorithm).
Henrik Boström5b3541f2018-03-19 12:52:56701 // These tests test the integration of the stats traversal algorithm inside of
702 // RTCStatsCollector. See rtcstatstraveral_unittest.cc for more stats
703 // traversal tests.
704 ExampleStatsGraph SetupExampleStatsGraphForSelectorTests() {
705 ExampleStatsGraph graph;
706
707 // codec (send)
708 graph.send_codec_id = "RTCCodec_VideoMid_Outbound_1";
709 cricket::VideoMediaInfo video_media_info;
710 RtpCodecParameters send_codec;
711 send_codec.payload_type = 1;
712 send_codec.clock_rate = 0;
713 video_media_info.send_codecs.insert(
714 std::make_pair(send_codec.payload_type, send_codec));
715 // codec (recv)
716 graph.recv_codec_id = "RTCCodec_VideoMid_Inbound_2";
717 RtpCodecParameters recv_codec;
718 recv_codec.payload_type = 2;
719 recv_codec.clock_rate = 0;
720 video_media_info.receive_codecs.insert(
721 std::make_pair(recv_codec.payload_type, recv_codec));
722 // outbound-rtp
723 graph.outbound_rtp_id = "RTCOutboundRTPVideoStream_3";
724 video_media_info.senders.push_back(cricket::VideoSenderInfo());
725 video_media_info.senders[0].local_stats.push_back(
726 cricket::SsrcSenderInfo());
727 video_media_info.senders[0].local_stats[0].ssrc = 3;
728 video_media_info.senders[0].codec_payload_type = send_codec.payload_type;
Henrik Boströma0ff50c2020-05-05 13:54:46729 video_media_info.aggregated_senders.push_back(video_media_info.senders[0]);
Henrik Boström5b3541f2018-03-19 12:52:56730 // inbound-rtp
731 graph.inbound_rtp_id = "RTCInboundRTPVideoStream_4";
732 video_media_info.receivers.push_back(cricket::VideoReceiverInfo());
733 video_media_info.receivers[0].local_stats.push_back(
734 cricket::SsrcReceiverInfo());
735 video_media_info.receivers[0].local_stats[0].ssrc = 4;
736 video_media_info.receivers[0].codec_payload_type = recv_codec.payload_type;
737 // transport
738 graph.transport_id = "RTCTransport_TransportName_1";
Tommi19015512022-02-02 10:49:35739 pc_->AddVideoChannel("VideoMid", "TransportName", video_media_info);
Henrik Boström5b3541f2018-03-19 12:52:56740 // track (sender)
741 graph.sender = stats_->SetupLocalTrackAndSender(
Henrik Boström646fda02019-05-22 13:49:42742 cricket::MEDIA_TYPE_VIDEO, "LocalVideoTrackID", 3, false, 50);
Henrik Boström5b3541f2018-03-19 12:52:56743 graph.sender_track_id = "RTCMediaStreamTrack_sender_" +
Jonas Olsson6b1985d2018-07-05 09:59:48744 rtc::ToString(graph.sender->AttachmentId());
Henrik Boström5b3541f2018-03-19 12:52:56745 // track (receiver) and stream (remote stream)
746 graph.receiver = stats_->SetupRemoteTrackAndReceiver(
747 cricket::MEDIA_TYPE_VIDEO, "RemoteVideoTrackID", "RemoteStreamId", 4);
748 graph.receiver_track_id = "RTCMediaStreamTrack_receiver_" +
Jonas Olsson6b1985d2018-07-05 09:59:48749 rtc::ToString(graph.receiver->AttachmentId());
Henrik Boström5b3541f2018-03-19 12:52:56750 graph.remote_stream_id = "RTCMediaStream_RemoteStreamId";
751 // peer-connection
752 graph.peer_connection_id = "RTCPeerConnection";
Henrik Boström646fda02019-05-22 13:49:42753 // media-source (kind: video)
754 graph.media_source_id =
755 "RTCVideoSource_" + rtc::ToString(graph.sender->AttachmentId());
Henrik Boström5b3541f2018-03-19 12:52:56756
757 // Expected stats graph:
758 //
Henrik Boström646fda02019-05-22 13:49:42759 // +--- track (sender) stream (remote stream) ---> track (receiver)
760 // | ^ ^
761 // | | |
762 // | +--------- outbound-rtp inbound-rtp ---------------+
763 // | | | | | |
764 // | | v v v v
765 // | | codec (send) transport codec (recv) peer-connection
766 // v v
767 // media-source
Henrik Boström5b3541f2018-03-19 12:52:56768
769 // Verify the stats graph is set up correctly.
770 graph.full_report = stats_->GetStatsReport();
Henrik Boström646fda02019-05-22 13:49:42771 EXPECT_EQ(graph.full_report->size(), 10u);
Henrik Boström5b3541f2018-03-19 12:52:56772 EXPECT_TRUE(graph.full_report->Get(graph.send_codec_id));
773 EXPECT_TRUE(graph.full_report->Get(graph.recv_codec_id));
774 EXPECT_TRUE(graph.full_report->Get(graph.outbound_rtp_id));
775 EXPECT_TRUE(graph.full_report->Get(graph.inbound_rtp_id));
776 EXPECT_TRUE(graph.full_report->Get(graph.transport_id));
777 EXPECT_TRUE(graph.full_report->Get(graph.sender_track_id));
778 EXPECT_TRUE(graph.full_report->Get(graph.receiver_track_id));
779 EXPECT_TRUE(graph.full_report->Get(graph.remote_stream_id));
780 EXPECT_TRUE(graph.full_report->Get(graph.peer_connection_id));
Henrik Boström646fda02019-05-22 13:49:42781 EXPECT_TRUE(graph.full_report->Get(graph.media_source_id));
782 const auto& sender_track = graph.full_report->Get(graph.sender_track_id)
783 ->cast_to<RTCMediaStreamTrackStats>();
784 EXPECT_EQ(*sender_track.media_source_id, graph.media_source_id);
Henrik Boström5b3541f2018-03-19 12:52:56785 const auto& outbound_rtp = graph.full_report->Get(graph.outbound_rtp_id)
786 ->cast_to<RTCOutboundRTPStreamStats>();
Henrik Boström646fda02019-05-22 13:49:42787 EXPECT_EQ(*outbound_rtp.media_source_id, graph.media_source_id);
Henrik Boström5b3541f2018-03-19 12:52:56788 EXPECT_EQ(*outbound_rtp.codec_id, graph.send_codec_id);
789 EXPECT_EQ(*outbound_rtp.track_id, graph.sender_track_id);
790 EXPECT_EQ(*outbound_rtp.transport_id, graph.transport_id);
791 const auto& inbound_rtp = graph.full_report->Get(graph.inbound_rtp_id)
792 ->cast_to<RTCInboundRTPStreamStats>();
793 EXPECT_EQ(*inbound_rtp.codec_id, graph.recv_codec_id);
794 EXPECT_EQ(*inbound_rtp.track_id, graph.receiver_track_id);
795 EXPECT_EQ(*inbound_rtp.transport_id, graph.transport_id);
796
797 return graph;
798 }
799
Alessio Bazzicaf7b1b952021-03-23 16:23:04800 // Sets up an example stats graph (see ASCII art below) for an audio only call
801 // and checks that the expected stats are generated.
802 ExampleStatsGraph SetupExampleStatsVoiceGraph(
803 bool add_remote_outbound_stats) {
804 constexpr uint32_t kLocalSsrc = 3;
805 constexpr uint32_t kRemoteSsrc = 4;
806 ExampleStatsGraph graph;
807
808 // codec (send)
809 graph.send_codec_id = "RTCCodec_VoiceMid_Outbound_1";
810 cricket::VoiceMediaInfo media_info;
811 RtpCodecParameters send_codec;
812 send_codec.payload_type = 1;
813 send_codec.clock_rate = 0;
814 media_info.send_codecs.insert(
815 std::make_pair(send_codec.payload_type, send_codec));
816 // codec (recv)
817 graph.recv_codec_id = "RTCCodec_VoiceMid_Inbound_2";
818 RtpCodecParameters recv_codec;
819 recv_codec.payload_type = 2;
820 recv_codec.clock_rate = 0;
821 media_info.receive_codecs.insert(
822 std::make_pair(recv_codec.payload_type, recv_codec));
823 // outbound-rtp
824 graph.outbound_rtp_id = "RTCOutboundRTPAudioStream_3";
825 media_info.senders.push_back(cricket::VoiceSenderInfo());
826 media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
827 media_info.senders[0].local_stats[0].ssrc = kLocalSsrc;
828 media_info.senders[0].codec_payload_type = send_codec.payload_type;
829 // inbound-rtp
830 graph.inbound_rtp_id = "RTCInboundRTPAudioStream_4";
831 media_info.receivers.push_back(cricket::VoiceReceiverInfo());
832 media_info.receivers[0].local_stats.push_back(cricket::SsrcReceiverInfo());
833 media_info.receivers[0].local_stats[0].ssrc = kRemoteSsrc;
834 media_info.receivers[0].codec_payload_type = recv_codec.payload_type;
835 // remote-outbound-rtp
836 if (add_remote_outbound_stats) {
837 graph.remote_outbound_rtp_id = "RTCRemoteOutboundRTPAudioStream_4";
838 media_info.receivers[0].last_sender_report_timestamp_ms =
839 kRemoteOutboundStatsTimestampMs;
840 media_info.receivers[0].last_sender_report_remote_timestamp_ms =
841 kRemoteOutboundStatsRemoteTimestampMs;
842 media_info.receivers[0].sender_reports_packets_sent =
843 kRemoteOutboundStatsPacketsSent;
844 media_info.receivers[0].sender_reports_bytes_sent =
845 kRemoteOutboundStatsBytesSent;
846 media_info.receivers[0].sender_reports_reports_count =
847 kRemoteOutboundStatsReportsCount;
848 }
849
850 // transport
851 graph.transport_id = "RTCTransport_TransportName_1";
Tommi19015512022-02-02 10:49:35852 pc_->AddVoiceChannel("VoiceMid", "TransportName", media_info);
Alessio Bazzicaf7b1b952021-03-23 16:23:04853 // track (sender)
854 graph.sender = stats_->SetupLocalTrackAndSender(
855 cricket::MEDIA_TYPE_AUDIO, "LocalAudioTrackID", kLocalSsrc, false, 50);
856 graph.sender_track_id = "RTCMediaStreamTrack_sender_" +
857 rtc::ToString(graph.sender->AttachmentId());
858 // track (receiver) and stream (remote stream)
859 graph.receiver = stats_->SetupRemoteTrackAndReceiver(
860 cricket::MEDIA_TYPE_AUDIO, "RemoteAudioTrackID", "RemoteStreamId",
861 kRemoteSsrc);
862 graph.receiver_track_id = "RTCMediaStreamTrack_receiver_" +
863 rtc::ToString(graph.receiver->AttachmentId());
864 graph.remote_stream_id = "RTCMediaStream_RemoteStreamId";
865 // peer-connection
866 graph.peer_connection_id = "RTCPeerConnection";
867 // media-source (kind: video)
868 graph.media_source_id =
869 "RTCAudioSource_" + rtc::ToString(graph.sender->AttachmentId());
870
871 // Expected stats graph:
872 //
873 // +--- track (sender) stream (remote stream) ---> track (receiver)
874 // | ^ ^
875 // | | |
876 // | +--------- outbound-rtp inbound-rtp ---------------+
877 // | | | | | |
878 // | | v v v v
879 // | | codec (send) transport codec (recv) peer-connection
880 // v v
881 // media-source
882
883 // Verify the stats graph is set up correctly.
884 graph.full_report = stats_->GetStatsReport();
885 EXPECT_EQ(graph.full_report->size(), add_remote_outbound_stats ? 11u : 10u);
886 EXPECT_TRUE(graph.full_report->Get(graph.send_codec_id));
887 EXPECT_TRUE(graph.full_report->Get(graph.recv_codec_id));
888 EXPECT_TRUE(graph.full_report->Get(graph.outbound_rtp_id));
889 EXPECT_TRUE(graph.full_report->Get(graph.inbound_rtp_id));
890 EXPECT_TRUE(graph.full_report->Get(graph.transport_id));
891 EXPECT_TRUE(graph.full_report->Get(graph.sender_track_id));
892 EXPECT_TRUE(graph.full_report->Get(graph.receiver_track_id));
893 EXPECT_TRUE(graph.full_report->Get(graph.remote_stream_id));
894 EXPECT_TRUE(graph.full_report->Get(graph.peer_connection_id));
895 EXPECT_TRUE(graph.full_report->Get(graph.media_source_id));
896 // `graph.remote_outbound_rtp_id` is omitted on purpose so that expectations
897 // can be added by the caller depending on what value it sets for the
898 // `add_remote_outbound_stats` argument.
899 const auto& sender_track = graph.full_report->Get(graph.sender_track_id)
900 ->cast_to<RTCMediaStreamTrackStats>();
901 EXPECT_EQ(*sender_track.media_source_id, graph.media_source_id);
902 const auto& outbound_rtp = graph.full_report->Get(graph.outbound_rtp_id)
903 ->cast_to<RTCOutboundRTPStreamStats>();
904 EXPECT_EQ(*outbound_rtp.media_source_id, graph.media_source_id);
905 EXPECT_EQ(*outbound_rtp.codec_id, graph.send_codec_id);
906 EXPECT_EQ(*outbound_rtp.track_id, graph.sender_track_id);
907 EXPECT_EQ(*outbound_rtp.transport_id, graph.transport_id);
908 const auto& inbound_rtp = graph.full_report->Get(graph.inbound_rtp_id)
909 ->cast_to<RTCInboundRTPStreamStats>();
910 EXPECT_EQ(*inbound_rtp.codec_id, graph.recv_codec_id);
911 EXPECT_EQ(*inbound_rtp.track_id, graph.receiver_track_id);
912 EXPECT_EQ(*inbound_rtp.transport_id, graph.transport_id);
913
914 return graph;
915 }
916
hbosc82f2e12016-09-05 08:36:50917 protected:
Steve Anton5b387312018-02-03 00:00:20918 rtc::ScopedFakeClock fake_clock_;
Niels Möller83830f32022-05-20 07:12:57919 rtc::AutoThread main_thread_;
Steve Anton5b387312018-02-03 00:00:20920 rtc::scoped_refptr<FakePeerConnectionForStats> pc_;
921 std::unique_ptr<RTCStatsCollectorWrapper> stats_;
hbosc82f2e12016-09-05 08:36:50922};
923
924TEST_F(RTCStatsCollectorTest, SingleCallback) {
925 rtc::scoped_refptr<const RTCStatsReport> result;
Steve Anton5b387312018-02-03 00:00:20926 stats_->stats_collector()->GetStatsReport(RTCStatsObtainer::Create(&result));
Niels Möllerafb246b2022-04-20 12:26:50927 EXPECT_TRUE_WAIT(result != nullptr, kGetStatsReportTimeoutMs);
hbosc82f2e12016-09-05 08:36:50928}
929
930TEST_F(RTCStatsCollectorTest, MultipleCallbacks) {
Steve Anton5b387312018-02-03 00:00:20931 rtc::scoped_refptr<const RTCStatsReport> a, b, c;
932 stats_->stats_collector()->GetStatsReport(RTCStatsObtainer::Create(&a));
933 stats_->stats_collector()->GetStatsReport(RTCStatsObtainer::Create(&b));
934 stats_->stats_collector()->GetStatsReport(RTCStatsObtainer::Create(&c));
Niels Möllerafb246b2022-04-20 12:26:50935 EXPECT_TRUE_WAIT(a != nullptr, kGetStatsReportTimeoutMs);
936 EXPECT_TRUE_WAIT(b != nullptr, kGetStatsReportTimeoutMs);
937 EXPECT_TRUE_WAIT(c != nullptr, kGetStatsReportTimeoutMs);
Steve Anton5b387312018-02-03 00:00:20938
hbosc82f2e12016-09-05 08:36:50939 EXPECT_EQ(a.get(), b.get());
940 EXPECT_EQ(b.get(), c.get());
941}
942
943TEST_F(RTCStatsCollectorTest, CachedStatsReports) {
Artem Titov880fa812021-07-30 20:30:23944 // Caching should ensure `a` and `b` are the same report.
Steve Anton5b387312018-02-03 00:00:20945 rtc::scoped_refptr<const RTCStatsReport> a = stats_->GetStatsReport();
946 rtc::scoped_refptr<const RTCStatsReport> b = stats_->GetStatsReport();
hbosd565b732016-08-30 21:04:35947 EXPECT_EQ(a.get(), b.get());
948 // Invalidate cache by clearing it.
Steve Anton5b387312018-02-03 00:00:20949 stats_->stats_collector()->ClearCachedStatsReport();
950 rtc::scoped_refptr<const RTCStatsReport> c = stats_->GetStatsReport();
hbosd565b732016-08-30 21:04:35951 EXPECT_NE(b.get(), c.get());
952 // Invalidate cache by advancing time.
Danil Chapovalov0c626af2020-02-10 10:16:00953 fake_clock_.AdvanceTime(TimeDelta::Millis(51));
Steve Anton5b387312018-02-03 00:00:20954 rtc::scoped_refptr<const RTCStatsReport> d = stats_->GetStatsReport();
hbosd565b732016-08-30 21:04:35955 EXPECT_TRUE(d);
956 EXPECT_NE(c.get(), d.get());
957}
958
hbosc82f2e12016-09-05 08:36:50959TEST_F(RTCStatsCollectorTest, MultipleCallbacksWithInvalidatedCacheInBetween) {
Steve Anton5b387312018-02-03 00:00:20960 rtc::scoped_refptr<const RTCStatsReport> a, b, c;
961 stats_->stats_collector()->GetStatsReport(RTCStatsObtainer::Create(&a));
962 stats_->stats_collector()->GetStatsReport(RTCStatsObtainer::Create(&b));
hbosc82f2e12016-09-05 08:36:50963 // Cache is invalidated after 50 ms.
Danil Chapovalov0c626af2020-02-10 10:16:00964 fake_clock_.AdvanceTime(TimeDelta::Millis(51));
Steve Anton5b387312018-02-03 00:00:20965 stats_->stats_collector()->GetStatsReport(RTCStatsObtainer::Create(&c));
Niels Möllerafb246b2022-04-20 12:26:50966 EXPECT_TRUE_WAIT(a != nullptr, kGetStatsReportTimeoutMs);
967 EXPECT_TRUE_WAIT(b != nullptr, kGetStatsReportTimeoutMs);
968 EXPECT_TRUE_WAIT(c != nullptr, kGetStatsReportTimeoutMs);
hbosc82f2e12016-09-05 08:36:50969 EXPECT_EQ(a.get(), b.get());
Artem Titov880fa812021-07-30 20:30:23970 // The act of doing `AdvanceTime` processes all messages. If this was not the
971 // case we might not require `c` to be fresher than `b`.
hbosc82f2e12016-09-05 08:36:50972 EXPECT_NE(c.get(), b.get());
973}
974
Harald Alvestrand910cdc22020-01-09 11:58:23975TEST_F(RTCStatsCollectorTest, ToJsonProducesParseableJson) {
976 ExampleStatsGraph graph = SetupExampleStatsGraphForSelectorTests();
977 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
978 std::string json_format = report->ToJson();
Mirko Bonadeie99f6872021-06-24 13:24:59979
980 Json::CharReaderBuilder builder;
Harald Alvestrand910cdc22020-01-09 11:58:23981 Json::Value json_value;
Mirko Bonadeie99f6872021-06-24 13:24:59982 std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
983 ASSERT_TRUE(reader->parse(json_format.c_str(),
984 json_format.c_str() + json_format.size(),
985 &json_value, nullptr));
986
Harald Alvestrand910cdc22020-01-09 11:58:23987 // A very brief sanity check on the result.
988 EXPECT_EQ(report->size(), json_value.size());
989}
990
hbos6ab97ce02016-10-03 21:16:56991TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsSingle) {
Steve Anton5b387312018-02-03 00:00:20992 const char kTransportName[] = "transport";
993
994 pc_->AddVoiceChannel("audio", kTransportName);
995
hbos6ab97ce02016-10-03 21:16:56996 std::unique_ptr<CertificateInfo> local_certinfo =
997 CreateFakeCertificateAndInfoFromDers(
Yves Gerey665174f2018-06-19 13:03:05998 std::vector<std::string>({"(local) single certificate"}));
Steve Anton5b387312018-02-03 00:00:20999 pc_->SetLocalCertificate(kTransportName, local_certinfo->certificate);
1000
hbos6ab97ce02016-10-03 21:16:561001 std::unique_ptr<CertificateInfo> remote_certinfo =
1002 CreateFakeCertificateAndInfoFromDers(
Yves Gerey665174f2018-06-19 13:03:051003 std::vector<std::string>({"(remote) single certificate"}));
Taylor Brandstetterc3928662018-02-23 21:04:511004 pc_->SetRemoteCertChain(
Benjamin Wright6c6c9df2018-10-25 08:16:261005 kTransportName,
1006 remote_certinfo->certificate->GetSSLCertificateChain().Clone());
hbos6ab97ce02016-10-03 21:16:561007
Steve Anton5b387312018-02-03 00:00:201008 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbos6ab97ce02016-10-03 21:16:561009
hbos23368e12016-12-21 12:29:171010 ExpectReportContainsCertificateInfo(report, *local_certinfo);
1011 ExpectReportContainsCertificateInfo(report, *remote_certinfo);
hbos6ab97ce02016-10-03 21:16:561012}
1013
hbos0adb8282016-11-23 10:32:061014TEST_F(RTCStatsCollectorTest, CollectRTCCodecStats) {
hbos0adb8282016-11-23 10:32:061015 // Audio
1016 cricket::VoiceMediaInfo voice_media_info;
1017
1018 RtpCodecParameters inbound_audio_codec;
1019 inbound_audio_codec.payload_type = 1;
deadbeefe702b302017-02-04 20:09:011020 inbound_audio_codec.kind = cricket::MEDIA_TYPE_AUDIO;
1021 inbound_audio_codec.name = "opus";
Oskar Sundbomcbc71b22017-11-16 09:56:071022 inbound_audio_codec.clock_rate = 1337;
Johannes Kron72d69152020-02-10 13:05:551023 inbound_audio_codec.num_channels = 1;
1024 inbound_audio_codec.parameters = {{"minptime", "10"}, {"useinbandfec", "1"}};
hbos0adb8282016-11-23 10:32:061025 voice_media_info.receive_codecs.insert(
1026 std::make_pair(inbound_audio_codec.payload_type, inbound_audio_codec));
1027
1028 RtpCodecParameters outbound_audio_codec;
1029 outbound_audio_codec.payload_type = 2;
deadbeefe702b302017-02-04 20:09:011030 outbound_audio_codec.kind = cricket::MEDIA_TYPE_AUDIO;
1031 outbound_audio_codec.name = "isac";
Oskar Sundbomcbc71b22017-11-16 09:56:071032 outbound_audio_codec.clock_rate = 1338;
Johannes Kron72d69152020-02-10 13:05:551033 outbound_audio_codec.num_channels = 2;
hbos0adb8282016-11-23 10:32:061034 voice_media_info.send_codecs.insert(
1035 std::make_pair(outbound_audio_codec.payload_type, outbound_audio_codec));
1036
Tommi19015512022-02-02 10:49:351037 pc_->AddVoiceChannel("AudioMid", "TransportName", voice_media_info);
hbos0adb8282016-11-23 10:32:061038
1039 // Video
1040 cricket::VideoMediaInfo video_media_info;
1041
1042 RtpCodecParameters inbound_video_codec;
1043 inbound_video_codec.payload_type = 3;
deadbeefe702b302017-02-04 20:09:011044 inbound_video_codec.kind = cricket::MEDIA_TYPE_VIDEO;
1045 inbound_video_codec.name = "H264";
Oskar Sundbomcbc71b22017-11-16 09:56:071046 inbound_video_codec.clock_rate = 1339;
Johannes Kron72d69152020-02-10 13:05:551047 inbound_video_codec.parameters = {{"level-asymmetry-allowed", "1"},
1048 {"packetization-mode", "1"},
1049 {"profile-level-id", "42001f"}};
hbos0adb8282016-11-23 10:32:061050 video_media_info.receive_codecs.insert(
1051 std::make_pair(inbound_video_codec.payload_type, inbound_video_codec));
1052
1053 RtpCodecParameters outbound_video_codec;
1054 outbound_video_codec.payload_type = 4;
deadbeefe702b302017-02-04 20:09:011055 outbound_video_codec.kind = cricket::MEDIA_TYPE_VIDEO;
1056 outbound_video_codec.name = "VP8";
Oskar Sundbomcbc71b22017-11-16 09:56:071057 outbound_video_codec.clock_rate = 1340;
hbos0adb8282016-11-23 10:32:061058 video_media_info.send_codecs.insert(
1059 std::make_pair(outbound_video_codec.payload_type, outbound_video_codec));
1060
Tommi19015512022-02-02 10:49:351061 pc_->AddVideoChannel("VideoMid", "TransportName", video_media_info);
hbos0adb8282016-11-23 10:32:061062
Steve Anton5b387312018-02-03 00:00:201063 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbos0adb8282016-11-23 10:32:061064
Steve Anton57858b32018-02-15 23:19:501065 RTCCodecStats expected_inbound_audio_codec("RTCCodec_AudioMid_Inbound_1",
1066 report->timestamp_us());
hbos0adb8282016-11-23 10:32:061067 expected_inbound_audio_codec.payload_type = 1;
hbos13f54b22017-02-28 14:56:041068 expected_inbound_audio_codec.mime_type = "audio/opus";
hbos0adb8282016-11-23 10:32:061069 expected_inbound_audio_codec.clock_rate = 1337;
Johannes Kron72d69152020-02-10 13:05:551070 expected_inbound_audio_codec.channels = 1;
1071 expected_inbound_audio_codec.sdp_fmtp_line = "minptime=10;useinbandfec=1";
Philipp Hancke95157a02020-11-16 19:08:271072 expected_inbound_audio_codec.transport_id = "RTCTransport_TransportName_1";
hbos0adb8282016-11-23 10:32:061073
Steve Anton57858b32018-02-15 23:19:501074 RTCCodecStats expected_outbound_audio_codec("RTCCodec_AudioMid_Outbound_2",
1075 report->timestamp_us());
hbos0adb8282016-11-23 10:32:061076 expected_outbound_audio_codec.payload_type = 2;
hbos13f54b22017-02-28 14:56:041077 expected_outbound_audio_codec.mime_type = "audio/isac";
hbos0adb8282016-11-23 10:32:061078 expected_outbound_audio_codec.clock_rate = 1338;
Johannes Kron72d69152020-02-10 13:05:551079 expected_outbound_audio_codec.channels = 2;
Philipp Hancke95157a02020-11-16 19:08:271080 expected_outbound_audio_codec.transport_id = "RTCTransport_TransportName_1";
hbos0adb8282016-11-23 10:32:061081
Steve Anton57858b32018-02-15 23:19:501082 RTCCodecStats expected_inbound_video_codec("RTCCodec_VideoMid_Inbound_3",
1083 report->timestamp_us());
hbos0adb8282016-11-23 10:32:061084 expected_inbound_video_codec.payload_type = 3;
hbos13f54b22017-02-28 14:56:041085 expected_inbound_video_codec.mime_type = "video/H264";
hbos0adb8282016-11-23 10:32:061086 expected_inbound_video_codec.clock_rate = 1339;
Johannes Kron72d69152020-02-10 13:05:551087 expected_inbound_video_codec.sdp_fmtp_line =
1088 "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f";
Philipp Hancke95157a02020-11-16 19:08:271089 expected_inbound_video_codec.transport_id = "RTCTransport_TransportName_1";
hbos0adb8282016-11-23 10:32:061090
Steve Anton57858b32018-02-15 23:19:501091 RTCCodecStats expected_outbound_video_codec("RTCCodec_VideoMid_Outbound_4",
1092 report->timestamp_us());
hbos0adb8282016-11-23 10:32:061093 expected_outbound_video_codec.payload_type = 4;
hbos13f54b22017-02-28 14:56:041094 expected_outbound_video_codec.mime_type = "video/VP8";
hbos0adb8282016-11-23 10:32:061095 expected_outbound_video_codec.clock_rate = 1340;
Philipp Hancke95157a02020-11-16 19:08:271096 expected_outbound_video_codec.transport_id = "RTCTransport_TransportName_1";
hbos0adb8282016-11-23 10:32:061097
nissec8ee8822017-01-18 15:20:551098 ASSERT_TRUE(report->Get(expected_inbound_audio_codec.id()));
Yves Gerey665174f2018-06-19 13:03:051099 EXPECT_EQ(
1100 expected_inbound_audio_codec,
1101 report->Get(expected_inbound_audio_codec.id())->cast_to<RTCCodecStats>());
hbos0adb8282016-11-23 10:32:061102
nissec8ee8822017-01-18 15:20:551103 ASSERT_TRUE(report->Get(expected_outbound_audio_codec.id()));
hbos0adb8282016-11-23 10:32:061104 EXPECT_EQ(expected_outbound_audio_codec,
Yves Gerey665174f2018-06-19 13:03:051105 report->Get(expected_outbound_audio_codec.id())
1106 ->cast_to<RTCCodecStats>());
hbos0adb8282016-11-23 10:32:061107
nissec8ee8822017-01-18 15:20:551108 ASSERT_TRUE(report->Get(expected_inbound_video_codec.id()));
Yves Gerey665174f2018-06-19 13:03:051109 EXPECT_EQ(
1110 expected_inbound_video_codec,
1111 report->Get(expected_inbound_video_codec.id())->cast_to<RTCCodecStats>());
hbos0adb8282016-11-23 10:32:061112
nissec8ee8822017-01-18 15:20:551113 ASSERT_TRUE(report->Get(expected_outbound_video_codec.id()));
hbos0adb8282016-11-23 10:32:061114 EXPECT_EQ(expected_outbound_video_codec,
Yves Gerey665174f2018-06-19 13:03:051115 report->Get(expected_outbound_video_codec.id())
1116 ->cast_to<RTCCodecStats>());
hbos0adb8282016-11-23 10:32:061117}
1118
hbos6ab97ce02016-10-03 21:16:561119TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsMultiple) {
Steve Anton5b387312018-02-03 00:00:201120 const char kAudioTransport[] = "audio";
1121 const char kVideoTransport[] = "video";
1122
1123 pc_->AddVoiceChannel("audio", kAudioTransport);
Tommi19015512022-02-02 10:49:351124
hbos6ab97ce02016-10-03 21:16:561125 std::unique_ptr<CertificateInfo> audio_local_certinfo =
1126 CreateFakeCertificateAndInfoFromDers(
Yves Gerey665174f2018-06-19 13:03:051127 std::vector<std::string>({"(local) audio"}));
Steve Anton5b387312018-02-03 00:00:201128 pc_->SetLocalCertificate(kAudioTransport, audio_local_certinfo->certificate);
hbos6ab97ce02016-10-03 21:16:561129 std::unique_ptr<CertificateInfo> audio_remote_certinfo =
1130 CreateFakeCertificateAndInfoFromDers(
Yves Gerey665174f2018-06-19 13:03:051131 std::vector<std::string>({"(remote) audio"}));
Taylor Brandstetterc3928662018-02-23 21:04:511132 pc_->SetRemoteCertChain(
1133 kAudioTransport,
Benjamin Wright6c6c9df2018-10-25 08:16:261134 audio_remote_certinfo->certificate->GetSSLCertificateChain().Clone());
hbos6ab97ce02016-10-03 21:16:561135
Steve Anton5b387312018-02-03 00:00:201136 pc_->AddVideoChannel("video", kVideoTransport);
hbos6ab97ce02016-10-03 21:16:561137 std::unique_ptr<CertificateInfo> video_local_certinfo =
1138 CreateFakeCertificateAndInfoFromDers(
Yves Gerey665174f2018-06-19 13:03:051139 std::vector<std::string>({"(local) video"}));
Steve Anton5b387312018-02-03 00:00:201140 pc_->SetLocalCertificate(kVideoTransport, video_local_certinfo->certificate);
hbos6ab97ce02016-10-03 21:16:561141 std::unique_ptr<CertificateInfo> video_remote_certinfo =
1142 CreateFakeCertificateAndInfoFromDers(
Yves Gerey665174f2018-06-19 13:03:051143 std::vector<std::string>({"(remote) video"}));
Taylor Brandstetterc3928662018-02-23 21:04:511144 pc_->SetRemoteCertChain(
1145 kVideoTransport,
Benjamin Wright6c6c9df2018-10-25 08:16:261146 video_remote_certinfo->certificate->GetSSLCertificateChain().Clone());
hbos6ab97ce02016-10-03 21:16:561147
Steve Anton5b387312018-02-03 00:00:201148 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbos23368e12016-12-21 12:29:171149 ExpectReportContainsCertificateInfo(report, *audio_local_certinfo);
1150 ExpectReportContainsCertificateInfo(report, *audio_remote_certinfo);
1151 ExpectReportContainsCertificateInfo(report, *video_local_certinfo);
1152 ExpectReportContainsCertificateInfo(report, *video_remote_certinfo);
hbos6ab97ce02016-10-03 21:16:561153}
1154
1155TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsChain) {
Steve Anton5b387312018-02-03 00:00:201156 const char kTransportName[] = "transport";
1157
1158 pc_->AddVoiceChannel("audio", kTransportName);
1159
hbos6ab97ce02016-10-03 21:16:561160 std::unique_ptr<CertificateInfo> local_certinfo =
Steve Anton5b387312018-02-03 00:00:201161 CreateFakeCertificateAndInfoFromDers(
1162 {"(local) this", "(local) is", "(local) a", "(local) chain"});
1163 pc_->SetLocalCertificate(kTransportName, local_certinfo->certificate);
1164
hbos6ab97ce02016-10-03 21:16:561165 std::unique_ptr<CertificateInfo> remote_certinfo =
Steve Anton5b387312018-02-03 00:00:201166 CreateFakeCertificateAndInfoFromDers({"(remote) this", "(remote) is",
1167 "(remote) another",
1168 "(remote) chain"});
Taylor Brandstetterc3928662018-02-23 21:04:511169 pc_->SetRemoteCertChain(
Benjamin Wright6c6c9df2018-10-25 08:16:261170 kTransportName,
1171 remote_certinfo->certificate->GetSSLCertificateChain().Clone());
hbos6ab97ce02016-10-03 21:16:561172
Steve Anton5b387312018-02-03 00:00:201173 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbos23368e12016-12-21 12:29:171174 ExpectReportContainsCertificateInfo(report, *local_certinfo);
1175 ExpectReportContainsCertificateInfo(report, *remote_certinfo);
hbos6ab97ce02016-10-03 21:16:561176}
1177
Harald Alvestrand928e7a32019-07-31 11:16:451178TEST_F(RTCStatsCollectorTest, CollectTwoRTCDataChannelStatsWithPendingId) {
Niels Möllere7cc8832022-01-04 14:20:031179 pc_->AddSctpDataChannel(rtc::make_ref_counted<MockSctpDataChannel>(
1180 /*id=*/-1, DataChannelInterface::kConnecting));
1181 pc_->AddSctpDataChannel(rtc::make_ref_counted<MockSctpDataChannel>(
1182 /*id=*/-1, DataChannelInterface::kConnecting));
Harald Alvestrand928e7a32019-07-31 11:16:451183
1184 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
1185}
1186
hboscc555c52016-10-18 19:48:311187TEST_F(RTCStatsCollectorTest, CollectRTCDataChannelStats) {
Harald Alvestrand928e7a32019-07-31 11:16:451188 // Note: The test assumes data channel IDs are predictable.
1189 // This is not a safe assumption, but in order to make it work for
1190 // the test, we reset the ID allocator at test start.
Taylor Brandstetter3a034e12020-07-09 22:32:341191 SctpDataChannel::ResetInternalIdAllocatorForTesting(-1);
Niels Möllere7cc8832022-01-04 14:20:031192 pc_->AddSctpDataChannel(rtc::make_ref_counted<MockSctpDataChannel>(
Taylor Brandstetter3a034e12020-07-09 22:32:341193 0, "MockSctpDataChannel0", DataChannelInterface::kConnecting, "udp", 1, 2,
1194 3, 4));
hbosdbb64d82016-12-21 09:57:461195 RTCDataChannelStats expected_data_channel0("RTCDataChannel_0", 0);
Taylor Brandstetter3a034e12020-07-09 22:32:341196 expected_data_channel0.label = "MockSctpDataChannel0";
hbosdbb64d82016-12-21 09:57:461197 expected_data_channel0.protocol = "udp";
Harald Alvestrand10ef8472020-06-05 13:38:511198 expected_data_channel0.data_channel_identifier = 0;
hbosdbb64d82016-12-21 09:57:461199 expected_data_channel0.state = "connecting";
1200 expected_data_channel0.messages_sent = 1;
1201 expected_data_channel0.bytes_sent = 2;
1202 expected_data_channel0.messages_received = 3;
1203 expected_data_channel0.bytes_received = 4;
1204
Niels Möllere7cc8832022-01-04 14:20:031205 pc_->AddSctpDataChannel(rtc::make_ref_counted<MockSctpDataChannel>(
1206 1, "MockSctpDataChannel1", DataChannelInterface::kOpen, "tcp", 5, 6, 7,
1207 8));
hbosdbb64d82016-12-21 09:57:461208 RTCDataChannelStats expected_data_channel1("RTCDataChannel_1", 0);
Taylor Brandstetter3a034e12020-07-09 22:32:341209 expected_data_channel1.label = "MockSctpDataChannel1";
hbosdbb64d82016-12-21 09:57:461210 expected_data_channel1.protocol = "tcp";
Harald Alvestrand10ef8472020-06-05 13:38:511211 expected_data_channel1.data_channel_identifier = 1;
hbosdbb64d82016-12-21 09:57:461212 expected_data_channel1.state = "open";
1213 expected_data_channel1.messages_sent = 5;
1214 expected_data_channel1.bytes_sent = 6;
1215 expected_data_channel1.messages_received = 7;
1216 expected_data_channel1.bytes_received = 8;
1217
Niels Möllere7cc8832022-01-04 14:20:031218 pc_->AddSctpDataChannel(rtc::make_ref_counted<MockSctpDataChannel>(
Taylor Brandstetter3a034e12020-07-09 22:32:341219 2, "MockSctpDataChannel2", DataChannelInterface::kClosing, "udp", 9, 10,
1220 11, 12));
hbosdbb64d82016-12-21 09:57:461221 RTCDataChannelStats expected_data_channel2("RTCDataChannel_2", 0);
Taylor Brandstetter3a034e12020-07-09 22:32:341222 expected_data_channel2.label = "MockSctpDataChannel2";
hbosdbb64d82016-12-21 09:57:461223 expected_data_channel2.protocol = "udp";
Harald Alvestrand10ef8472020-06-05 13:38:511224 expected_data_channel2.data_channel_identifier = 2;
hbosdbb64d82016-12-21 09:57:461225 expected_data_channel2.state = "closing";
1226 expected_data_channel2.messages_sent = 9;
1227 expected_data_channel2.bytes_sent = 10;
1228 expected_data_channel2.messages_received = 11;
1229 expected_data_channel2.bytes_received = 12;
1230
Niels Möllere7cc8832022-01-04 14:20:031231 pc_->AddSctpDataChannel(rtc::make_ref_counted<MockSctpDataChannel>(
1232 3, "MockSctpDataChannel3", DataChannelInterface::kClosed, "tcp", 13, 14,
1233 15, 16));
hbosdbb64d82016-12-21 09:57:461234 RTCDataChannelStats expected_data_channel3("RTCDataChannel_3", 0);
Taylor Brandstetter3a034e12020-07-09 22:32:341235 expected_data_channel3.label = "MockSctpDataChannel3";
hbosdbb64d82016-12-21 09:57:461236 expected_data_channel3.protocol = "tcp";
Harald Alvestrand10ef8472020-06-05 13:38:511237 expected_data_channel3.data_channel_identifier = 3;
hbosdbb64d82016-12-21 09:57:461238 expected_data_channel3.state = "closed";
1239 expected_data_channel3.messages_sent = 13;
1240 expected_data_channel3.bytes_sent = 14;
1241 expected_data_channel3.messages_received = 15;
1242 expected_data_channel3.bytes_received = 16;
hboscc555c52016-10-18 19:48:311243
Steve Anton5b387312018-02-03 00:00:201244 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
1245
hbosdbb64d82016-12-21 09:57:461246 ASSERT_TRUE(report->Get(expected_data_channel0.id()));
Yves Gerey665174f2018-06-19 13:03:051247 EXPECT_EQ(
1248 expected_data_channel0,
1249 report->Get(expected_data_channel0.id())->cast_to<RTCDataChannelStats>());
hbosdbb64d82016-12-21 09:57:461250 ASSERT_TRUE(report->Get(expected_data_channel1.id()));
Yves Gerey665174f2018-06-19 13:03:051251 EXPECT_EQ(
1252 expected_data_channel1,
1253 report->Get(expected_data_channel1.id())->cast_to<RTCDataChannelStats>());
hbosdbb64d82016-12-21 09:57:461254 ASSERT_TRUE(report->Get(expected_data_channel2.id()));
Yves Gerey665174f2018-06-19 13:03:051255 EXPECT_EQ(
1256 expected_data_channel2,
1257 report->Get(expected_data_channel2.id())->cast_to<RTCDataChannelStats>());
hbosdbb64d82016-12-21 09:57:461258 ASSERT_TRUE(report->Get(expected_data_channel3.id()));
Yves Gerey665174f2018-06-19 13:03:051259 EXPECT_EQ(
1260 expected_data_channel3,
1261 report->Get(expected_data_channel3.id())->cast_to<RTCDataChannelStats>());
hboscc555c52016-10-18 19:48:311262}
1263
hbosab9f6e42016-10-07 09:18:471264TEST_F(RTCStatsCollectorTest, CollectRTCIceCandidateStats) {
1265 // Candidates in the first transport stats.
Jonas Oreland0d13bbd2022-03-02 10:17:361266 std::unique_ptr<cricket::Candidate> a_local_host = CreateFakeCandidate(
1267 "1.2.3.4", 5, "a_local_host's protocol", rtc::ADAPTER_TYPE_VPN,
1268 cricket::LOCAL_PORT_TYPE, 0, rtc::ADAPTER_TYPE_ETHERNET);
hbosc42ba322016-12-21 11:31:451269 RTCLocalIceCandidateStats expected_a_local_host(
1270 "RTCIceCandidate_" + a_local_host->id(), 0);
hbosb4e426e2017-01-02 17:59:311271 expected_a_local_host.transport_id = "RTCTransport_a_0";
Gary Liu37e489c2017-11-21 18:49:361272 expected_a_local_host.network_type = "vpn";
hbosc42ba322016-12-21 11:31:451273 expected_a_local_host.ip = "1.2.3.4";
Philipp Hanckea9ba4502021-03-22 12:22:541274 expected_a_local_host.address = "1.2.3.4";
hbosc42ba322016-12-21 11:31:451275 expected_a_local_host.port = 5;
1276 expected_a_local_host.protocol = "a_local_host's protocol";
1277 expected_a_local_host.candidate_type = "host";
1278 expected_a_local_host.priority = 0;
Jonas Oreland0d13bbd2022-03-02 10:17:361279 expected_a_local_host.vpn = true;
1280 expected_a_local_host.network_adapter_type = RTCNetworkAdapterType::kEthernet;
hbosc42ba322016-12-21 11:31:451281
hbosab9f6e42016-10-07 09:18:471282 std::unique_ptr<cricket::Candidate> a_remote_srflx = CreateFakeCandidate(
Gary Liu37e489c2017-11-21 18:49:361283 "6.7.8.9", 10, "remote_srflx's protocol", rtc::ADAPTER_TYPE_UNKNOWN,
1284 cricket::STUN_PORT_TYPE, 1);
hbosc42ba322016-12-21 11:31:451285 RTCRemoteIceCandidateStats expected_a_remote_srflx(
1286 "RTCIceCandidate_" + a_remote_srflx->id(), 0);
hbosb4e426e2017-01-02 17:59:311287 expected_a_remote_srflx.transport_id = "RTCTransport_a_0";
hbosc42ba322016-12-21 11:31:451288 expected_a_remote_srflx.ip = "6.7.8.9";
Philipp Hanckea9ba4502021-03-22 12:22:541289 expected_a_remote_srflx.address = "6.7.8.9";
hbosc42ba322016-12-21 11:31:451290 expected_a_remote_srflx.port = 10;
1291 expected_a_remote_srflx.protocol = "remote_srflx's protocol";
1292 expected_a_remote_srflx.candidate_type = "srflx";
1293 expected_a_remote_srflx.priority = 1;
1294
hbosab9f6e42016-10-07 09:18:471295 std::unique_ptr<cricket::Candidate> a_local_prflx = CreateFakeCandidate(
Jonas Oreland0d13bbd2022-03-02 10:17:361296 "11.12.13.14", 15, "a_local_prflx's protocol",
1297 rtc::ADAPTER_TYPE_CELLULAR_2G, cricket::PRFLX_PORT_TYPE, 2);
hbosc42ba322016-12-21 11:31:451298 RTCLocalIceCandidateStats expected_a_local_prflx(
1299 "RTCIceCandidate_" + a_local_prflx->id(), 0);
hbosb4e426e2017-01-02 17:59:311300 expected_a_local_prflx.transport_id = "RTCTransport_a_0";
Gary Liu37e489c2017-11-21 18:49:361301 expected_a_local_prflx.network_type = "cellular";
hbosc42ba322016-12-21 11:31:451302 expected_a_local_prflx.ip = "11.12.13.14";
Philipp Hanckea9ba4502021-03-22 12:22:541303 expected_a_local_prflx.address = "11.12.13.14";
hbosc42ba322016-12-21 11:31:451304 expected_a_local_prflx.port = 15;
1305 expected_a_local_prflx.protocol = "a_local_prflx's protocol";
1306 expected_a_local_prflx.candidate_type = "prflx";
1307 expected_a_local_prflx.priority = 2;
Jonas Oreland0d13bbd2022-03-02 10:17:361308 expected_a_local_prflx.vpn = false;
1309 expected_a_local_prflx.network_adapter_type =
1310 RTCNetworkAdapterType::kCellular2g;
hbosc42ba322016-12-21 11:31:451311
hbosab9f6e42016-10-07 09:18:471312 std::unique_ptr<cricket::Candidate> a_remote_relay = CreateFakeCandidate(
Gary Liu37e489c2017-11-21 18:49:361313 "16.17.18.19", 20, "a_remote_relay's protocol", rtc::ADAPTER_TYPE_UNKNOWN,
1314 cricket::RELAY_PORT_TYPE, 3);
hbosc42ba322016-12-21 11:31:451315 RTCRemoteIceCandidateStats expected_a_remote_relay(
1316 "RTCIceCandidate_" + a_remote_relay->id(), 0);
hbosb4e426e2017-01-02 17:59:311317 expected_a_remote_relay.transport_id = "RTCTransport_a_0";
hbosc42ba322016-12-21 11:31:451318 expected_a_remote_relay.ip = "16.17.18.19";
Philipp Hanckea9ba4502021-03-22 12:22:541319 expected_a_remote_relay.address = "16.17.18.19";
hbosc42ba322016-12-21 11:31:451320 expected_a_remote_relay.port = 20;
1321 expected_a_remote_relay.protocol = "a_remote_relay's protocol";
1322 expected_a_remote_relay.candidate_type = "relay";
1323 expected_a_remote_relay.priority = 3;
1324
Philipp Hancke95513752018-09-27 12:40:081325 std::unique_ptr<cricket::Candidate> a_local_relay = CreateFakeCandidate(
1326 "16.17.18.19", 21, "a_local_relay's protocol", rtc::ADAPTER_TYPE_UNKNOWN,
1327 cricket::RELAY_PORT_TYPE, 1);
1328 a_local_relay->set_relay_protocol("tcp");
Philipp Hancke05b29c72022-02-02 11:06:151329 a_local_relay->set_url("turn:url1");
Philipp Hancke95513752018-09-27 12:40:081330
Philipp Hanckefbd52c02021-11-10 22:02:171331 RTCLocalIceCandidateStats expected_a_local_relay(
Philipp Hancke95513752018-09-27 12:40:081332 "RTCIceCandidate_" + a_local_relay->id(), 0);
1333 expected_a_local_relay.transport_id = "RTCTransport_a_0";
Philipp Hanckefbd52c02021-11-10 22:02:171334 expected_a_local_relay.network_type = "unknown";
Philipp Hancke95513752018-09-27 12:40:081335 expected_a_local_relay.ip = "16.17.18.19";
Philipp Hanckea9ba4502021-03-22 12:22:541336 expected_a_local_relay.address = "16.17.18.19";
Philipp Hancke95513752018-09-27 12:40:081337 expected_a_local_relay.port = 21;
1338 expected_a_local_relay.protocol = "a_local_relay's protocol";
1339 expected_a_local_relay.relay_protocol = "tcp";
1340 expected_a_local_relay.candidate_type = "relay";
1341 expected_a_local_relay.priority = 1;
Philipp Hancke05b29c72022-02-02 11:06:151342 expected_a_local_relay.url = "turn:url1";
Jonas Oreland0d13bbd2022-03-02 10:17:361343 expected_a_local_relay.vpn = false;
1344 expected_a_local_relay.network_adapter_type = RTCNetworkAdapterType::kUnknown;
Philipp Hancke95513752018-09-27 12:40:081345
Philipp Hancke21c4b1e2021-11-11 06:45:591346 std::unique_ptr<cricket::Candidate> a_local_relay_prflx = CreateFakeCandidate(
1347 "11.12.13.20", 22, "a_local_relay_prflx's protocol",
1348 rtc::ADAPTER_TYPE_UNKNOWN, cricket::PRFLX_PORT_TYPE, 1);
1349 a_local_relay_prflx->set_relay_protocol("udp");
1350
1351 RTCLocalIceCandidateStats expected_a_local_relay_prflx(
1352 "RTCIceCandidate_" + a_local_relay_prflx->id(), 0);
1353 expected_a_local_relay_prflx.transport_id = "RTCTransport_a_0";
1354 expected_a_local_relay_prflx.network_type = "unknown";
1355 expected_a_local_relay_prflx.ip = "11.12.13.20";
1356 expected_a_local_relay_prflx.address = "11.12.13.20";
1357 expected_a_local_relay_prflx.port = 22;
1358 expected_a_local_relay_prflx.protocol = "a_local_relay_prflx's protocol";
1359 expected_a_local_relay_prflx.relay_protocol = "udp";
1360 expected_a_local_relay_prflx.candidate_type = "prflx";
1361 expected_a_local_relay_prflx.priority = 1;
Jonas Oreland0d13bbd2022-03-02 10:17:361362 expected_a_local_relay_prflx.vpn = false;
1363 expected_a_local_relay_prflx.network_adapter_type =
1364 RTCNetworkAdapterType::kUnknown;
Philipp Hancke21c4b1e2021-11-11 06:45:591365
Philipp Hancke6e57ca22022-06-09 13:58:181366 // A non-paired local candidate.
1367 std::unique_ptr<cricket::Candidate> a_local_host_not_paired =
1368 CreateFakeCandidate("1.2.3.4", 4404, "a_local_host_not_paired's protocol",
1369 rtc::ADAPTER_TYPE_VPN, cricket::LOCAL_PORT_TYPE, 0,
1370 rtc::ADAPTER_TYPE_ETHERNET);
1371 RTCLocalIceCandidateStats expected_a_local_host_not_paired(
1372 "RTCIceCandidate_" + a_local_host_not_paired->id(), 0);
1373 expected_a_local_host_not_paired.transport_id = "RTCTransport_a_0";
1374 expected_a_local_host_not_paired.network_type = "vpn";
1375 expected_a_local_host_not_paired.ip = "1.2.3.4";
1376 expected_a_local_host_not_paired.address = "1.2.3.4";
1377 expected_a_local_host_not_paired.port = 4404;
1378 expected_a_local_host_not_paired.protocol =
1379 "a_local_host_not_paired's protocol";
1380 expected_a_local_host_not_paired.candidate_type = "host";
1381 expected_a_local_host_not_paired.priority = 0;
1382 expected_a_local_host_not_paired.vpn = true;
1383 expected_a_local_host_not_paired.network_adapter_type =
1384 RTCNetworkAdapterType::kEthernet;
1385
hbosab9f6e42016-10-07 09:18:471386 // Candidates in the second transport stats.
Gary Liu37e489c2017-11-21 18:49:361387 std::unique_ptr<cricket::Candidate> b_local =
1388 CreateFakeCandidate("42.42.42.42", 42, "b_local's protocol",
1389 rtc::ADAPTER_TYPE_WIFI, cricket::LOCAL_PORT_TYPE, 42);
Yves Gerey665174f2018-06-19 13:03:051390 RTCLocalIceCandidateStats expected_b_local("RTCIceCandidate_" + b_local->id(),
1391 0);
hbosb4e426e2017-01-02 17:59:311392 expected_b_local.transport_id = "RTCTransport_b_0";
Gary Liu37e489c2017-11-21 18:49:361393 expected_b_local.network_type = "wifi";
hbosc42ba322016-12-21 11:31:451394 expected_b_local.ip = "42.42.42.42";
Philipp Hanckea9ba4502021-03-22 12:22:541395 expected_b_local.address = "42.42.42.42";
hbosc42ba322016-12-21 11:31:451396 expected_b_local.port = 42;
1397 expected_b_local.protocol = "b_local's protocol";
1398 expected_b_local.candidate_type = "host";
1399 expected_b_local.priority = 42;
Jonas Oreland0d13bbd2022-03-02 10:17:361400 expected_b_local.vpn = false;
1401 expected_b_local.network_adapter_type = RTCNetworkAdapterType::kWifi;
hbosc42ba322016-12-21 11:31:451402
hbosab9f6e42016-10-07 09:18:471403 std::unique_ptr<cricket::Candidate> b_remote = CreateFakeCandidate(
Gary Liu37e489c2017-11-21 18:49:361404 "42.42.42.42", 42, "b_remote's protocol", rtc::ADAPTER_TYPE_UNKNOWN,
1405 cricket::LOCAL_PORT_TYPE, 42);
hbosc42ba322016-12-21 11:31:451406 RTCRemoteIceCandidateStats expected_b_remote(
1407 "RTCIceCandidate_" + b_remote->id(), 0);
hbosb4e426e2017-01-02 17:59:311408 expected_b_remote.transport_id = "RTCTransport_b_0";
hbosc42ba322016-12-21 11:31:451409 expected_b_remote.ip = "42.42.42.42";
Philipp Hanckea9ba4502021-03-22 12:22:541410 expected_b_remote.address = "42.42.42.42";
hbosc42ba322016-12-21 11:31:451411 expected_b_remote.port = 42;
1412 expected_b_remote.protocol = "b_remote's protocol";
1413 expected_b_remote.candidate_type = "host";
1414 expected_b_remote.priority = 42;
hbosab9f6e42016-10-07 09:18:471415
Philipp Hancke95513752018-09-27 12:40:081416 // Add candidate pairs to connection.
hbosab9f6e42016-10-07 09:18:471417 cricket::TransportChannelStats a_transport_channel_stats;
Jonas Oreland149dc722019-08-28 06:10:271418 a_transport_channel_stats.ice_transport_stats.connection_infos.push_back(
hbosab9f6e42016-10-07 09:18:471419 cricket::ConnectionInfo());
Jonas Oreland149dc722019-08-28 06:10:271420 a_transport_channel_stats.ice_transport_stats.connection_infos[0]
1421 .local_candidate = *a_local_host.get();
1422 a_transport_channel_stats.ice_transport_stats.connection_infos[0]
1423 .remote_candidate = *a_remote_srflx.get();
1424 a_transport_channel_stats.ice_transport_stats.connection_infos.push_back(
hbosab9f6e42016-10-07 09:18:471425 cricket::ConnectionInfo());
Jonas Oreland149dc722019-08-28 06:10:271426 a_transport_channel_stats.ice_transport_stats.connection_infos[1]
1427 .local_candidate = *a_local_prflx.get();
1428 a_transport_channel_stats.ice_transport_stats.connection_infos[1]
1429 .remote_candidate = *a_remote_relay.get();
1430 a_transport_channel_stats.ice_transport_stats.connection_infos.push_back(
Philipp Hancke95513752018-09-27 12:40:081431 cricket::ConnectionInfo());
Jonas Oreland149dc722019-08-28 06:10:271432 a_transport_channel_stats.ice_transport_stats.connection_infos[2]
1433 .local_candidate = *a_local_relay.get();
1434 a_transport_channel_stats.ice_transport_stats.connection_infos[2]
1435 .remote_candidate = *a_remote_relay.get();
Philipp Hancke21c4b1e2021-11-11 06:45:591436 a_transport_channel_stats.ice_transport_stats.connection_infos.push_back(
1437 cricket::ConnectionInfo());
1438 a_transport_channel_stats.ice_transport_stats.connection_infos[3]
1439 .local_candidate = *a_local_relay_prflx.get();
1440 a_transport_channel_stats.ice_transport_stats.connection_infos[3]
1441 .remote_candidate = *a_remote_relay.get();
Philipp Hancke6e57ca22022-06-09 13:58:181442 a_transport_channel_stats.ice_transport_stats.candidate_stats_list.push_back(
1443 cricket::CandidateStats(*a_local_host_not_paired.get()));
Steve Anton5b387312018-02-03 00:00:201444
1445 pc_->AddVoiceChannel("audio", "a");
1446 pc_->SetTransportStats("a", a_transport_channel_stats);
hbosab9f6e42016-10-07 09:18:471447
1448 cricket::TransportChannelStats b_transport_channel_stats;
Jonas Oreland149dc722019-08-28 06:10:271449 b_transport_channel_stats.ice_transport_stats.connection_infos.push_back(
hbosab9f6e42016-10-07 09:18:471450 cricket::ConnectionInfo());
Jonas Oreland149dc722019-08-28 06:10:271451 b_transport_channel_stats.ice_transport_stats.connection_infos[0]
1452 .local_candidate = *b_local.get();
1453 b_transport_channel_stats.ice_transport_stats.connection_infos[0]
1454 .remote_candidate = *b_remote.get();
hbosab9f6e42016-10-07 09:18:471455
Steve Anton5b387312018-02-03 00:00:201456 pc_->AddVideoChannel("video", "b");
1457 pc_->SetTransportStats("b", b_transport_channel_stats);
hbosab9f6e42016-10-07 09:18:471458
Steve Anton5b387312018-02-03 00:00:201459 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbosc42ba322016-12-21 11:31:451460
hbosb4e426e2017-01-02 17:59:311461 ASSERT_TRUE(report->Get(expected_a_local_host.id()));
Yves Gerey665174f2018-06-19 13:03:051462 EXPECT_EQ(expected_a_local_host, report->Get(expected_a_local_host.id())
1463 ->cast_to<RTCLocalIceCandidateStats>());
Philipp Hancke6e57ca22022-06-09 13:58:181464
1465 ASSERT_TRUE(report->Get(expected_a_local_host_not_paired.id()));
1466 EXPECT_EQ(expected_a_local_host_not_paired,
1467 report->Get(expected_a_local_host_not_paired.id())
1468 ->cast_to<RTCLocalIceCandidateStats>());
1469
hbosb4e426e2017-01-02 17:59:311470 ASSERT_TRUE(report->Get(expected_a_remote_srflx.id()));
hbosc42ba322016-12-21 11:31:451471 EXPECT_EQ(expected_a_remote_srflx,
Yves Gerey665174f2018-06-19 13:03:051472 report->Get(expected_a_remote_srflx.id())
1473 ->cast_to<RTCRemoteIceCandidateStats>());
hbosb4e426e2017-01-02 17:59:311474 ASSERT_TRUE(report->Get(expected_a_local_prflx.id()));
Yves Gerey665174f2018-06-19 13:03:051475 EXPECT_EQ(expected_a_local_prflx, report->Get(expected_a_local_prflx.id())
1476 ->cast_to<RTCLocalIceCandidateStats>());
hbosb4e426e2017-01-02 17:59:311477 ASSERT_TRUE(report->Get(expected_a_remote_relay.id()));
hbosc42ba322016-12-21 11:31:451478 EXPECT_EQ(expected_a_remote_relay,
Yves Gerey665174f2018-06-19 13:03:051479 report->Get(expected_a_remote_relay.id())
1480 ->cast_to<RTCRemoteIceCandidateStats>());
Philipp Hanckefbd52c02021-11-10 22:02:171481 ASSERT_TRUE(report->Get(expected_a_local_relay.id()));
1482 EXPECT_EQ(expected_a_local_relay, report->Get(expected_a_local_relay.id())
1483 ->cast_to<RTCLocalIceCandidateStats>());
Philipp Hancke21c4b1e2021-11-11 06:45:591484 ASSERT_TRUE(report->Get(expected_a_local_relay_prflx.id()));
1485 EXPECT_EQ(expected_a_local_relay_prflx,
1486 report->Get(expected_a_local_relay_prflx.id())
1487 ->cast_to<RTCLocalIceCandidateStats>());
hbosb4e426e2017-01-02 17:59:311488 ASSERT_TRUE(report->Get(expected_b_local.id()));
Yves Gerey665174f2018-06-19 13:03:051489 EXPECT_EQ(
1490 expected_b_local,
1491 report->Get(expected_b_local.id())->cast_to<RTCLocalIceCandidateStats>());
hbosb4e426e2017-01-02 17:59:311492 ASSERT_TRUE(report->Get(expected_b_remote.id()));
Yves Gerey665174f2018-06-19 13:03:051493 EXPECT_EQ(expected_b_remote, report->Get(expected_b_remote.id())
1494 ->cast_to<RTCRemoteIceCandidateStats>());
hbosb4e426e2017-01-02 17:59:311495 EXPECT_TRUE(report->Get("RTCTransport_a_0"));
1496 EXPECT_TRUE(report->Get("RTCTransport_b_0"));
hbosab9f6e42016-10-07 09:18:471497}
1498
hbosc47a0c32016-10-11 21:54:491499TEST_F(RTCStatsCollectorTest, CollectRTCIceCandidatePairStats) {
Steve Anton5b387312018-02-03 00:00:201500 const char kTransportName[] = "transport";
hbos338f78a2017-02-07 14:41:211501
Gary Liu37e489c2017-11-21 18:49:361502 std::unique_ptr<cricket::Candidate> local_candidate =
1503 CreateFakeCandidate("42.42.42.42", 42, "protocol", rtc::ADAPTER_TYPE_WIFI,
1504 cricket::LOCAL_PORT_TYPE, 42);
hbosc47a0c32016-10-11 21:54:491505 std::unique_ptr<cricket::Candidate> remote_candidate = CreateFakeCandidate(
Gary Liu37e489c2017-11-21 18:49:361506 "42.42.42.42", 42, "protocol", rtc::ADAPTER_TYPE_UNKNOWN,
1507 cricket::LOCAL_PORT_TYPE, 42);
hbosc47a0c32016-10-11 21:54:491508
hbosc47a0c32016-10-11 21:54:491509 cricket::ConnectionInfo connection_info;
hbos338f78a2017-02-07 14:41:211510 connection_info.best_connection = false;
hbosc47a0c32016-10-11 21:54:491511 connection_info.local_candidate = *local_candidate.get();
1512 connection_info.remote_candidate = *remote_candidate.get();
1513 connection_info.writable = true;
Taylor Brandstetter79326ea2021-09-28 22:09:531514 connection_info.sent_discarded_packets = 3;
1515 connection_info.sent_total_packets = 10;
1516 connection_info.packets_received = 51;
1517 connection_info.sent_discarded_bytes = 7;
hbosc47a0c32016-10-11 21:54:491518 connection_info.sent_total_bytes = 42;
1519 connection_info.recv_total_bytes = 1234;
hbosbf8d3e52017-02-28 14:34:471520 connection_info.total_round_trip_time_ms = 0;
Danil Chapovalov66cadcc2018-06-19 14:47:431521 connection_info.current_round_trip_time_ms = absl::nullopt;
hbosd82f5122016-12-09 12:12:391522 connection_info.recv_ping_requests = 2020;
hbose448dd52016-12-12 09:22:531523 connection_info.sent_ping_requests_total = 2020;
1524 connection_info.sent_ping_requests_before_first_response = 2000;
hbosc47a0c32016-10-11 21:54:491525 connection_info.recv_ping_responses = 4321;
1526 connection_info.sent_ping_responses = 1000;
hbos06495bc2017-01-02 16:08:181527 connection_info.state = cricket::IceCandidatePairState::IN_PROGRESS;
1528 connection_info.priority = 5555;
hbos92eaec62017-02-27 09:38:081529 connection_info.nominated = false;
hbosc47a0c32016-10-11 21:54:491530
1531 cricket::TransportChannelStats transport_channel_stats;
hbos0583b282016-11-30 09:50:141532 transport_channel_stats.component = cricket::ICE_CANDIDATE_COMPONENT_RTP;
Jonas Oreland149dc722019-08-28 06:10:271533 transport_channel_stats.ice_transport_stats.connection_infos.push_back(
1534 connection_info);
hbosc47a0c32016-10-11 21:54:491535
Steve Anton5b387312018-02-03 00:00:201536 pc_->AddVideoChannel("video", kTransportName);
1537 pc_->SetTransportStats(kTransportName, transport_channel_stats);
hbosc47a0c32016-10-11 21:54:491538
Steve Anton5b387312018-02-03 00:00:201539 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbos0583b282016-11-30 09:50:141540
1541 RTCIceCandidatePairStats expected_pair("RTCIceCandidatePair_" +
1542 local_candidate->id() + "_" +
1543 remote_candidate->id(),
1544 report->timestamp_us());
1545 expected_pair.transport_id =
1546 "RTCTransport_transport_" +
Jonas Olsson6b1985d2018-07-05 09:59:481547 rtc::ToString(cricket::ICE_CANDIDATE_COMPONENT_RTP);
hbos0583b282016-11-30 09:50:141548 expected_pair.local_candidate_id = "RTCIceCandidate_" + local_candidate->id();
1549 expected_pair.remote_candidate_id =
1550 "RTCIceCandidate_" + remote_candidate->id();
hbos06495bc2017-01-02 16:08:181551 expected_pair.state = RTCStatsIceCandidatePairState::kInProgress;
1552 expected_pair.priority = 5555;
hbos92eaec62017-02-27 09:38:081553 expected_pair.nominated = false;
hbos0583b282016-11-30 09:50:141554 expected_pair.writable = true;
Taylor Brandstetter79326ea2021-09-28 22:09:531555 expected_pair.packets_sent = 7;
1556 expected_pair.packets_received = 51;
1557 expected_pair.packets_discarded_on_send = 3;
hbos0583b282016-11-30 09:50:141558 expected_pair.bytes_sent = 42;
1559 expected_pair.bytes_received = 1234;
Taylor Brandstetter79326ea2021-09-28 22:09:531560 expected_pair.bytes_discarded_on_send = 7;
hbosbf8d3e52017-02-28 14:34:471561 expected_pair.total_round_trip_time = 0.0;
hbosd82f5122016-12-09 12:12:391562 expected_pair.requests_received = 2020;
hbose448dd52016-12-12 09:22:531563 expected_pair.requests_sent = 2000;
hbos0583b282016-11-30 09:50:141564 expected_pair.responses_received = 4321;
1565 expected_pair.responses_sent = 1000;
hbose448dd52016-12-12 09:22:531566 expected_pair.consent_requests_sent = (2020 - 2000);
Artem Titovcfea2182021-08-09 23:22:311567 // `expected_pair.current_round_trip_time` should be undefined because the
hbosbf8d3e52017-02-28 14:34:471568 // current RTT is not set.
Artem Titovcfea2182021-08-09 23:22:311569 // `expected_pair.available_[outgoing/incoming]_bitrate` should be undefined
hbos338f78a2017-02-07 14:41:211570 // because is is not the current pair.
hbos0583b282016-11-30 09:50:141571
hbosdbb64d82016-12-21 09:57:461572 ASSERT_TRUE(report->Get(expected_pair.id()));
hbos0583b282016-11-30 09:50:141573 EXPECT_EQ(
1574 expected_pair,
1575 report->Get(expected_pair.id())->cast_to<RTCIceCandidatePairStats>());
hbosb4e426e2017-01-02 17:59:311576 EXPECT_TRUE(report->Get(*expected_pair.transport_id));
hbos0583b282016-11-30 09:50:141577
hbos92eaec62017-02-27 09:38:081578 // Set nominated and "GetStats" again.
Jonas Oreland149dc722019-08-28 06:10:271579 transport_channel_stats.ice_transport_stats.connection_infos[0].nominated =
1580 true;
Steve Anton5b387312018-02-03 00:00:201581 pc_->SetTransportStats(kTransportName, transport_channel_stats);
1582 report = stats_->GetFreshStatsReport();
hbos92eaec62017-02-27 09:38:081583 expected_pair.nominated = true;
1584 ASSERT_TRUE(report->Get(expected_pair.id()));
1585 EXPECT_EQ(
1586 expected_pair,
1587 report->Get(expected_pair.id())->cast_to<RTCIceCandidatePairStats>());
1588 EXPECT_TRUE(report->Get(*expected_pair.transport_id));
1589
hbosbf8d3e52017-02-28 14:34:471590 // Set round trip times and "GetStats" again.
Jonas Oreland149dc722019-08-28 06:10:271591 transport_channel_stats.ice_transport_stats.connection_infos[0]
1592 .total_round_trip_time_ms = 7331;
1593 transport_channel_stats.ice_transport_stats.connection_infos[0]
1594 .current_round_trip_time_ms = 1337;
Steve Anton5b387312018-02-03 00:00:201595 pc_->SetTransportStats(kTransportName, transport_channel_stats);
1596 report = stats_->GetFreshStatsReport();
hbosbf8d3e52017-02-28 14:34:471597 expected_pair.total_round_trip_time = 7.331;
1598 expected_pair.current_round_trip_time = 1.337;
1599 ASSERT_TRUE(report->Get(expected_pair.id()));
1600 EXPECT_EQ(
1601 expected_pair,
1602 report->Get(expected_pair.id())->cast_to<RTCIceCandidatePairStats>());
1603 EXPECT_TRUE(report->Get(*expected_pair.transport_id));
1604
hbos338f78a2017-02-07 14:41:211605 // Make pair the current pair, clear bandwidth and "GetStats" again.
Jonas Oreland149dc722019-08-28 06:10:271606 transport_channel_stats.ice_transport_stats.connection_infos[0]
1607 .best_connection = true;
Steve Anton5b387312018-02-03 00:00:201608 pc_->SetTransportStats(kTransportName, transport_channel_stats);
1609 report = stats_->GetFreshStatsReport();
hbos338f78a2017-02-07 14:41:211610 // |expected_pair.available_[outgoing/incoming]_bitrate| should still be
1611 // undefined because bandwidth is not set.
1612 ASSERT_TRUE(report->Get(expected_pair.id()));
1613 EXPECT_EQ(
1614 expected_pair,
1615 report->Get(expected_pair.id())->cast_to<RTCIceCandidatePairStats>());
1616 EXPECT_TRUE(report->Get(*expected_pair.transport_id));
1617
1618 // Set bandwidth and "GetStats" again.
stefanf79ade12017-06-02 13:44:031619 webrtc::Call::Stats call_stats;
1620 const int kSendBandwidth = 888;
1621 call_stats.send_bandwidth_bps = kSendBandwidth;
1622 const int kRecvBandwidth = 999;
1623 call_stats.recv_bandwidth_bps = kRecvBandwidth;
Steve Anton5b387312018-02-03 00:00:201624 pc_->SetCallStats(call_stats);
1625 report = stats_->GetFreshStatsReport();
stefanf79ade12017-06-02 13:44:031626 expected_pair.available_outgoing_bitrate = kSendBandwidth;
1627 expected_pair.available_incoming_bitrate = kRecvBandwidth;
hbos338f78a2017-02-07 14:41:211628 ASSERT_TRUE(report->Get(expected_pair.id()));
1629 EXPECT_EQ(
1630 expected_pair,
1631 report->Get(expected_pair.id())->cast_to<RTCIceCandidatePairStats>());
1632 EXPECT_TRUE(report->Get(*expected_pair.transport_id));
1633
hbosc42ba322016-12-21 11:31:451634 RTCLocalIceCandidateStats expected_local_candidate(
1635 *expected_pair.local_candidate_id, report->timestamp_us());
hbosb4e426e2017-01-02 17:59:311636 expected_local_candidate.transport_id = *expected_pair.transport_id;
Gary Liu37e489c2017-11-21 18:49:361637 expected_local_candidate.network_type = "wifi";
hbosc42ba322016-12-21 11:31:451638 expected_local_candidate.ip = "42.42.42.42";
Philipp Hanckea9ba4502021-03-22 12:22:541639 expected_local_candidate.address = "42.42.42.42";
hbosc42ba322016-12-21 11:31:451640 expected_local_candidate.port = 42;
1641 expected_local_candidate.protocol = "protocol";
1642 expected_local_candidate.candidate_type = "host";
1643 expected_local_candidate.priority = 42;
Jonas Oreland0d13bbd2022-03-02 10:17:361644 expected_local_candidate.vpn = false;
1645 expected_local_candidate.network_adapter_type = RTCNetworkAdapterType::kWifi;
hbosc42ba322016-12-21 11:31:451646 ASSERT_TRUE(report->Get(expected_local_candidate.id()));
1647 EXPECT_EQ(expected_local_candidate,
Yves Gerey665174f2018-06-19 13:03:051648 report->Get(expected_local_candidate.id())
1649 ->cast_to<RTCLocalIceCandidateStats>());
hbosc42ba322016-12-21 11:31:451650
1651 RTCRemoteIceCandidateStats expected_remote_candidate(
1652 *expected_pair.remote_candidate_id, report->timestamp_us());
hbosb4e426e2017-01-02 17:59:311653 expected_remote_candidate.transport_id = *expected_pair.transport_id;
hbosc42ba322016-12-21 11:31:451654 expected_remote_candidate.ip = "42.42.42.42";
Philipp Hanckea9ba4502021-03-22 12:22:541655 expected_remote_candidate.address = "42.42.42.42";
hbosc42ba322016-12-21 11:31:451656 expected_remote_candidate.port = 42;
1657 expected_remote_candidate.protocol = "protocol";
1658 expected_remote_candidate.candidate_type = "host";
1659 expected_remote_candidate.priority = 42;
1660 ASSERT_TRUE(report->Get(expected_remote_candidate.id()));
1661 EXPECT_EQ(expected_remote_candidate,
Yves Gerey665174f2018-06-19 13:03:051662 report->Get(expected_remote_candidate.id())
1663 ->cast_to<RTCRemoteIceCandidateStats>());
hbosc47a0c32016-10-11 21:54:491664}
1665
hbosd565b732016-08-30 21:04:351666TEST_F(RTCStatsCollectorTest, CollectRTCPeerConnectionStats) {
hbosd565b732016-08-30 21:04:351667 {
Steve Anton5b387312018-02-03 00:00:201668 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbos82ebe022016-11-14 09:41:091669 RTCPeerConnectionStats expected("RTCPeerConnection",
1670 report->timestamp_us());
1671 expected.data_channels_opened = 0;
1672 expected.data_channels_closed = 0;
hbosdbb64d82016-12-21 09:57:461673 ASSERT_TRUE(report->Get("RTCPeerConnection"));
Yves Gerey665174f2018-06-19 13:03:051674 EXPECT_EQ(
1675 expected,
1676 report->Get("RTCPeerConnection")->cast_to<RTCPeerConnectionStats>());
hbosd565b732016-08-30 21:04:351677 }
1678
Tomas Gunnarsson7d3cfbf2020-06-15 11:47:421679 // TODO(bugs.webrtc.org/11547): Supply a separate network thread.
Harald Alvestrand9e5aeb92022-05-11 09:35:361680 FakeDataChannelController controller;
Taylor Brandstetter3a034e12020-07-09 22:32:341681 rtc::scoped_refptr<SctpDataChannel> dummy_channel_a = SctpDataChannel::Create(
Harald Alvestrand9e5aeb92022-05-11 09:35:361682 &controller, "DummyChannelA", InternalDataChannelInit(),
Tomas Gunnarsson7d3cfbf2020-06-15 11:47:421683 rtc::Thread::Current(), rtc::Thread::Current());
Mirko Bonadeie0bc8d22022-02-08 07:41:251684 pc_->SignalSctpDataChannelCreated()(dummy_channel_a.get());
Taylor Brandstetter3a034e12020-07-09 22:32:341685 rtc::scoped_refptr<SctpDataChannel> dummy_channel_b = SctpDataChannel::Create(
Harald Alvestrand9e5aeb92022-05-11 09:35:361686 &controller, "DummyChannelB", InternalDataChannelInit(),
Tomas Gunnarsson7d3cfbf2020-06-15 11:47:421687 rtc::Thread::Current(), rtc::Thread::Current());
Mirko Bonadeie0bc8d22022-02-08 07:41:251688 pc_->SignalSctpDataChannelCreated()(dummy_channel_b.get());
hbosd565b732016-08-30 21:04:351689
hbos82ebe022016-11-14 09:41:091690 dummy_channel_a->SignalOpened(dummy_channel_a.get());
1691 // Closing a channel that is not opened should not affect the counts.
1692 dummy_channel_b->SignalClosed(dummy_channel_b.get());
1693
hbosd565b732016-08-30 21:04:351694 {
Steve Anton5b387312018-02-03 00:00:201695 rtc::scoped_refptr<const RTCStatsReport> report =
1696 stats_->GetFreshStatsReport();
hbos82ebe022016-11-14 09:41:091697 RTCPeerConnectionStats expected("RTCPeerConnection",
1698 report->timestamp_us());
1699 expected.data_channels_opened = 1;
1700 expected.data_channels_closed = 0;
hbosdbb64d82016-12-21 09:57:461701 ASSERT_TRUE(report->Get("RTCPeerConnection"));
Yves Gerey665174f2018-06-19 13:03:051702 EXPECT_EQ(
1703 expected,
1704 report->Get("RTCPeerConnection")->cast_to<RTCPeerConnectionStats>());
hbos82ebe022016-11-14 09:41:091705 }
1706
1707 dummy_channel_b->SignalOpened(dummy_channel_b.get());
1708 dummy_channel_b->SignalClosed(dummy_channel_b.get());
1709
1710 {
Steve Anton5b387312018-02-03 00:00:201711 rtc::scoped_refptr<const RTCStatsReport> report =
1712 stats_->GetFreshStatsReport();
hbos82ebe022016-11-14 09:41:091713 RTCPeerConnectionStats expected("RTCPeerConnection",
1714 report->timestamp_us());
1715 expected.data_channels_opened = 2;
1716 expected.data_channels_closed = 1;
hbosdbb64d82016-12-21 09:57:461717 ASSERT_TRUE(report->Get("RTCPeerConnection"));
Yves Gerey665174f2018-06-19 13:03:051718 EXPECT_EQ(
1719 expected,
1720 report->Get("RTCPeerConnection")->cast_to<RTCPeerConnectionStats>());
hbosd565b732016-08-30 21:04:351721 }
hbos5bf9def2017-03-20 10:14:141722
1723 // Re-opening a data channel (or opening a new data channel that is re-using
1724 // the same address in memory) should increase the opened count.
1725 dummy_channel_b->SignalOpened(dummy_channel_b.get());
1726
1727 {
Steve Anton5b387312018-02-03 00:00:201728 rtc::scoped_refptr<const RTCStatsReport> report =
1729 stats_->GetFreshStatsReport();
hbos5bf9def2017-03-20 10:14:141730 RTCPeerConnectionStats expected("RTCPeerConnection",
1731 report->timestamp_us());
1732 expected.data_channels_opened = 3;
1733 expected.data_channels_closed = 1;
1734 ASSERT_TRUE(report->Get("RTCPeerConnection"));
Yves Gerey665174f2018-06-19 13:03:051735 EXPECT_EQ(
1736 expected,
1737 report->Get("RTCPeerConnection")->cast_to<RTCPeerConnectionStats>());
hbos5bf9def2017-03-20 10:14:141738 }
1739
1740 dummy_channel_a->SignalClosed(dummy_channel_a.get());
1741 dummy_channel_b->SignalClosed(dummy_channel_b.get());
1742
1743 {
Steve Anton5b387312018-02-03 00:00:201744 rtc::scoped_refptr<const RTCStatsReport> report =
1745 stats_->GetFreshStatsReport();
hbos5bf9def2017-03-20 10:14:141746 RTCPeerConnectionStats expected("RTCPeerConnection",
1747 report->timestamp_us());
1748 expected.data_channels_opened = 3;
1749 expected.data_channels_closed = 3;
1750 ASSERT_TRUE(report->Get("RTCPeerConnection"));
Yves Gerey665174f2018-06-19 13:03:051751 EXPECT_EQ(
1752 expected,
1753 report->Get("RTCPeerConnection")->cast_to<RTCPeerConnectionStats>());
hbos5bf9def2017-03-20 10:14:141754 }
hbosd565b732016-08-30 21:04:351755}
1756
hbos09bc1282016-11-08 14:29:221757TEST_F(RTCStatsCollectorTest,
Harald Alvestranda3dab842018-01-14 08:18:581758 CollectLocalRTCMediaStreamStatsAndRTCMediaStreamTrackStats_Audio) {
hbos09bc1282016-11-08 14:29:221759 rtc::scoped_refptr<MediaStream> local_stream =
Seth Hampson845e8782018-03-02 19:34:101760 MediaStream::Create("LocalStreamId");
Steve Anton5b387312018-02-03 00:00:201761 pc_->mutable_local_streams()->AddStream(local_stream);
hbos09bc1282016-11-08 14:29:221762
1763 // Local audio track
hbos9e302742017-01-20 10:47:101764 rtc::scoped_refptr<MediaStreamTrackInterface> local_audio_track =
1765 CreateFakeTrack(cricket::MEDIA_TYPE_AUDIO, "LocalAudioTrackID",
1766 MediaStreamTrackInterface::kEnded);
Harald Alvestrand2f7ad282022-04-21 11:35:431767 local_stream->AddTrack(rtc::scoped_refptr<AudioTrackInterface>(
1768 static_cast<AudioTrackInterface*>(local_audio_track.get())));
hbos9e302742017-01-20 10:47:101769
1770 cricket::VoiceSenderInfo voice_sender_info_ssrc1;
1771 voice_sender_info_ssrc1.local_stats.push_back(cricket::SsrcSenderInfo());
1772 voice_sender_info_ssrc1.local_stats[0].ssrc = 1;
Ivo Creusen56d460902017-11-24 16:29:591773 voice_sender_info_ssrc1.apm_statistics.echo_return_loss = 42.0;
1774 voice_sender_info_ssrc1.apm_statistics.echo_return_loss_enhancement = 52.0;
hbos9e302742017-01-20 10:47:101775
Steve Anton5b387312018-02-03 00:00:201776 stats_->CreateMockRtpSendersReceiversAndChannels(
Harald Alvestranda3dab842018-01-14 08:18:581777 {std::make_pair(local_audio_track.get(), voice_sender_info_ssrc1)}, {},
Seth Hampson13b8bad2018-03-13 23:05:281778 {}, {}, {local_stream->id()}, {});
Harald Alvestranda3dab842018-01-14 08:18:581779
Steve Anton5b387312018-02-03 00:00:201780 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
Harald Alvestranda3dab842018-01-14 08:18:581781
1782 RTCMediaStreamStats expected_local_stream(
Niels Möllerafb246b2022-04-20 12:26:501783 IdForType<RTCMediaStreamStats>(report.get()), report->timestamp_us());
Seth Hampson13b8bad2018-03-13 23:05:281784 expected_local_stream.stream_identifier = local_stream->id();
Harald Alvestranda3dab842018-01-14 08:18:581785 expected_local_stream.track_ids = {
Niels Möllerafb246b2022-04-20 12:26:501786 IdForType<RTCMediaStreamTrackStats>(report.get())};
Harald Alvestranda3dab842018-01-14 08:18:581787 ASSERT_TRUE(report->Get(expected_local_stream.id()))
1788 << "Did not find " << expected_local_stream.id() << " in "
1789 << report->ToJson();
1790 EXPECT_EQ(
1791 expected_local_stream,
1792 report->Get(expected_local_stream.id())->cast_to<RTCMediaStreamStats>());
1793
1794 RTCMediaStreamTrackStats expected_local_audio_track_ssrc1(
Niels Möllerafb246b2022-04-20 12:26:501795 IdForType<RTCMediaStreamTrackStats>(report.get()), report->timestamp_us(),
Harald Alvestranda3dab842018-01-14 08:18:581796 RTCMediaStreamTrackKind::kAudio);
1797 expected_local_audio_track_ssrc1.track_identifier = local_audio_track->id();
Henrik Boström646fda02019-05-22 13:49:421798 expected_local_audio_track_ssrc1.media_source_id =
1799 "RTCAudioSource_11"; // Attachment ID = SSRC + 10
Harald Alvestranda3dab842018-01-14 08:18:581800 expected_local_audio_track_ssrc1.remote_source = false;
1801 expected_local_audio_track_ssrc1.ended = true;
1802 expected_local_audio_track_ssrc1.detached = false;
Harald Alvestranda3dab842018-01-14 08:18:581803 expected_local_audio_track_ssrc1.echo_return_loss = 42.0;
1804 expected_local_audio_track_ssrc1.echo_return_loss_enhancement = 52.0;
1805 ASSERT_TRUE(report->Get(expected_local_audio_track_ssrc1.id()))
1806 << "Did not find " << expected_local_audio_track_ssrc1.id() << " in "
1807 << report->ToJson();
1808 EXPECT_EQ(expected_local_audio_track_ssrc1,
1809 report->Get(expected_local_audio_track_ssrc1.id())
1810 ->cast_to<RTCMediaStreamTrackStats>());
1811}
1812
1813TEST_F(RTCStatsCollectorTest,
1814 CollectRemoteRTCMediaStreamStatsAndRTCMediaStreamTrackStats_Audio) {
Harald Alvestranda3dab842018-01-14 08:18:581815 rtc::scoped_refptr<MediaStream> remote_stream =
Seth Hampson845e8782018-03-02 19:34:101816 MediaStream::Create("RemoteStreamId");
Steve Anton5b387312018-02-03 00:00:201817 pc_->mutable_remote_streams()->AddStream(remote_stream);
Harald Alvestranda3dab842018-01-14 08:18:581818
hbos09bc1282016-11-08 14:29:221819 // Remote audio track
hbos9e302742017-01-20 10:47:101820 rtc::scoped_refptr<MediaStreamTrackInterface> remote_audio_track =
1821 CreateFakeTrack(cricket::MEDIA_TYPE_AUDIO, "RemoteAudioTrackID",
1822 MediaStreamTrackInterface::kLive);
Harald Alvestrand2f7ad282022-04-21 11:35:431823 remote_stream->AddTrack(rtc::scoped_refptr<AudioTrackInterface>(
1824 static_cast<AudioTrackInterface*>(remote_audio_track.get())));
hbos9e302742017-01-20 10:47:101825
1826 cricket::VoiceReceiverInfo voice_receiver_info;
1827 voice_receiver_info.local_stats.push_back(cricket::SsrcReceiverInfo());
1828 voice_receiver_info.local_stats[0].ssrc = 3;
Philipp Hanckeaa83cc72020-10-27 08:50:361829 voice_receiver_info.audio_level = 16383; // [0,32767]
zsteine76bd3a2017-07-14 19:17:491830 voice_receiver_info.total_output_energy = 0.125;
Steve Anton2dbc69f2017-08-25 00:15:131831 voice_receiver_info.total_samples_received = 4567;
zsteine76bd3a2017-07-14 19:17:491832 voice_receiver_info.total_output_duration = 0.25;
Steve Anton2dbc69f2017-08-25 00:15:131833 voice_receiver_info.concealed_samples = 123;
Gustaf Ullberg9a2e9062017-09-18 07:28:201834 voice_receiver_info.concealment_events = 12;
Ivo Creusen8d8ffdb2019-04-30 07:45:211835 voice_receiver_info.inserted_samples_for_deceleration = 987;
1836 voice_receiver_info.removed_samples_for_acceleration = 876;
1837 voice_receiver_info.silent_concealed_samples = 765;
Byoungchan Lee899b29e2021-06-29 13:09:181838 voice_receiver_info.jitter_buffer_delay_seconds = 3.456;
Chen Xing0acffb52019-01-15 14:46:291839 voice_receiver_info.jitter_buffer_emitted_count = 13;
Artem Titove618cc92020-03-11 10:18:541840 voice_receiver_info.jitter_buffer_target_delay_seconds = 7.894;
Ruslan Burakov8af88962018-11-22 16:21:101841 voice_receiver_info.jitter_buffer_flushes = 7;
Jakob Ivarsson352ce5c2018-11-27 11:52:161842 voice_receiver_info.delayed_packet_outage_samples = 15;
Jakob Ivarsson232b3fd2019-03-06 08:18:401843 voice_receiver_info.relative_packet_arrival_delay_seconds = 16;
Henrik Lundin44125fa2019-04-29 15:00:461844 voice_receiver_info.interruption_count = 7788;
1845 voice_receiver_info.total_interruption_duration_ms = 778899;
hbos9e302742017-01-20 10:47:101846
Steve Anton5b387312018-02-03 00:00:201847 stats_->CreateMockRtpSendersReceiversAndChannels(
Harald Alvestranda3dab842018-01-14 08:18:581848 {}, {std::make_pair(remote_audio_track.get(), voice_receiver_info)}, {},
1849 {}, {}, {remote_stream});
hbos09bc1282016-11-08 14:29:221850
Steve Anton5b387312018-02-03 00:00:201851 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbos09bc1282016-11-08 14:29:221852
hbos09bc1282016-11-08 14:29:221853 RTCMediaStreamStats expected_remote_stream(
Niels Möllerafb246b2022-04-20 12:26:501854 IdForType<RTCMediaStreamStats>(report.get()), report->timestamp_us());
Seth Hampson13b8bad2018-03-13 23:05:281855 expected_remote_stream.stream_identifier = remote_stream->id();
Niels Möllerafb246b2022-04-20 12:26:501856 expected_remote_stream.track_ids = std::vector<std::string>(
1857 {IdForType<RTCMediaStreamTrackStats>(report.get())});
Harald Alvestranda3dab842018-01-14 08:18:581858 ASSERT_TRUE(report->Get(expected_remote_stream.id()))
1859 << "Did not find " << expected_remote_stream.id() << " in "
1860 << report->ToJson();
Yves Gerey665174f2018-06-19 13:03:051861 EXPECT_EQ(
1862 expected_remote_stream,
1863 report->Get(expected_remote_stream.id())->cast_to<RTCMediaStreamStats>());
hbos09bc1282016-11-08 14:29:221864
hbos09bc1282016-11-08 14:29:221865 RTCMediaStreamTrackStats expected_remote_audio_track(
Niels Möllerafb246b2022-04-20 12:26:501866 IdForType<RTCMediaStreamTrackStats>(report.get()), report->timestamp_us(),
Harald Alvestranda3dab842018-01-14 08:18:581867 RTCMediaStreamTrackKind::kAudio);
hbos09bc1282016-11-08 14:29:221868 expected_remote_audio_track.track_identifier = remote_audio_track->id();
Artem Titovcfea2182021-08-09 23:22:311869 // `expected_remote_audio_track.media_source_id` should be undefined
Henrik Boström646fda02019-05-22 13:49:421870 // because the track is remote.
hbos09bc1282016-11-08 14:29:221871 expected_remote_audio_track.remote_source = true;
1872 expected_remote_audio_track.ended = false;
1873 expected_remote_audio_track.detached = false;
Philipp Hanckeaa83cc72020-10-27 08:50:361874 expected_remote_audio_track.audio_level = 16383.0 / 32767.0; // [0,1]
zsteine76bd3a2017-07-14 19:17:491875 expected_remote_audio_track.total_audio_energy = 0.125;
Steve Anton2dbc69f2017-08-25 00:15:131876 expected_remote_audio_track.total_samples_received = 4567;
zsteine76bd3a2017-07-14 19:17:491877 expected_remote_audio_track.total_samples_duration = 0.25;
Steve Anton2dbc69f2017-08-25 00:15:131878 expected_remote_audio_track.concealed_samples = 123;
Gustaf Ullberg9a2e9062017-09-18 07:28:201879 expected_remote_audio_track.concealment_events = 12;
Ivo Creusen8d8ffdb2019-04-30 07:45:211880 expected_remote_audio_track.inserted_samples_for_deceleration = 987;
1881 expected_remote_audio_track.removed_samples_for_acceleration = 876;
1882 expected_remote_audio_track.silent_concealed_samples = 765;
Byoungchan Lee899b29e2021-06-29 13:09:181883 expected_remote_audio_track.jitter_buffer_delay = 3.456;
Chen Xing0acffb52019-01-15 14:46:291884 expected_remote_audio_track.jitter_buffer_emitted_count = 13;
Artem Titove618cc92020-03-11 10:18:541885 expected_remote_audio_track.jitter_buffer_target_delay = 7.894;
Ruslan Burakov8af88962018-11-22 16:21:101886 expected_remote_audio_track.jitter_buffer_flushes = 7;
Jakob Ivarsson352ce5c2018-11-27 11:52:161887 expected_remote_audio_track.delayed_packet_outage_samples = 15;
Jakob Ivarsson232b3fd2019-03-06 08:18:401888 expected_remote_audio_track.relative_packet_arrival_delay = 16;
Henrik Lundin44125fa2019-04-29 15:00:461889 expected_remote_audio_track.interruption_count = 7788;
1890 expected_remote_audio_track.total_interruption_duration = 778.899;
hbosdbb64d82016-12-21 09:57:461891 ASSERT_TRUE(report->Get(expected_remote_audio_track.id()));
hbos09bc1282016-11-08 14:29:221892 EXPECT_EQ(expected_remote_audio_track,
Yves Gerey665174f2018-06-19 13:03:051893 report->Get(expected_remote_audio_track.id())
1894 ->cast_to<RTCMediaStreamTrackStats>());
hbos09bc1282016-11-08 14:29:221895}
1896
1897TEST_F(RTCStatsCollectorTest,
Harald Alvestranda3dab842018-01-14 08:18:581898 CollectLocalRTCMediaStreamStatsAndRTCMediaStreamTrackStats_Video) {
hbos09bc1282016-11-08 14:29:221899 rtc::scoped_refptr<MediaStream> local_stream =
Seth Hampson845e8782018-03-02 19:34:101900 MediaStream::Create("LocalStreamId");
Steve Anton5b387312018-02-03 00:00:201901 pc_->mutable_local_streams()->AddStream(local_stream);
hbos09bc1282016-11-08 14:29:221902
1903 // Local video track
hbos9e302742017-01-20 10:47:101904 rtc::scoped_refptr<MediaStreamTrackInterface> local_video_track =
1905 CreateFakeTrack(cricket::MEDIA_TYPE_VIDEO, "LocalVideoTrackID",
1906 MediaStreamTrackInterface::kLive);
Harald Alvestrand2f7ad282022-04-21 11:35:431907 local_stream->AddTrack(rtc::scoped_refptr<VideoTrackInterface>(
1908 static_cast<VideoTrackInterface*>(local_video_track.get())));
hbos09bc1282016-11-08 14:29:221909
hbos9e302742017-01-20 10:47:101910 cricket::VideoSenderInfo video_sender_info_ssrc1;
1911 video_sender_info_ssrc1.local_stats.push_back(cricket::SsrcSenderInfo());
1912 video_sender_info_ssrc1.local_stats[0].ssrc = 1;
1913 video_sender_info_ssrc1.send_frame_width = 1234;
1914 video_sender_info_ssrc1.send_frame_height = 4321;
hbosfefe0762017-01-20 14:14:251915 video_sender_info_ssrc1.frames_encoded = 11;
Ilya Nikolaevskiy70473fc2018-02-28 15:35:031916 video_sender_info_ssrc1.huge_frames_sent = 1;
hbos9e302742017-01-20 10:47:101917
Steve Anton5b387312018-02-03 00:00:201918 stats_->CreateMockRtpSendersReceiversAndChannels(
Harald Alvestranda3dab842018-01-14 08:18:581919 {}, {},
1920 {std::make_pair(local_video_track.get(), video_sender_info_ssrc1)}, {},
Seth Hampson13b8bad2018-03-13 23:05:281921 {local_stream->id()}, {});
Harald Alvestranda3dab842018-01-14 08:18:581922
Steve Anton5b387312018-02-03 00:00:201923 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
Harald Alvestranda3dab842018-01-14 08:18:581924
1925 auto stats_of_my_type = report->GetStatsOfType<RTCMediaStreamStats>();
Mirko Bonadeie12c1fe2018-07-03 10:53:231926 ASSERT_EQ(1U, stats_of_my_type.size()) << "No stream in " << report->ToJson();
Harald Alvestranda3dab842018-01-14 08:18:581927 auto stats_of_track_type = report->GetStatsOfType<RTCMediaStreamTrackStats>();
Mirko Bonadeie12c1fe2018-07-03 10:53:231928 ASSERT_EQ(1U, stats_of_track_type.size())
Harald Alvestranda3dab842018-01-14 08:18:581929 << "Wrong number of tracks in " << report->ToJson();
1930
1931 RTCMediaStreamStats expected_local_stream(stats_of_my_type[0]->id(),
1932 report->timestamp_us());
Seth Hampson13b8bad2018-03-13 23:05:281933 expected_local_stream.stream_identifier = local_stream->id();
Harald Alvestranda3dab842018-01-14 08:18:581934 expected_local_stream.track_ids =
1935 std::vector<std::string>({stats_of_track_type[0]->id()});
1936 ASSERT_TRUE(report->Get(expected_local_stream.id()));
1937 EXPECT_EQ(
1938 expected_local_stream,
1939 report->Get(expected_local_stream.id())->cast_to<RTCMediaStreamStats>());
1940
1941 RTCMediaStreamTrackStats expected_local_video_track_ssrc1(
1942 stats_of_track_type[0]->id(), report->timestamp_us(),
1943 RTCMediaStreamTrackKind::kVideo);
1944 expected_local_video_track_ssrc1.track_identifier = local_video_track->id();
Henrik Boström646fda02019-05-22 13:49:421945 expected_local_video_track_ssrc1.media_source_id =
1946 "RTCVideoSource_11"; // Attachment ID = SSRC + 10
Harald Alvestranda3dab842018-01-14 08:18:581947 expected_local_video_track_ssrc1.remote_source = false;
1948 expected_local_video_track_ssrc1.ended = false;
1949 expected_local_video_track_ssrc1.detached = false;
1950 expected_local_video_track_ssrc1.frame_width = 1234;
1951 expected_local_video_track_ssrc1.frame_height = 4321;
1952 expected_local_video_track_ssrc1.frames_sent = 11;
Ilya Nikolaevskiy70473fc2018-02-28 15:35:031953 expected_local_video_track_ssrc1.huge_frames_sent = 1;
Harald Alvestranda3dab842018-01-14 08:18:581954 ASSERT_TRUE(report->Get(expected_local_video_track_ssrc1.id()));
1955 EXPECT_EQ(expected_local_video_track_ssrc1,
1956 report->Get(expected_local_video_track_ssrc1.id())
1957 ->cast_to<RTCMediaStreamTrackStats>());
1958}
1959
1960TEST_F(RTCStatsCollectorTest,
1961 CollectRemoteRTCMediaStreamStatsAndRTCMediaStreamTrackStats_Video) {
Harald Alvestranda3dab842018-01-14 08:18:581962 rtc::scoped_refptr<MediaStream> remote_stream =
Seth Hampson845e8782018-03-02 19:34:101963 MediaStream::Create("RemoteStreamId");
Steve Anton5b387312018-02-03 00:00:201964 pc_->mutable_remote_streams()->AddStream(remote_stream);
Harald Alvestranda3dab842018-01-14 08:18:581965
hbos9e302742017-01-20 10:47:101966 // Remote video track with values
1967 rtc::scoped_refptr<MediaStreamTrackInterface> remote_video_track_ssrc3 =
1968 CreateFakeTrack(cricket::MEDIA_TYPE_VIDEO, "RemoteVideoTrackID3",
1969 MediaStreamTrackInterface::kEnded);
Harald Alvestrand2f7ad282022-04-21 11:35:431970 remote_stream->AddTrack(rtc::scoped_refptr<VideoTrackInterface>(
1971 static_cast<VideoTrackInterface*>(remote_video_track_ssrc3.get())));
hbos9e302742017-01-20 10:47:101972
1973 cricket::VideoReceiverInfo video_receiver_info_ssrc3;
1974 video_receiver_info_ssrc3.local_stats.push_back(cricket::SsrcReceiverInfo());
1975 video_receiver_info_ssrc3.local_stats[0].ssrc = 3;
1976 video_receiver_info_ssrc3.frame_width = 6789;
1977 video_receiver_info_ssrc3.frame_height = 9876;
Guido Urdaneta67378412019-05-28 15:38:081978 video_receiver_info_ssrc3.jitter_buffer_delay_seconds = 2.5;
1979 video_receiver_info_ssrc3.jitter_buffer_emitted_count = 25;
hbos50cfe1f2017-01-23 15:21:551980 video_receiver_info_ssrc3.frames_received = 1000;
1981 video_receiver_info_ssrc3.frames_decoded = 995;
Johannes Kron0c141c52019-08-26 13:04:431982 video_receiver_info_ssrc3.frames_dropped = 10;
hbos50cfe1f2017-01-23 15:21:551983 video_receiver_info_ssrc3.frames_rendered = 990;
Sergey Silkin02371062019-01-31 15:45:421984 video_receiver_info_ssrc3.freeze_count = 3;
1985 video_receiver_info_ssrc3.pause_count = 2;
1986 video_receiver_info_ssrc3.total_freezes_duration_ms = 1000;
1987 video_receiver_info_ssrc3.total_pauses_duration_ms = 10000;
1988 video_receiver_info_ssrc3.total_frames_duration_ms = 15000;
1989 video_receiver_info_ssrc3.sum_squared_frame_durations = 1.5;
hbos9e302742017-01-20 10:47:101990
Steve Anton5b387312018-02-03 00:00:201991 stats_->CreateMockRtpSendersReceiversAndChannels(
Harald Alvestranda3dab842018-01-14 08:18:581992 {}, {}, {},
Harald Alvestrandc72af932018-01-11 16:18:191993 {std::make_pair(remote_video_track_ssrc3.get(),
Harald Alvestranda3dab842018-01-14 08:18:581994 video_receiver_info_ssrc3)},
1995 {}, {remote_stream});
hbos09bc1282016-11-08 14:29:221996
Steve Anton5b387312018-02-03 00:00:201997 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbos09bc1282016-11-08 14:29:221998
Harald Alvestranda3dab842018-01-14 08:18:581999 auto stats_of_my_type = report->GetStatsOfType<RTCMediaStreamStats>();
Mirko Bonadeie12c1fe2018-07-03 10:53:232000 ASSERT_EQ(1U, stats_of_my_type.size()) << "No stream in " << report->ToJson();
Harald Alvestranda3dab842018-01-14 08:18:582001 auto stats_of_track_type = report->GetStatsOfType<RTCMediaStreamTrackStats>();
Mirko Bonadeie12c1fe2018-07-03 10:53:232002 ASSERT_EQ(1U, stats_of_track_type.size())
Harald Alvestranda3dab842018-01-14 08:18:582003 << "Wrong number of tracks in " << report->ToJson();
2004 ASSERT_TRUE(*(stats_of_track_type[0]->remote_source));
hbos09bc1282016-11-08 14:29:222005
Harald Alvestranda3dab842018-01-14 08:18:582006 RTCMediaStreamStats expected_remote_stream(stats_of_my_type[0]->id(),
2007 report->timestamp_us());
Seth Hampson13b8bad2018-03-13 23:05:282008 expected_remote_stream.stream_identifier = remote_stream->id();
Harald Alvestranda3dab842018-01-14 08:18:582009 expected_remote_stream.track_ids =
2010 std::vector<std::string>({stats_of_track_type[0]->id()});
hbosdbb64d82016-12-21 09:57:462011 ASSERT_TRUE(report->Get(expected_remote_stream.id()));
Yves Gerey665174f2018-06-19 13:03:052012 EXPECT_EQ(
2013 expected_remote_stream,
2014 report->Get(expected_remote_stream.id())->cast_to<RTCMediaStreamStats>());
hbos09bc1282016-11-08 14:29:222015
hbos9e302742017-01-20 10:47:102016 RTCMediaStreamTrackStats expected_remote_video_track_ssrc3(
Harald Alvestranda3dab842018-01-14 08:18:582017 stats_of_track_type[0]->id(), report->timestamp_us(),
2018 RTCMediaStreamTrackKind::kVideo);
hbos9e302742017-01-20 10:47:102019 expected_remote_video_track_ssrc3.track_identifier =
2020 remote_video_track_ssrc3->id();
Artem Titovcfea2182021-08-09 23:22:312021 // `expected_remote_video_track_ssrc3.media_source_id` should be undefined
Henrik Boström646fda02019-05-22 13:49:422022 // because the track is remote.
hbos9e302742017-01-20 10:47:102023 expected_remote_video_track_ssrc3.remote_source = true;
2024 expected_remote_video_track_ssrc3.ended = true;
2025 expected_remote_video_track_ssrc3.detached = false;
2026 expected_remote_video_track_ssrc3.frame_width = 6789;
2027 expected_remote_video_track_ssrc3.frame_height = 9876;
Guido Urdaneta67378412019-05-28 15:38:082028 expected_remote_video_track_ssrc3.jitter_buffer_delay = 2.5;
2029 expected_remote_video_track_ssrc3.jitter_buffer_emitted_count = 25;
hbos50cfe1f2017-01-23 15:21:552030 expected_remote_video_track_ssrc3.frames_received = 1000;
2031 expected_remote_video_track_ssrc3.frames_decoded = 995;
Johannes Kron0c141c52019-08-26 13:04:432032 expected_remote_video_track_ssrc3.frames_dropped = 10;
Sergey Silkin02371062019-01-31 15:45:422033 expected_remote_video_track_ssrc3.freeze_count = 3;
2034 expected_remote_video_track_ssrc3.pause_count = 2;
2035 expected_remote_video_track_ssrc3.total_freezes_duration = 1;
2036 expected_remote_video_track_ssrc3.total_pauses_duration = 10;
2037 expected_remote_video_track_ssrc3.total_frames_duration = 15;
2038 expected_remote_video_track_ssrc3.sum_squared_frame_durations = 1.5;
2039
hbos9e302742017-01-20 10:47:102040 ASSERT_TRUE(report->Get(expected_remote_video_track_ssrc3.id()));
2041 EXPECT_EQ(expected_remote_video_track_ssrc3,
Yves Gerey665174f2018-06-19 13:03:052042 report->Get(expected_remote_video_track_ssrc3.id())
2043 ->cast_to<RTCMediaStreamTrackStats>());
hbos09bc1282016-11-08 14:29:222044}
2045
hboseeafe942016-11-01 10:00:172046TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Audio) {
hboseeafe942016-11-01 10:00:172047 cricket::VoiceMediaInfo voice_media_info;
hbos0adb8282016-11-23 10:32:062048
hboseeafe942016-11-01 10:00:172049 voice_media_info.receivers.push_back(cricket::VoiceReceiverInfo());
2050 voice_media_info.receivers[0].local_stats.push_back(
2051 cricket::SsrcReceiverInfo());
2052 voice_media_info.receivers[0].local_stats[0].ssrc = 1;
Harald Alvestrand719487e2017-12-13 11:26:042053 voice_media_info.receivers[0].packets_lost = -1; // Signed per RFC3550
Minyue Li28a2c632021-07-07 13:53:382054 voice_media_info.receivers[0].packets_discarded = 7788;
hboseeafe942016-11-01 10:00:172055 voice_media_info.receivers[0].packets_rcvd = 2;
Jakob Ivarssone54914a2021-07-01 09:16:052056 voice_media_info.receivers[0].nacks_sent = 5;
Ivo Creusen8d8ffdb2019-04-30 07:45:212057 voice_media_info.receivers[0].fec_packets_discarded = 5566;
2058 voice_media_info.receivers[0].fec_packets_received = 6677;
Niels Möllerac0a4cb2019-10-09 13:01:332059 voice_media_info.receivers[0].payload_bytes_rcvd = 3;
2060 voice_media_info.receivers[0].header_and_padding_bytes_rcvd = 4;
Oskar Sundbomcbc71b22017-11-16 09:56:072061 voice_media_info.receivers[0].codec_payload_type = 42;
hboseeafe942016-11-01 10:00:172062 voice_media_info.receivers[0].jitter_ms = 4500;
Eldar Rello4e5bc9f2020-07-06 11:18:072063 voice_media_info.receivers[0].jitter_buffer_delay_seconds = 1.0;
2064 voice_media_info.receivers[0].jitter_buffer_emitted_count = 2;
2065 voice_media_info.receivers[0].total_samples_received = 3;
2066 voice_media_info.receivers[0].concealed_samples = 4;
2067 voice_media_info.receivers[0].silent_concealed_samples = 5;
2068 voice_media_info.receivers[0].concealment_events = 6;
2069 voice_media_info.receivers[0].inserted_samples_for_deceleration = 7;
2070 voice_media_info.receivers[0].removed_samples_for_acceleration = 8;
Philipp Hanckeaa83cc72020-10-27 08:50:362071 voice_media_info.receivers[0].audio_level = 14442; // [0,32767]
Eldar Rello4e5bc9f2020-07-06 11:18:072072 voice_media_info.receivers[0].total_output_energy = 10.0;
2073 voice_media_info.receivers[0].total_output_duration = 11.0;
2074
Henrik Boström01738c62019-04-15 15:32:002075 voice_media_info.receivers[0].last_packet_received_timestamp_ms =
2076 absl::nullopt;
hbos0adb8282016-11-23 10:32:062077
2078 RtpCodecParameters codec_parameters;
2079 codec_parameters.payload_type = 42;
deadbeefe702b302017-02-04 20:09:012080 codec_parameters.kind = cricket::MEDIA_TYPE_AUDIO;
2081 codec_parameters.name = "dummy";
Oskar Sundbomcbc71b22017-11-16 09:56:072082 codec_parameters.clock_rate = 0;
hbos0adb8282016-11-23 10:32:062083 voice_media_info.receive_codecs.insert(
2084 std::make_pair(codec_parameters.payload_type, codec_parameters));
2085
Tommi19015512022-02-02 10:49:352086 auto* voice_media_channel =
2087 pc_->AddVoiceChannel("AudioMid", "TransportName", voice_media_info);
Henrik Boström5b3541f2018-03-19 12:52:562088 stats_->SetupRemoteTrackAndReceiver(
2089 cricket::MEDIA_TYPE_AUDIO, "RemoteAudioTrackID", "RemoteStreamId", 1);
hboseeafe942016-11-01 10:00:172090
Steve Anton5b387312018-02-03 00:00:202091 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hboseeafe942016-11-01 10:00:172092
Harald Alvestranda3dab842018-01-14 08:18:582093 auto stats_of_track_type = report->GetStatsOfType<RTCMediaStreamTrackStats>();
Mirko Bonadeie12c1fe2018-07-03 10:53:232094 ASSERT_EQ(1U, stats_of_track_type.size());
Harald Alvestranda3dab842018-01-14 08:18:582095
Yves Gerey665174f2018-06-19 13:03:052096 RTCInboundRTPStreamStats expected_audio("RTCInboundRTPAudioStream_1",
2097 report->timestamp_us());
hbos3443bb72017-02-07 14:28:112098 expected_audio.ssrc = 1;
hboseeafe942016-11-01 10:00:172099 expected_audio.media_type = "audio";
Philipp Hancke3bc01662018-08-28 12:55:032100 expected_audio.kind = "audio";
Henrik Boströma6c7d5c2022-06-16 14:55:312101 expected_audio.track_identifier = "RemoteAudioTrackID";
Henrik Boström1ab61882022-06-16 15:07:332102 expected_audio.mid = "AudioMid";
Harald Alvestranda3dab842018-01-14 08:18:582103 expected_audio.track_id = stats_of_track_type[0]->id();
Steve Anton57858b32018-02-15 23:19:502104 expected_audio.transport_id = "RTCTransport_TransportName_1";
2105 expected_audio.codec_id = "RTCCodec_AudioMid_Inbound_42";
hboseeafe942016-11-01 10:00:172106 expected_audio.packets_received = 2;
Jakob Ivarssone54914a2021-07-01 09:16:052107 expected_audio.nack_count = 5;
Ivo Creusen8d8ffdb2019-04-30 07:45:212108 expected_audio.fec_packets_discarded = 5566;
2109 expected_audio.fec_packets_received = 6677;
hboseeafe942016-11-01 10:00:172110 expected_audio.bytes_received = 3;
Niels Möllerac0a4cb2019-10-09 13:01:332111 expected_audio.header_bytes_received = 4;
Harald Alvestrand719487e2017-12-13 11:26:042112 expected_audio.packets_lost = -1;
Minyue Li28a2c632021-07-07 13:53:382113 expected_audio.packets_discarded = 7788;
Artem Titovcfea2182021-08-09 23:22:312114 // `expected_audio.last_packet_received_timestamp` should be undefined.
hboseeafe942016-11-01 10:00:172115 expected_audio.jitter = 4.5;
Eldar Rello4e5bc9f2020-07-06 11:18:072116 expected_audio.jitter_buffer_delay = 1.0;
2117 expected_audio.jitter_buffer_emitted_count = 2;
2118 expected_audio.total_samples_received = 3;
2119 expected_audio.concealed_samples = 4;
2120 expected_audio.silent_concealed_samples = 5;
2121 expected_audio.concealment_events = 6;
2122 expected_audio.inserted_samples_for_deceleration = 7;
2123 expected_audio.removed_samples_for_acceleration = 8;
Philipp Hanckeaa83cc72020-10-27 08:50:362124 expected_audio.audio_level = 14442.0 / 32767.0; // [0,1]
Eldar Rello4e5bc9f2020-07-06 11:18:072125 expected_audio.total_audio_energy = 10.0;
2126 expected_audio.total_samples_duration = 11.0;
2127
nissec8ee8822017-01-18 15:20:552128 ASSERT_TRUE(report->Get(expected_audio.id()));
hbosa51d4f32017-02-16 13:34:482129 EXPECT_EQ(
2130 report->Get(expected_audio.id())->cast_to<RTCInboundRTPStreamStats>(),
2131 expected_audio);
Henrik Boström01738c62019-04-15 15:32:002132
2133 // Set previously undefined values and "GetStats" again.
2134 voice_media_info.receivers[0].last_packet_received_timestamp_ms = 3000;
Alessio Bazzicac366d512021-03-22 14:36:532135 expected_audio.last_packet_received_timestamp = 3000.0;
Åsa Perssonfcf79cc2019-10-22 13:23:442136 voice_media_info.receivers[0].estimated_playout_ntp_timestamp_ms = 4567;
2137 expected_audio.estimated_playout_timestamp = 4567;
Henrik Boström01738c62019-04-15 15:32:002138 voice_media_channel->SetStats(voice_media_info);
2139
2140 report = stats_->GetFreshStatsReport();
2141
2142 ASSERT_TRUE(report->Get(expected_audio.id()));
2143 EXPECT_EQ(
2144 report->Get(expected_audio.id())->cast_to<RTCInboundRTPStreamStats>(),
2145 expected_audio);
hbosb0ae9202017-01-27 14:35:162146 EXPECT_TRUE(report->Get(*expected_audio.track_id));
hbos84abeb12017-01-16 14:16:442147 EXPECT_TRUE(report->Get(*expected_audio.transport_id));
2148 EXPECT_TRUE(report->Get(*expected_audio.codec_id));
hboseeafe942016-11-01 10:00:172149}
2150
2151TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Video) {
hboseeafe942016-11-01 10:00:172152 cricket::VideoMediaInfo video_media_info;
hbos0adb8282016-11-23 10:32:062153
hboseeafe942016-11-01 10:00:172154 video_media_info.receivers.push_back(cricket::VideoReceiverInfo());
2155 video_media_info.receivers[0].local_stats.push_back(
2156 cricket::SsrcReceiverInfo());
2157 video_media_info.receivers[0].local_stats[0].ssrc = 1;
2158 video_media_info.receivers[0].packets_rcvd = 2;
hbos02cd4d62016-12-09 12:19:442159 video_media_info.receivers[0].packets_lost = 42;
Niels Möllerac0a4cb2019-10-09 13:01:332160 video_media_info.receivers[0].payload_bytes_rcvd = 3;
2161 video_media_info.receivers[0].header_and_padding_bytes_rcvd = 12;
Oskar Sundbomcbc71b22017-11-16 09:56:072162 video_media_info.receivers[0].codec_payload_type = 42;
hbos820f5782016-11-22 11:16:502163 video_media_info.receivers[0].firs_sent = 5;
2164 video_media_info.receivers[0].plis_sent = 6;
2165 video_media_info.receivers[0].nacks_sent = 7;
Eldar Rello4e5bc9f2020-07-06 11:18:072166 video_media_info.receivers[0].frames_received = 8;
2167 video_media_info.receivers[0].frames_decoded = 9;
Rasmus Brandt2efae772019-06-27 12:29:342168 video_media_info.receivers[0].key_frames_decoded = 3;
Eldar Rello4e5bc9f2020-07-06 11:18:072169 video_media_info.receivers[0].frames_dropped = 13;
Danil Chapovalov66cadcc2018-06-19 14:47:432170 video_media_info.receivers[0].qp_sum = absl::nullopt;
Philipp Hancked970b092022-06-17 05:34:232171 video_media_info.receivers[0].total_decode_time =
2172 webrtc::TimeDelta::Seconds(9);
Philipp Hanckea16a6a62022-04-25 10:21:302173 video_media_info.receivers[0].total_processing_delay =
2174 webrtc::TimeDelta::Millis(600);
Philipp Hancke0359ba22022-05-05 13:55:362175 video_media_info.receivers[0].total_assembly_time =
2176 webrtc::TimeDelta::Millis(500);
2177 video_media_info.receivers[0].frames_assembled_from_multiple_packets = 23;
Johannes Kron00376e12019-11-25 09:25:422178 video_media_info.receivers[0].total_inter_frame_delay = 0.123;
2179 video_media_info.receivers[0].total_squared_inter_frame_delay = 0.00456;
Di Wu (RP Room Eng)8af6b492021-02-20 01:34:222180 video_media_info.receivers[0].jitter_ms = 1199;
Byoungchan Lee899b29e2021-06-29 13:09:182181 video_media_info.receivers[0].jitter_buffer_delay_seconds = 3.456;
2182 video_media_info.receivers[0].jitter_buffer_emitted_count = 13;
Johannes Kron00376e12019-11-25 09:25:422183
Henrik Boström01738c62019-04-15 15:32:002184 video_media_info.receivers[0].last_packet_received_timestamp_ms =
2185 absl::nullopt;
Henrik Boström2e069262019-04-09 11:59:312186 video_media_info.receivers[0].content_type = VideoContentType::UNSPECIFIED;
Åsa Perssonfcf79cc2019-10-22 13:23:442187 video_media_info.receivers[0].estimated_playout_ntp_timestamp_ms =
2188 absl::nullopt;
Henrik Boström6b430862019-08-16 11:09:512189 video_media_info.receivers[0].decoder_implementation_name = "";
Philipp Hancke6fb8d1a2022-05-30 10:37:042190 video_media_info.receivers[0].min_playout_delay_ms = 50;
hbos0adb8282016-11-23 10:32:062191
Philipp Hancke3719a0c2022-07-04 16:24:462192 // Note: these two values intentionally differ,
2193 // only the decoded one should show up.
2194 video_media_info.receivers[0].framerate_rcvd = 15;
2195 video_media_info.receivers[0].framerate_decoded = 5;
2196
hbos0adb8282016-11-23 10:32:062197 RtpCodecParameters codec_parameters;
2198 codec_parameters.payload_type = 42;
Philipp Hancke3719a0c2022-07-04 16:24:462199 codec_parameters.kind = cricket::MEDIA_TYPE_VIDEO;
deadbeefe702b302017-02-04 20:09:012200 codec_parameters.name = "dummy";
Oskar Sundbomcbc71b22017-11-16 09:56:072201 codec_parameters.clock_rate = 0;
hbos0adb8282016-11-23 10:32:062202 video_media_info.receive_codecs.insert(
2203 std::make_pair(codec_parameters.payload_type, codec_parameters));
2204
Tommi19015512022-02-02 10:49:352205 auto* video_media_channel =
2206 pc_->AddVideoChannel("VideoMid", "TransportName", video_media_info);
Henrik Boström5b3541f2018-03-19 12:52:562207 stats_->SetupRemoteTrackAndReceiver(
2208 cricket::MEDIA_TYPE_VIDEO, "RemoteVideoTrackID", "RemoteStreamId", 1);
hboseeafe942016-11-01 10:00:172209
Steve Anton5b387312018-02-03 00:00:202210 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hboseeafe942016-11-01 10:00:172211
Yves Gerey665174f2018-06-19 13:03:052212 RTCInboundRTPStreamStats expected_video("RTCInboundRTPVideoStream_1",
2213 report->timestamp_us());
hbos3443bb72017-02-07 14:28:112214 expected_video.ssrc = 1;
hbos820f5782016-11-22 11:16:502215 expected_video.media_type = "video";
Philipp Hancke3bc01662018-08-28 12:55:032216 expected_video.kind = "video";
Henrik Boströma6c7d5c2022-06-16 14:55:312217 expected_video.track_identifier = "RemoteVideoTrackID";
Henrik Boström1ab61882022-06-16 15:07:332218 expected_video.mid = "VideoMid";
Niels Möllerafb246b2022-04-20 12:26:502219 expected_video.track_id = IdForType<RTCMediaStreamTrackStats>(report.get());
Steve Anton57858b32018-02-15 23:19:502220 expected_video.transport_id = "RTCTransport_TransportName_1";
2221 expected_video.codec_id = "RTCCodec_VideoMid_Inbound_42";
hbos820f5782016-11-22 11:16:502222 expected_video.fir_count = 5;
2223 expected_video.pli_count = 6;
2224 expected_video.nack_count = 7;
2225 expected_video.packets_received = 2;
2226 expected_video.bytes_received = 3;
Niels Möllerac0a4cb2019-10-09 13:01:332227 expected_video.header_bytes_received = 12;
hbos02cd4d62016-12-09 12:19:442228 expected_video.packets_lost = 42;
Eldar Rello4e5bc9f2020-07-06 11:18:072229 expected_video.frames_received = 8;
2230 expected_video.frames_decoded = 9;
Rasmus Brandt2efae772019-06-27 12:29:342231 expected_video.key_frames_decoded = 3;
Eldar Rello4e5bc9f2020-07-06 11:18:072232 expected_video.frames_dropped = 13;
Artem Titovcfea2182021-08-09 23:22:312233 // `expected_video.qp_sum` should be undefined.
Johannes Kronbfd343b2019-07-01 08:07:502234 expected_video.total_decode_time = 9.0;
Philipp Hanckea16a6a62022-04-25 10:21:302235 expected_video.total_processing_delay = 0.6;
Philipp Hancke0359ba22022-05-05 13:55:362236 expected_video.total_assembly_time = 0.5;
2237 expected_video.frames_assembled_from_multiple_packets = 23;
Johannes Kron00376e12019-11-25 09:25:422238 expected_video.total_inter_frame_delay = 0.123;
2239 expected_video.total_squared_inter_frame_delay = 0.00456;
Di Wu (RP Room Eng)8af6b492021-02-20 01:34:222240 expected_video.jitter = 1.199;
Byoungchan Lee899b29e2021-06-29 13:09:182241 expected_video.jitter_buffer_delay = 3.456;
2242 expected_video.jitter_buffer_emitted_count = 13;
Artem Titovcfea2182021-08-09 23:22:312243 // `expected_video.last_packet_received_timestamp` should be undefined.
2244 // `expected_video.content_type` should be undefined.
2245 // `expected_video.decoder_implementation` should be undefined.
Philipp Hancke6fb8d1a2022-05-30 10:37:042246 expected_video.min_playout_delay = 0.05;
Philipp Hancke3719a0c2022-07-04 16:24:462247 expected_video.frames_per_second = 5;
hboseeafe942016-11-01 10:00:172248
nissec8ee8822017-01-18 15:20:552249 ASSERT_TRUE(report->Get(expected_video.id()));
hbosa51d4f32017-02-16 13:34:482250 EXPECT_EQ(
2251 report->Get(expected_video.id())->cast_to<RTCInboundRTPStreamStats>(),
2252 expected_video);
hboseeafe942016-11-01 10:00:172253
hbosa51d4f32017-02-16 13:34:482254 // Set previously undefined values and "GetStats" again.
Oskar Sundbomcbc71b22017-11-16 09:56:072255 video_media_info.receivers[0].qp_sum = 9;
hbosa51d4f32017-02-16 13:34:482256 expected_video.qp_sum = 9;
Åsa Perssonfcf79cc2019-10-22 13:23:442257 video_media_info.receivers[0].last_packet_received_timestamp_ms = 1000;
Alessio Bazzica5cf8c2c2021-03-24 07:51:262258 expected_video.last_packet_received_timestamp = 1000.0;
Henrik Boström2e069262019-04-09 11:59:312259 video_media_info.receivers[0].content_type = VideoContentType::SCREENSHARE;
2260 expected_video.content_type = "screenshare";
Åsa Perssonfcf79cc2019-10-22 13:23:442261 video_media_info.receivers[0].estimated_playout_ntp_timestamp_ms = 1234;
2262 expected_video.estimated_playout_timestamp = 1234;
Henrik Boström6b430862019-08-16 11:09:512263 video_media_info.receivers[0].decoder_implementation_name = "libfoodecoder";
2264 expected_video.decoder_implementation = "libfoodecoder";
Steve Anton5b387312018-02-03 00:00:202265 video_media_channel->SetStats(video_media_info);
hbosa51d4f32017-02-16 13:34:482266
Steve Anton5b387312018-02-03 00:00:202267 report = stats_->GetFreshStatsReport();
hbosa51d4f32017-02-16 13:34:482268
2269 ASSERT_TRUE(report->Get(expected_video.id()));
2270 EXPECT_EQ(
2271 report->Get(expected_video.id())->cast_to<RTCInboundRTPStreamStats>(),
2272 expected_video);
hbosb0ae9202017-01-27 14:35:162273 EXPECT_TRUE(report->Get(*expected_video.track_id));
hbos84abeb12017-01-16 14:16:442274 EXPECT_TRUE(report->Get(*expected_video.transport_id));
hbosa51d4f32017-02-16 13:34:482275 EXPECT_TRUE(report->Get(*expected_video.codec_id));
hboseeafe942016-11-01 10:00:172276}
2277
hbos6ded1902016-11-01 08:50:462278TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Audio) {
hbos6ded1902016-11-01 08:50:462279 cricket::VoiceMediaInfo voice_media_info;
hbos0adb8282016-11-23 10:32:062280
hbos6ded1902016-11-01 08:50:462281 voice_media_info.senders.push_back(cricket::VoiceSenderInfo());
2282 voice_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
2283 voice_media_info.senders[0].local_stats[0].ssrc = 1;
2284 voice_media_info.senders[0].packets_sent = 2;
Henrik Boströmcf96e0f2019-04-17 11:51:532285 voice_media_info.senders[0].retransmitted_packets_sent = 20;
Niels Möllerac0a4cb2019-10-09 13:01:332286 voice_media_info.senders[0].payload_bytes_sent = 3;
2287 voice_media_info.senders[0].header_and_padding_bytes_sent = 12;
Henrik Boströmcf96e0f2019-04-17 11:51:532288 voice_media_info.senders[0].retransmitted_bytes_sent = 30;
Jakob Ivarssone91c9922021-07-06 07:55:432289 voice_media_info.senders[0].nacks_rcvd = 31;
Jakob Ivarssonbf087452021-11-11 12:43:492290 voice_media_info.senders[0].target_bitrate = 32000;
Oskar Sundbomcbc71b22017-11-16 09:56:072291 voice_media_info.senders[0].codec_payload_type = 42;
hbos0adb8282016-11-23 10:32:062292
2293 RtpCodecParameters codec_parameters;
2294 codec_parameters.payload_type = 42;
deadbeefe702b302017-02-04 20:09:012295 codec_parameters.kind = cricket::MEDIA_TYPE_AUDIO;
2296 codec_parameters.name = "dummy";
Oskar Sundbomcbc71b22017-11-16 09:56:072297 codec_parameters.clock_rate = 0;
hbos0adb8282016-11-23 10:32:062298 voice_media_info.send_codecs.insert(
2299 std::make_pair(codec_parameters.payload_type, codec_parameters));
2300
Tommi19015512022-02-02 10:49:352301 pc_->AddVoiceChannel("AudioMid", "TransportName", voice_media_info);
Steve Anton5b387312018-02-03 00:00:202302 stats_->SetupLocalTrackAndSender(cricket::MEDIA_TYPE_AUDIO,
Henrik Boström646fda02019-05-22 13:49:422303 "LocalAudioTrackID", 1, true,
2304 /*attachment_id=*/50);
hbos6ded1902016-11-01 08:50:462305
Steve Anton5b387312018-02-03 00:00:202306 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbos6ded1902016-11-01 08:50:462307
Yves Gerey665174f2018-06-19 13:03:052308 RTCOutboundRTPStreamStats expected_audio("RTCOutboundRTPAudioStream_1",
2309 report->timestamp_us());
Henrik Boström646fda02019-05-22 13:49:422310 expected_audio.media_source_id = "RTCAudioSource_50";
Artem Titovcfea2182021-08-09 23:22:312311 // `expected_audio.remote_id` should be undefined.
Henrik Boström1ab61882022-06-16 15:07:332312 expected_audio.mid = "AudioMid";
hbos3443bb72017-02-07 14:28:112313 expected_audio.ssrc = 1;
hbos6ded1902016-11-01 08:50:462314 expected_audio.media_type = "audio";
Philipp Hancke3bc01662018-08-28 12:55:032315 expected_audio.kind = "audio";
Niels Möllerafb246b2022-04-20 12:26:502316 expected_audio.track_id = IdForType<RTCMediaStreamTrackStats>(report.get());
Steve Anton57858b32018-02-15 23:19:502317 expected_audio.transport_id = "RTCTransport_TransportName_1";
2318 expected_audio.codec_id = "RTCCodec_AudioMid_Outbound_42";
hbos6ded1902016-11-01 08:50:462319 expected_audio.packets_sent = 2;
Henrik Boströmcf96e0f2019-04-17 11:51:532320 expected_audio.retransmitted_packets_sent = 20;
hbos6ded1902016-11-01 08:50:462321 expected_audio.bytes_sent = 3;
Niels Möllerac0a4cb2019-10-09 13:01:332322 expected_audio.header_bytes_sent = 12;
Henrik Boströmcf96e0f2019-04-17 11:51:532323 expected_audio.retransmitted_bytes_sent = 30;
Jakob Ivarssone91c9922021-07-06 07:55:432324 expected_audio.nack_count = 31;
Jakob Ivarssonbf087452021-11-11 12:43:492325 expected_audio.target_bitrate = 32000;
hboscd195be2017-02-07 16:31:272326
hboscd195be2017-02-07 16:31:272327 ASSERT_TRUE(report->Get(expected_audio.id()));
hbosa51d4f32017-02-16 13:34:482328 EXPECT_EQ(
2329 report->Get(expected_audio.id())->cast_to<RTCOutboundRTPStreamStats>(),
2330 expected_audio);
skvladed02c6d2017-02-07 18:45:312331
hbosa51d4f32017-02-16 13:34:482332 ASSERT_TRUE(report->Get(expected_audio.id()));
2333 EXPECT_EQ(
2334 report->Get(expected_audio.id())->cast_to<RTCOutboundRTPStreamStats>(),
2335 expected_audio);
hbosb0ae9202017-01-27 14:35:162336 EXPECT_TRUE(report->Get(*expected_audio.track_id));
hbos84abeb12017-01-16 14:16:442337 EXPECT_TRUE(report->Get(*expected_audio.transport_id));
2338 EXPECT_TRUE(report->Get(*expected_audio.codec_id));
hbos6ded1902016-11-01 08:50:462339}
2340
2341TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Video) {
hbos6ded1902016-11-01 08:50:462342 cricket::VideoMediaInfo video_media_info;
hbos0adb8282016-11-23 10:32:062343
hbos6ded1902016-11-01 08:50:462344 video_media_info.senders.push_back(cricket::VideoSenderInfo());
2345 video_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
2346 video_media_info.senders[0].local_stats[0].ssrc = 1;
2347 video_media_info.senders[0].firs_rcvd = 2;
2348 video_media_info.senders[0].plis_rcvd = 3;
2349 video_media_info.senders[0].nacks_rcvd = 4;
2350 video_media_info.senders[0].packets_sent = 5;
Henrik Boströmcf96e0f2019-04-17 11:51:532351 video_media_info.senders[0].retransmitted_packets_sent = 50;
Niels Möllerac0a4cb2019-10-09 13:01:332352 video_media_info.senders[0].payload_bytes_sent = 6;
2353 video_media_info.senders[0].header_and_padding_bytes_sent = 12;
Henrik Boströmcf96e0f2019-04-17 11:51:532354 video_media_info.senders[0].retransmitted_bytes_sent = 60;
Oskar Sundbomcbc71b22017-11-16 09:56:072355 video_media_info.senders[0].codec_payload_type = 42;
hbos6769c492017-01-02 16:35:132356 video_media_info.senders[0].frames_encoded = 8;
Rasmus Brandt2efae772019-06-27 12:29:342357 video_media_info.senders[0].key_frames_encoded = 3;
Henrik Boströmf71362f2019-04-08 14:14:232358 video_media_info.senders[0].total_encode_time_ms = 9000;
Henrik Boström23aff9b2019-05-20 13:15:382359 video_media_info.senders[0].total_encoded_bytes_target = 1234;
Henrik Boström9fe18342019-05-16 16:38:202360 video_media_info.senders[0].total_packet_send_delay_ms = 10000;
Henrik Boströmce33b6a2019-05-28 15:42:382361 video_media_info.senders[0].quality_limitation_reason =
2362 QualityLimitationReason::kBandwidth;
Byoungchan Lee7d235352021-05-28 12:32:042363 video_media_info.senders[0].quality_limitation_durations_ms
2364 [webrtc::QualityLimitationReason::kBandwidth] = 300;
Evan Shrubsolecc62b162019-09-09 09:26:452365 video_media_info.senders[0].quality_limitation_resolution_changes = 56u;
Danil Chapovalov66cadcc2018-06-19 14:47:432366 video_media_info.senders[0].qp_sum = absl::nullopt;
Henrik Boström2e069262019-04-09 11:59:312367 video_media_info.senders[0].content_type = VideoContentType::UNSPECIFIED;
Henrik Boström6b430862019-08-16 11:09:512368 video_media_info.senders[0].encoder_implementation_name = "";
Henrik Boströma0ff50c2020-05-05 13:54:462369 video_media_info.senders[0].send_frame_width = 200;
2370 video_media_info.senders[0].send_frame_height = 100;
2371 video_media_info.senders[0].framerate_sent = 10;
2372 video_media_info.senders[0].frames_sent = 5;
2373 video_media_info.senders[0].huge_frames_sent = 2;
2374 video_media_info.aggregated_senders.push_back(video_media_info.senders[0]);
hbos0adb8282016-11-23 10:32:062375 RtpCodecParameters codec_parameters;
2376 codec_parameters.payload_type = 42;
deadbeefe702b302017-02-04 20:09:012377 codec_parameters.kind = cricket::MEDIA_TYPE_AUDIO;
2378 codec_parameters.name = "dummy";
Oskar Sundbomcbc71b22017-11-16 09:56:072379 codec_parameters.clock_rate = 0;
hbos0adb8282016-11-23 10:32:062380 video_media_info.send_codecs.insert(
2381 std::make_pair(codec_parameters.payload_type, codec_parameters));
2382
Tommi19015512022-02-02 10:49:352383 auto* video_media_channel =
2384 pc_->AddVideoChannel("VideoMid", "TransportName", video_media_info);
Steve Anton5b387312018-02-03 00:00:202385 stats_->SetupLocalTrackAndSender(cricket::MEDIA_TYPE_VIDEO,
Henrik Boström646fda02019-05-22 13:49:422386 "LocalVideoTrackID", 1, true,
2387 /*attachment_id=*/50);
hbos6ded1902016-11-01 08:50:462388
Steve Anton5b387312018-02-03 00:00:202389 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbos6ded1902016-11-01 08:50:462390
Harald Alvestranda3dab842018-01-14 08:18:582391 auto stats_of_my_type = report->GetStatsOfType<RTCOutboundRTPStreamStats>();
Mirko Bonadeie12c1fe2018-07-03 10:53:232392 ASSERT_EQ(1U, stats_of_my_type.size());
Harald Alvestranda3dab842018-01-14 08:18:582393 auto stats_of_track_type = report->GetStatsOfType<RTCMediaStreamTrackStats>();
Mirko Bonadeie12c1fe2018-07-03 10:53:232394 ASSERT_EQ(1U, stats_of_track_type.size());
Harald Alvestranda3dab842018-01-14 08:18:582395
2396 RTCOutboundRTPStreamStats expected_video(stats_of_my_type[0]->id(),
2397 report->timestamp_us());
Henrik Boström646fda02019-05-22 13:49:422398 expected_video.media_source_id = "RTCVideoSource_50";
Artem Titovcfea2182021-08-09 23:22:312399 // `expected_video.remote_id` should be undefined.
Henrik Boström1ab61882022-06-16 15:07:332400 expected_video.mid = "VideoMid";
hbos3443bb72017-02-07 14:28:112401 expected_video.ssrc = 1;
hbos6ded1902016-11-01 08:50:462402 expected_video.media_type = "video";
Philipp Hancke3bc01662018-08-28 12:55:032403 expected_video.kind = "video";
Harald Alvestranda3dab842018-01-14 08:18:582404 expected_video.track_id = stats_of_track_type[0]->id();
Steve Anton57858b32018-02-15 23:19:502405 expected_video.transport_id = "RTCTransport_TransportName_1";
2406 expected_video.codec_id = "RTCCodec_VideoMid_Outbound_42";
hbos6ded1902016-11-01 08:50:462407 expected_video.fir_count = 2;
2408 expected_video.pli_count = 3;
2409 expected_video.nack_count = 4;
2410 expected_video.packets_sent = 5;
Henrik Boströmcf96e0f2019-04-17 11:51:532411 expected_video.retransmitted_packets_sent = 50;
hbos6ded1902016-11-01 08:50:462412 expected_video.bytes_sent = 6;
Niels Möllerac0a4cb2019-10-09 13:01:332413 expected_video.header_bytes_sent = 12;
Henrik Boströmcf96e0f2019-04-17 11:51:532414 expected_video.retransmitted_bytes_sent = 60;
skvladed02c6d2017-02-07 18:45:312415 expected_video.frames_encoded = 8;
Rasmus Brandt2efae772019-06-27 12:29:342416 expected_video.key_frames_encoded = 3;
Henrik Boströmf71362f2019-04-08 14:14:232417 expected_video.total_encode_time = 9.0;
Henrik Boström23aff9b2019-05-20 13:15:382418 expected_video.total_encoded_bytes_target = 1234;
Henrik Boström9fe18342019-05-16 16:38:202419 expected_video.total_packet_send_delay = 10.0;
Henrik Boströmce33b6a2019-05-28 15:42:382420 expected_video.quality_limitation_reason = "bandwidth";
Byoungchan Lee7d235352021-05-28 12:32:042421 expected_video.quality_limitation_durations = std::map<std::string, double>{
Philipp Hancke3fd9cbc2022-01-10 16:41:432422 std::pair<std::string, double>{"bandwidth", 0.3},
Byoungchan Lee7d235352021-05-28 12:32:042423 };
Evan Shrubsolecc62b162019-09-09 09:26:452424 expected_video.quality_limitation_resolution_changes = 56u;
Eldar Rello9276e2c2020-06-10 14:53:392425 expected_video.frame_width = 200u;
2426 expected_video.frame_height = 100u;
2427 expected_video.frames_per_second = 10.0;
2428 expected_video.frames_sent = 5;
2429 expected_video.huge_frames_sent = 2;
Artem Titovcfea2182021-08-09 23:22:312430 // `expected_video.content_type` should be undefined.
2431 // `expected_video.qp_sum` should be undefined.
2432 // `expected_video.encoder_implementation` should be undefined.
hboscd195be2017-02-07 16:31:272433 ASSERT_TRUE(report->Get(expected_video.id()));
Harald Alvestranda3dab842018-01-14 08:18:582434
hbosa51d4f32017-02-16 13:34:482435 EXPECT_EQ(
2436 report->Get(expected_video.id())->cast_to<RTCOutboundRTPStreamStats>(),
2437 expected_video);
skvladed02c6d2017-02-07 18:45:312438
hbosa51d4f32017-02-16 13:34:482439 // Set previously undefined values and "GetStats" again.
Oskar Sundbomcbc71b22017-11-16 09:56:072440 video_media_info.senders[0].qp_sum = 9;
hbosa51d4f32017-02-16 13:34:482441 expected_video.qp_sum = 9;
Henrik Boström2e069262019-04-09 11:59:312442 video_media_info.senders[0].content_type = VideoContentType::SCREENSHARE;
2443 expected_video.content_type = "screenshare";
Henrik Boström6b430862019-08-16 11:09:512444 video_media_info.senders[0].encoder_implementation_name = "libfooencoder";
Henrik Boströma0ff50c2020-05-05 13:54:462445 video_media_info.aggregated_senders[0] = video_media_info.senders[0];
Henrik Boström6b430862019-08-16 11:09:512446 expected_video.encoder_implementation = "libfooencoder";
Steve Anton5b387312018-02-03 00:00:202447 video_media_channel->SetStats(video_media_info);
hbosa51d4f32017-02-16 13:34:482448
Steve Anton5b387312018-02-03 00:00:202449 report = stats_->GetFreshStatsReport();
hbosa51d4f32017-02-16 13:34:482450
2451 ASSERT_TRUE(report->Get(expected_video.id()));
2452 EXPECT_EQ(
2453 report->Get(expected_video.id())->cast_to<RTCOutboundRTPStreamStats>(),
2454 expected_video);
hbosb0ae9202017-01-27 14:35:162455 EXPECT_TRUE(report->Get(*expected_video.track_id));
hbos84abeb12017-01-16 14:16:442456 EXPECT_TRUE(report->Get(*expected_video.transport_id));
2457 EXPECT_TRUE(report->Get(*expected_video.codec_id));
hbos6ded1902016-11-01 08:50:462458}
2459
hbos2fa7c672016-10-24 11:00:052460TEST_F(RTCStatsCollectorTest, CollectRTCTransportStats) {
Steve Anton5b387312018-02-03 00:00:202461 const char kTransportName[] = "transport";
2462
2463 pc_->AddVoiceChannel("audio", kTransportName);
2464
Gary Liu37e489c2017-11-21 18:49:362465 std::unique_ptr<cricket::Candidate> rtp_local_candidate =
2466 CreateFakeCandidate("42.42.42.42", 42, "protocol", rtc::ADAPTER_TYPE_WIFI,
2467 cricket::LOCAL_PORT_TYPE, 42);
hbos2fa7c672016-10-24 11:00:052468 std::unique_ptr<cricket::Candidate> rtp_remote_candidate =
2469 CreateFakeCandidate("42.42.42.42", 42, "protocol",
Gary Liu37e489c2017-11-21 18:49:362470 rtc::ADAPTER_TYPE_UNKNOWN, cricket::LOCAL_PORT_TYPE,
2471 42);
hbos2fa7c672016-10-24 11:00:052472 std::unique_ptr<cricket::Candidate> rtcp_local_candidate =
Gary Liu37e489c2017-11-21 18:49:362473 CreateFakeCandidate("42.42.42.42", 42, "protocol", rtc::ADAPTER_TYPE_WIFI,
hbos2fa7c672016-10-24 11:00:052474 cricket::LOCAL_PORT_TYPE, 42);
2475 std::unique_ptr<cricket::Candidate> rtcp_remote_candidate =
2476 CreateFakeCandidate("42.42.42.42", 42, "protocol",
Gary Liu37e489c2017-11-21 18:49:362477 rtc::ADAPTER_TYPE_UNKNOWN, cricket::LOCAL_PORT_TYPE,
2478 42);
hbos2fa7c672016-10-24 11:00:052479
hbos2fa7c672016-10-24 11:00:052480 cricket::ConnectionInfo rtp_connection_info;
2481 rtp_connection_info.best_connection = false;
2482 rtp_connection_info.local_candidate = *rtp_local_candidate.get();
2483 rtp_connection_info.remote_candidate = *rtp_remote_candidate.get();
2484 rtp_connection_info.sent_total_bytes = 42;
2485 rtp_connection_info.recv_total_bytes = 1337;
Artem Titovedacbd52020-07-06 14:06:372486 rtp_connection_info.sent_total_packets = 3;
2487 rtp_connection_info.sent_discarded_packets = 2;
2488 rtp_connection_info.packets_received = 4;
hbos2fa7c672016-10-24 11:00:052489 cricket::TransportChannelStats rtp_transport_channel_stats;
2490 rtp_transport_channel_stats.component = cricket::ICE_CANDIDATE_COMPONENT_RTP;
Jonas Oreland149dc722019-08-28 06:10:272491 rtp_transport_channel_stats.ice_transport_stats.connection_infos.push_back(
2492 rtp_connection_info);
Mirko Bonadei9f6808b2021-05-21 18:46:092493 rtp_transport_channel_stats.dtls_state = DtlsTransportState::kNew;
Jonas Oreland42da5a92022-03-01 12:55:372494 rtp_transport_channel_stats.ice_transport_stats.bytes_sent = 42;
2495 rtp_transport_channel_stats.ice_transport_stats.packets_sent = 1;
2496 rtp_transport_channel_stats.ice_transport_stats.bytes_received = 1337;
2497 rtp_transport_channel_stats.ice_transport_stats.packets_received = 4;
Jonas Oreland149dc722019-08-28 06:10:272498 rtp_transport_channel_stats.ice_transport_stats
2499 .selected_candidate_pair_changes = 1;
Philipp Hancke95b1a342022-05-05 05:53:542500 rtp_transport_channel_stats.ice_transport_stats.ice_local_username_fragment =
2501 "thelocalufrag";
Steve Anton5b387312018-02-03 00:00:202502 pc_->SetTransportStats(kTransportName, {rtp_transport_channel_stats});
hbos2fa7c672016-10-24 11:00:052503
2504 // Get stats without RTCP, an active connection or certificates.
Steve Anton5b387312018-02-03 00:00:202505 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbos0583b282016-11-30 09:50:142506
2507 RTCTransportStats expected_rtp_transport(
2508 "RTCTransport_transport_" +
Jonas Olsson6b1985d2018-07-05 09:59:482509 rtc::ToString(cricket::ICE_CANDIDATE_COMPONENT_RTP),
hbos0583b282016-11-30 09:50:142510 report->timestamp_us());
2511 expected_rtp_transport.bytes_sent = 42;
Artem Titovedacbd52020-07-06 14:06:372512 expected_rtp_transport.packets_sent = 1;
hbos0583b282016-11-30 09:50:142513 expected_rtp_transport.bytes_received = 1337;
Artem Titovedacbd52020-07-06 14:06:372514 expected_rtp_transport.packets_received = 4;
hbos7064d592017-01-16 15:38:022515 expected_rtp_transport.dtls_state = RTCDtlsTransportState::kNew;
Philipp Hancke69c1df22022-04-22 13:46:242516 expected_rtp_transport.dtls_role = RTCDtlsRole::kUnknown;
Jonas Oreland149dc722019-08-28 06:10:272517 expected_rtp_transport.selected_candidate_pair_changes = 1;
Philipp Hanckecc1b9b02022-05-04 16:58:262518 expected_rtp_transport.ice_role = RTCIceRole::kUnknown;
Philipp Hancke95b1a342022-05-05 05:53:542519 expected_rtp_transport.ice_local_username_fragment = "thelocalufrag";
Philipp Hancke1f491572022-05-09 15:43:312520 expected_rtp_transport.ice_state = RTCIceTransportState::kNew;
hbos0583b282016-11-30 09:50:142521
hbosdbb64d82016-12-21 09:57:462522 ASSERT_TRUE(report->Get(expected_rtp_transport.id()));
hbos0583b282016-11-30 09:50:142523 EXPECT_EQ(
2524 expected_rtp_transport,
2525 report->Get(expected_rtp_transport.id())->cast_to<RTCTransportStats>());
hbos2fa7c672016-10-24 11:00:052526
2527 cricket::ConnectionInfo rtcp_connection_info;
2528 rtcp_connection_info.best_connection = false;
2529 rtcp_connection_info.local_candidate = *rtcp_local_candidate.get();
2530 rtcp_connection_info.remote_candidate = *rtcp_remote_candidate.get();
2531 rtcp_connection_info.sent_total_bytes = 1337;
2532 rtcp_connection_info.recv_total_bytes = 42;
Artem Titovedacbd52020-07-06 14:06:372533 rtcp_connection_info.sent_total_packets = 3;
2534 rtcp_connection_info.sent_discarded_packets = 2;
2535 rtcp_connection_info.packets_received = 4;
hbos2fa7c672016-10-24 11:00:052536 cricket::TransportChannelStats rtcp_transport_channel_stats;
2537 rtcp_transport_channel_stats.component =
2538 cricket::ICE_CANDIDATE_COMPONENT_RTCP;
Jonas Oreland149dc722019-08-28 06:10:272539 rtcp_transport_channel_stats.ice_transport_stats.connection_infos.push_back(
2540 rtcp_connection_info);
Mirko Bonadei9f6808b2021-05-21 18:46:092541 rtcp_transport_channel_stats.dtls_state = DtlsTransportState::kConnecting;
Jonas Oreland42da5a92022-03-01 12:55:372542 rtcp_transport_channel_stats.ice_transport_stats.bytes_sent = 1337;
2543 rtcp_transport_channel_stats.ice_transport_stats.packets_sent = 1;
2544 rtcp_transport_channel_stats.ice_transport_stats.bytes_received = 42;
2545 rtcp_transport_channel_stats.ice_transport_stats.packets_received = 4;
Philipp Hancke95b1a342022-05-05 05:53:542546 rtcp_transport_channel_stats.ice_transport_stats.ice_local_username_fragment =
2547 "thelocalufrag";
Philipp Hancke1f491572022-05-09 15:43:312548 rtcp_transport_channel_stats.ice_transport_stats.ice_state =
2549 IceTransportState::kChecking;
Steve Anton5b387312018-02-03 00:00:202550 pc_->SetTransportStats(kTransportName, {rtp_transport_channel_stats,
2551 rtcp_transport_channel_stats});
hbos2fa7c672016-10-24 11:00:052552
hbos2fa7c672016-10-24 11:00:052553 // Get stats with RTCP and without an active connection or certificates.
Steve Anton5b387312018-02-03 00:00:202554 report = stats_->GetFreshStatsReport();
hbos0583b282016-11-30 09:50:142555
2556 RTCTransportStats expected_rtcp_transport(
2557 "RTCTransport_transport_" +
Jonas Olsson6b1985d2018-07-05 09:59:482558 rtc::ToString(cricket::ICE_CANDIDATE_COMPONENT_RTCP),
hbos0583b282016-11-30 09:50:142559 report->timestamp_us());
2560 expected_rtcp_transport.bytes_sent = 1337;
Artem Titovedacbd52020-07-06 14:06:372561 expected_rtcp_transport.packets_sent = 1;
hbos0583b282016-11-30 09:50:142562 expected_rtcp_transport.bytes_received = 42;
Artem Titovedacbd52020-07-06 14:06:372563 expected_rtcp_transport.packets_received = 4;
hbos7064d592017-01-16 15:38:022564 expected_rtcp_transport.dtls_state = RTCDtlsTransportState::kConnecting;
Philipp Hancke69c1df22022-04-22 13:46:242565 expected_rtcp_transport.dtls_role = RTCDtlsRole::kUnknown;
Jonas Oreland149dc722019-08-28 06:10:272566 expected_rtcp_transport.selected_candidate_pair_changes = 0;
Philipp Hanckecc1b9b02022-05-04 16:58:262567 expected_rtcp_transport.ice_role = RTCIceRole::kUnknown;
Philipp Hancke95b1a342022-05-05 05:53:542568 expected_rtcp_transport.ice_local_username_fragment = "thelocalufrag";
Philipp Hancke1f491572022-05-09 15:43:312569 expected_rtcp_transport.ice_state = RTCIceTransportState::kChecking;
hbos0583b282016-11-30 09:50:142570
2571 expected_rtp_transport.rtcp_transport_stats_id = expected_rtcp_transport.id();
hbosdbb64d82016-12-21 09:57:462572 ASSERT_TRUE(report->Get(expected_rtp_transport.id()));
hbos0583b282016-11-30 09:50:142573 EXPECT_EQ(
2574 expected_rtp_transport,
2575 report->Get(expected_rtp_transport.id())->cast_to<RTCTransportStats>());
hbosdbb64d82016-12-21 09:57:462576 ASSERT_TRUE(report->Get(expected_rtcp_transport.id()));
hbos0583b282016-11-30 09:50:142577 EXPECT_EQ(
2578 expected_rtcp_transport,
2579 report->Get(expected_rtcp_transport.id())->cast_to<RTCTransportStats>());
hbos2fa7c672016-10-24 11:00:052580
hbos7064d592017-01-16 15:38:022581 // Get stats with an active connection (selected candidate pair).
Jonas Oreland149dc722019-08-28 06:10:272582 rtcp_transport_channel_stats.ice_transport_stats.connection_infos[0]
2583 .best_connection = true;
Steve Anton5b387312018-02-03 00:00:202584 pc_->SetTransportStats(kTransportName, {rtp_transport_channel_stats,
2585 rtcp_transport_channel_stats});
hbos2fa7c672016-10-24 11:00:052586
Steve Anton5b387312018-02-03 00:00:202587 report = stats_->GetFreshStatsReport();
hbos0583b282016-11-30 09:50:142588
hbos0583b282016-11-30 09:50:142589 expected_rtcp_transport.selected_candidate_pair_id =
2590 "RTCIceCandidatePair_" + rtcp_local_candidate->id() + "_" +
2591 rtcp_remote_candidate->id();
2592
hbosdbb64d82016-12-21 09:57:462593 ASSERT_TRUE(report->Get(expected_rtp_transport.id()));
hbos0583b282016-11-30 09:50:142594 EXPECT_EQ(
2595 expected_rtp_transport,
2596 report->Get(expected_rtp_transport.id())->cast_to<RTCTransportStats>());
hbosdbb64d82016-12-21 09:57:462597 ASSERT_TRUE(report->Get(expected_rtcp_transport.id()));
hbos0583b282016-11-30 09:50:142598 EXPECT_EQ(
2599 expected_rtcp_transport,
2600 report->Get(expected_rtcp_transport.id())->cast_to<RTCTransportStats>());
hbos2fa7c672016-10-24 11:00:052601
2602 // Get stats with certificates.
2603 std::unique_ptr<CertificateInfo> local_certinfo =
Steve Anton5b387312018-02-03 00:00:202604 CreateFakeCertificateAndInfoFromDers({"(local) local", "(local) chain"});
2605 pc_->SetLocalCertificate(kTransportName, local_certinfo->certificate);
hbos2fa7c672016-10-24 11:00:052606 std::unique_ptr<CertificateInfo> remote_certinfo =
2607 CreateFakeCertificateAndInfoFromDers(
Steve Anton5b387312018-02-03 00:00:202608 {"(remote) local", "(remote) chain"});
Taylor Brandstetterc3928662018-02-23 21:04:512609 pc_->SetRemoteCertChain(
Benjamin Wright6c6c9df2018-10-25 08:16:262610 kTransportName,
2611 remote_certinfo->certificate->GetSSLCertificateChain().Clone());
hbos2fa7c672016-10-24 11:00:052612
Steve Anton5b387312018-02-03 00:00:202613 report = stats_->GetFreshStatsReport();
hbos0583b282016-11-30 09:50:142614
2615 expected_rtp_transport.local_certificate_id =
2616 "RTCCertificate_" + local_certinfo->fingerprints[0];
2617 expected_rtp_transport.remote_certificate_id =
2618 "RTCCertificate_" + remote_certinfo->fingerprints[0];
2619
2620 expected_rtcp_transport.local_certificate_id =
2621 *expected_rtp_transport.local_certificate_id;
2622 expected_rtcp_transport.remote_certificate_id =
2623 *expected_rtp_transport.remote_certificate_id;
2624
hbosdbb64d82016-12-21 09:57:462625 ASSERT_TRUE(report->Get(expected_rtp_transport.id()));
hbos0583b282016-11-30 09:50:142626 EXPECT_EQ(
2627 expected_rtp_transport,
2628 report->Get(expected_rtp_transport.id())->cast_to<RTCTransportStats>());
hbosdbb64d82016-12-21 09:57:462629 ASSERT_TRUE(report->Get(expected_rtcp_transport.id()));
hbos0583b282016-11-30 09:50:142630 EXPECT_EQ(
2631 expected_rtcp_transport,
2632 report->Get(expected_rtcp_transport.id())->cast_to<RTCTransportStats>());
hbos2fa7c672016-10-24 11:00:052633}
2634
Harald Alvestrand5cb78072019-10-28 08:51:172635TEST_F(RTCStatsCollectorTest, CollectRTCTransportStatsWithCrypto) {
2636 const char kTransportName[] = "transport";
2637
2638 pc_->AddVoiceChannel("audio", kTransportName);
2639
2640 std::unique_ptr<cricket::Candidate> rtp_local_candidate =
2641 CreateFakeCandidate("42.42.42.42", 42, "protocol", rtc::ADAPTER_TYPE_WIFI,
2642 cricket::LOCAL_PORT_TYPE, 42);
2643 std::unique_ptr<cricket::Candidate> rtp_remote_candidate =
2644 CreateFakeCandidate("42.42.42.42", 42, "protocol",
2645 rtc::ADAPTER_TYPE_UNKNOWN, cricket::LOCAL_PORT_TYPE,
2646 42);
2647 std::unique_ptr<cricket::Candidate> rtcp_local_candidate =
2648 CreateFakeCandidate("42.42.42.42", 42, "protocol", rtc::ADAPTER_TYPE_WIFI,
2649 cricket::LOCAL_PORT_TYPE, 42);
2650 std::unique_ptr<cricket::Candidate> rtcp_remote_candidate =
2651 CreateFakeCandidate("42.42.42.42", 42, "protocol",
2652 rtc::ADAPTER_TYPE_UNKNOWN, cricket::LOCAL_PORT_TYPE,
2653 42);
2654
2655 cricket::ConnectionInfo rtp_connection_info;
2656 rtp_connection_info.best_connection = false;
2657 rtp_connection_info.local_candidate = *rtp_local_candidate.get();
2658 rtp_connection_info.remote_candidate = *rtp_remote_candidate.get();
Harald Alvestrand5cb78072019-10-28 08:51:172659 cricket::TransportChannelStats rtp_transport_channel_stats;
2660 rtp_transport_channel_stats.component = cricket::ICE_CANDIDATE_COMPONENT_RTP;
2661 rtp_transport_channel_stats.ice_transport_stats.connection_infos.push_back(
2662 rtp_connection_info);
2663 // The state must be connected in order for crypto parameters to show up.
Mirko Bonadei9f6808b2021-05-21 18:46:092664 rtp_transport_channel_stats.dtls_state = DtlsTransportState::kConnected;
Harald Alvestrand5cb78072019-10-28 08:51:172665 rtp_transport_channel_stats.ice_transport_stats
2666 .selected_candidate_pair_changes = 1;
2667 rtp_transport_channel_stats.ssl_version_bytes = 0x0203;
Philipp Hancke69c1df22022-04-22 13:46:242668 rtp_transport_channel_stats.dtls_role = rtc::SSL_CLIENT;
Philipp Hanckecc1b9b02022-05-04 16:58:262669 rtp_transport_channel_stats.ice_transport_stats.ice_role =
2670 cricket::ICEROLE_CONTROLLING;
Philipp Hancke95b1a342022-05-05 05:53:542671 rtp_transport_channel_stats.ice_transport_stats.ice_local_username_fragment =
2672 "thelocalufrag";
Philipp Hancke1f491572022-05-09 15:43:312673 rtp_transport_channel_stats.ice_transport_stats.ice_state =
2674 IceTransportState::kConnected;
Harald Alvestrand5cb78072019-10-28 08:51:172675 // 0x2F is TLS_RSA_WITH_AES_128_CBC_SHA according to IANA
2676 rtp_transport_channel_stats.ssl_cipher_suite = 0x2F;
Mirko Bonadei7750d802021-07-26 15:27:422677 rtp_transport_channel_stats.srtp_crypto_suite = rtc::kSrtpAes128CmSha1_80;
Harald Alvestrand5cb78072019-10-28 08:51:172678 pc_->SetTransportStats(kTransportName, {rtp_transport_channel_stats});
2679
2680 // Get stats
2681 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
2682
2683 RTCTransportStats expected_rtp_transport(
2684 "RTCTransport_transport_" +
2685 rtc::ToString(cricket::ICE_CANDIDATE_COMPONENT_RTP),
2686 report->timestamp_us());
Harald Alvestrand5cb78072019-10-28 08:51:172687 expected_rtp_transport.dtls_state = RTCDtlsTransportState::kConnected;
2688 expected_rtp_transport.selected_candidate_pair_changes = 1;
Philipp Hanckecc1b9b02022-05-04 16:58:262689 expected_rtp_transport.ice_role = RTCIceRole::kUnknown;
Jonas Oreland42da5a92022-03-01 12:55:372690 expected_rtp_transport.bytes_sent = 0;
2691 expected_rtp_transport.bytes_received = 0;
2692 expected_rtp_transport.packets_sent = 0;
2693 expected_rtp_transport.packets_received = 0;
Philipp Hancke95b1a342022-05-05 05:53:542694 expected_rtp_transport.ice_role = RTCIceRole::kControlling;
2695 expected_rtp_transport.ice_local_username_fragment = "thelocalufrag";
Philipp Hancke1f491572022-05-09 15:43:312696 expected_rtp_transport.ice_state = "connected";
Harald Alvestrand5cb78072019-10-28 08:51:172697 // Crypto parameters
2698 expected_rtp_transport.tls_version = "0203";
Philipp Hancke69c1df22022-04-22 13:46:242699 expected_rtp_transport.dtls_role = RTCDtlsRole::kClient;
Harald Alvestrand5cb78072019-10-28 08:51:172700 expected_rtp_transport.dtls_cipher = "TLS_RSA_WITH_AES_128_CBC_SHA";
2701 expected_rtp_transport.srtp_cipher = "AES_CM_128_HMAC_SHA1_80";
2702
2703 ASSERT_TRUE(report->Get(expected_rtp_transport.id()));
2704 EXPECT_EQ(
2705 expected_rtp_transport,
2706 report->Get(expected_rtp_transport.id())->cast_to<RTCTransportStats>());
2707}
2708
Harald Alvestrand89061872018-01-02 13:08:342709TEST_F(RTCStatsCollectorTest, CollectNoStreamRTCOutboundRTPStreamStats_Audio) {
Harald Alvestrand89061872018-01-02 13:08:342710 cricket::VoiceMediaInfo voice_media_info;
2711
2712 voice_media_info.senders.push_back(cricket::VoiceSenderInfo());
2713 voice_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
2714 voice_media_info.senders[0].local_stats[0].ssrc = 1;
2715 voice_media_info.senders[0].packets_sent = 2;
Henrik Boströmcf96e0f2019-04-17 11:51:532716 voice_media_info.senders[0].retransmitted_packets_sent = 20;
Niels Möllerac0a4cb2019-10-09 13:01:332717 voice_media_info.senders[0].payload_bytes_sent = 3;
2718 voice_media_info.senders[0].header_and_padding_bytes_sent = 4;
Henrik Boströmcf96e0f2019-04-17 11:51:532719 voice_media_info.senders[0].retransmitted_bytes_sent = 30;
Jakob Ivarssone91c9922021-07-06 07:55:432720 voice_media_info.senders[0].nacks_rcvd = 31;
Harald Alvestrand89061872018-01-02 13:08:342721 voice_media_info.senders[0].codec_payload_type = 42;
2722
2723 RtpCodecParameters codec_parameters;
2724 codec_parameters.payload_type = 42;
2725 codec_parameters.kind = cricket::MEDIA_TYPE_AUDIO;
2726 codec_parameters.name = "dummy";
2727 codec_parameters.clock_rate = 0;
2728 voice_media_info.send_codecs.insert(
2729 std::make_pair(codec_parameters.payload_type, codec_parameters));
2730
Steve Anton5b387312018-02-03 00:00:202731 // Emulates the case where AddTrack is used without an associated MediaStream
Tommi19015512022-02-02 10:49:352732 pc_->AddVoiceChannel("AudioMid", "TransportName", voice_media_info);
Steve Anton5b387312018-02-03 00:00:202733 stats_->SetupLocalTrackAndSender(cricket::MEDIA_TYPE_AUDIO,
Henrik Boström646fda02019-05-22 13:49:422734 "LocalAudioTrackID", 1, false,
2735 /*attachment_id=*/50);
Harald Alvestrand89061872018-01-02 13:08:342736
Steve Anton5b387312018-02-03 00:00:202737 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
Harald Alvestrand89061872018-01-02 13:08:342738
2739 RTCOutboundRTPStreamStats expected_audio("RTCOutboundRTPAudioStream_1",
2740 report->timestamp_us());
Henrik Boström646fda02019-05-22 13:49:422741 expected_audio.media_source_id = "RTCAudioSource_50";
Henrik Boström1ab61882022-06-16 15:07:332742 expected_audio.mid = "AudioMid";
Harald Alvestrand89061872018-01-02 13:08:342743 expected_audio.ssrc = 1;
Harald Alvestrand89061872018-01-02 13:08:342744 expected_audio.media_type = "audio";
Philipp Hancke3bc01662018-08-28 12:55:032745 expected_audio.kind = "audio";
Niels Möllerafb246b2022-04-20 12:26:502746 expected_audio.track_id = IdForType<RTCMediaStreamTrackStats>(report.get());
Steve Anton57858b32018-02-15 23:19:502747 expected_audio.transport_id = "RTCTransport_TransportName_1";
2748 expected_audio.codec_id = "RTCCodec_AudioMid_Outbound_42";
Harald Alvestrand89061872018-01-02 13:08:342749 expected_audio.packets_sent = 2;
Henrik Boströmcf96e0f2019-04-17 11:51:532750 expected_audio.retransmitted_packets_sent = 20;
Harald Alvestrand89061872018-01-02 13:08:342751 expected_audio.bytes_sent = 3;
Niels Möllerac0a4cb2019-10-09 13:01:332752 expected_audio.header_bytes_sent = 4;
Henrik Boströmcf96e0f2019-04-17 11:51:532753 expected_audio.retransmitted_bytes_sent = 30;
Jakob Ivarssone91c9922021-07-06 07:55:432754 expected_audio.nack_count = 31;
Harald Alvestrand89061872018-01-02 13:08:342755
2756 ASSERT_TRUE(report->Get(expected_audio.id()));
2757 EXPECT_EQ(
2758 report->Get(expected_audio.id())->cast_to<RTCOutboundRTPStreamStats>(),
2759 expected_audio);
Harald Alvestrand89061872018-01-02 13:08:342760 EXPECT_TRUE(report->Get(*expected_audio.track_id));
2761 EXPECT_TRUE(report->Get(*expected_audio.transport_id));
2762 EXPECT_TRUE(report->Get(*expected_audio.codec_id));
2763}
2764
Henrik Boström646fda02019-05-22 13:49:422765TEST_F(RTCStatsCollectorTest, RTCAudioSourceStatsCollectedForSenderWithTrack) {
2766 const uint32_t kSsrc = 4;
2767 const int kAttachmentId = 42;
2768
2769 cricket::VoiceMediaInfo voice_media_info;
2770 voice_media_info.senders.push_back(cricket::VoiceSenderInfo());
2771 voice_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
2772 voice_media_info.senders[0].local_stats[0].ssrc = kSsrc;
Henrik Boströmd2c336f2019-07-03 15:11:102773 voice_media_info.senders[0].audio_level = 32767; // [0,32767]
2774 voice_media_info.senders[0].total_input_energy = 2.0;
2775 voice_media_info.senders[0].total_input_duration = 3.0;
Taylor Brandstetter64851c02021-06-24 20:32:502776 voice_media_info.senders[0].apm_statistics.echo_return_loss = 42.0;
2777 voice_media_info.senders[0].apm_statistics.echo_return_loss_enhancement =
2778 52.0;
Tommi19015512022-02-02 10:49:352779 pc_->AddVoiceChannel("AudioMid", "TransportName", voice_media_info);
Henrik Boström646fda02019-05-22 13:49:422780 stats_->SetupLocalTrackAndSender(cricket::MEDIA_TYPE_AUDIO,
2781 "LocalAudioTrackID", kSsrc, false,
2782 kAttachmentId);
2783
2784 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
2785
2786 RTCAudioSourceStats expected_audio("RTCAudioSource_42",
2787 report->timestamp_us());
2788 expected_audio.track_identifier = "LocalAudioTrackID";
2789 expected_audio.kind = "audio";
Henrik Boströmd2c336f2019-07-03 15:11:102790 expected_audio.audio_level = 1.0; // [0,1]
2791 expected_audio.total_audio_energy = 2.0;
2792 expected_audio.total_samples_duration = 3.0;
Taylor Brandstetter64851c02021-06-24 20:32:502793 expected_audio.echo_return_loss = 42.0;
2794 expected_audio.echo_return_loss_enhancement = 52.0;
Henrik Boström646fda02019-05-22 13:49:422795
2796 ASSERT_TRUE(report->Get(expected_audio.id()));
2797 EXPECT_EQ(report->Get(expected_audio.id())->cast_to<RTCAudioSourceStats>(),
2798 expected_audio);
2799}
2800
2801TEST_F(RTCStatsCollectorTest, RTCVideoSourceStatsCollectedForSenderWithTrack) {
2802 const uint32_t kSsrc = 4;
2803 const int kAttachmentId = 42;
2804 const int kVideoSourceWidth = 12;
2805 const int kVideoSourceHeight = 34;
2806
2807 cricket::VideoMediaInfo video_media_info;
Henrik Boströma0ff50c2020-05-05 13:54:462808 video_media_info.aggregated_senders.push_back(cricket::VideoSenderInfo());
Henrik Boström646fda02019-05-22 13:49:422809 video_media_info.senders.push_back(cricket::VideoSenderInfo());
2810 video_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
2811 video_media_info.senders[0].local_stats[0].ssrc = kSsrc;
Byoungchan Leeefe46b62021-11-10 02:23:562812 video_media_info.senders[0].framerate_input = 29.0;
Henrik Boströma0ff50c2020-05-05 13:54:462813 video_media_info.aggregated_senders[0].local_stats.push_back(
2814 cricket::SsrcSenderInfo());
2815 video_media_info.aggregated_senders[0].local_stats[0].ssrc = kSsrc;
Byoungchan Leeefe46b62021-11-10 02:23:562816 video_media_info.aggregated_senders[0].framerate_input = 29.0;
Di Wu668dbf62021-02-27 08:29:152817 video_media_info.aggregated_senders[0].frames = 10001;
Tommi19015512022-02-02 10:49:352818 pc_->AddVideoChannel("VideoMid", "TransportName", video_media_info);
Henrik Boström646fda02019-05-22 13:49:422819
2820 auto video_source = FakeVideoTrackSourceForStats::Create(kVideoSourceWidth,
2821 kVideoSourceHeight);
2822 auto video_track = FakeVideoTrackForStats::Create(
2823 "LocalVideoTrackID", MediaStreamTrackInterface::kLive, video_source);
2824 rtc::scoped_refptr<MockRtpSenderInternal> sender = CreateMockSender(
2825 cricket::MEDIA_TYPE_VIDEO, video_track, kSsrc, kAttachmentId, {});
Tommi6589def2022-02-17 22:36:472826 EXPECT_CALL(*sender, Stop());
2827 EXPECT_CALL(*sender, SetMediaChannel(_));
Henrik Boström646fda02019-05-22 13:49:422828 pc_->AddSender(sender);
2829
2830 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
2831
2832 RTCVideoSourceStats expected_video("RTCVideoSource_42",
2833 report->timestamp_us());
2834 expected_video.track_identifier = "LocalVideoTrackID";
2835 expected_video.kind = "video";
2836 expected_video.width = kVideoSourceWidth;
2837 expected_video.height = kVideoSourceHeight;
Byoungchan Leeefe46b62021-11-10 02:23:562838 expected_video.frames_per_second = 29.0;
Di Wu668dbf62021-02-27 08:29:152839 expected_video.frames = 10001;
Henrik Boström646fda02019-05-22 13:49:422840
2841 ASSERT_TRUE(report->Get(expected_video.id()));
2842 EXPECT_EQ(report->Get(expected_video.id())->cast_to<RTCVideoSourceStats>(),
2843 expected_video);
2844}
2845
2846// This test exercises the current behavior and code path, but the correct
2847// behavior is to report frame rate even if we have no SSRC.
2848// TODO(hbos): When we know the frame rate even if we have no SSRC, update the
2849// expectations of this test.
2850TEST_F(RTCStatsCollectorTest,
2851 RTCVideoSourceStatsMissingFrameRateWhenSenderHasNoSsrc) {
2852 // TODO(https://crbug.com/webrtc/8694): When 0 is no longer a magic value for
2853 // "none", update this test.
2854 const uint32_t kNoSsrc = 0;
2855 const int kAttachmentId = 42;
2856 const int kVideoSourceWidth = 12;
2857 const int kVideoSourceHeight = 34;
2858
2859 cricket::VideoMediaInfo video_media_info;
2860 video_media_info.senders.push_back(cricket::VideoSenderInfo());
2861 video_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
Byoungchan Leeefe46b62021-11-10 02:23:562862 video_media_info.senders[0].framerate_input = 29.0;
Tommi19015512022-02-02 10:49:352863 pc_->AddVideoChannel("VideoMid", "TransportName", video_media_info);
Henrik Boström646fda02019-05-22 13:49:422864
2865 auto video_source = FakeVideoTrackSourceForStats::Create(kVideoSourceWidth,
2866 kVideoSourceHeight);
2867 auto video_track = FakeVideoTrackForStats::Create(
2868 "LocalVideoTrackID", MediaStreamTrackInterface::kLive, video_source);
2869 rtc::scoped_refptr<MockRtpSenderInternal> sender = CreateMockSender(
2870 cricket::MEDIA_TYPE_VIDEO, video_track, kNoSsrc, kAttachmentId, {});
Tommi6589def2022-02-17 22:36:472871 EXPECT_CALL(*sender, Stop());
2872 EXPECT_CALL(*sender, SetMediaChannel(_));
Henrik Boström646fda02019-05-22 13:49:422873 pc_->AddSender(sender);
2874
2875 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
2876 ASSERT_TRUE(report->Get("RTCVideoSource_42"));
2877 auto video_stats =
2878 report->Get("RTCVideoSource_42")->cast_to<RTCVideoSourceStats>();
2879 EXPECT_FALSE(video_stats.frames_per_second.is_defined());
Di Wu668dbf62021-02-27 08:29:152880 EXPECT_FALSE(video_stats.frames.is_defined());
Henrik Boström646fda02019-05-22 13:49:422881}
2882
2883// The track not having a source is not expected to be true in practise, but
2884// this is true in some tests relying on fakes. This test covers that code path.
2885TEST_F(RTCStatsCollectorTest,
2886 RTCVideoSourceStatsMissingResolutionWhenTrackHasNoSource) {
2887 const uint32_t kSsrc = 4;
2888 const int kAttachmentId = 42;
2889
2890 cricket::VideoMediaInfo video_media_info;
2891 video_media_info.senders.push_back(cricket::VideoSenderInfo());
2892 video_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
2893 video_media_info.senders[0].local_stats[0].ssrc = kSsrc;
Byoungchan Leeefe46b62021-11-10 02:23:562894 video_media_info.senders[0].framerate_input = 29.0;
Tommi19015512022-02-02 10:49:352895 pc_->AddVideoChannel("VideoMid", "TransportName", video_media_info);
Henrik Boström646fda02019-05-22 13:49:422896
2897 auto video_track = FakeVideoTrackForStats::Create(
2898 "LocalVideoTrackID", MediaStreamTrackInterface::kLive,
2899 /*source=*/nullptr);
2900 rtc::scoped_refptr<MockRtpSenderInternal> sender = CreateMockSender(
2901 cricket::MEDIA_TYPE_VIDEO, video_track, kSsrc, kAttachmentId, {});
Tommi6589def2022-02-17 22:36:472902 EXPECT_CALL(*sender, Stop());
2903 EXPECT_CALL(*sender, SetMediaChannel(_));
Henrik Boström646fda02019-05-22 13:49:422904 pc_->AddSender(sender);
2905
2906 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
2907 ASSERT_TRUE(report->Get("RTCVideoSource_42"));
2908 auto video_stats =
2909 report->Get("RTCVideoSource_42")->cast_to<RTCVideoSourceStats>();
2910 EXPECT_FALSE(video_stats.width.is_defined());
2911 EXPECT_FALSE(video_stats.height.is_defined());
2912}
2913
2914TEST_F(RTCStatsCollectorTest,
2915 RTCAudioSourceStatsNotCollectedForSenderWithoutTrack) {
2916 const uint32_t kSsrc = 4;
2917 const int kAttachmentId = 42;
2918
2919 cricket::VoiceMediaInfo voice_media_info;
2920 voice_media_info.senders.push_back(cricket::VoiceSenderInfo());
2921 voice_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
2922 voice_media_info.senders[0].local_stats[0].ssrc = kSsrc;
Tommi19015512022-02-02 10:49:352923 pc_->AddVoiceChannel("AudioMid", "TransportName", voice_media_info);
Henrik Boström646fda02019-05-22 13:49:422924 rtc::scoped_refptr<MockRtpSenderInternal> sender = CreateMockSender(
2925 cricket::MEDIA_TYPE_AUDIO, /*track=*/nullptr, kSsrc, kAttachmentId, {});
Tommi6589def2022-02-17 22:36:472926 EXPECT_CALL(*sender, Stop());
2927 EXPECT_CALL(*sender, SetMediaChannel(_));
Henrik Boström646fda02019-05-22 13:49:422928 pc_->AddSender(sender);
2929
2930 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
2931 EXPECT_FALSE(report->Get("RTCAudioSource_42"));
2932}
2933
Henrik Boström883eefc2019-05-27 11:40:252934// Parameterized tests on cricket::MediaType (audio or video).
2935class RTCStatsCollectorTestWithParamKind
2936 : public RTCStatsCollectorTest,
2937 public ::testing::WithParamInterface<cricket::MediaType> {
2938 public:
2939 RTCStatsCollectorTestWithParamKind() : media_type_(GetParam()) {
2940 RTC_DCHECK(media_type_ == cricket::MEDIA_TYPE_AUDIO ||
2941 media_type_ == cricket::MEDIA_TYPE_VIDEO);
2942 }
2943
2944 std::string MediaTypeUpperCase() const {
2945 switch (media_type_) {
2946 case cricket::MEDIA_TYPE_AUDIO:
2947 return "Audio";
2948 case cricket::MEDIA_TYPE_VIDEO:
2949 return "Video";
2950 case cricket::MEDIA_TYPE_DATA:
Philipp Hancke4e8c1152020-10-13 10:43:152951 case cricket::MEDIA_TYPE_UNSUPPORTED:
Artem Titovd3251962021-11-15 15:57:072952 RTC_DCHECK_NOTREACHED();
Henrik Boström883eefc2019-05-27 11:40:252953 return "";
2954 }
2955 }
2956
2957 std::string MediaTypeLowerCase() const {
2958 std::string str = MediaTypeUpperCase();
2959 std::transform(str.begin(), str.end(), str.begin(), ::tolower);
2960 return str;
2961 }
2962
2963 // Adds a sender and channel of the appropriate kind, creating a sender info
Artem Titov880fa812021-07-30 20:30:232964 // with the report block's `source_ssrc` and report block data.
Eldar Relloc07e9042020-07-03 08:08:072965 void AddSenderInfoAndMediaChannel(
2966 std::string transport_name,
2967 const std::vector<ReportBlockData>& report_block_datas,
2968 absl::optional<RtpCodecParameters> codec) {
Henrik Boström883eefc2019-05-27 11:40:252969 switch (media_type_) {
2970 case cricket::MEDIA_TYPE_AUDIO: {
2971 cricket::VoiceMediaInfo voice_media_info;
Eldar Relloc07e9042020-07-03 08:08:072972 for (const auto& report_block_data : report_block_datas) {
2973 cricket::VoiceSenderInfo sender;
2974 sender.local_stats.push_back(cricket::SsrcSenderInfo());
2975 sender.local_stats[0].ssrc =
2976 report_block_data.report_block().source_ssrc;
2977 if (codec.has_value()) {
2978 sender.codec_payload_type = codec->payload_type;
2979 voice_media_info.send_codecs.insert(
2980 std::make_pair(codec->payload_type, *codec));
2981 }
2982 sender.report_block_datas.push_back(report_block_data);
2983 voice_media_info.senders.push_back(sender);
Henrik Boström883eefc2019-05-27 11:40:252984 }
Tommi19015512022-02-02 10:49:352985 pc_->AddVoiceChannel("mid", transport_name, voice_media_info);
Henrik Boström883eefc2019-05-27 11:40:252986 return;
2987 }
2988 case cricket::MEDIA_TYPE_VIDEO: {
2989 cricket::VideoMediaInfo video_media_info;
Eldar Relloc07e9042020-07-03 08:08:072990 for (const auto& report_block_data : report_block_datas) {
2991 cricket::VideoSenderInfo sender;
2992 sender.local_stats.push_back(cricket::SsrcSenderInfo());
2993 sender.local_stats[0].ssrc =
2994 report_block_data.report_block().source_ssrc;
2995 if (codec.has_value()) {
2996 sender.codec_payload_type = codec->payload_type;
2997 video_media_info.send_codecs.insert(
2998 std::make_pair(codec->payload_type, *codec));
2999 }
3000 sender.report_block_datas.push_back(report_block_data);
3001 video_media_info.aggregated_senders.push_back(sender);
3002 video_media_info.senders.push_back(sender);
Henrik Boström883eefc2019-05-27 11:40:253003 }
Tommi19015512022-02-02 10:49:353004 pc_->AddVideoChannel("mid", transport_name, video_media_info);
Henrik Boström883eefc2019-05-27 11:40:253005 return;
3006 }
3007 case cricket::MEDIA_TYPE_DATA:
Philipp Hancke4e8c1152020-10-13 10:43:153008 case cricket::MEDIA_TYPE_UNSUPPORTED:
Artem Titovd3251962021-11-15 15:57:073009 RTC_DCHECK_NOTREACHED();
Henrik Boström883eefc2019-05-27 11:40:253010 }
3011 }
3012
3013 protected:
3014 cricket::MediaType media_type_;
3015};
3016
3017// Verifies RTCRemoteInboundRtpStreamStats members that don't require
3018// RTCCodecStats (codecId, jitter) and without setting up an RTCP transport.
3019TEST_P(RTCStatsCollectorTestWithParamKind,
3020 RTCRemoteInboundRtpStreamStatsCollectedFromReportBlock) {
3021 const int64_t kReportBlockTimestampUtcUs = 123456789;
Di Wu86f04ad2021-03-01 07:36:033022 const uint8_t kFractionLost = 12;
Di Wu88a51b22021-03-01 19:22:063023 const int64_t kRoundTripTimeSample1Ms = 1234;
3024 const double kRoundTripTimeSample1Seconds = 1.234;
3025 const int64_t kRoundTripTimeSample2Ms = 13000;
3026 const double kRoundTripTimeSample2Seconds = 13;
Henrik Boström883eefc2019-05-27 11:40:253027
3028 // The report block's timestamp cannot be from the future, set the fake clock
3029 // to match.
Danil Chapovalov0c626af2020-02-10 10:16:003030 fake_clock_.SetTime(Timestamp::Micros(kReportBlockTimestampUtcUs));
Eldar Relloc07e9042020-07-03 08:08:073031 auto ssrcs = {12, 13};
3032 std::vector<ReportBlockData> report_block_datas;
3033 for (auto ssrc : ssrcs) {
3034 RTCPReportBlock report_block;
3035 // The remote-inbound-rtp SSRC and the outbound-rtp SSRC is the same as the
Artem Titov880fa812021-07-30 20:30:233036 // `source_ssrc`, "SSRC of the RTP packet sender".
Eldar Relloc07e9042020-07-03 08:08:073037 report_block.source_ssrc = ssrc;
3038 report_block.packets_lost = 7;
Di Wu86f04ad2021-03-01 07:36:033039 report_block.fraction_lost = kFractionLost;
Eldar Relloc07e9042020-07-03 08:08:073040 ReportBlockData report_block_data;
3041 report_block_data.SetReportBlock(report_block, kReportBlockTimestampUtcUs);
Di Wu88a51b22021-03-01 19:22:063042 report_block_data.AddRoundTripTimeSample(kRoundTripTimeSample1Ms);
Eldar Relloc07e9042020-07-03 08:08:073043 // Only the last sample should be exposed as the
Artem Titovcfea2182021-08-09 23:22:313044 // `RTCRemoteInboundRtpStreamStats::round_trip_time`.
Di Wu88a51b22021-03-01 19:22:063045 report_block_data.AddRoundTripTimeSample(kRoundTripTimeSample2Ms);
Eldar Relloc07e9042020-07-03 08:08:073046 report_block_datas.push_back(report_block_data);
3047 }
3048 AddSenderInfoAndMediaChannel("TransportName", report_block_datas,
Henrik Boström883eefc2019-05-27 11:40:253049 absl::nullopt);
3050
3051 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
Eldar Relloc07e9042020-07-03 08:08:073052 for (auto ssrc : ssrcs) {
3053 std::string stream_id = "Stream_" + std::to_string(ssrc);
3054 RTCRemoteInboundRtpStreamStats expected_remote_inbound_rtp(
3055 "RTCRemoteInboundRtp" + MediaTypeUpperCase() + stream_id,
3056 kReportBlockTimestampUtcUs);
3057 expected_remote_inbound_rtp.ssrc = ssrc;
Di Wu86f04ad2021-03-01 07:36:033058 expected_remote_inbound_rtp.fraction_lost =
3059 static_cast<double>(kFractionLost) / (1 << 8);
Eldar Relloc07e9042020-07-03 08:08:073060 expected_remote_inbound_rtp.kind = MediaTypeLowerCase();
3061 expected_remote_inbound_rtp.transport_id =
3062 "RTCTransport_TransportName_1"; // 1 for RTP (we have no RTCP
3063 // transport)
3064 expected_remote_inbound_rtp.packets_lost = 7;
3065 expected_remote_inbound_rtp.local_id =
3066 "RTCOutboundRTP" + MediaTypeUpperCase() + stream_id;
Di Wu88a51b22021-03-01 19:22:063067 expected_remote_inbound_rtp.round_trip_time = kRoundTripTimeSample2Seconds;
3068 expected_remote_inbound_rtp.total_round_trip_time =
3069 kRoundTripTimeSample1Seconds + kRoundTripTimeSample2Seconds;
3070 expected_remote_inbound_rtp.round_trip_time_measurements = 2;
Artem Titov880fa812021-07-30 20:30:233071 // This test does not set up RTCCodecStats, so `codec_id` and `jitter` are
Eldar Relloc07e9042020-07-03 08:08:073072 // expected to be missing. These are tested separately.
Henrik Boström883eefc2019-05-27 11:40:253073
Eldar Relloc07e9042020-07-03 08:08:073074 ASSERT_TRUE(report->Get(expected_remote_inbound_rtp.id()));
3075 EXPECT_EQ(report->Get(expected_remote_inbound_rtp.id())
3076 ->cast_to<RTCRemoteInboundRtpStreamStats>(),
3077 expected_remote_inbound_rtp);
3078 EXPECT_TRUE(report->Get(*expected_remote_inbound_rtp.transport_id));
3079 ASSERT_TRUE(report->Get(*expected_remote_inbound_rtp.local_id));
3080 // Lookup works in both directions.
3081 EXPECT_EQ(*report->Get(*expected_remote_inbound_rtp.local_id)
3082 ->cast_to<RTCOutboundRTPStreamStats>()
3083 .remote_id,
3084 expected_remote_inbound_rtp.id());
3085 }
Henrik Boström883eefc2019-05-27 11:40:253086}
3087
3088TEST_P(RTCStatsCollectorTestWithParamKind,
3089 RTCRemoteInboundRtpStreamStatsWithTimestampFromReportBlock) {
3090 const int64_t kReportBlockTimestampUtcUs = 123456789;
Danil Chapovalov0c626af2020-02-10 10:16:003091 fake_clock_.SetTime(Timestamp::Micros(kReportBlockTimestampUtcUs));
Henrik Boström883eefc2019-05-27 11:40:253092
3093 RTCPReportBlock report_block;
Henrik Boström8605fbf2019-06-24 14:44:513094 // The remote-inbound-rtp SSRC and the outbound-rtp SSRC is the same as the
Artem Titov880fa812021-07-30 20:30:233095 // `source_ssrc`, "SSRC of the RTP packet sender".
Henrik Boström883eefc2019-05-27 11:40:253096 report_block.source_ssrc = 12;
3097 ReportBlockData report_block_data;
3098 report_block_data.SetReportBlock(report_block, kReportBlockTimestampUtcUs);
3099
Eldar Relloc07e9042020-07-03 08:08:073100 AddSenderInfoAndMediaChannel("TransportName", {report_block_data},
Henrik Boström883eefc2019-05-27 11:40:253101 absl::nullopt);
3102
3103 // Advance time, it should be OK to have fresher reports than report blocks.
Danil Chapovalov0c626af2020-02-10 10:16:003104 fake_clock_.AdvanceTime(TimeDelta::Micros(1234));
Henrik Boström883eefc2019-05-27 11:40:253105
3106 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
3107
3108 std::string remote_inbound_rtp_id =
Henrik Boström8605fbf2019-06-24 14:44:513109 "RTCRemoteInboundRtp" + MediaTypeUpperCase() + "Stream_12";
Henrik Boström883eefc2019-05-27 11:40:253110 ASSERT_TRUE(report->Get(remote_inbound_rtp_id));
3111 auto& remote_inbound_rtp = report->Get(remote_inbound_rtp_id)
3112 ->cast_to<RTCRemoteInboundRtpStreamStats>();
3113
3114 // Even though the report time is different, the remote-inbound-rtp timestamp
3115 // is of the time that the report block was received.
3116 EXPECT_EQ(kReportBlockTimestampUtcUs + 1234, report->timestamp_us());
3117 EXPECT_EQ(kReportBlockTimestampUtcUs, remote_inbound_rtp.timestamp_us());
3118}
3119
3120TEST_P(RTCStatsCollectorTestWithParamKind,
3121 RTCRemoteInboundRtpStreamStatsWithCodecBasedMembers) {
3122 const int64_t kReportBlockTimestampUtcUs = 123456789;
Danil Chapovalov0c626af2020-02-10 10:16:003123 fake_clock_.SetTime(Timestamp::Micros(kReportBlockTimestampUtcUs));
Henrik Boström883eefc2019-05-27 11:40:253124
3125 RTCPReportBlock report_block;
Henrik Boström8605fbf2019-06-24 14:44:513126 // The remote-inbound-rtp SSRC and the outbound-rtp SSRC is the same as the
Artem Titov880fa812021-07-30 20:30:233127 // `source_ssrc`, "SSRC of the RTP packet sender".
Henrik Boström883eefc2019-05-27 11:40:253128 report_block.source_ssrc = 12;
3129 report_block.jitter = 5000;
3130 ReportBlockData report_block_data;
3131 report_block_data.SetReportBlock(report_block, kReportBlockTimestampUtcUs);
3132
3133 RtpCodecParameters codec;
3134 codec.payload_type = 3;
3135 codec.kind = media_type_;
3136 codec.clock_rate = 1000;
3137
Eldar Relloc07e9042020-07-03 08:08:073138 AddSenderInfoAndMediaChannel("TransportName", {report_block_data}, codec);
Henrik Boström883eefc2019-05-27 11:40:253139
3140 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
3141
3142 std::string remote_inbound_rtp_id =
Henrik Boström8605fbf2019-06-24 14:44:513143 "RTCRemoteInboundRtp" + MediaTypeUpperCase() + "Stream_12";
Henrik Boström883eefc2019-05-27 11:40:253144 ASSERT_TRUE(report->Get(remote_inbound_rtp_id));
3145 auto& remote_inbound_rtp = report->Get(remote_inbound_rtp_id)
3146 ->cast_to<RTCRemoteInboundRtpStreamStats>();
3147
3148 EXPECT_TRUE(remote_inbound_rtp.codec_id.is_defined());
3149 EXPECT_TRUE(report->Get(*remote_inbound_rtp.codec_id));
3150
3151 EXPECT_TRUE(remote_inbound_rtp.jitter.is_defined());
3152 // The jitter (in seconds) is the report block's jitter divided by the codec's
3153 // clock rate.
3154 EXPECT_EQ(5.0, *remote_inbound_rtp.jitter);
3155}
3156
3157TEST_P(RTCStatsCollectorTestWithParamKind,
3158 RTCRemoteInboundRtpStreamStatsWithRtcpTransport) {
3159 const int64_t kReportBlockTimestampUtcUs = 123456789;
Danil Chapovalov0c626af2020-02-10 10:16:003160 fake_clock_.SetTime(Timestamp::Micros(kReportBlockTimestampUtcUs));
Henrik Boström883eefc2019-05-27 11:40:253161
3162 RTCPReportBlock report_block;
Henrik Boström8605fbf2019-06-24 14:44:513163 // The remote-inbound-rtp SSRC and the outbound-rtp SSRC is the same as the
Artem Titov880fa812021-07-30 20:30:233164 // `source_ssrc`, "SSRC of the RTP packet sender".
Henrik Boström883eefc2019-05-27 11:40:253165 report_block.source_ssrc = 12;
3166 ReportBlockData report_block_data;
3167 report_block_data.SetReportBlock(report_block, kReportBlockTimestampUtcUs);
3168
3169 cricket::TransportChannelStats rtp_transport_channel_stats;
3170 rtp_transport_channel_stats.component = cricket::ICE_CANDIDATE_COMPONENT_RTP;
Mirko Bonadei9f6808b2021-05-21 18:46:093171 rtp_transport_channel_stats.dtls_state = DtlsTransportState::kNew;
Henrik Boström883eefc2019-05-27 11:40:253172 cricket::TransportChannelStats rtcp_transport_channel_stats;
3173 rtcp_transport_channel_stats.component =
3174 cricket::ICE_CANDIDATE_COMPONENT_RTCP;
Mirko Bonadei9f6808b2021-05-21 18:46:093175 rtcp_transport_channel_stats.dtls_state = DtlsTransportState::kNew;
Henrik Boström883eefc2019-05-27 11:40:253176 pc_->SetTransportStats("TransportName", {rtp_transport_channel_stats,
3177 rtcp_transport_channel_stats});
Eldar Relloc07e9042020-07-03 08:08:073178 AddSenderInfoAndMediaChannel("TransportName", {report_block_data},
Henrik Boström883eefc2019-05-27 11:40:253179 absl::nullopt);
3180
3181 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
3182
3183 std::string remote_inbound_rtp_id =
Henrik Boström8605fbf2019-06-24 14:44:513184 "RTCRemoteInboundRtp" + MediaTypeUpperCase() + "Stream_12";
Henrik Boström883eefc2019-05-27 11:40:253185 ASSERT_TRUE(report->Get(remote_inbound_rtp_id));
3186 auto& remote_inbound_rtp = report->Get(remote_inbound_rtp_id)
3187 ->cast_to<RTCRemoteInboundRtpStreamStats>();
3188
3189 EXPECT_TRUE(remote_inbound_rtp.transport_id.is_defined());
3190 EXPECT_EQ("RTCTransport_TransportName_2", // 2 for RTCP
3191 *remote_inbound_rtp.transport_id);
3192 EXPECT_TRUE(report->Get(*remote_inbound_rtp.transport_id));
3193}
3194
Mirko Bonadei1b575412019-09-23 06:34:503195INSTANTIATE_TEST_SUITE_P(All,
Henrik Boström883eefc2019-05-27 11:40:253196 RTCStatsCollectorTestWithParamKind,
3197 ::testing::Values(cricket::MEDIA_TYPE_AUDIO, // "/0"
3198 cricket::MEDIA_TYPE_VIDEO)); // "/1"
3199
Alessio Bazzicaf7b1b952021-03-23 16:23:043200// Checks that no remote outbound stats are collected if not available in
3201// `VoiceMediaInfo`.
3202TEST_F(RTCStatsCollectorTest,
3203 RTCRemoteOutboundRtpAudioStreamStatsNotCollected) {
3204 ExampleStatsGraph graph =
3205 SetupExampleStatsVoiceGraph(/*add_remote_outbound_stats=*/false);
3206 EXPECT_FALSE(graph.full_report->Get(graph.remote_outbound_rtp_id));
3207 // Also check that no other remote outbound report is created (in case the
3208 // expected ID is incorrect).
3209 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
3210 ASSERT_NE(report->begin(), report->end())
3211 << "No reports have been generated.";
3212 for (const auto& stats : *report) {
3213 SCOPED_TRACE(stats.id());
3214 EXPECT_NE(stats.type(), RTCRemoteOutboundRtpStreamStats::kType);
3215 }
3216}
3217
3218// Checks that the remote outbound stats are collected when available in
3219// `VoiceMediaInfo`.
3220TEST_F(RTCStatsCollectorTest, RTCRemoteOutboundRtpAudioStreamStatsCollected) {
3221 ExampleStatsGraph graph =
3222 SetupExampleStatsVoiceGraph(/*add_remote_outbound_stats=*/true);
3223 ASSERT_TRUE(graph.full_report->Get(graph.remote_outbound_rtp_id));
3224 const auto& remote_outbound_rtp =
3225 graph.full_report->Get(graph.remote_outbound_rtp_id)
3226 ->cast_to<RTCRemoteOutboundRtpStreamStats>();
3227 EXPECT_EQ(remote_outbound_rtp.timestamp_us(),
3228 kRemoteOutboundStatsTimestampMs * rtc::kNumMicrosecsPerMillisec);
3229 EXPECT_FLOAT_EQ(*remote_outbound_rtp.remote_timestamp,
3230 static_cast<double>(kRemoteOutboundStatsRemoteTimestampMs));
3231 EXPECT_EQ(*remote_outbound_rtp.packets_sent, kRemoteOutboundStatsPacketsSent);
3232 EXPECT_EQ(*remote_outbound_rtp.bytes_sent, kRemoteOutboundStatsBytesSent);
3233 EXPECT_EQ(*remote_outbound_rtp.reports_sent,
3234 kRemoteOutboundStatsReportsCount);
3235}
3236
Henrik Boström646fda02019-05-22 13:49:423237TEST_F(RTCStatsCollectorTest,
3238 RTCVideoSourceStatsNotCollectedForSenderWithoutTrack) {
3239 const uint32_t kSsrc = 4;
3240 const int kAttachmentId = 42;
3241
3242 cricket::VideoMediaInfo video_media_info;
3243 video_media_info.senders.push_back(cricket::VideoSenderInfo());
3244 video_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
3245 video_media_info.senders[0].local_stats[0].ssrc = kSsrc;
Byoungchan Leeefe46b62021-11-10 02:23:563246 video_media_info.senders[0].framerate_input = 29.0;
Tommi19015512022-02-02 10:49:353247 pc_->AddVideoChannel("VideoMid", "TransportName", video_media_info);
Henrik Boström646fda02019-05-22 13:49:423248
3249 rtc::scoped_refptr<MockRtpSenderInternal> sender = CreateMockSender(
3250 cricket::MEDIA_TYPE_VIDEO, /*track=*/nullptr, kSsrc, kAttachmentId, {});
Tommi6589def2022-02-17 22:36:473251 EXPECT_CALL(*sender, Stop());
3252 EXPECT_CALL(*sender, SetMediaChannel(_));
Henrik Boström646fda02019-05-22 13:49:423253 pc_->AddSender(sender);
3254
3255 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
3256 EXPECT_FALSE(report->Get("RTCVideoSource_42"));
3257}
3258
Taylor Brandstetter64851c02021-06-24 20:32:503259// Test collecting echo return loss stats from the audio processor attached to
3260// the track, rather than the voice sender info.
3261TEST_F(RTCStatsCollectorTest, CollectEchoReturnLossFromTrackAudioProcessor) {
3262 rtc::scoped_refptr<MediaStream> local_stream =
3263 MediaStream::Create("LocalStreamId");
3264 pc_->mutable_local_streams()->AddStream(local_stream);
3265
3266 // Local audio track
3267 rtc::scoped_refptr<MediaStreamTrackInterface> local_audio_track =
3268 CreateFakeTrack(cricket::MEDIA_TYPE_AUDIO, "LocalAudioTrackID",
3269 MediaStreamTrackInterface::kEnded,
3270 /*create_fake_audio_processor=*/true);
Harald Alvestrand2f7ad282022-04-21 11:35:433271 local_stream->AddTrack(rtc::scoped_refptr<AudioTrackInterface>(
3272 static_cast<AudioTrackInterface*>(local_audio_track.get())));
Taylor Brandstetter64851c02021-06-24 20:32:503273
3274 cricket::VoiceSenderInfo voice_sender_info_ssrc1;
3275 voice_sender_info_ssrc1.local_stats.push_back(cricket::SsrcSenderInfo());
3276 voice_sender_info_ssrc1.local_stats[0].ssrc = 1;
3277
3278 stats_->CreateMockRtpSendersReceiversAndChannels(
3279 {std::make_pair(local_audio_track.get(), voice_sender_info_ssrc1)}, {},
3280 {}, {}, {local_stream->id()}, {});
3281
3282 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
3283
3284 RTCMediaStreamTrackStats expected_local_audio_track_ssrc1(
Niels Möllerafb246b2022-04-20 12:26:503285 IdForType<RTCMediaStreamTrackStats>(report.get()), report->timestamp_us(),
Taylor Brandstetter64851c02021-06-24 20:32:503286 RTCMediaStreamTrackKind::kAudio);
3287 expected_local_audio_track_ssrc1.track_identifier = local_audio_track->id();
3288 expected_local_audio_track_ssrc1.media_source_id =
3289 "RTCAudioSource_11"; // Attachment ID = SSRC + 10
3290 expected_local_audio_track_ssrc1.remote_source = false;
3291 expected_local_audio_track_ssrc1.ended = true;
3292 expected_local_audio_track_ssrc1.detached = false;
3293 expected_local_audio_track_ssrc1.echo_return_loss = 2.0;
3294 expected_local_audio_track_ssrc1.echo_return_loss_enhancement = 3.0;
3295 ASSERT_TRUE(report->Get(expected_local_audio_track_ssrc1.id()))
3296 << "Did not find " << expected_local_audio_track_ssrc1.id() << " in "
3297 << report->ToJson();
3298 EXPECT_EQ(expected_local_audio_track_ssrc1,
3299 report->Get(expected_local_audio_track_ssrc1.id())
3300 ->cast_to<RTCMediaStreamTrackStats>());
3301
3302 RTCAudioSourceStats expected_audio("RTCAudioSource_11",
3303 report->timestamp_us());
3304 expected_audio.track_identifier = "LocalAudioTrackID";
3305 expected_audio.kind = "audio";
3306 expected_audio.audio_level = 0;
3307 expected_audio.total_audio_energy = 0;
3308 expected_audio.total_samples_duration = 0;
3309 expected_audio.echo_return_loss = 2.0;
3310 expected_audio.echo_return_loss_enhancement = 3.0;
3311
3312 ASSERT_TRUE(report->Get(expected_audio.id()));
3313 EXPECT_EQ(report->Get(expected_audio.id())->cast_to<RTCAudioSourceStats>(),
3314 expected_audio);
3315}
3316
Henrik Boström5b3541f2018-03-19 12:52:563317TEST_F(RTCStatsCollectorTest, GetStatsWithSenderSelector) {
3318 ExampleStatsGraph graph = SetupExampleStatsGraphForSelectorTests();
3319 // Expected stats graph when filtered by sender:
3320 //
Henrik Boström646fda02019-05-22 13:49:423321 // +--- track (sender)
3322 // | ^
3323 // | |
3324 // | +--------- outbound-rtp
3325 // | | | |
3326 // | | v v
3327 // | | codec (send) transport
3328 // v v
3329 // media-source
Henrik Boström5b3541f2018-03-19 12:52:563330 rtc::scoped_refptr<const RTCStatsReport> sender_report =
3331 stats_->GetStatsReportWithSenderSelector(graph.sender);
3332 EXPECT_TRUE(sender_report);
3333 EXPECT_EQ(sender_report->timestamp_us(), graph.full_report->timestamp_us());
Henrik Boström646fda02019-05-22 13:49:423334 EXPECT_EQ(sender_report->size(), 5u);
Henrik Boström5b3541f2018-03-19 12:52:563335 EXPECT_TRUE(sender_report->Get(graph.send_codec_id));
3336 EXPECT_FALSE(sender_report->Get(graph.recv_codec_id));
3337 EXPECT_TRUE(sender_report->Get(graph.outbound_rtp_id));
3338 EXPECT_FALSE(sender_report->Get(graph.inbound_rtp_id));
3339 EXPECT_TRUE(sender_report->Get(graph.transport_id));
3340 EXPECT_TRUE(sender_report->Get(graph.sender_track_id));
3341 EXPECT_FALSE(sender_report->Get(graph.receiver_track_id));
3342 EXPECT_FALSE(sender_report->Get(graph.remote_stream_id));
3343 EXPECT_FALSE(sender_report->Get(graph.peer_connection_id));
Henrik Boström646fda02019-05-22 13:49:423344 EXPECT_TRUE(sender_report->Get(graph.media_source_id));
Henrik Boström5b3541f2018-03-19 12:52:563345}
3346
3347TEST_F(RTCStatsCollectorTest, GetStatsWithReceiverSelector) {
3348 ExampleStatsGraph graph = SetupExampleStatsGraphForSelectorTests();
3349 // Expected stats graph when filtered by receiver:
3350 //
Henrik Boström646fda02019-05-22 13:49:423351 // track (receiver)
3352 // ^
3353 // |
3354 // inbound-rtp ---------------+
3355 // | |
3356 // v v
3357 // transport codec (recv)
Henrik Boström5b3541f2018-03-19 12:52:563358 rtc::scoped_refptr<const RTCStatsReport> receiver_report =
3359 stats_->GetStatsReportWithReceiverSelector(graph.receiver);
3360 EXPECT_TRUE(receiver_report);
3361 EXPECT_EQ(receiver_report->size(), 4u);
3362 EXPECT_EQ(receiver_report->timestamp_us(), graph.full_report->timestamp_us());
3363 EXPECT_FALSE(receiver_report->Get(graph.send_codec_id));
3364 EXPECT_TRUE(receiver_report->Get(graph.recv_codec_id));
3365 EXPECT_FALSE(receiver_report->Get(graph.outbound_rtp_id));
3366 EXPECT_TRUE(receiver_report->Get(graph.inbound_rtp_id));
3367 EXPECT_TRUE(receiver_report->Get(graph.transport_id));
3368 EXPECT_FALSE(receiver_report->Get(graph.sender_track_id));
3369 EXPECT_TRUE(receiver_report->Get(graph.receiver_track_id));
3370 EXPECT_FALSE(receiver_report->Get(graph.remote_stream_id));
3371 EXPECT_FALSE(receiver_report->Get(graph.peer_connection_id));
Henrik Boström646fda02019-05-22 13:49:423372 EXPECT_FALSE(receiver_report->Get(graph.media_source_id));
Henrik Boström5b3541f2018-03-19 12:52:563373}
3374
3375TEST_F(RTCStatsCollectorTest, GetStatsWithNullSenderSelector) {
3376 ExampleStatsGraph graph = SetupExampleStatsGraphForSelectorTests();
3377 rtc::scoped_refptr<const RTCStatsReport> empty_report =
3378 stats_->GetStatsReportWithSenderSelector(nullptr);
3379 EXPECT_TRUE(empty_report);
3380 EXPECT_EQ(empty_report->timestamp_us(), graph.full_report->timestamp_us());
3381 EXPECT_EQ(empty_report->size(), 0u);
3382}
3383
3384TEST_F(RTCStatsCollectorTest, GetStatsWithNullReceiverSelector) {
3385 ExampleStatsGraph graph = SetupExampleStatsGraphForSelectorTests();
3386 rtc::scoped_refptr<const RTCStatsReport> empty_report =
3387 stats_->GetStatsReportWithReceiverSelector(nullptr);
3388 EXPECT_TRUE(empty_report);
3389 EXPECT_EQ(empty_report->timestamp_us(), graph.full_report->timestamp_us());
3390 EXPECT_EQ(empty_report->size(), 0u);
3391}
3392
Harald Alvestrand89061872018-01-02 13:08:343393// When the PC has not had SetLocalDescription done, tracks all have
3394// SSRC 0, meaning "unconnected".
Harald Alvestrandb8e12012018-01-23 14:28:163395// In this state, we report on track stats, but not RTP stats.
3396TEST_F(RTCStatsCollectorTest, StatsReportedOnZeroSsrc) {
Harald Alvestrand89061872018-01-02 13:08:343397 rtc::scoped_refptr<MediaStreamTrackInterface> track =
3398 CreateFakeTrack(cricket::MEDIA_TYPE_AUDIO, "audioTrack",
3399 MediaStreamTrackInterface::kLive);
Steve Anton57858b32018-02-15 23:19:503400 rtc::scoped_refptr<MockRtpSenderInternal> sender =
Henrik Boström646fda02019-05-22 13:49:423401 CreateMockSender(cricket::MEDIA_TYPE_AUDIO, track, 0, 49, {});
Tommi6589def2022-02-17 22:36:473402 EXPECT_CALL(*sender, Stop());
Steve Anton5b387312018-02-03 00:00:203403 pc_->AddSender(sender);
3404
3405 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
3406
Harald Alvestrand89061872018-01-02 13:08:343407 std::vector<const RTCMediaStreamTrackStats*> track_stats =
3408 report->GetStatsOfType<RTCMediaStreamTrackStats>();
Mirko Bonadeie12c1fe2018-07-03 10:53:233409 EXPECT_EQ(1U, track_stats.size());
Steve Anton5b387312018-02-03 00:00:203410
Harald Alvestrandb8e12012018-01-23 14:28:163411 std::vector<const RTCRTPStreamStats*> rtp_stream_stats =
3412 report->GetStatsOfType<RTCRTPStreamStats>();
Mirko Bonadeie12c1fe2018-07-03 10:53:233413 EXPECT_EQ(0U, rtp_stream_stats.size());
Harald Alvestrand89061872018-01-02 13:08:343414}
3415
Harald Alvestrand76d29522018-01-30 13:43:293416TEST_F(RTCStatsCollectorTest, DoNotCrashOnSsrcChange) {
3417 rtc::scoped_refptr<MediaStreamTrackInterface> track =
3418 CreateFakeTrack(cricket::MEDIA_TYPE_AUDIO, "audioTrack",
3419 MediaStreamTrackInterface::kLive);
Steve Anton57858b32018-02-15 23:19:503420 rtc::scoped_refptr<MockRtpSenderInternal> sender =
Henrik Boström646fda02019-05-22 13:49:423421 CreateMockSender(cricket::MEDIA_TYPE_AUDIO, track, 4711, 49, {});
Tommi6589def2022-02-17 22:36:473422 EXPECT_CALL(*sender, Stop());
Steve Anton5b387312018-02-03 00:00:203423 pc_->AddSender(sender);
3424
Harald Alvestrand76d29522018-01-30 13:43:293425 // We do not generate any matching voice_sender_info stats.
Steve Anton5b387312018-02-03 00:00:203426 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
3427
Harald Alvestrand76d29522018-01-30 13:43:293428 std::vector<const RTCMediaStreamTrackStats*> track_stats =
3429 report->GetStatsOfType<RTCMediaStreamTrackStats>();
Mirko Bonadeie12c1fe2018-07-03 10:53:233430 EXPECT_EQ(1U, track_stats.size());
Harald Alvestrand76d29522018-01-30 13:43:293431}
3432
Taylor Brandstetter87d5a742018-03-06 17:42:253433// Used for test below, to test calling GetStatsReport during a callback.
Taylor Brandstetter25e022f2018-03-08 17:53:473434class RecursiveCallback : public RTCStatsCollectorCallback {
Taylor Brandstetter87d5a742018-03-06 17:42:253435 public:
Taylor Brandstetter25e022f2018-03-08 17:53:473436 explicit RecursiveCallback(RTCStatsCollectorWrapper* stats) : stats_(stats) {}
Taylor Brandstetter87d5a742018-03-06 17:42:253437
3438 void OnStatsDelivered(
3439 const rtc::scoped_refptr<const RTCStatsReport>& report) override {
3440 stats_->GetStatsReport();
3441 called_ = true;
3442 }
3443
3444 bool called() const { return called_; }
3445
3446 private:
3447 RTCStatsCollectorWrapper* stats_;
3448 bool called_ = false;
3449};
3450
3451// Test that nothing bad happens if a callback causes GetStatsReport to be
3452// called again recursively. Regression test for crbug.com/webrtc/8973.
Taylor Brandstetter25e022f2018-03-08 17:53:473453TEST_F(RTCStatsCollectorTest, DoNotCrashWhenGetStatsCalledDuringCallback) {
Niels Möller027c7932022-01-25 12:56:073454 auto callback1 = rtc::make_ref_counted<RecursiveCallback>(stats_.get());
3455 auto callback2 = rtc::make_ref_counted<RecursiveCallback>(stats_.get());
Taylor Brandstetter87d5a742018-03-06 17:42:253456 stats_->stats_collector()->GetStatsReport(callback1);
3457 stats_->stats_collector()->GetStatsReport(callback2);
3458 EXPECT_TRUE_WAIT(callback1->called(), kGetStatsReportTimeoutMs);
3459 EXPECT_TRUE_WAIT(callback2->called(), kGetStatsReportTimeoutMs);
3460}
3461
Steve Anton5b387312018-02-03 00:00:203462class RTCTestStats : public RTCStats {
hbosc82f2e12016-09-05 08:36:503463 public:
Steve Anton5b387312018-02-03 00:00:203464 WEBRTC_RTCSTATS_DECL();
3465
3466 RTCTestStats(const std::string& id, int64_t timestamp_us)
3467 : RTCStats(id, timestamp_us), dummy_stat("dummyStat") {}
3468
3469 RTCStatsMember<int32_t> dummy_stat;
3470};
3471
Mirko Bonadeic4dd7302019-02-25 08:12:023472WEBRTC_RTCSTATS_IMPL(RTCTestStats, RTCStats, "test-stats", &dummy_stat)
Steve Anton5b387312018-02-03 00:00:203473
3474// Overrides the stats collection to verify thread usage and that the resulting
3475// partial reports are merged.
3476class FakeRTCStatsCollector : public RTCStatsCollector,
3477 public RTCStatsCollectorCallback {
3478 public:
3479 static rtc::scoped_refptr<FakeRTCStatsCollector> Create(
3480 PeerConnectionInternal* pc,
3481 int64_t cache_lifetime_us) {
Niels Möllere7cc8832022-01-04 14:20:033482 return rtc::scoped_refptr<FakeRTCStatsCollector>(
3483 new rtc::RefCountedObject<FakeRTCStatsCollector>(pc,
3484 cache_lifetime_us));
Steve Anton5b387312018-02-03 00:00:203485 }
3486
Tomas Gunnarssone6de5ae2021-04-22 16:16:353487 // Since FakeRTCStatsCollector inherits twice from RefCountInterface, once via
3488 // RTCStatsCollector and once via RTCStatsCollectorCallback, scoped_refptr
3489 // will get confused about which AddRef()/Release() methods to call.
3490 // So to remove all doubt, we declare them here again in the class that we
3491 // give to scoped_refptr.
3492 // Satisfying the implementation of these methods and associating them with a
3493 // reference counter, will be done by RefCountedObject.
3494 virtual void AddRef() const = 0;
3495 virtual rtc::RefCountReleaseStatus Release() const = 0;
3496
Steve Anton5b387312018-02-03 00:00:203497 // RTCStatsCollectorCallback implementation.
3498 void OnStatsDelivered(
3499 const rtc::scoped_refptr<const RTCStatsReport>& report) override {
3500 EXPECT_TRUE(signaling_thread_->IsCurrent());
Markus Handell6fcd0f82020-07-07 17:08:533501 MutexLock lock(&lock_);
Steve Anton5b387312018-02-03 00:00:203502 delivered_report_ = report;
3503 }
3504
3505 void VerifyThreadUsageAndResultsMerging() {
3506 GetStatsReport(rtc::scoped_refptr<RTCStatsCollectorCallback>(this));
3507 EXPECT_TRUE_WAIT(HasVerifiedResults(), kGetStatsReportTimeoutMs);
3508 }
3509
3510 bool HasVerifiedResults() {
3511 EXPECT_TRUE(signaling_thread_->IsCurrent());
Markus Handell6fcd0f82020-07-07 17:08:533512 MutexLock lock(&lock_);
Steve Anton5b387312018-02-03 00:00:203513 if (!delivered_report_)
3514 return false;
3515 EXPECT_EQ(produced_on_signaling_thread_, 1);
3516 EXPECT_EQ(produced_on_network_thread_, 1);
3517
3518 EXPECT_TRUE(delivered_report_->Get("SignalingThreadStats"));
3519 EXPECT_TRUE(delivered_report_->Get("NetworkThreadStats"));
3520
3521 produced_on_signaling_thread_ = 0;
3522 produced_on_network_thread_ = 0;
3523 delivered_report_ = nullptr;
3524 return true;
hbosc82f2e12016-09-05 08:36:503525 }
3526
3527 protected:
Steve Anton5b387312018-02-03 00:00:203528 FakeRTCStatsCollector(PeerConnectionInternal* pc, int64_t cache_lifetime)
3529 : RTCStatsCollector(pc, cache_lifetime),
3530 signaling_thread_(pc->signaling_thread()),
3531 worker_thread_(pc->worker_thread()),
3532 network_thread_(pc->network_thread()) {}
3533
Henrik Boström40b030e2019-02-28 08:49:313534 void ProducePartialResultsOnSignalingThreadImpl(
3535 int64_t timestamp_us,
3536 RTCStatsReport* partial_report) override {
Steve Anton5b387312018-02-03 00:00:203537 EXPECT_TRUE(signaling_thread_->IsCurrent());
3538 {
Markus Handell6fcd0f82020-07-07 17:08:533539 MutexLock lock(&lock_);
Steve Anton5b387312018-02-03 00:00:203540 EXPECT_FALSE(delivered_report_);
3541 ++produced_on_signaling_thread_;
3542 }
3543
Henrik Boström40b030e2019-02-28 08:49:313544 partial_report->AddStats(std::unique_ptr<const RTCStats>(
Steve Anton5b387312018-02-03 00:00:203545 new RTCTestStats("SignalingThreadStats", timestamp_us)));
Steve Anton5b387312018-02-03 00:00:203546 }
Henrik Boström40b030e2019-02-28 08:49:313547 void ProducePartialResultsOnNetworkThreadImpl(
3548 int64_t timestamp_us,
3549 const std::map<std::string, cricket::TransportStats>&
3550 transport_stats_by_name,
3551 const std::map<std::string, CertificateStatsPair>& transport_cert_stats,
3552 RTCStatsReport* partial_report) override {
Steve Anton5b387312018-02-03 00:00:203553 EXPECT_TRUE(network_thread_->IsCurrent());
3554 {
Markus Handell6fcd0f82020-07-07 17:08:533555 MutexLock lock(&lock_);
Steve Anton5b387312018-02-03 00:00:203556 EXPECT_FALSE(delivered_report_);
3557 ++produced_on_network_thread_;
3558 }
3559
Henrik Boström40b030e2019-02-28 08:49:313560 partial_report->AddStats(std::unique_ptr<const RTCStats>(
Steve Anton5b387312018-02-03 00:00:203561 new RTCTestStats("NetworkThreadStats", timestamp_us)));
Steve Anton5b387312018-02-03 00:00:203562 }
3563
3564 private:
3565 rtc::Thread* const signaling_thread_;
3566 rtc::Thread* const worker_thread_;
3567 rtc::Thread* const network_thread_;
3568
Markus Handell6fcd0f82020-07-07 17:08:533569 Mutex lock_;
Steve Anton5b387312018-02-03 00:00:203570 rtc::scoped_refptr<const RTCStatsReport> delivered_report_;
3571 int produced_on_signaling_thread_ = 0;
3572 int produced_on_network_thread_ = 0;
hbosc82f2e12016-09-05 08:36:503573};
3574
Steve Anton5b387312018-02-03 00:00:203575TEST(RTCStatsCollectorTestWithFakeCollector, ThreadUsageAndResultsMerging) {
Niels Möller83830f32022-05-20 07:12:573576 rtc::AutoThread main_thread_;
Niels Möller027c7932022-01-25 12:56:073577 auto pc = rtc::make_ref_counted<FakePeerConnectionForStats>();
Steve Anton5b387312018-02-03 00:00:203578 rtc::scoped_refptr<FakeRTCStatsCollector> stats_collector(
Niels Möllerafb246b2022-04-20 12:26:503579 FakeRTCStatsCollector::Create(pc.get(),
3580 50 * rtc::kNumMicrosecsPerMillisec));
Steve Anton5b387312018-02-03 00:00:203581 stats_collector->VerifyThreadUsageAndResultsMerging();
hbosc82f2e12016-09-05 08:36:503582}
3583
3584} // namespace
3585
hbosd565b732016-08-30 21:04:353586} // namespace webrtc