blob: 3099d1188a73616a06a9824225c84768349d4f28 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:361/*
kjellanderb24317b2016-02-10 15:54:432 * Copyright 2014 The WebRTC project authors. All Rights Reserved.
henrike@webrtc.org28e20752013-07-10 00:45:363 *
kjellanderb24317b2016-02-10 15:54:434 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
henrike@webrtc.org28e20752013-07-10 00:45:369 */
10
Henrik Boströmf7859892022-07-04 12:36:3711#include "pc/legacy_stats_collector.h"
Jonas Olssona4d87372019-07-05 17:08:3312
henrike@webrtc.org28e20752013-07-10 00:45:3613#include <stdio.h>
Jonas Olssona4d87372019-07-05 17:08:3314
Harald Alvestrandc24a2182022-02-23 13:44:5915#include <cstdint>
deadbeefcbecd352015-09-23 18:50:2716
Steve Anton64b626b2019-01-29 01:25:2617#include "absl/algorithm/container.h"
Yves Gerey3e707812018-11-28 15:47:4918#include "absl/types/optional.h"
19#include "api/audio_codecs/audio_encoder.h"
20#include "api/candidate.h"
Steve Anton10542f22019-01-11 17:11:0021#include "api/data_channel_interface.h"
Harald Alvestrand9cb42c82020-10-11 13:03:4722#include "api/media_stream_track.h"
Harald Alvestrandc24a2182022-02-23 13:44:5923#include "api/media_types.h"
24#include "api/rtp_sender_interface.h"
Mirko Bonadeid9708072019-01-25 19:26:4825#include "api/scoped_refptr.h"
Yves Gerey3e707812018-11-28 15:47:4926#include "call/call.h"
Steve Anton10542f22019-01-11 17:11:0027#include "media/base/media_channel.h"
Yves Gerey3e707812018-11-28 15:47:4928#include "modules/audio_processing/include/audio_processing_statistics.h"
Harald Alvestrandc24a2182022-02-23 13:44:5929#include "p2p/base/ice_transport_internal.h"
Steve Anton10542f22019-01-11 17:11:0030#include "pc/media_stream.h"
Harald Alvestrandc24a2182022-02-23 13:44:5931#include "pc/rtp_receiver.h"
32#include "pc/rtp_sender.h"
Taylor Brandstetter3a034e12020-07-09 22:32:3433#include "pc/sctp_data_channel.h"
Steve Anton10542f22019-01-11 17:11:0034#include "pc/test/fake_peer_connection_for_stats.h"
35#include "pc/test/fake_video_track_source.h"
Steve Antonefe4c922019-03-27 17:26:0636#include "pc/test/mock_rtp_receiver_internal.h"
37#include "pc/test/mock_rtp_sender_internal.h"
Steve Anton10542f22019-01-11 17:11:0038#include "pc/transport_stats.h"
39#include "pc/video_track.h"
40#include "rtc_base/fake_ssl_identity.h"
41#include "rtc_base/message_digest.h"
42#include "rtc_base/net_helper.h"
Tommi0fe65102023-03-31 10:09:3043#include "rtc_base/null_socket_server.h"
Steve Anton10542f22019-01-11 17:11:0044#include "rtc_base/rtc_certificate.h"
Steve Anton10542f22019-01-11 17:11:0045#include "rtc_base/socket_address.h"
46#include "rtc_base/ssl_identity.h"
47#include "rtc_base/ssl_stream_adapter.h"
48#include "rtc_base/string_encode.h"
Artem Titova76af0c2018-07-23 15:38:1249#include "rtc_base/third_party/base64/base64.h"
Yves Gerey3e707812018-11-28 15:47:4950#include "rtc_base/thread.h"
Harald Alvestrandc24a2182022-02-23 13:44:5951#include "test/gmock.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3152#include "test/gtest.h"
henrike@webrtc.org28e20752013-07-10 00:45:3653
Steve Anton3871f6f2018-01-26 18:25:5354using cricket::ConnectionInfo;
55using cricket::SsrcReceiverInfo;
56using cricket::TransportChannelStats;
57using cricket::VideoMediaInfo;
58using cricket::VideoReceiverInfo;
59using cricket::VideoSenderInfo;
60using cricket::VoiceMediaInfo;
61using cricket::VoiceReceiverInfo;
62using cricket::VoiceSenderInfo;
Tomas Gunnarsson16de2162022-01-26 09:21:5763using ::testing::_;
64using ::testing::AtMost;
Steve Antonefe4c922019-03-27 17:26:0665using ::testing::Return;
66using ::testing::UnorderedElementsAre;
henrike@webrtc.org28e20752013-07-10 00:45:3667
guoweis@webrtc.org950c5182014-12-16 23:01:3168namespace webrtc {
henrike@webrtc.org28e20752013-07-10 00:45:3669
tkchin7d06a8c2016-04-04 21:10:4370namespace internal {
71// This value comes from openssl/tls1.h
72static const int TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xC014;
73} // namespace internal
74
henrike@webrtc.org28e20752013-07-10 00:45:3675// Error return values
76const char kNotFound[] = "NOT FOUND";
henrike@webrtc.org28e20752013-07-10 00:45:3677
wu@webrtc.org97077a32013-10-25 21:18:3378// Constant names for track identification.
xians@webrtc.org4cb01282014-06-12 14:57:0579const char kLocalTrackId[] = "local_track_id";
80const char kRemoteTrackId[] = "remote_track_id";
Peter Boström0c4e06b2015-10-07 10:23:2181const uint32_t kSsrcOfTrack = 1234;
wu@webrtc.org97077a32013-10-25 21:18:3382
Steve Anton3871f6f2018-01-26 18:25:5383class FakeAudioProcessor : public AudioProcessorInterface {
henrike@webrtc.org40b3b682014-03-03 18:30:1184 public:
85 FakeAudioProcessor() {}
86 ~FakeAudioProcessor() {}
87
88 private:
Ivo Creusenae0260962017-11-20 12:07:1689 AudioProcessorInterface::AudioProcessorStatistics GetStats(
Ivo Creusen56d460902017-11-24 16:29:5990 bool has_recv_streams) override {
Ivo Creusenae0260962017-11-20 12:07:1691 AudioProcessorStatistics stats;
Ivo Creusen56d460902017-11-24 16:29:5992 if (has_recv_streams) {
93 stats.apm_statistics.echo_return_loss = 2.0;
94 stats.apm_statistics.echo_return_loss_enhancement = 3.0;
95 stats.apm_statistics.delay_median_ms = 4;
96 stats.apm_statistics.delay_standard_deviation_ms = 5;
97 }
Ivo Creusenae0260962017-11-20 12:07:1698 return stats;
99 }
henrike@webrtc.org40b3b682014-03-03 18:30:11100};
101
Steve Anton3871f6f2018-01-26 18:25:53102class FakeAudioTrack : public MediaStreamTrack<AudioTrackInterface> {
henrike@webrtc.org40b3b682014-03-03 18:30:11103 public:
xians@webrtc.org4cb01282014-06-12 14:57:05104 explicit FakeAudioTrack(const std::string& id)
Steve Anton3871f6f2018-01-26 18:25:53105 : MediaStreamTrack<AudioTrackInterface>(id),
Tommi87f70902021-04-27 12:43:08106 processor_(rtc::make_ref_counted<FakeAudioProcessor>()) {}
kjellander@webrtc.org14665ff2015-03-04 12:58:35107 std::string kind() const override { return "audio"; }
Steve Anton3871f6f2018-01-26 18:25:53108 AudioSourceInterface* GetSource() const override { return NULL; }
109 void AddSink(AudioTrackSinkInterface* sink) override {}
110 void RemoveSink(AudioTrackSinkInterface* sink) override {}
kjellander@webrtc.org14665ff2015-03-04 12:58:35111 bool GetSignalLevel(int* level) override {
henrike@webrtc.org40b3b682014-03-03 18:30:11112 *level = 1;
113 return true;
114 }
Steve Anton3871f6f2018-01-26 18:25:53115 rtc::scoped_refptr<AudioProcessorInterface> GetAudioProcessor() override {
henrike@webrtc.orgb90991d2014-03-04 19:54:57116 return processor_;
henrike@webrtc.org40b3b682014-03-03 18:30:11117 }
118
119 private:
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52120 rtc::scoped_refptr<FakeAudioProcessor> processor_;
henrike@webrtc.org40b3b682014-03-03 18:30:11121};
122
zhihuang6ba3b192016-05-13 18:46:35123// This fake audio processor is used to verify that the undesired initial values
124// (-1) will be filtered out.
Steve Anton3871f6f2018-01-26 18:25:53125class FakeAudioProcessorWithInitValue : public AudioProcessorInterface {
zhihuang6ba3b192016-05-13 18:46:35126 public:
127 FakeAudioProcessorWithInitValue() {}
128 ~FakeAudioProcessorWithInitValue() {}
129
130 private:
Ivo Creusenae0260962017-11-20 12:07:16131 AudioProcessorInterface::AudioProcessorStatistics GetStats(
132 bool /*has_recv_streams*/) override {
133 AudioProcessorStatistics stats;
Ivo Creusenae0260962017-11-20 12:07:16134 return stats;
135 }
zhihuang6ba3b192016-05-13 18:46:35136};
137
138class FakeAudioTrackWithInitValue
Steve Anton3871f6f2018-01-26 18:25:53139 : public MediaStreamTrack<AudioTrackInterface> {
zhihuang6ba3b192016-05-13 18:46:35140 public:
141 explicit FakeAudioTrackWithInitValue(const std::string& id)
Steve Anton3871f6f2018-01-26 18:25:53142 : MediaStreamTrack<AudioTrackInterface>(id),
Tommi87f70902021-04-27 12:43:08143 processor_(rtc::make_ref_counted<FakeAudioProcessorWithInitValue>()) {}
zhihuang6ba3b192016-05-13 18:46:35144 std::string kind() const override { return "audio"; }
Steve Anton3871f6f2018-01-26 18:25:53145 AudioSourceInterface* GetSource() const override { return NULL; }
146 void AddSink(AudioTrackSinkInterface* sink) override {}
147 void RemoveSink(AudioTrackSinkInterface* sink) override {}
zhihuang6ba3b192016-05-13 18:46:35148 bool GetSignalLevel(int* level) override {
149 *level = 1;
150 return true;
151 }
Steve Anton3871f6f2018-01-26 18:25:53152 rtc::scoped_refptr<AudioProcessorInterface> GetAudioProcessor() override {
zhihuang6ba3b192016-05-13 18:46:35153 return processor_;
154 }
155
156 private:
157 rtc::scoped_refptr<FakeAudioProcessorWithInitValue> processor_;
158};
159
henrike@webrtc.org40b3b682014-03-03 18:30:11160bool GetValue(const StatsReport* report,
tommi@webrtc.org242068d2014-07-14 20:19:56161 StatsReport::StatsValueName name,
wu@webrtc.org4551b792013-10-09 15:37:36162 std::string* value) {
tommi@webrtc.org92f40182015-03-04 15:25:19163 const StatsReport::Value* v = report->FindValue(name);
164 if (!v)
165 return false;
166 *value = v->ToString();
167 return true;
wu@webrtc.org4551b792013-10-09 15:37:36168}
169
tommi@webrtc.org4fb7e252015-01-21 11:36:18170std::string ExtractStatsValue(const StatsReport::StatsType& type,
henrike@webrtc.org40b3b682014-03-03 18:30:11171 const StatsReports& reports,
tommi@webrtc.org242068d2014-07-14 20:19:56172 StatsReport::StatsValueName name) {
tommi@webrtc.org4fb7e252015-01-21 11:36:18173 for (const auto* r : reports) {
wu@webrtc.org4551b792013-10-09 15:37:36174 std::string ret;
tommi@webrtc.org4fb7e252015-01-21 11:36:18175 if (r->type() == type && GetValue(r, name, &ret))
wu@webrtc.org4551b792013-10-09 15:37:36176 return ret;
henrike@webrtc.org28e20752013-07-10 00:45:36177 }
178
179 return kNotFound;
180}
181
tommi@webrtc.orgd3900292015-03-12 16:35:55182StatsReport::Id TypedIdFromIdString(StatsReport::StatsType type,
183 const std::string& value) {
tommi@webrtc.org4fb7e252015-01-21 11:36:18184 EXPECT_FALSE(value.empty());
tommi@webrtc.orgd3900292015-03-12 16:35:55185 StatsReport::Id id;
tommi@webrtc.org4fb7e252015-01-21 11:36:18186 if (value.empty())
tommi@webrtc.orgd3900292015-03-12 16:35:55187 return id;
tommi@webrtc.org4fb7e252015-01-21 11:36:18188
189 // This has assumptions about how the ID is constructed. As is, this is
190 // OK since this is for testing purposes only, but if we ever need this
191 // in production, we should add a generic method that does this.
192 size_t index = value.find('_');
193 EXPECT_NE(index, std::string::npos);
194 if (index == std::string::npos || index == (value.length() - 1))
tommi@webrtc.orgd3900292015-03-12 16:35:55195 return id;
tommi@webrtc.org4fb7e252015-01-21 11:36:18196
197 id = StatsReport::NewTypedId(type, value.substr(index + 1));
198 EXPECT_EQ(id->ToString(), value);
tommi@webrtc.orgd3900292015-03-12 16:35:55199 return id;
tommi@webrtc.org4fb7e252015-01-21 11:36:18200}
201
tommi@webrtc.orgd3900292015-03-12 16:35:55202StatsReport::Id IdFromCertIdString(const std::string& cert_id) {
203 return TypedIdFromIdString(StatsReport::kStatsReportTypeCertificate, cert_id);
tommi@webrtc.org4fb7e252015-01-21 11:36:18204}
205
Artem Titov880fa812021-07-30 20:30:23206// Finds the `n`-th report of type `type` in `reports`.
207// `n` starts from 1 for finding the first report.
Yves Gerey665174f2018-06-19 13:03:05208const StatsReport* FindNthReportByType(const StatsReports& reports,
209 const StatsReport::StatsType& type,
210 int n) {
henrike@webrtc.org28e20752013-07-10 00:45:36211 for (size_t i = 0; i < reports.size(); ++i) {
tommi@webrtc.org4fb7e252015-01-21 11:36:18212 if (reports[i]->type() == type) {
henrike@webrtc.org28e20752013-07-10 00:45:36213 n--;
214 if (n == 0)
tommi@webrtc.org5b06b062014-08-15 08:38:30215 return reports[i];
henrike@webrtc.org28e20752013-07-10 00:45:36216 }
217 }
tommi@webrtc.org4fb7e252015-01-21 11:36:18218 return nullptr;
henrike@webrtc.org28e20752013-07-10 00:45:36219}
220
Artem Titov880fa812021-07-30 20:30:23221// Returns the value of the stat identified by `name` in the `n`-th report of
222// type `type` in `reports`.
223// `n` starts from 1 for finding the first report.
224// If either the `n`-th report is not found, or the stat is not present in that
Steve Antonefe4c922019-03-27 17:26:06225// report, then nullopt is returned.
226absl::optional<std::string> GetValueInNthReportByType(
227 const StatsReports& reports,
228 StatsReport::StatsType type,
229 StatsReport::StatsValueName name,
230 int n) {
231 const StatsReport* report = FindNthReportByType(reports, type, n);
232 if (!report) {
233 return absl::nullopt;
234 }
235 std::string value;
236 if (!GetValue(report, name, &value)) {
237 return absl::nullopt;
238 }
239 return value;
240}
241
242std::vector<const StatsReport*> GetReportsByType(const StatsReports& reports,
243 StatsReport::StatsType type) {
244 std::vector<const StatsReport*> filtered_reports;
245 for (const StatsReport* report : reports) {
246 if (report->type() == type) {
247 filtered_reports.push_back(report);
248 }
249 }
250 return filtered_reports;
251}
252
henrike@webrtc.org40b3b682014-03-03 18:30:11253const StatsReport* FindReportById(const StatsReports& reports,
tommi@webrtc.org4fb7e252015-01-21 11:36:18254 const StatsReport::Id& id) {
tommi@webrtc.org8e327c42015-01-19 20:41:26255 for (const auto* r : reports) {
tommi@webrtc.orgd3900292015-03-12 16:35:55256 if (r->id()->Equals(id))
tommi@webrtc.org8e327c42015-01-19 20:41:26257 return r;
henrike@webrtc.org28e20752013-07-10 00:45:36258 }
tommi@webrtc.org8e327c42015-01-19 20:41:26259 return nullptr;
henrike@webrtc.org28e20752013-07-10 00:45:36260}
261
Mirko Bonadeic61ce0d2017-11-21 16:04:20262std::string ExtractSsrcStatsValue(const StatsReports& reports,
tommi@webrtc.org242068d2014-07-14 20:19:56263 StatsReport::StatsValueName name) {
tommi@webrtc.org4fb7e252015-01-21 11:36:18264 return ExtractStatsValue(StatsReport::kStatsReportTypeSsrc, reports, name);
henrike@webrtc.org28e20752013-07-10 00:45:36265}
266
Mirko Bonadeic61ce0d2017-11-21 16:04:20267std::string ExtractBweStatsValue(const StatsReports& reports,
tommi@webrtc.org242068d2014-07-14 20:19:56268 StatsReport::StatsValueName name) {
Yves Gerey665174f2018-06-19 13:03:05269 return ExtractStatsValue(StatsReport::kStatsReportTypeBwe, reports, name);
henrike@webrtc.org28e20752013-07-10 00:45:36270}
271
wu@webrtc.org4551b792013-10-09 15:37:36272std::string DerToPem(const std::string& der) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52273 return rtc::SSLIdentity::DerToPem(
Yves Gerey665174f2018-06-19 13:03:05274 rtc::kPemTypeCertificate,
275 reinterpret_cast<const unsigned char*>(der.c_str()), der.length());
wu@webrtc.org4551b792013-10-09 15:37:36276}
277
Yves Gerey665174f2018-06-19 13:03:05278std::vector<std::string> DersToPems(const std::vector<std::string>& ders) {
wu@webrtc.org4551b792013-10-09 15:37:36279 std::vector<std::string> pems(ders.size());
Steve Anton64b626b2019-01-29 01:25:26280 absl::c_transform(ders, pems.begin(), DerToPem);
wu@webrtc.org4551b792013-10-09 15:37:36281 return pems;
282}
283
henrike@webrtc.org40b3b682014-03-03 18:30:11284void CheckCertChainReports(const StatsReports& reports,
wu@webrtc.org4551b792013-10-09 15:37:36285 const std::vector<std::string>& ders,
tommi@webrtc.org4fb7e252015-01-21 11:36:18286 const StatsReport::Id& start_id) {
tommi@webrtc.orgd3900292015-03-12 16:35:55287 StatsReport::Id cert_id;
tommi@webrtc.org4fb7e252015-01-21 11:36:18288 const StatsReport::Id* certificate_id = &start_id;
wu@webrtc.org4551b792013-10-09 15:37:36289 size_t i = 0;
290 while (true) {
tommi@webrtc.org4fb7e252015-01-21 11:36:18291 const StatsReport* report = FindReportById(reports, *certificate_id);
wu@webrtc.org4551b792013-10-09 15:37:36292 ASSERT_TRUE(report != NULL);
mallinath@webrtc.org19f27e62013-10-13 17:18:27293
wu@webrtc.org4551b792013-10-09 15:37:36294 std::string der_base64;
Yves Gerey665174f2018-06-19 13:03:05295 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameDer, &der_base64));
tommi@webrtc.org4fb7e252015-01-21 11:36:18296 std::string der = rtc::Base64::Decode(der_base64, rtc::Base64::DO_STRICT);
wu@webrtc.org4551b792013-10-09 15:37:36297 EXPECT_EQ(ders[i], der);
mallinath@webrtc.org19f27e62013-10-13 17:18:27298
299 std::string fingerprint_algorithm;
Yves Gerey665174f2018-06-19 13:03:05300 EXPECT_TRUE(GetValue(report,
301 StatsReport::kStatsValueNameFingerprintAlgorithm,
302 &fingerprint_algorithm));
mallinath@webrtc.org19f27e62013-10-13 17:18:27303 // The digest algorithm for a FakeSSLCertificate is always SHA-1.
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52304 std::string sha_1_str = rtc::DIGEST_SHA_1;
mallinath@webrtc.org19f27e62013-10-13 17:18:27305 EXPECT_EQ(sha_1_str, fingerprint_algorithm);
306
tommi@webrtc.org4fb7e252015-01-21 11:36:18307 std::string fingerprint;
308 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameFingerprint,
309 &fingerprint));
310 EXPECT_FALSE(fingerprint.empty());
mallinath@webrtc.org19f27e62013-10-13 17:18:27311
wu@webrtc.org4551b792013-10-09 15:37:36312 ++i;
tommi@webrtc.org4fb7e252015-01-21 11:36:18313 std::string issuer_id;
Yves Gerey665174f2018-06-19 13:03:05314 if (!GetValue(report, StatsReport::kStatsValueNameIssuerId, &issuer_id)) {
wu@webrtc.org4551b792013-10-09 15:37:36315 break;
tommi@webrtc.org4fb7e252015-01-21 11:36:18316 }
317
tommi@webrtc.orgd3900292015-03-12 16:35:55318 cert_id = IdFromCertIdString(issuer_id);
319 certificate_id = &cert_id;
wu@webrtc.org4551b792013-10-09 15:37:36320 }
321 EXPECT_EQ(ders.size(), i);
322}
323
Yves Gerey665174f2018-06-19 13:03:05324void VerifyVoiceReceiverInfoReport(const StatsReport* report,
325 const cricket::VoiceReceiverInfo& info) {
buildbot@webrtc.org3e01e0b2014-05-13 17:54:10326 std::string value_in_report;
Yves Gerey665174f2018-06-19 13:03:05327 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameAudioOutputLevel,
328 &value_in_report));
Jonas Olsson6b1985d2018-07-05 09:59:48329 EXPECT_EQ(rtc::ToString(info.audio_level), value_in_report);
Yves Gerey665174f2018-06-19 13:03:05330 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameBytesReceived,
331 &value_in_report));
Philipp Hancke6a7bf102023-04-21 17:32:42332 EXPECT_EQ(rtc::ToString(info.payload_bytes_received +
333 info.header_and_padding_bytes_received),
Niels Möllerac0a4cb2019-10-09 13:01:33334 value_in_report);
Yves Gerey665174f2018-06-19 13:03:05335 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameJitterReceived,
336 &value_in_report));
Jonas Olsson6b1985d2018-07-05 09:59:48337 EXPECT_EQ(rtc::ToString(info.jitter_ms), value_in_report);
Yves Gerey665174f2018-06-19 13:03:05338 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameJitterBufferMs,
339 &value_in_report));
Jonas Olsson6b1985d2018-07-05 09:59:48340 EXPECT_EQ(rtc::ToString(info.jitter_buffer_ms), value_in_report);
Yves Gerey665174f2018-06-19 13:03:05341 EXPECT_TRUE(GetValue(report,
342 StatsReport::kStatsValueNamePreferredJitterBufferMs,
343 &value_in_report));
Jonas Olsson6b1985d2018-07-05 09:59:48344 EXPECT_EQ(rtc::ToString(info.jitter_buffer_preferred_ms), value_in_report);
Yves Gerey665174f2018-06-19 13:03:05345 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameCurrentDelayMs,
346 &value_in_report));
Jonas Olsson6b1985d2018-07-05 09:59:48347 EXPECT_EQ(rtc::ToString(info.delay_estimate_ms), value_in_report);
Yves Gerey665174f2018-06-19 13:03:05348 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameExpandRate,
349 &value_in_report));
Jonas Olsson6b1985d2018-07-05 09:59:48350 EXPECT_EQ(rtc::ToString(info.expand_rate), value_in_report);
Yves Gerey665174f2018-06-19 13:03:05351 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameSpeechExpandRate,
352 &value_in_report));
Jonas Olsson6b1985d2018-07-05 09:59:48353 EXPECT_EQ(rtc::ToString(info.speech_expand_rate), value_in_report);
Henrik Lundin8e6fd462015-06-02 07:24:52354 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameAccelerateRate,
355 &value_in_report));
Jonas Olsson6b1985d2018-07-05 09:59:48356 EXPECT_EQ(rtc::ToString(info.accelerate_rate), value_in_report);
Henrik Lundin8e6fd462015-06-02 07:24:52357 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNamePreemptiveExpandRate,
358 &value_in_report));
Jonas Olsson6b1985d2018-07-05 09:59:48359 EXPECT_EQ(rtc::ToString(info.preemptive_expand_rate), value_in_report);
minyue@webrtc.org652bc372015-02-18 23:50:46360 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameSecondaryDecodedRate,
361 &value_in_report));
Jonas Olsson6b1985d2018-07-05 09:59:48362 EXPECT_EQ(rtc::ToString(info.secondary_decoded_rate), value_in_report);
minyue-webrtc0e320ec2017-08-28 11:51:27363 EXPECT_TRUE(GetValue(report,
364 StatsReport::kStatsValueNameSecondaryDiscardedRate,
365 &value_in_report));
Jonas Olsson6b1985d2018-07-05 09:59:48366 EXPECT_EQ(rtc::ToString(info.secondary_discarded_rate), value_in_report);
Yves Gerey665174f2018-06-19 13:03:05367 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNamePacketsReceived,
368 &value_in_report));
Philipp Hancke6a7bf102023-04-21 17:32:42369 EXPECT_EQ(rtc::ToString(info.packets_received), value_in_report);
Yves Gerey665174f2018-06-19 13:03:05370 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameDecodingCTSG,
371 &value_in_report));
Jonas Olsson6b1985d2018-07-05 09:59:48372 EXPECT_EQ(rtc::ToString(info.decoding_calls_to_silence_generator),
Yves Gerey665174f2018-06-19 13:03:05373 value_in_report);
374 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameDecodingCTN,
375 &value_in_report));
Jonas Olsson6b1985d2018-07-05 09:59:48376 EXPECT_EQ(rtc::ToString(info.decoding_calls_to_neteq), value_in_report);
Yves Gerey665174f2018-06-19 13:03:05377 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameDecodingNormal,
378 &value_in_report));
Jonas Olsson6b1985d2018-07-05 09:59:48379 EXPECT_EQ(rtc::ToString(info.decoding_normal), value_in_report);
Yves Gerey665174f2018-06-19 13:03:05380 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameDecodingPLC,
381 &value_in_report));
Jonas Olsson6b1985d2018-07-05 09:59:48382 EXPECT_EQ(rtc::ToString(info.decoding_plc), value_in_report);
Alex Narest5b5d97c2019-08-07 16:15:08383 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameDecodingCodecPLC,
384 &value_in_report));
385 EXPECT_EQ(rtc::ToString(info.decoding_codec_plc), value_in_report);
Yves Gerey665174f2018-06-19 13:03:05386 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameDecodingCNG,
387 &value_in_report));
Jonas Olsson6b1985d2018-07-05 09:59:48388 EXPECT_EQ(rtc::ToString(info.decoding_cng), value_in_report);
Yves Gerey665174f2018-06-19 13:03:05389 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameDecodingPLCCNG,
390 &value_in_report));
Jonas Olsson6b1985d2018-07-05 09:59:48391 EXPECT_EQ(rtc::ToString(info.decoding_plc_cng), value_in_report);
henrik.lundin63489782016-09-20 08:47:12392 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameDecodingMutedOutput,
393 &value_in_report));
Jonas Olsson6b1985d2018-07-05 09:59:48394 EXPECT_EQ(rtc::ToString(info.decoding_muted_output), value_in_report);
henrik.lundin63489782016-09-20 08:47:12395 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameCodecName,
396 &value_in_report));
buildbot@webrtc.org3e01e0b2014-05-13 17:54:10397}
398
henrike@webrtc.org40b3b682014-03-03 18:30:11399void VerifyVoiceSenderInfoReport(const StatsReport* report,
400 const cricket::VoiceSenderInfo& sinfo) {
401 std::string value_in_report;
Yves Gerey665174f2018-06-19 13:03:05402 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameCodecName,
403 &value_in_report));
henrike@webrtc.org40b3b682014-03-03 18:30:11404 EXPECT_EQ(sinfo.codec_name, value_in_report);
Yves Gerey665174f2018-06-19 13:03:05405 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameBytesSent,
406 &value_in_report));
Niels Möllerac0a4cb2019-10-09 13:01:33407 EXPECT_EQ(rtc::ToString(sinfo.payload_bytes_sent +
408 sinfo.header_and_padding_bytes_sent),
409 value_in_report);
Yves Gerey665174f2018-06-19 13:03:05410 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNamePacketsSent,
411 &value_in_report));
Jonas Olsson6b1985d2018-07-05 09:59:48412 EXPECT_EQ(rtc::ToString(sinfo.packets_sent), value_in_report);
Yves Gerey665174f2018-06-19 13:03:05413 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNamePacketsLost,
414 &value_in_report));
Jonas Olsson6b1985d2018-07-05 09:59:48415 EXPECT_EQ(rtc::ToString(sinfo.packets_lost), value_in_report);
Yves Gerey665174f2018-06-19 13:03:05416 EXPECT_TRUE(
417 GetValue(report, StatsReport::kStatsValueNameRtt, &value_in_report));
Jonas Olsson6b1985d2018-07-05 09:59:48418 EXPECT_EQ(rtc::ToString(sinfo.rtt_ms), value_in_report);
Yves Gerey665174f2018-06-19 13:03:05419 EXPECT_TRUE(
420 GetValue(report, StatsReport::kStatsValueNameRtt, &value_in_report));
Jonas Olsson6b1985d2018-07-05 09:59:48421 EXPECT_EQ(rtc::ToString(sinfo.rtt_ms), value_in_report);
Yves Gerey665174f2018-06-19 13:03:05422 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameJitterReceived,
423 &value_in_report));
Jonas Olsson6b1985d2018-07-05 09:59:48424 EXPECT_EQ(rtc::ToString(sinfo.jitter_ms), value_in_report);
Ivo Creusen56d460902017-11-24 16:29:59425 if (sinfo.apm_statistics.delay_median_ms) {
426 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameEchoDelayMedian,
427 &value_in_report));
Jonas Olsson6b1985d2018-07-05 09:59:48428 EXPECT_EQ(rtc::ToString(*sinfo.apm_statistics.delay_median_ms),
Ivo Creusen56d460902017-11-24 16:29:59429 value_in_report);
430 } else {
431 EXPECT_FALSE(GetValue(report, StatsReport::kStatsValueNameEchoDelayMedian,
432 &value_in_report));
433 }
434 if (sinfo.apm_statistics.delay_standard_deviation_ms) {
435 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameEchoDelayStdDev,
436 &value_in_report));
Jonas Olsson6b1985d2018-07-05 09:59:48437 EXPECT_EQ(rtc::ToString(*sinfo.apm_statistics.delay_standard_deviation_ms),
438 value_in_report);
Ivo Creusen56d460902017-11-24 16:29:59439 } else {
440 EXPECT_FALSE(GetValue(report, StatsReport::kStatsValueNameEchoDelayStdDev,
441 &value_in_report));
442 }
443 if (sinfo.apm_statistics.echo_return_loss) {
444 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameEchoReturnLoss,
445 &value_in_report));
Jonas Olsson6b1985d2018-07-05 09:59:48446 EXPECT_EQ(rtc::ToString(*sinfo.apm_statistics.echo_return_loss),
Ivo Creusen56d460902017-11-24 16:29:59447 value_in_report);
448 } else {
449 EXPECT_FALSE(GetValue(report, StatsReport::kStatsValueNameEchoReturnLoss,
450 &value_in_report));
451 }
452 if (sinfo.apm_statistics.echo_return_loss_enhancement) {
453 EXPECT_TRUE(GetValue(report,
454 StatsReport::kStatsValueNameEchoReturnLossEnhancement,
455 &value_in_report));
Jonas Olsson6b1985d2018-07-05 09:59:48456 EXPECT_EQ(rtc::ToString(*sinfo.apm_statistics.echo_return_loss_enhancement),
457 value_in_report);
Ivo Creusen56d460902017-11-24 16:29:59458 } else {
459 EXPECT_FALSE(GetValue(report,
460 StatsReport::kStatsValueNameEchoReturnLossEnhancement,
461 &value_in_report));
462 }
463 if (sinfo.apm_statistics.residual_echo_likelihood) {
464 EXPECT_TRUE(GetValue(report,
465 StatsReport::kStatsValueNameResidualEchoLikelihood,
466 &value_in_report));
Jonas Olsson6b1985d2018-07-05 09:59:48467 EXPECT_EQ(rtc::ToString(*sinfo.apm_statistics.residual_echo_likelihood),
468 value_in_report);
Ivo Creusen56d460902017-11-24 16:29:59469 } else {
470 EXPECT_FALSE(GetValue(report,
471 StatsReport::kStatsValueNameResidualEchoLikelihood,
472 &value_in_report));
473 }
474 if (sinfo.apm_statistics.residual_echo_likelihood_recent_max) {
475 EXPECT_TRUE(GetValue(
476 report, StatsReport::kStatsValueNameResidualEchoLikelihoodRecentMax,
477 &value_in_report));
Jonas Olsson6b1985d2018-07-05 09:59:48478 EXPECT_EQ(rtc::ToString(
Ivo Creusen56d460902017-11-24 16:29:59479 *sinfo.apm_statistics.residual_echo_likelihood_recent_max),
480 value_in_report);
481 } else {
482 EXPECT_FALSE(GetValue(
483 report, StatsReport::kStatsValueNameResidualEchoLikelihoodRecentMax,
484 &value_in_report));
485 }
ivoc8c63a822016-10-21 11:10:03486 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameAudioInputLevel,
487 &value_in_report));
Jonas Olsson6b1985d2018-07-05 09:59:48488 EXPECT_EQ(rtc::ToString(sinfo.audio_level), value_in_report);
ivoce1198e02017-09-08 15:13:19489 EXPECT_TRUE(GetValue(report,
490 StatsReport::kStatsValueNameAnaBitrateActionCounter,
491 &value_in_report));
492 ASSERT_TRUE(sinfo.ana_statistics.bitrate_action_counter);
Jonas Olsson6b1985d2018-07-05 09:59:48493 EXPECT_EQ(rtc::ToString(*sinfo.ana_statistics.bitrate_action_counter),
494 value_in_report);
ivoce1198e02017-09-08 15:13:19495 EXPECT_TRUE(GetValue(report,
496 StatsReport::kStatsValueNameAnaChannelActionCounter,
497 &value_in_report));
498 ASSERT_TRUE(sinfo.ana_statistics.channel_action_counter);
Jonas Olsson6b1985d2018-07-05 09:59:48499 EXPECT_EQ(rtc::ToString(*sinfo.ana_statistics.channel_action_counter),
500 value_in_report);
ivoce1198e02017-09-08 15:13:19501 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameAnaDtxActionCounter,
502 &value_in_report));
503 ASSERT_TRUE(sinfo.ana_statistics.dtx_action_counter);
Jonas Olsson6b1985d2018-07-05 09:59:48504 EXPECT_EQ(rtc::ToString(*sinfo.ana_statistics.dtx_action_counter),
ivoce1198e02017-09-08 15:13:19505 value_in_report);
506 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameAnaFecActionCounter,
507 &value_in_report));
508 ASSERT_TRUE(sinfo.ana_statistics.fec_action_counter);
Jonas Olsson6b1985d2018-07-05 09:59:48509 EXPECT_EQ(rtc::ToString(*sinfo.ana_statistics.fec_action_counter),
ivoce1198e02017-09-08 15:13:19510 value_in_report);
ivoc0d0b9122017-09-08 20:24:21511 EXPECT_TRUE(GetValue(
512 report, StatsReport::kStatsValueNameAnaFrameLengthIncreaseCounter,
513 &value_in_report));
514 ASSERT_TRUE(sinfo.ana_statistics.frame_length_increase_counter);
Jonas Olsson6b1985d2018-07-05 09:59:48515 EXPECT_EQ(rtc::ToString(*sinfo.ana_statistics.frame_length_increase_counter),
ivoce1198e02017-09-08 15:13:19516 value_in_report);
ivoc0d0b9122017-09-08 20:24:21517 EXPECT_TRUE(GetValue(
518 report, StatsReport::kStatsValueNameAnaFrameLengthDecreaseCounter,
519 &value_in_report));
520 ASSERT_TRUE(sinfo.ana_statistics.frame_length_decrease_counter);
Jonas Olsson6b1985d2018-07-05 09:59:48521 EXPECT_EQ(rtc::ToString(*sinfo.ana_statistics.frame_length_decrease_counter),
ivoc0d0b9122017-09-08 20:24:21522 value_in_report);
523 EXPECT_TRUE(GetValue(report,
524 StatsReport::kStatsValueNameAnaUplinkPacketLossFraction,
525 &value_in_report));
526 ASSERT_TRUE(sinfo.ana_statistics.uplink_packet_loss_fraction);
Jonas Olsson6b1985d2018-07-05 09:59:48527 EXPECT_EQ(rtc::ToString(*sinfo.ana_statistics.uplink_packet_loss_fraction),
528 value_in_report);
henrike@webrtc.org40b3b682014-03-03 18:30:11529}
530
xians@webrtc.org4cb01282014-06-12 14:57:05531// Helper methods to avoid duplication of code.
Steve Antonefe4c922019-03-27 17:26:06532void InitVoiceSenderInfo(cricket::VoiceSenderInfo* voice_sender_info,
533 uint32_t ssrc = kSsrcOfTrack) {
534 voice_sender_info->add_ssrc(ssrc);
xians@webrtc.org4cb01282014-06-12 14:57:05535 voice_sender_info->codec_name = "fake_codec";
Niels Möllerac0a4cb2019-10-09 13:01:33536 voice_sender_info->payload_bytes_sent = 88;
537 voice_sender_info->header_and_padding_bytes_sent = 12;
xians@webrtc.org4cb01282014-06-12 14:57:05538 voice_sender_info->packets_sent = 101;
539 voice_sender_info->rtt_ms = 102;
540 voice_sender_info->fraction_lost = 103;
541 voice_sender_info->jitter_ms = 104;
542 voice_sender_info->packets_lost = 105;
xians@webrtc.org4cb01282014-06-12 14:57:05543 voice_sender_info->audio_level = 107;
Sam Zackrisson5f2ffee2018-11-01 12:51:24544 voice_sender_info->apm_statistics.echo_return_loss = 108;
545 voice_sender_info->apm_statistics.echo_return_loss_enhancement = 109;
546 voice_sender_info->apm_statistics.delay_median_ms = 110;
547 voice_sender_info->apm_statistics.delay_standard_deviation_ms = 111;
Ivo Creusen56d460902017-11-24 16:29:59548 voice_sender_info->ana_statistics.bitrate_action_counter = 112;
549 voice_sender_info->ana_statistics.channel_action_counter = 113;
550 voice_sender_info->ana_statistics.dtx_action_counter = 114;
551 voice_sender_info->ana_statistics.fec_action_counter = 115;
552 voice_sender_info->ana_statistics.frame_length_increase_counter = 116;
553 voice_sender_info->ana_statistics.frame_length_decrease_counter = 117;
554 voice_sender_info->ana_statistics.uplink_packet_loss_fraction = 118.0;
xians@webrtc.org4cb01282014-06-12 14:57:05555}
556
557void UpdateVoiceSenderInfoFromAudioTrack(
zhihuang6ba3b192016-05-13 18:46:35558 AudioTrackInterface* audio_track,
Ivo Creusen56d460902017-11-24 16:29:59559 cricket::VoiceSenderInfo* voice_sender_info,
560 bool has_remote_tracks) {
xians@webrtc.org4cb01282014-06-12 14:57:05561 audio_track->GetSignalLevel(&voice_sender_info->audio_level);
Steve Anton3871f6f2018-01-26 18:25:53562 AudioProcessorInterface::AudioProcessorStatistics audio_processor_stats =
563 audio_track->GetAudioProcessor()->GetStats(has_remote_tracks);
Ivo Creusen56d460902017-11-24 16:29:59564 voice_sender_info->apm_statistics = audio_processor_stats.apm_statistics;
xians@webrtc.org4cb01282014-06-12 14:57:05565}
566
567void InitVoiceReceiverInfo(cricket::VoiceReceiverInfo* voice_receiver_info) {
568 voice_receiver_info->add_ssrc(kSsrcOfTrack);
Philipp Hancke6a7bf102023-04-21 17:32:42569 voice_receiver_info->payload_bytes_received = 98;
570 voice_receiver_info->header_and_padding_bytes_received = 12;
571 voice_receiver_info->packets_received = 111;
xians@webrtc.org4cb01282014-06-12 14:57:05572 voice_receiver_info->packets_lost = 114;
xians@webrtc.org4cb01282014-06-12 14:57:05573 voice_receiver_info->jitter_ms = 116;
574 voice_receiver_info->jitter_buffer_ms = 117;
575 voice_receiver_info->jitter_buffer_preferred_ms = 118;
576 voice_receiver_info->delay_estimate_ms = 119;
577 voice_receiver_info->audio_level = 120;
578 voice_receiver_info->expand_rate = 121;
minyue@webrtc.org652bc372015-02-18 23:50:46579 voice_receiver_info->speech_expand_rate = 122;
580 voice_receiver_info->secondary_decoded_rate = 123;
Henrik Lundin8e6fd462015-06-02 07:24:52581 voice_receiver_info->accelerate_rate = 124;
582 voice_receiver_info->preemptive_expand_rate = 125;
minyue-webrtc0e320ec2017-08-28 11:51:27583 voice_receiver_info->secondary_discarded_rate = 126;
Alex Narest5b5d97c2019-08-07 16:15:08584 voice_receiver_info->decoding_codec_plc = 127;
xians@webrtc.org4cb01282014-06-12 14:57:05585}
586
Henrik Boströmf7859892022-07-04 12:36:37587class LegacyStatsCollectorForTest : public LegacyStatsCollector {
decurtis@webrtc.org322a5642015-02-03 22:09:37588 public:
Henrik Boströmf7859892022-07-04 12:36:37589 explicit LegacyStatsCollectorForTest(PeerConnectionInternal* pc)
590 : LegacyStatsCollector(pc), time_now_(19477) {}
decurtis@webrtc.org322a5642015-02-03 22:09:37591
Yves Gerey665174f2018-06-19 13:03:05592 double GetTimeNow() override { return time_now_; }
decurtis@webrtc.org322a5642015-02-03 22:09:37593
594 private:
595 double time_now_;
596};
597
Henrik Boströmf7859892022-07-04 12:36:37598class LegacyStatsCollectorTest : public ::testing::Test {
henrike@webrtc.org28e20752013-07-10 00:45:36599 protected:
Steve Anton3871f6f2018-01-26 18:25:53600 rtc::scoped_refptr<FakePeerConnectionForStats> CreatePeerConnection() {
Tommi87f70902021-04-27 12:43:08601 return rtc::make_ref_counted<FakePeerConnectionForStats>();
henrike@webrtc.org28e20752013-07-10 00:45:36602 }
603
Henrik Boströmf7859892022-07-04 12:36:37604 std::unique_ptr<LegacyStatsCollectorForTest> CreateStatsCollector(
Steve Anton3871f6f2018-01-26 18:25:53605 PeerConnectionInternal* pc) {
Henrik Boströmf7859892022-07-04 12:36:37606 return std::make_unique<LegacyStatsCollectorForTest>(pc);
wu@webrtc.org97077a32013-10-25 21:18:33607 }
608
Steve Anton3871f6f2018-01-26 18:25:53609 void VerifyAudioTrackStats(FakeAudioTrack* audio_track,
Henrik Boströmf7859892022-07-04 12:36:37610 LegacyStatsCollectorForTest* stats,
Steve Anton3871f6f2018-01-26 18:25:53611 const VoiceMediaInfo& voice_info,
612 StatsReports* reports) {
xians@webrtc.org01bda202014-07-09 07:38:38613 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
Tommic811ab52022-01-11 15:33:23614 stats->InvalidateCache();
Steve Anton3871f6f2018-01-26 18:25:53615 stats->GetStats(nullptr, reports);
xians@webrtc.org01bda202014-07-09 07:38:38616
617 // Verify the existence of the track report.
Yves Gerey665174f2018-06-19 13:03:05618 const StatsReport* report =
619 FindNthReportByType(*reports, StatsReport::kStatsReportTypeSsrc, 1);
Steve Anton3871f6f2018-01-26 18:25:53620 ASSERT_TRUE(report);
jbauchbe24c942015-06-22 22:06:43621 EXPECT_EQ(stats->GetTimeNow(), report->timestamp());
Yves Gerey665174f2018-06-19 13:03:05622 std::string track_id =
623 ExtractSsrcStatsValue(*reports, StatsReport::kStatsValueNameTrackId);
xians@webrtc.org01bda202014-07-09 07:38:38624 EXPECT_EQ(audio_track->id(), track_id);
Yves Gerey665174f2018-06-19 13:03:05625 std::string ssrc_id =
626 ExtractSsrcStatsValue(*reports, StatsReport::kStatsValueNameSsrc);
Jonas Olsson6b1985d2018-07-05 09:59:48627 EXPECT_EQ(rtc::ToString(kSsrcOfTrack), ssrc_id);
xians@webrtc.org01bda202014-07-09 07:38:38628
Yves Gerey665174f2018-06-19 13:03:05629 std::string media_type =
630 ExtractSsrcStatsValue(*reports, StatsReport::kStatsValueNameMediaType);
fippobec70ab2016-01-28 09:27:15631 EXPECT_EQ("audio", media_type);
632
xians@webrtc.org01bda202014-07-09 07:38:38633 // Verifies the values in the track report.
Steve Anton3871f6f2018-01-26 18:25:53634 if (!voice_info.senders.empty()) {
635 VerifyVoiceSenderInfoReport(report, voice_info.senders[0]);
xians@webrtc.org01bda202014-07-09 07:38:38636 }
Steve Anton3871f6f2018-01-26 18:25:53637 if (!voice_info.receivers.empty()) {
638 VerifyVoiceReceiverInfoReport(report, voice_info.receivers[0]);
xians@webrtc.org01bda202014-07-09 07:38:38639 }
640
641 // Verify we get the same result by passing a track to GetStats().
642 StatsReports track_reports; // returned values.
643 stats->GetStats(audio_track, &track_reports);
644 const StatsReport* track_report = FindNthReportByType(
645 track_reports, StatsReport::kStatsReportTypeSsrc, 1);
Steve Anton3871f6f2018-01-26 18:25:53646 ASSERT_TRUE(track_report);
jbauchbe24c942015-06-22 22:06:43647 EXPECT_EQ(stats->GetTimeNow(), track_report->timestamp());
xians@webrtc.org01bda202014-07-09 07:38:38648 track_id = ExtractSsrcStatsValue(track_reports,
649 StatsReport::kStatsValueNameTrackId);
650 EXPECT_EQ(audio_track->id(), track_id);
Yves Gerey665174f2018-06-19 13:03:05651 ssrc_id =
652 ExtractSsrcStatsValue(track_reports, StatsReport::kStatsValueNameSsrc);
Jonas Olsson6b1985d2018-07-05 09:59:48653 EXPECT_EQ(rtc::ToString(kSsrcOfTrack), ssrc_id);
Steve Anton3871f6f2018-01-26 18:25:53654 if (!voice_info.senders.empty()) {
655 VerifyVoiceSenderInfoReport(track_report, voice_info.senders[0]);
656 }
657 if (!voice_info.receivers.empty()) {
658 VerifyVoiceReceiverInfoReport(track_report, voice_info.receivers[0]);
659 }
henrike@webrtc.org40b3b682014-03-03 18:30:11660 }
661
Taylor Brandstetterc3928662018-02-23 21:04:51662 void TestCertificateReports(const rtc::FakeSSLIdentity& local_identity,
663 const std::vector<std::string>& local_ders,
664 const rtc::FakeSSLIdentity& remote_identity,
665 const std::vector<std::string>& remote_ders) {
Steve Anton3871f6f2018-01-26 18:25:53666 const std::string kTransportName = "transport";
decurtis@webrtc.org487a4442015-01-15 22:55:07667
Steve Anton3871f6f2018-01-26 18:25:53668 auto pc = CreatePeerConnection();
Niels Möllerafb246b2022-04-20 12:26:50669 auto stats = CreateStatsCollector(pc.get());
Steve Anton3871f6f2018-01-26 18:25:53670
Steve Anton5b387312018-02-03 00:00:20671 pc->AddVoiceChannel("audio", kTransportName);
wu@webrtc.org4551b792013-10-09 15:37:36672
673 // Fake stats to process.
Steve Anton3871f6f2018-01-26 18:25:53674 TransportChannelStats channel_stats;
wu@webrtc.org4551b792013-10-09 15:37:36675 channel_stats.component = 1;
Mirko Bonadei7750d802021-07-26 15:27:42676 channel_stats.srtp_crypto_suite = rtc::kSrtpAes128CmSha1_80;
tkchin7d06a8c2016-04-04 21:10:43677 channel_stats.ssl_cipher_suite =
678 internal::TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA;
Steve Anton3871f6f2018-01-26 18:25:53679 pc->SetTransportStats(kTransportName, channel_stats);
wu@webrtc.org4551b792013-10-09 15:37:36680
Taylor Brandstetterc3928662018-02-23 21:04:51681 // Fake certificate to report.
Henrik Boströmd8281982015-08-27 08:12:24682 rtc::scoped_refptr<rtc::RTCCertificate> local_certificate(
Harald Alvestrandb33a0ca2020-04-16 12:59:40683 rtc::RTCCertificate::Create(local_identity.Clone()));
Steve Anton3871f6f2018-01-26 18:25:53684 pc->SetLocalCertificate(kTransportName, local_certificate);
Taylor Brandstetterc3928662018-02-23 21:04:51685 pc->SetRemoteCertChain(kTransportName,
Steve Antonf25303e2018-10-16 22:23:31686 remote_identity.cert_chain().Clone());
wu@webrtc.org4551b792013-10-09 15:37:36687
Steve Anton3871f6f2018-01-26 18:25:53688 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
wu@webrtc.org4551b792013-10-09 15:37:36689
Steve Anton3871f6f2018-01-26 18:25:53690 StatsReports reports;
691 stats->GetStats(nullptr, &reports);
wu@webrtc.org4551b792013-10-09 15:37:36692
Yves Gerey665174f2018-06-19 13:03:05693 const StatsReport* channel_report =
694 FindNthReportByType(reports, StatsReport::kStatsReportTypeComponent, 1);
Steve Anton3871f6f2018-01-26 18:25:53695 EXPECT_TRUE(channel_report);
wu@webrtc.org4551b792013-10-09 15:37:36696
697 // Check local certificate chain.
Yves Gerey665174f2018-06-19 13:03:05698 std::string local_certificate_id =
699 ExtractStatsValue(StatsReport::kStatsReportTypeComponent, reports,
700 StatsReport::kStatsValueNameLocalCertificateId);
wu@webrtc.orgb9a088b2014-02-13 23:18:49701 if (local_ders.size() > 0) {
702 EXPECT_NE(kNotFound, local_certificate_id);
tommi@webrtc.orgd3900292015-03-12 16:35:55703 StatsReport::Id id(IdFromCertIdString(local_certificate_id));
704 CheckCertChainReports(reports, local_ders, id);
wu@webrtc.orgb9a088b2014-02-13 23:18:49705 } else {
706 EXPECT_EQ(kNotFound, local_certificate_id);
707 }
wu@webrtc.org4551b792013-10-09 15:37:36708
709 // Check remote certificate chain.
Yves Gerey665174f2018-06-19 13:03:05710 std::string remote_certificate_id =
711 ExtractStatsValue(StatsReport::kStatsReportTypeComponent, reports,
712 StatsReport::kStatsValueNameRemoteCertificateId);
wu@webrtc.orgb9a088b2014-02-13 23:18:49713 if (remote_ders.size() > 0) {
714 EXPECT_NE(kNotFound, remote_certificate_id);
tommi@webrtc.orgd3900292015-03-12 16:35:55715 StatsReport::Id id(IdFromCertIdString(remote_certificate_id));
716 CheckCertChainReports(reports, remote_ders, id);
wu@webrtc.orgb9a088b2014-02-13 23:18:49717 } else {
718 EXPECT_EQ(kNotFound, remote_certificate_id);
719 }
pthatcher@webrtc.org7bea1ff2015-03-04 01:38:30720
721 // Check negotiated ciphers.
Guo-wei Shieh521ed7b2015-11-19 03:41:53722 std::string dtls_cipher_suite =
723 ExtractStatsValue(StatsReport::kStatsReportTypeComponent, reports,
724 StatsReport::kStatsValueNameDtlsCipher);
725 EXPECT_EQ(rtc::SSLStreamAdapter::SslCipherSuiteToName(
tkchin7d06a8c2016-04-04 21:10:43726 internal::TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA),
Guo-wei Shieh521ed7b2015-11-19 03:41:53727 dtls_cipher_suite);
728 std::string srtp_crypto_suite =
729 ExtractStatsValue(StatsReport::kStatsReportTypeComponent, reports,
730 StatsReport::kStatsValueNameSrtpCipher);
Mirko Bonadei7750d802021-07-26 15:27:42731 EXPECT_EQ(rtc::SrtpCryptoSuiteToName(rtc::kSrtpAes128CmSha1_80),
Guo-wei Shieh521ed7b2015-11-19 03:41:53732 srtp_crypto_suite);
wu@webrtc.org4551b792013-10-09 15:37:36733 }
Niels Möller83830f32022-05-20 07:12:57734
735 private:
736 rtc::AutoThread main_thread_;
Harald Alvestrand75ceef22018-01-04 14:26:13737};
738
Steve Antonefe4c922019-03-27 17:26:06739static rtc::scoped_refptr<MockRtpSenderInternal> CreateMockSender(
740 rtc::scoped_refptr<MediaStreamTrackInterface> track,
741 uint32_t ssrc) {
Tommi87f70902021-04-27 12:43:08742 auto sender = rtc::make_ref_counted<MockRtpSenderInternal>();
Steve Antonefe4c922019-03-27 17:26:06743 EXPECT_CALL(*sender, track()).WillRepeatedly(Return(track));
744 EXPECT_CALL(*sender, ssrc()).WillRepeatedly(Return(ssrc));
745 EXPECT_CALL(*sender, media_type())
746 .WillRepeatedly(
747 Return(track->kind() == MediaStreamTrackInterface::kAudioKind
748 ? cricket::MEDIA_TYPE_AUDIO
749 : cricket::MEDIA_TYPE_VIDEO));
Tomas Gunnarsson16de2162022-01-26 09:21:57750 EXPECT_CALL(*sender, SetMediaChannel(_)).Times(AtMost(2));
751 EXPECT_CALL(*sender, SetTransceiverAsStopped()).Times(AtMost(1));
752 EXPECT_CALL(*sender, Stop());
Steve Antonefe4c922019-03-27 17:26:06753 return sender;
754}
755
756static rtc::scoped_refptr<MockRtpReceiverInternal> CreateMockReceiver(
757 rtc::scoped_refptr<MediaStreamTrackInterface> track,
758 uint32_t ssrc) {
Tommi87f70902021-04-27 12:43:08759 auto receiver = rtc::make_ref_counted<MockRtpReceiverInternal>();
Steve Antonefe4c922019-03-27 17:26:06760 EXPECT_CALL(*receiver, track()).WillRepeatedly(Return(track));
761 EXPECT_CALL(*receiver, ssrc()).WillRepeatedly(Return(ssrc));
762 EXPECT_CALL(*receiver, media_type())
763 .WillRepeatedly(
764 Return(track->kind() == MediaStreamTrackInterface::kAudioKind
765 ? cricket::MEDIA_TYPE_AUDIO
766 : cricket::MEDIA_TYPE_VIDEO));
Tommi6589def2022-02-17 22:36:47767 EXPECT_CALL(*receiver, SetMediaChannel(_)).WillRepeatedly(Return());
768 EXPECT_CALL(*receiver, Stop()).WillRepeatedly(Return());
Steve Antonefe4c922019-03-27 17:26:06769 return receiver;
770}
771
Henrik Boströmf7859892022-07-04 12:36:37772class StatsCollectorTrackTest : public LegacyStatsCollectorTest,
Harald Alvestrand75ceef22018-01-04 14:26:13773 public ::testing::WithParamInterface<bool> {
774 public:
775 // Adds a outgoing video track with a given SSRC into the stats.
776 // If GetParam() returns true, the track is also inserted into the local
777 // stream, which is created if necessary.
Steve Anton3871f6f2018-01-26 18:25:53778 void AddOutgoingVideoTrack(FakePeerConnectionForStats* pc,
Henrik Boströmf7859892022-07-04 12:36:37779 LegacyStatsCollectorForTest* stats) {
Harald Alvestrand2f7ad282022-04-21 11:35:43780 video_track_ = VideoTrack::Create(
781 kLocalTrackId, FakeVideoTrackSource::Create(), rtc::Thread::Current());
Harald Alvestrand75ceef22018-01-04 14:26:13782 if (GetParam()) {
783 if (!stream_)
Seth Hampson845e8782018-03-02 19:34:10784 stream_ = MediaStream::Create("streamid");
Harald Alvestrand2f7ad282022-04-21 11:35:43785 stream_->AddTrack(video_track());
Niels Möllerafb246b2022-04-20 12:26:50786 stats->AddStream(stream_.get());
Harald Alvestrand75ceef22018-01-04 14:26:13787 } else {
Harald Alvestrand2f7ad282022-04-21 11:35:43788 stats->AddTrack(video_track_.get());
Harald Alvestrand75ceef22018-01-04 14:26:13789 }
Harald Alvestrand2f7ad282022-04-21 11:35:43790 pc->AddSender(CreateMockSender(video_track_, kSsrcOfTrack));
Harald Alvestrand75ceef22018-01-04 14:26:13791 }
792
793 // Adds a incoming video track with a given SSRC into the stats.
Steve Anton3871f6f2018-01-26 18:25:53794 void AddIncomingVideoTrack(FakePeerConnectionForStats* pc,
Henrik Boströmf7859892022-07-04 12:36:37795 LegacyStatsCollectorForTest* stats) {
Harald Alvestrand2f7ad282022-04-21 11:35:43796 video_track_ = VideoTrack::Create(
797 kRemoteTrackId, FakeVideoTrackSource::Create(), rtc::Thread::Current());
Harald Alvestrand75ceef22018-01-04 14:26:13798 if (GetParam()) {
Seth Hampson845e8782018-03-02 19:34:10799 stream_ = MediaStream::Create("streamid");
Harald Alvestrand2f7ad282022-04-21 11:35:43800 stream_->AddTrack(video_track());
Niels Möllerafb246b2022-04-20 12:26:50801 stats->AddStream(stream_.get());
Harald Alvestrand75ceef22018-01-04 14:26:13802 } else {
Harald Alvestrand2f7ad282022-04-21 11:35:43803 stats->AddTrack(video_track_.get());
Harald Alvestrand75ceef22018-01-04 14:26:13804 }
Harald Alvestrand2f7ad282022-04-21 11:35:43805 pc->AddReceiver(CreateMockReceiver(video_track_, kSsrcOfTrack));
Harald Alvestrand75ceef22018-01-04 14:26:13806 }
807
808 // Adds a outgoing audio track with a given SSRC into the stats,
809 // and register it into the stats object.
810 // If GetParam() returns true, the track is also inserted into the local
811 // stream, which is created if necessary.
Steve Antonefe4c922019-03-27 17:26:06812 rtc::scoped_refptr<RtpSenderInterface> AddOutgoingAudioTrack(
813 FakePeerConnectionForStats* pc,
Henrik Boströmf7859892022-07-04 12:36:37814 LegacyStatsCollectorForTest* stats) {
Tommi87f70902021-04-27 12:43:08815 audio_track_ = rtc::make_ref_counted<FakeAudioTrack>(kLocalTrackId);
Harald Alvestrand75ceef22018-01-04 14:26:13816 if (GetParam()) {
817 if (!stream_)
Seth Hampson845e8782018-03-02 19:34:10818 stream_ = MediaStream::Create("streamid");
Harald Alvestrand2f7ad282022-04-21 11:35:43819 stream_->AddTrack(audio_track());
Niels Möllerafb246b2022-04-20 12:26:50820 stats->AddStream(stream_.get());
Harald Alvestrand75ceef22018-01-04 14:26:13821 } else {
Niels Möllerafb246b2022-04-20 12:26:50822 stats->AddTrack(audio_track_.get());
Harald Alvestrand75ceef22018-01-04 14:26:13823 }
Steve Antonefe4c922019-03-27 17:26:06824 return pc->AddSender(CreateMockSender(audio_track_, kSsrcOfTrack));
Harald Alvestrand75ceef22018-01-04 14:26:13825 }
826
827 // Adds a incoming audio track with a given SSRC into the stats.
Steve Anton3871f6f2018-01-26 18:25:53828 void AddIncomingAudioTrack(FakePeerConnectionForStats* pc,
Henrik Boströmf7859892022-07-04 12:36:37829 LegacyStatsCollectorForTest* stats) {
Tommi87f70902021-04-27 12:43:08830 audio_track_ = rtc::make_ref_counted<FakeAudioTrack>(kRemoteTrackId);
Harald Alvestrand75ceef22018-01-04 14:26:13831 if (GetParam()) {
Niels Möllerafb246b2022-04-20 12:26:50832 if (stream_ == nullptr)
Seth Hampson845e8782018-03-02 19:34:10833 stream_ = MediaStream::Create("streamid");
Harald Alvestrand2f7ad282022-04-21 11:35:43834 stream_->AddTrack(audio_track());
Niels Möllerafb246b2022-04-20 12:26:50835 stats->AddStream(stream_.get());
Harald Alvestrand75ceef22018-01-04 14:26:13836 } else {
Niels Möllerafb246b2022-04-20 12:26:50837 stats->AddTrack(audio_track_.get());
Harald Alvestrand75ceef22018-01-04 14:26:13838 }
Steve Antonefe4c922019-03-27 17:26:06839 pc->AddReceiver(CreateMockReceiver(audio_track_, kSsrcOfTrack));
Harald Alvestrand75ceef22018-01-04 14:26:13840 }
841
Harald Alvestrand2f7ad282022-04-21 11:35:43842 rtc::scoped_refptr<AudioTrackInterface> audio_track() { return audio_track_; }
843 rtc::scoped_refptr<VideoTrackInterface> video_track() { return video_track_; }
844
Steve Anton3871f6f2018-01-26 18:25:53845 rtc::scoped_refptr<MediaStream> stream_;
Harald Alvestrand2f7ad282022-04-21 11:35:43846 rtc::scoped_refptr<VideoTrack> video_track_;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52847 rtc::scoped_refptr<FakeAudioTrack> audio_track_;
henrike@webrtc.org28e20752013-07-10 00:45:36848};
849
Tommi0fe65102023-03-31 10:09:30850TEST(StatsCollectionTest, DetachAndMerge) {
851 StatsCollection collection;
852 ASSERT_EQ(collection.size(), 0u);
853
854 // Create a new report with some information.
855 StatsReport::Id id(
856 StatsReport::NewTypedId(StatsReport::kStatsReportTypeTrack, "track_id"));
857 StatsReport* report = collection.ReplaceOrAddNew(id);
858 report->AddString(StatsReport::kStatsValueNameTrackId, "track_id");
859 ASSERT_TRUE(report);
860 // Check that looking it up, yields the same report.
861 ASSERT_EQ(report, collection.FindOrAddNew(id));
862 // There should be one report now.
863 ASSERT_EQ(collection.size(), 1u);
864
865 // Detach the internal container from the StatsCollection.
866 StatsCollection::Container container = collection.DetachCollection();
867 EXPECT_EQ(container.size(), 1u);
868 EXPECT_EQ(collection.size(), 0u);
869 EXPECT_EQ(nullptr, collection.Find(id));
870
871 // Merge it back and test if we find the same report.
872 collection.MergeCollection(std::move(container));
873 EXPECT_EQ(collection.size(), 1u);
874 EXPECT_EQ(report, collection.Find(id));
875}
876
877// Similar to `DetachAndMerge` above but detaches on one thread, merges on
878// another to test that we don't trigger sequence checker.
879TEST(StatsCollectionTest, DetachAndMergeThreaded) {
880 rtc::Thread new_thread(std::make_unique<rtc::NullSocketServer>());
881 new_thread.Start();
882
883 StatsReport::Id id(
884 StatsReport::NewTypedId(StatsReport::kStatsReportTypeTrack, "track_id"));
885
886 StatsReport* expected_report = nullptr;
887
888 StatsCollection::Container container = new_thread.BlockingCall([&] {
889 StatsCollection collection;
890 expected_report = collection.ReplaceOrAddNew(id);
891 expected_report->AddString(StatsReport::kStatsValueNameTrackId, "track_id");
892 return collection.DetachCollection();
893 });
894
895 StatsCollection collection;
896 collection.MergeCollection(std::move(container));
897 EXPECT_EQ(collection.size(), 1u);
898 EXPECT_EQ(expected_report, collection.Find(id));
899
900 new_thread.Stop();
901}
Henrik Boströmf7859892022-07-04 12:36:37902TEST_F(LegacyStatsCollectorTest, FilterOutNegativeDataChannelId) {
Steve Anton3871f6f2018-01-26 18:25:53903 auto pc = CreatePeerConnection();
Niels Möllerafb246b2022-04-20 12:26:50904 auto stats = CreateStatsCollector(pc.get());
zhihuang6ba3b192016-05-13 18:46:35905
Steve Anton3871f6f2018-01-26 18:25:53906 pc->AddSctpDataChannel("hacks");
zhihuang6ba3b192016-05-13 18:46:35907
Steve Anton3871f6f2018-01-26 18:25:53908 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
zhihuang6ba3b192016-05-13 18:46:35909 StatsReports reports;
Steve Anton3871f6f2018-01-26 18:25:53910 stats->GetStats(nullptr, &reports);
zhihuang6ba3b192016-05-13 18:46:35911
912 const StatsReport* report =
913 FindNthReportByType(reports, StatsReport::kStatsReportTypeDataChannel, 1);
914
915 std::string value_in_report;
916 EXPECT_FALSE(GetValue(report, StatsReport::kStatsValueNameDataChannelId,
917 &value_in_report));
918}
919
decurtis@webrtc.org487a4442015-01-15 22:55:07920// Verify that ExtractDataInfo populates reports.
Henrik Boströmf7859892022-07-04 12:36:37921TEST_F(LegacyStatsCollectorTest, ExtractDataInfo) {
Steve Anton3871f6f2018-01-26 18:25:53922 const std::string kDataChannelLabel = "hacks";
923 constexpr int kDataChannelId = 31337;
924 const std::string kConnectingString = DataChannelInterface::DataStateString(
decurtis@webrtc.org487a4442015-01-15 22:55:07925 DataChannelInterface::DataState::kConnecting);
926
Steve Anton3871f6f2018-01-26 18:25:53927 auto pc = CreatePeerConnection();
Niels Möllerafb246b2022-04-20 12:26:50928 auto stats = CreateStatsCollector(pc.get());
decurtis@webrtc.org487a4442015-01-15 22:55:07929
Steve Anton3871f6f2018-01-26 18:25:53930 InternalDataChannelInit init;
931 init.id = kDataChannelId;
932 pc->AddSctpDataChannel(kDataChannelLabel, init);
decurtis@webrtc.org487a4442015-01-15 22:55:07933
Steve Anton3871f6f2018-01-26 18:25:53934 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
decurtis@webrtc.org487a4442015-01-15 22:55:07935 StatsReports reports;
Steve Anton3871f6f2018-01-26 18:25:53936 stats->GetStats(nullptr, &reports);
decurtis@webrtc.org322a5642015-02-03 22:09:37937
938 const StatsReport* report =
939 FindNthReportByType(reports, StatsReport::kStatsReportTypeDataChannel, 1);
940
Steve Anton3871f6f2018-01-26 18:25:53941 StatsReport::Id report_id = StatsReport::NewTypedIntId(
942 StatsReport::kStatsReportTypeDataChannel, kDataChannelId);
decurtis@webrtc.org322a5642015-02-03 22:09:37943
Steve Anton3871f6f2018-01-26 18:25:53944 EXPECT_TRUE(report_id->Equals(report->id()));
decurtis@webrtc.org322a5642015-02-03 22:09:37945
Steve Anton3871f6f2018-01-26 18:25:53946 EXPECT_EQ(stats->GetTimeNow(), report->timestamp());
947 EXPECT_EQ(kDataChannelLabel,
948 ExtractStatsValue(StatsReport::kStatsReportTypeDataChannel, reports,
949 StatsReport::kStatsValueNameLabel));
Jonas Olsson6b1985d2018-07-05 09:59:48950 EXPECT_EQ(rtc::ToString(kDataChannelId),
Peter Boström0c4e06b2015-10-07 10:23:21951 ExtractStatsValue(StatsReport::kStatsReportTypeDataChannel, reports,
decurtis@webrtc.org487a4442015-01-15 22:55:07952 StatsReport::kStatsValueNameDataChannelId));
Steve Anton3871f6f2018-01-26 18:25:53953 EXPECT_EQ(kConnectingString,
954 ExtractStatsValue(StatsReport::kStatsReportTypeDataChannel, reports,
955 StatsReport::kStatsValueNameState));
Yves Gerey665174f2018-06-19 13:03:05956 EXPECT_EQ("",
957 ExtractStatsValue(StatsReport::kStatsReportTypeDataChannel, reports,
958 StatsReport::kStatsValueNameProtocol));
decurtis@webrtc.org487a4442015-01-15 22:55:07959}
960
henrike@webrtc.org28e20752013-07-10 00:45:36961// This test verifies that 64-bit counters are passed successfully.
Harald Alvestrand75ceef22018-01-04 14:26:13962TEST_P(StatsCollectorTrackTest, BytesCounterHandles64Bits) {
henrike@webrtc.org28e20752013-07-10 00:45:36963 // The number of bytes must be larger than 0xFFFFFFFF for this test.
Steve Anton3871f6f2018-01-26 18:25:53964 constexpr int64_t kBytesSent = 12345678901234LL;
henrike@webrtc.org28e20752013-07-10 00:45:36965
Steve Anton3871f6f2018-01-26 18:25:53966 auto pc = CreatePeerConnection();
Niels Möllerafb246b2022-04-20 12:26:50967 auto stats = CreateStatsCollector(pc.get());
henrike@webrtc.org28e20752013-07-10 00:45:36968
Steve Anton3871f6f2018-01-26 18:25:53969 VideoSenderInfo video_sender_info;
sergeyu@chromium.org5bc25c42013-12-05 00:24:06970 video_sender_info.add_ssrc(1234);
Niels Möllerac0a4cb2019-10-09 13:01:33971 video_sender_info.payload_bytes_sent = kBytesSent;
972 video_sender_info.header_and_padding_bytes_sent = 0;
Steve Anton3871f6f2018-01-26 18:25:53973 VideoMediaInfo video_info;
Henrik Boströma0ff50c2020-05-05 13:54:46974 video_info.aggregated_senders.push_back(video_sender_info);
Steve Anton5b387312018-02-03 00:00:20975
Tommi19015512022-02-02 10:49:35976 pc->AddVideoChannel("video", "transport", video_info);
henrike@webrtc.org28e20752013-07-10 00:45:36977
Niels Möllerafb246b2022-04-20 12:26:50978 AddOutgoingVideoTrack(pc.get(), stats.get());
Steve Anton3871f6f2018-01-26 18:25:53979
980 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
981 StatsReports reports;
982 stats->GetStats(nullptr, &reports);
983
984 EXPECT_EQ(
985 rtc::ToString(kBytesSent),
986 ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameBytesSent));
henrike@webrtc.org28e20752013-07-10 00:45:36987}
988
Alex Narest42308f62017-06-19 15:58:12989// Test that audio BWE information is reported via stats.
Harald Alvestrand75ceef22018-01-04 14:26:13990TEST_P(StatsCollectorTrackTest, AudioBandwidthEstimationInfoIsReported) {
Alex Narest42308f62017-06-19 15:58:12991 // Set up an SSRC just to test that we get both kinds of stats back: SSRC and
992 // BWE.
Steve Anton3871f6f2018-01-26 18:25:53993 constexpr int64_t kBytesSent = 12345678901234LL;
994 constexpr int kSendBandwidth = 1234567;
995 constexpr int kRecvBandwidth = 12345678;
996 constexpr int kPacerDelay = 123;
Alex Narest42308f62017-06-19 15:58:12997
Steve Anton3871f6f2018-01-26 18:25:53998 auto pc = CreatePeerConnection();
Niels Möllerafb246b2022-04-20 12:26:50999 auto stats = CreateStatsCollector(pc.get());
Alex Narest42308f62017-06-19 15:58:121000
Steve Anton3871f6f2018-01-26 18:25:531001 VoiceSenderInfo voice_sender_info;
Alex Narest42308f62017-06-19 15:58:121002 voice_sender_info.add_ssrc(1234);
Niels Möllerac0a4cb2019-10-09 13:01:331003 voice_sender_info.payload_bytes_sent = kBytesSent - 12;
1004 voice_sender_info.header_and_padding_bytes_sent = 12;
Steve Anton3871f6f2018-01-26 18:25:531005 VoiceMediaInfo voice_info;
1006 voice_info.senders.push_back(voice_sender_info);
Steve Anton5b387312018-02-03 00:00:201007
Harald Alvestrand2f553702023-03-07 10:10:031008 auto voice_media_channels = pc->AddVoiceChannel("audio", "transport");
1009 voice_media_channels.first->SetStats(voice_info);
1010 voice_media_channels.second->SetStats(voice_info);
Alex Narest42308f62017-06-19 15:58:121011
Niels Möllerafb246b2022-04-20 12:26:501012 AddOutgoingAudioTrack(pc.get(), stats.get());
Steve Anton3871f6f2018-01-26 18:25:531013
1014 Call::Stats call_stats;
Alex Narest42308f62017-06-19 15:58:121015 call_stats.send_bandwidth_bps = kSendBandwidth;
1016 call_stats.recv_bandwidth_bps = kRecvBandwidth;
1017 call_stats.pacer_delay_ms = kPacerDelay;
Steve Anton3871f6f2018-01-26 18:25:531018 pc->SetCallStats(call_stats);
Alex Narest42308f62017-06-19 15:58:121019
Steve Anton3871f6f2018-01-26 18:25:531020 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1021 StatsReports reports;
1022 stats->GetStats(nullptr, &reports);
1023
1024 EXPECT_EQ(
1025 rtc::ToString(kBytesSent),
1026 ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameBytesSent));
1027 EXPECT_EQ(rtc::ToString(kSendBandwidth),
1028 ExtractBweStatsValue(
1029 reports, StatsReport::kStatsValueNameAvailableSendBandwidth));
1030 EXPECT_EQ(
1031 rtc::ToString(kRecvBandwidth),
1032 ExtractBweStatsValue(
1033 reports, StatsReport::kStatsValueNameAvailableReceiveBandwidth));
1034 EXPECT_EQ(
1035 rtc::ToString(kPacerDelay),
1036 ExtractBweStatsValue(reports, StatsReport::kStatsValueNameBucketDelay));
Alex Narest42308f62017-06-19 15:58:121037}
1038
1039// Test that video BWE information is reported via stats.
Harald Alvestrand75ceef22018-01-04 14:26:131040TEST_P(StatsCollectorTrackTest, VideoBandwidthEstimationInfoIsReported) {
henrike@webrtc.org28e20752013-07-10 00:45:361041 // Set up an SSRC just to test that we get both kinds of stats back: SSRC and
1042 // BWE.
Steve Anton3871f6f2018-01-26 18:25:531043 constexpr int64_t kBytesSent = 12345678901234LL;
1044 constexpr int kSendBandwidth = 1234567;
1045 constexpr int kRecvBandwidth = 12345678;
1046 constexpr int kPacerDelay = 123;
henrike@webrtc.org28e20752013-07-10 00:45:361047
Steve Anton3871f6f2018-01-26 18:25:531048 auto pc = CreatePeerConnection();
Niels Möllerafb246b2022-04-20 12:26:501049 auto stats = CreateStatsCollector(pc.get());
henrike@webrtc.org28e20752013-07-10 00:45:361050
Steve Anton3871f6f2018-01-26 18:25:531051 VideoSenderInfo video_sender_info;
sergeyu@chromium.org5bc25c42013-12-05 00:24:061052 video_sender_info.add_ssrc(1234);
Niels Möllerac0a4cb2019-10-09 13:01:331053 video_sender_info.payload_bytes_sent = kBytesSent - 12;
1054 video_sender_info.header_and_padding_bytes_sent = 12;
1055
Steve Anton3871f6f2018-01-26 18:25:531056 VideoMediaInfo video_info;
Henrik Boströma0ff50c2020-05-05 13:54:461057 video_info.aggregated_senders.push_back(video_sender_info);
Steve Anton5b387312018-02-03 00:00:201058
Tommi19015512022-02-02 10:49:351059 pc->AddVideoChannel("video", "transport", video_info);
henrike@webrtc.org28e20752013-07-10 00:45:361060
Niels Möllerafb246b2022-04-20 12:26:501061 AddOutgoingVideoTrack(pc.get(), stats.get());
Steve Anton3871f6f2018-01-26 18:25:531062
1063 Call::Stats call_stats;
stefanf79ade12017-06-02 13:44:031064 call_stats.send_bandwidth_bps = kSendBandwidth;
1065 call_stats.recv_bandwidth_bps = kRecvBandwidth;
1066 call_stats.pacer_delay_ms = kPacerDelay;
Steve Anton3871f6f2018-01-26 18:25:531067 pc->SetCallStats(call_stats);
wu@webrtc.org97077a32013-10-25 21:18:331068
Steve Anton3871f6f2018-01-26 18:25:531069 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1070 StatsReports reports;
1071 stats->GetStats(nullptr, &reports);
1072
1073 EXPECT_EQ(
1074 rtc::ToString(kBytesSent),
1075 ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameBytesSent));
1076 EXPECT_EQ(rtc::ToString(kSendBandwidth),
1077 ExtractBweStatsValue(
1078 reports, StatsReport::kStatsValueNameAvailableSendBandwidth));
1079 EXPECT_EQ(
1080 rtc::ToString(kRecvBandwidth),
1081 ExtractBweStatsValue(
1082 reports, StatsReport::kStatsValueNameAvailableReceiveBandwidth));
1083 EXPECT_EQ(
1084 rtc::ToString(kPacerDelay),
1085 ExtractBweStatsValue(reports, StatsReport::kStatsValueNameBucketDelay));
henrike@webrtc.org28e20752013-07-10 00:45:361086}
1087
1088// This test verifies that an object of type "googSession" always
1089// exists in the returned stats.
Henrik Boströmf7859892022-07-04 12:36:371090TEST_F(LegacyStatsCollectorTest, SessionObjectExists) {
Steve Anton3871f6f2018-01-26 18:25:531091 auto pc = CreatePeerConnection();
Niels Möllerafb246b2022-04-20 12:26:501092 auto stats = CreateStatsCollector(pc.get());
decurtis@webrtc.org487a4442015-01-15 22:55:071093
Steve Anton3871f6f2018-01-26 18:25:531094 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1095 StatsReports reports;
1096 stats->GetStats(nullptr, &reports);
1097
1098 EXPECT_TRUE(
1099 FindNthReportByType(reports, StatsReport::kStatsReportTypeSession, 1));
henrike@webrtc.org28e20752013-07-10 00:45:361100}
1101
1102// This test verifies that only one object of type "googSession" exists
1103// in the returned stats.
Henrik Boströmf7859892022-07-04 12:36:371104TEST_F(LegacyStatsCollectorTest, OnlyOneSessionObjectExists) {
Steve Anton3871f6f2018-01-26 18:25:531105 auto pc = CreatePeerConnection();
Niels Möllerafb246b2022-04-20 12:26:501106 auto stats = CreateStatsCollector(pc.get());
decurtis@webrtc.org487a4442015-01-15 22:55:071107
Steve Anton3871f6f2018-01-26 18:25:531108 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1109 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1110 StatsReports reports;
1111 stats->GetStats(nullptr, &reports);
1112
1113 EXPECT_TRUE(
1114 FindNthReportByType(reports, StatsReport::kStatsReportTypeSession, 1));
1115 EXPECT_FALSE(
1116 FindNthReportByType(reports, StatsReport::kStatsReportTypeSession, 2));
henrike@webrtc.org28e20752013-07-10 00:45:361117}
1118
1119// This test verifies that the empty track report exists in the returned stats
1120// without calling StatsCollector::UpdateStats.
Harald Alvestrand75ceef22018-01-04 14:26:131121TEST_P(StatsCollectorTrackTest, TrackObjectExistsWithoutUpdateStats) {
Steve Anton3871f6f2018-01-26 18:25:531122 auto pc = CreatePeerConnection();
Niels Möllerafb246b2022-04-20 12:26:501123 auto stats = CreateStatsCollector(pc.get());
decurtis@webrtc.org487a4442015-01-15 22:55:071124
Steve Anton5b387312018-02-03 00:00:201125 pc->AddVideoChannel("video", "transport");
Niels Möllerafb246b2022-04-20 12:26:501126 AddOutgoingVideoTrack(pc.get(), stats.get());
henrike@webrtc.org28e20752013-07-10 00:45:361127
henrike@webrtc.org28e20752013-07-10 00:45:361128 // Verfies the existence of the track report.
tommi@webrtc.org03505bc2014-07-14 20:15:261129 StatsReports reports;
Steve Anton3871f6f2018-01-26 18:25:531130 stats->GetStats(nullptr, &reports);
1131 ASSERT_EQ(1u, reports.size());
tommi@webrtc.org4fb7e252015-01-21 11:36:181132 EXPECT_EQ(StatsReport::kStatsReportTypeTrack, reports[0]->type());
jbauchbe24c942015-06-22 22:06:431133 EXPECT_EQ(0, reports[0]->timestamp());
henrike@webrtc.org28e20752013-07-10 00:45:361134
1135 std::string trackValue =
Yves Gerey665174f2018-06-19 13:03:051136 ExtractStatsValue(StatsReport::kStatsReportTypeTrack, reports,
henrike@webrtc.org40b3b682014-03-03 18:30:111137 StatsReport::kStatsValueNameTrackId);
xians@webrtc.org4cb01282014-06-12 14:57:051138 EXPECT_EQ(kLocalTrackId, trackValue);
henrike@webrtc.org28e20752013-07-10 00:45:361139}
1140
1141// This test verifies that the empty track report exists in the returned stats
1142// when StatsCollector::UpdateStats is called with ssrc stats.
Harald Alvestrand75ceef22018-01-04 14:26:131143TEST_P(StatsCollectorTrackTest, TrackAndSsrcObjectExistAfterUpdateSsrcStats) {
Steve Anton3871f6f2018-01-26 18:25:531144 constexpr int64_t kBytesSent = 12345678901234LL;
decurtis@webrtc.org487a4442015-01-15 22:55:071145
Steve Anton3871f6f2018-01-26 18:25:531146 auto pc = CreatePeerConnection();
Niels Möllerafb246b2022-04-20 12:26:501147 auto stats = CreateStatsCollector(pc.get());
deadbeefcbecd352015-09-23 18:50:271148
Steve Anton3871f6f2018-01-26 18:25:531149 VideoSenderInfo video_sender_info;
sergeyu@chromium.org5bc25c42013-12-05 00:24:061150 video_sender_info.add_ssrc(1234);
Niels Möllerac0a4cb2019-10-09 13:01:331151 video_sender_info.payload_bytes_sent = kBytesSent - 12;
1152 video_sender_info.header_and_padding_bytes_sent = 12;
Steve Anton3871f6f2018-01-26 18:25:531153 VideoMediaInfo video_info;
Henrik Boströma0ff50c2020-05-05 13:54:461154 video_info.aggregated_senders.push_back(video_sender_info);
Steve Anton5b387312018-02-03 00:00:201155
Tommi19015512022-02-02 10:49:351156 pc->AddVideoChannel("video", "transport", video_info);
henrike@webrtc.org28e20752013-07-10 00:45:361157
Niels Möllerafb246b2022-04-20 12:26:501158 AddOutgoingVideoTrack(pc.get(), stats.get());
henrike@webrtc.org28e20752013-07-10 00:45:361159
Steve Anton3871f6f2018-01-26 18:25:531160 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
tommi@webrtc.org03505bc2014-07-14 20:15:261161 StatsReports reports;
Steve Anton3871f6f2018-01-26 18:25:531162 stats->GetStats(nullptr, &reports);
1163
Artem Titov880fa812021-07-30 20:30:231164 // `reports` should contain at least one session report, one track report,
wu@webrtc.org97077a32013-10-25 21:18:331165 // and one ssrc report.
Steve Anton3871f6f2018-01-26 18:25:531166 EXPECT_LE(3u, reports.size());
Yves Gerey665174f2018-06-19 13:03:051167 const StatsReport* track_report =
1168 FindNthReportByType(reports, StatsReport::kStatsReportTypeTrack, 1);
xians@webrtc.org4cb01282014-06-12 14:57:051169 EXPECT_TRUE(track_report);
henrike@webrtc.org28e20752013-07-10 00:45:361170
Artem Titov880fa812021-07-30 20:30:231171 // Get report for the specific `track`.
tommi@webrtc.org5b06b062014-08-15 08:38:301172 reports.clear();
Harald Alvestrand2f7ad282022-04-21 11:35:431173 stats->GetStats(video_track_.get(), &reports);
Artem Titov880fa812021-07-30 20:30:231174 // `reports` should contain at least one session report, one track report,
wu@webrtc.org97077a32013-10-25 21:18:331175 // and one ssrc report.
Steve Anton3871f6f2018-01-26 18:25:531176 EXPECT_LE(3u, reports.size());
Yves Gerey665174f2018-06-19 13:03:051177 track_report =
1178 FindNthReportByType(reports, StatsReport::kStatsReportTypeTrack, 1);
Harald Alvestrand75ceef22018-01-04 14:26:131179 ASSERT_TRUE(track_report);
Steve Anton3871f6f2018-01-26 18:25:531180 EXPECT_EQ(stats->GetTimeNow(), track_report->timestamp());
henrike@webrtc.org28e20752013-07-10 00:45:361181
Yves Gerey665174f2018-06-19 13:03:051182 std::string ssrc_id =
1183 ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameSsrc);
Jonas Olsson6b1985d2018-07-05 09:59:481184 EXPECT_EQ(rtc::ToString(kSsrcOfTrack), ssrc_id);
henrike@webrtc.org28e20752013-07-10 00:45:361185
Yves Gerey665174f2018-06-19 13:03:051186 std::string track_id =
1187 ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameTrackId);
xians@webrtc.org4cb01282014-06-12 14:57:051188 EXPECT_EQ(kLocalTrackId, track_id);
fippobec70ab2016-01-28 09:27:151189
Yves Gerey665174f2018-06-19 13:03:051190 std::string media_type =
1191 ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameMediaType);
fippobec70ab2016-01-28 09:27:151192 EXPECT_EQ("video", media_type);
henrike@webrtc.org28e20752013-07-10 00:45:361193}
1194
1195// This test verifies that an SSRC object has the identifier of a Transport
1196// stats object, and that this transport stats object exists in stats.
Harald Alvestrand75ceef22018-01-04 14:26:131197TEST_P(StatsCollectorTrackTest, TransportObjectLinkedFromSsrcObject) {
Steve Anton3871f6f2018-01-26 18:25:531198 constexpr int64_t kBytesSent = 12345678901234LL;
decurtis@webrtc.org487a4442015-01-15 22:55:071199
Steve Anton3871f6f2018-01-26 18:25:531200 auto pc = CreatePeerConnection();
Niels Möllerafb246b2022-04-20 12:26:501201 auto stats = CreateStatsCollector(pc.get());
deadbeefcbecd352015-09-23 18:50:271202
Steve Anton3871f6f2018-01-26 18:25:531203 VideoSenderInfo video_sender_info;
sergeyu@chromium.org5bc25c42013-12-05 00:24:061204 video_sender_info.add_ssrc(1234);
Niels Möllerac0a4cb2019-10-09 13:01:331205 video_sender_info.payload_bytes_sent = kBytesSent - 12;
1206 video_sender_info.header_and_padding_bytes_sent = 12;
Steve Anton3871f6f2018-01-26 18:25:531207 VideoMediaInfo video_info;
Henrik Boströma0ff50c2020-05-05 13:54:461208 video_info.aggregated_senders.push_back(video_sender_info);
Steve Anton5b387312018-02-03 00:00:201209
Tommi19015512022-02-02 10:49:351210 pc->AddVideoChannel("video", "transport", video_info);
henrike@webrtc.org28e20752013-07-10 00:45:361211
Niels Möllerafb246b2022-04-20 12:26:501212 AddOutgoingVideoTrack(pc.get(), stats.get());
henrike@webrtc.org28e20752013-07-10 00:45:361213
Steve Anton3871f6f2018-01-26 18:25:531214 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
tommi@webrtc.org03505bc2014-07-14 20:15:261215 StatsReports reports;
Steve Anton3871f6f2018-01-26 18:25:531216 stats->GetStats(nullptr, &reports);
1217
Yves Gerey665174f2018-06-19 13:03:051218 std::string transport_id =
1219 ExtractStatsValue(StatsReport::kStatsReportTypeSsrc, reports,
1220 StatsReport::kStatsValueNameTransportId);
henrike@webrtc.org28e20752013-07-10 00:45:361221 ASSERT_NE(kNotFound, transport_id);
Steve Anton3871f6f2018-01-26 18:25:531222
tommi@webrtc.org4fb7e252015-01-21 11:36:181223 // Transport id component ID will always be 1.
1224 // This has assumptions about how the ID is constructed. As is, this is
1225 // OK since this is for testing purposes only, but if we ever need this
1226 // in production, we should add a generic method that does this.
1227 size_t index = transport_id.find('-');
1228 ASSERT_NE(std::string::npos, index);
1229 std::string content = transport_id.substr(index + 1);
1230 index = content.rfind('-');
1231 ASSERT_NE(std::string::npos, index);
1232 content = content.substr(0, index);
tommi@webrtc.orgd3900292015-03-12 16:35:551233 StatsReport::Id id(StatsReport::NewComponentId(content, 1));
tommi@webrtc.org4fb7e252015-01-21 11:36:181234 ASSERT_EQ(transport_id, id->ToString());
tommi@webrtc.orgd3900292015-03-12 16:35:551235 const StatsReport* transport_report = FindReportById(reports, id);
Steve Anton3871f6f2018-01-26 18:25:531236 ASSERT_TRUE(transport_report);
henrike@webrtc.org28e20752013-07-10 00:45:361237}
1238
wu@webrtc.org97077a32013-10-25 21:18:331239// This test verifies that a remote stats object will not be created for
1240// an outgoing SSRC where remote stats are not returned.
Harald Alvestrand75ceef22018-01-04 14:26:131241TEST_P(StatsCollectorTrackTest, RemoteSsrcInfoIsAbsent) {
Steve Anton3871f6f2018-01-26 18:25:531242 auto pc = CreatePeerConnection();
Niels Möllerafb246b2022-04-20 12:26:501243 auto stats = CreateStatsCollector(pc.get());
decurtis@webrtc.org487a4442015-01-15 22:55:071244
Steve Anton5b387312018-02-03 00:00:201245 pc->AddVideoChannel("video", "transport");
Niels Möllerafb246b2022-04-20 12:26:501246 AddOutgoingVideoTrack(pc.get(), stats.get());
wu@webrtc.org97077a32013-10-25 21:18:331247
Steve Anton3871f6f2018-01-26 18:25:531248 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
henrike@webrtc.org40b3b682014-03-03 18:30:111249 StatsReports reports;
Steve Anton3871f6f2018-01-26 18:25:531250 stats->GetStats(nullptr, &reports);
1251
Yves Gerey665174f2018-06-19 13:03:051252 const StatsReport* remote_report =
1253 FindNthReportByType(reports, StatsReport::kStatsReportTypeRemoteSsrc, 1);
Steve Anton3871f6f2018-01-26 18:25:531254 EXPECT_FALSE(remote_report);
wu@webrtc.org97077a32013-10-25 21:18:331255}
1256
1257// This test verifies that a remote stats object will be created for
1258// an outgoing SSRC where stats are returned.
Harald Alvestrand75ceef22018-01-04 14:26:131259TEST_P(StatsCollectorTrackTest, RemoteSsrcInfoIsPresent) {
Steve Anton3871f6f2018-01-26 18:25:531260 auto pc = CreatePeerConnection();
Niels Möllerafb246b2022-04-20 12:26:501261 auto stats = CreateStatsCollector(pc.get());
decurtis@webrtc.org487a4442015-01-15 22:55:071262
Steve Anton3871f6f2018-01-26 18:25:531263 SsrcReceiverInfo remote_ssrc_stats;
wu@webrtc.org97077a32013-10-25 21:18:331264 remote_ssrc_stats.timestamp = 12345.678;
1265 remote_ssrc_stats.ssrc = kSsrcOfTrack;
Steve Anton3871f6f2018-01-26 18:25:531266 VideoSenderInfo video_sender_info;
sergeyu@chromium.org5bc25c42013-12-05 00:24:061267 video_sender_info.add_ssrc(kSsrcOfTrack);
wu@webrtc.org97077a32013-10-25 21:18:331268 video_sender_info.remote_stats.push_back(remote_ssrc_stats);
Steve Anton3871f6f2018-01-26 18:25:531269 VideoMediaInfo video_info;
Henrik Boströma0ff50c2020-05-05 13:54:461270 video_info.aggregated_senders.push_back(video_sender_info);
Steve Anton5b387312018-02-03 00:00:201271
Tommi19015512022-02-02 10:49:351272 pc->AddVideoChannel("video", "transport", video_info);
wu@webrtc.org97077a32013-10-25 21:18:331273
Niels Möllerafb246b2022-04-20 12:26:501274 AddOutgoingVideoTrack(pc.get(), stats.get());
wu@webrtc.org97077a32013-10-25 21:18:331275
Steve Anton3871f6f2018-01-26 18:25:531276 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
tommi@webrtc.org03505bc2014-07-14 20:15:261277 StatsReports reports;
Steve Anton3871f6f2018-01-26 18:25:531278 stats->GetStats(nullptr, &reports);
xians@webrtc.org4cb01282014-06-12 14:57:051279
Yves Gerey665174f2018-06-19 13:03:051280 const StatsReport* remote_report =
1281 FindNthReportByType(reports, StatsReport::kStatsReportTypeRemoteSsrc, 1);
Steve Anton3871f6f2018-01-26 18:25:531282 ASSERT_TRUE(remote_report);
decurtis@webrtc.org322a5642015-02-03 22:09:371283 EXPECT_EQ(12345.678, remote_report->timestamp());
wu@webrtc.org97077a32013-10-25 21:18:331284}
1285
xians@webrtc.org4cb01282014-06-12 14:57:051286// This test verifies that the empty track report exists in the returned stats
1287// when StatsCollector::UpdateStats is called with ssrc stats.
Harald Alvestrand75ceef22018-01-04 14:26:131288TEST_P(StatsCollectorTrackTest, ReportsFromRemoteTrack) {
Steve Anton3871f6f2018-01-26 18:25:531289 constexpr int64_t kNumOfPacketsConcealed = 54321;
decurtis@webrtc.org487a4442015-01-15 22:55:071290
Steve Anton3871f6f2018-01-26 18:25:531291 auto pc = CreatePeerConnection();
Niels Möllerafb246b2022-04-20 12:26:501292 auto stats = CreateStatsCollector(pc.get());
deadbeefcbecd352015-09-23 18:50:271293
Steve Anton3871f6f2018-01-26 18:25:531294 VideoReceiverInfo video_receiver_info;
xians@webrtc.org4cb01282014-06-12 14:57:051295 video_receiver_info.add_ssrc(1234);
pbos@webrtc.org1ed62242015-02-19 13:57:031296 video_receiver_info.packets_concealed = kNumOfPacketsConcealed;
Steve Anton3871f6f2018-01-26 18:25:531297 VideoMediaInfo video_info;
1298 video_info.receivers.push_back(video_receiver_info);
Steve Anton5b387312018-02-03 00:00:201299
Tommi19015512022-02-02 10:49:351300 pc->AddVideoChannel("video", "transport", video_info);
xians@webrtc.org4cb01282014-06-12 14:57:051301
Niels Möllerafb246b2022-04-20 12:26:501302 AddIncomingVideoTrack(pc.get(), stats.get());
xians@webrtc.org4cb01282014-06-12 14:57:051303
Steve Anton3871f6f2018-01-26 18:25:531304 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
tommi@webrtc.org03505bc2014-07-14 20:15:261305 StatsReports reports;
Steve Anton3871f6f2018-01-26 18:25:531306 stats->GetStats(nullptr, &reports);
1307
Artem Titov880fa812021-07-30 20:30:231308 // `reports` should contain at least one session report, one track report,
xians@webrtc.org4cb01282014-06-12 14:57:051309 // and one ssrc report.
Steve Anton3871f6f2018-01-26 18:25:531310 EXPECT_LE(3u, reports.size());
Yves Gerey665174f2018-06-19 13:03:051311 const StatsReport* track_report =
1312 FindNthReportByType(reports, StatsReport::kStatsReportTypeTrack, 1);
Harald Alvestrand75ceef22018-01-04 14:26:131313 ASSERT_TRUE(track_report);
Steve Anton3871f6f2018-01-26 18:25:531314 EXPECT_EQ(stats->GetTimeNow(), track_report->timestamp());
xians@webrtc.org4cb01282014-06-12 14:57:051315
Yves Gerey665174f2018-06-19 13:03:051316 std::string ssrc_id =
1317 ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameSsrc);
Jonas Olsson6b1985d2018-07-05 09:59:481318 EXPECT_EQ(rtc::ToString(kSsrcOfTrack), ssrc_id);
xians@webrtc.org4cb01282014-06-12 14:57:051319
Yves Gerey665174f2018-06-19 13:03:051320 std::string track_id =
1321 ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameTrackId);
xians@webrtc.org4cb01282014-06-12 14:57:051322 EXPECT_EQ(kRemoteTrackId, track_id);
1323}
1324
guoweis@webrtc.org950c5182014-12-16 23:01:311325// This test verifies the Ice Candidate report should contain the correct
1326// information from local/remote candidates.
Henrik Boströmf7859892022-07-04 12:36:371327TEST_F(LegacyStatsCollectorTest, IceCandidateReport) {
Steve Anton3871f6f2018-01-26 18:25:531328 const std::string kTransportName = "transport";
1329 const rtc::AdapterType kNetworkType = rtc::ADAPTER_TYPE_ETHERNET;
1330 constexpr uint32_t kPriority = 1000;
decurtis@webrtc.org487a4442015-01-15 22:55:071331
Steve Anton3871f6f2018-01-26 18:25:531332 constexpr int kLocalPort = 2000;
1333 const std::string kLocalIp = "192.168.0.1";
1334 const rtc::SocketAddress kLocalAddress(kLocalIp, kLocalPort);
guoweis@webrtc.org950c5182014-12-16 23:01:311335
Steve Anton3871f6f2018-01-26 18:25:531336 constexpr int kRemotePort = 2001;
1337 const std::string kRemoteIp = "192.168.0.2";
1338 const rtc::SocketAddress kRemoteAddress(kRemoteIp, kRemotePort);
guoweis@webrtc.org950c5182014-12-16 23:01:311339
Steve Anton3871f6f2018-01-26 18:25:531340 auto pc = CreatePeerConnection();
Niels Möllerafb246b2022-04-20 12:26:501341 auto stats = CreateStatsCollector(pc.get());
guoweis@webrtc.org950c5182014-12-16 23:01:311342
Steve Anton3871f6f2018-01-26 18:25:531343 cricket::Candidate local;
1344 EXPECT_GT(local.id().length(), 0u);
1345 local.set_type(cricket::LOCAL_PORT_TYPE);
1346 local.set_protocol(cricket::UDP_PROTOCOL_NAME);
1347 local.set_address(kLocalAddress);
1348 local.set_priority(kPriority);
1349 local.set_network_type(kNetworkType);
guoweis@webrtc.org950c5182014-12-16 23:01:311350
Steve Anton3871f6f2018-01-26 18:25:531351 cricket::Candidate remote;
1352 EXPECT_GT(remote.id().length(), 0u);
1353 remote.set_type(cricket::PRFLX_PORT_TYPE);
1354 remote.set_protocol(cricket::UDP_PROTOCOL_NAME);
1355 remote.set_address(kRemoteAddress);
1356 remote.set_priority(kPriority);
1357 remote.set_network_type(kNetworkType);
guoweis@webrtc.org950c5182014-12-16 23:01:311358
Steve Anton3871f6f2018-01-26 18:25:531359 ConnectionInfo connection_info;
1360 connection_info.local_candidate = local;
1361 connection_info.remote_candidate = remote;
1362 TransportChannelStats channel_stats;
Jonas Oreland149dc722019-08-28 06:10:271363 channel_stats.ice_transport_stats.connection_infos.push_back(connection_info);
Steve Anton3871f6f2018-01-26 18:25:531364
Steve Anton5b387312018-02-03 00:00:201365 pc->AddVoiceChannel("audio", kTransportName);
Steve Anton3871f6f2018-01-26 18:25:531366 pc->SetTransportStats(kTransportName, channel_stats);
1367
1368 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1369 StatsReports reports;
1370 stats->GetStats(nullptr, &reports);
guoweis@webrtc.org950c5182014-12-16 23:01:311371
1372 // Verify the local candidate report is populated correctly.
1373 EXPECT_EQ(
Steve Anton3871f6f2018-01-26 18:25:531374 "Cand-" + local.id(),
1375 ExtractStatsValue(StatsReport::kStatsReportTypeCandidatePair, reports,
1376 StatsReport::kStatsValueNameLocalCandidateId));
1377 EXPECT_EQ(
1378 kLocalIp,
guoweis@webrtc.org950c5182014-12-16 23:01:311379 ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports,
1380 StatsReport::kStatsValueNameCandidateIPAddress));
1381 EXPECT_EQ(
Steve Anton3871f6f2018-01-26 18:25:531382 rtc::ToString(kLocalPort),
guoweis@webrtc.org950c5182014-12-16 23:01:311383 ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports,
1384 StatsReport::kStatsValueNameCandidatePortNumber));
1385 EXPECT_EQ(
1386 cricket::UDP_PROTOCOL_NAME,
1387 ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports,
1388 StatsReport::kStatsValueNameCandidateTransportType));
1389 EXPECT_EQ(
Steve Anton3871f6f2018-01-26 18:25:531390 rtc::ToString(kPriority),
guoweis@webrtc.org950c5182014-12-16 23:01:311391 ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports,
1392 StatsReport::kStatsValueNameCandidatePriority));
1393 EXPECT_EQ(
1394 IceCandidateTypeToStatsType(cricket::LOCAL_PORT_TYPE),
1395 ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports,
1396 StatsReport::kStatsValueNameCandidateType));
1397 EXPECT_EQ(
Steve Anton3871f6f2018-01-26 18:25:531398 AdapterTypeToStatsType(kNetworkType),
guoweis@webrtc.org950c5182014-12-16 23:01:311399 ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports,
1400 StatsReport::kStatsValueNameCandidateNetworkType));
1401
1402 // Verify the remote candidate report is populated correctly.
Steve Anton3871f6f2018-01-26 18:25:531403 EXPECT_EQ(
1404 "Cand-" + remote.id(),
1405 ExtractStatsValue(StatsReport::kStatsReportTypeCandidatePair, reports,
1406 StatsReport::kStatsValueNameRemoteCandidateId));
1407 EXPECT_EQ(kRemoteIp,
guoweis@webrtc.org950c5182014-12-16 23:01:311408 ExtractStatsValue(StatsReport::kStatsReportTypeIceRemoteCandidate,
1409 reports,
1410 StatsReport::kStatsValueNameCandidateIPAddress));
Steve Anton3871f6f2018-01-26 18:25:531411 EXPECT_EQ(rtc::ToString(kRemotePort),
guoweis@webrtc.org950c5182014-12-16 23:01:311412 ExtractStatsValue(StatsReport::kStatsReportTypeIceRemoteCandidate,
1413 reports,
1414 StatsReport::kStatsValueNameCandidatePortNumber));
1415 EXPECT_EQ(cricket::UDP_PROTOCOL_NAME,
1416 ExtractStatsValue(
1417 StatsReport::kStatsReportTypeIceRemoteCandidate, reports,
1418 StatsReport::kStatsValueNameCandidateTransportType));
Steve Anton3871f6f2018-01-26 18:25:531419 EXPECT_EQ(rtc::ToString(kPriority),
guoweis@webrtc.org950c5182014-12-16 23:01:311420 ExtractStatsValue(StatsReport::kStatsReportTypeIceRemoteCandidate,
1421 reports,
1422 StatsReport::kStatsValueNameCandidatePriority));
1423 EXPECT_EQ(
1424 IceCandidateTypeToStatsType(cricket::PRFLX_PORT_TYPE),
1425 ExtractStatsValue(StatsReport::kStatsReportTypeIceRemoteCandidate,
1426 reports, StatsReport::kStatsValueNameCandidateType));
1427 EXPECT_EQ(kNotFound,
1428 ExtractStatsValue(
1429 StatsReport::kStatsReportTypeIceRemoteCandidate, reports,
1430 StatsReport::kStatsValueNameCandidateNetworkType));
1431}
1432
wu@webrtc.org4551b792013-10-09 15:37:361433// This test verifies that all chained certificates are correctly
1434// reported
Henrik Boströmf7859892022-07-04 12:36:371435TEST_F(LegacyStatsCollectorTest, ChainedCertificateReportsCreated) {
wu@webrtc.org4551b792013-10-09 15:37:361436 // Build local certificate chain.
1437 std::vector<std::string> local_ders(5);
1438 local_ders[0] = "These";
1439 local_ders[1] = "are";
1440 local_ders[2] = "some";
1441 local_ders[3] = "der";
1442 local_ders[4] = "values";
Taylor Brandstetterc3928662018-02-23 21:04:511443 rtc::FakeSSLIdentity local_identity(DersToPems(local_ders));
wu@webrtc.org4551b792013-10-09 15:37:361444
1445 // Build remote certificate chain
1446 std::vector<std::string> remote_ders(4);
1447 remote_ders[0] = "A";
1448 remote_ders[1] = "non-";
1449 remote_ders[2] = "intersecting";
1450 remote_ders[3] = "set";
Taylor Brandstetterc3928662018-02-23 21:04:511451 rtc::FakeSSLIdentity remote_identity(DersToPems(remote_ders));
wu@webrtc.org4551b792013-10-09 15:37:361452
Taylor Brandstetterc3928662018-02-23 21:04:511453 TestCertificateReports(local_identity, local_ders, remote_identity,
kwibergb4d01c42016-04-06 12:15:061454 remote_ders);
wu@webrtc.org4551b792013-10-09 15:37:361455}
1456
1457// This test verifies that all certificates without chains are correctly
1458// reported.
Henrik Boströmf7859892022-07-04 12:36:371459TEST_F(LegacyStatsCollectorTest, ChainlessCertificateReportsCreated) {
wu@webrtc.org4551b792013-10-09 15:37:361460 // Build local certificate.
1461 std::string local_der = "This is the local der.";
Taylor Brandstetterc3928662018-02-23 21:04:511462 rtc::FakeSSLIdentity local_identity(DerToPem(local_der));
wu@webrtc.org4551b792013-10-09 15:37:361463
1464 // Build remote certificate.
1465 std::string remote_der = "This is somebody else's der.";
Taylor Brandstetterc3928662018-02-23 21:04:511466 rtc::FakeSSLIdentity remote_identity(DerToPem(remote_der));
wu@webrtc.org4551b792013-10-09 15:37:361467
Taylor Brandstetterc3928662018-02-23 21:04:511468 TestCertificateReports(local_identity, std::vector<std::string>(1, local_der),
1469 remote_identity,
kwibergb4d01c42016-04-06 12:15:061470 std::vector<std::string>(1, remote_der));
wu@webrtc.org4551b792013-10-09 15:37:361471}
1472
1473// This test verifies that the stats are generated correctly when no
1474// transport is present.
Henrik Boströmf7859892022-07-04 12:36:371475TEST_F(LegacyStatsCollectorTest, NoTransport) {
Steve Anton3871f6f2018-01-26 18:25:531476 auto pc = CreatePeerConnection();
Niels Möllerafb246b2022-04-20 12:26:501477 auto stats = CreateStatsCollector(pc.get());
decurtis@webrtc.org487a4442015-01-15 22:55:071478
Steve Anton3871f6f2018-01-26 18:25:531479 // This will cause the fake PeerConnection to generate a TransportStats entry
1480 // but with only a single dummy TransportChannelStats.
Steve Anton5b387312018-02-03 00:00:201481 pc->AddVoiceChannel("audio", "transport");
deadbeefcbecd352015-09-23 18:50:271482
Steve Anton3871f6f2018-01-26 18:25:531483 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1484 StatsReports reports;
1485 stats->GetStats(nullptr, &reports);
wu@webrtc.org4551b792013-10-09 15:37:361486
1487 // Check that the local certificate is absent.
Yves Gerey665174f2018-06-19 13:03:051488 std::string local_certificate_id =
1489 ExtractStatsValue(StatsReport::kStatsReportTypeComponent, reports,
1490 StatsReport::kStatsValueNameLocalCertificateId);
wu@webrtc.org4551b792013-10-09 15:37:361491 ASSERT_EQ(kNotFound, local_certificate_id);
1492
1493 // Check that the remote certificate is absent.
Yves Gerey665174f2018-06-19 13:03:051494 std::string remote_certificate_id =
1495 ExtractStatsValue(StatsReport::kStatsReportTypeComponent, reports,
1496 StatsReport::kStatsValueNameRemoteCertificateId);
wu@webrtc.org4551b792013-10-09 15:37:361497 ASSERT_EQ(kNotFound, remote_certificate_id);
pthatcher@webrtc.org7bea1ff2015-03-04 01:38:301498
1499 // Check that the negotiated ciphers are absent.
Guo-wei Shieh521ed7b2015-11-19 03:41:531500 std::string dtls_cipher_suite =
1501 ExtractStatsValue(StatsReport::kStatsReportTypeComponent, reports,
1502 StatsReport::kStatsValueNameDtlsCipher);
1503 ASSERT_EQ(kNotFound, dtls_cipher_suite);
1504 std::string srtp_crypto_suite =
1505 ExtractStatsValue(StatsReport::kStatsReportTypeComponent, reports,
1506 StatsReport::kStatsValueNameSrtpCipher);
1507 ASSERT_EQ(kNotFound, srtp_crypto_suite);
wu@webrtc.org4551b792013-10-09 15:37:361508}
1509
wu@webrtc.orgb9a088b2014-02-13 23:18:491510// This test verifies that a remote certificate with an unsupported digest
1511// algorithm is correctly ignored.
Henrik Boströmf7859892022-07-04 12:36:371512TEST_F(LegacyStatsCollectorTest, UnsupportedDigestIgnored) {
wu@webrtc.orgb9a088b2014-02-13 23:18:491513 // Build a local certificate.
1514 std::string local_der = "This is the local der.";
Taylor Brandstetterc3928662018-02-23 21:04:511515 rtc::FakeSSLIdentity local_identity(DerToPem(local_der));
wu@webrtc.orgb9a088b2014-02-13 23:18:491516
1517 // Build a remote certificate with an unsupported digest algorithm.
1518 std::string remote_der = "This is somebody else's der.";
Taylor Brandstetterc3928662018-02-23 21:04:511519 rtc::FakeSSLCertificate remote_cert(DerToPem(remote_der));
1520 remote_cert.set_digest_algorithm("foobar");
1521 rtc::FakeSSLIdentity remote_identity(remote_cert);
wu@webrtc.orgb9a088b2014-02-13 23:18:491522
Taylor Brandstetterc3928662018-02-23 21:04:511523 TestCertificateReports(local_identity, std::vector<std::string>(1, local_der),
1524 remote_identity, std::vector<std::string>());
wu@webrtc.orgb9a088b2014-02-13 23:18:491525}
1526
zhihuang6ba3b192016-05-13 18:46:351527// This test verifies that the audio/video related stats which are -1 initially
1528// will be filtered out.
Harald Alvestrand75ceef22018-01-04 14:26:131529TEST_P(StatsCollectorTrackTest, FilterOutNegativeInitialValues) {
Harald Alvestrand75ceef22018-01-04 14:26:131530 // This test uses streams, but only works for the stream case.
Steve Anton3871f6f2018-01-26 18:25:531531 if (!GetParam()) {
Harald Alvestrand75ceef22018-01-04 14:26:131532 return;
Steve Anton3871f6f2018-01-26 18:25:531533 }
zhihuang6ba3b192016-05-13 18:46:351534
Steve Anton3871f6f2018-01-26 18:25:531535 auto pc = CreatePeerConnection();
Niels Möllerafb246b2022-04-20 12:26:501536 auto stats = CreateStatsCollector(pc.get());
zhihuang6ba3b192016-05-13 18:46:351537
1538 // Create a local stream with a local audio track and adds it to the stats.
Seth Hampson845e8782018-03-02 19:34:101539 stream_ = MediaStream::Create("streamid");
Tommi87f70902021-04-27 12:43:081540 auto local_track =
1541 rtc::make_ref_counted<FakeAudioTrackWithInitValue>(kLocalTrackId);
Harald Alvestrand2f7ad282022-04-21 11:35:431542 stream_->AddTrack(rtc::scoped_refptr<AudioTrackInterface>(local_track.get()));
Steve Antonefe4c922019-03-27 17:26:061543 pc->AddSender(CreateMockSender(local_track, kSsrcOfTrack));
Harald Alvestrand75ceef22018-01-04 14:26:131544 if (GetParam()) {
Niels Möllerafb246b2022-04-20 12:26:501545 stats->AddStream(stream_.get());
Harald Alvestrand75ceef22018-01-04 14:26:131546 }
Steve Anton3871f6f2018-01-26 18:25:531547 stats->AddLocalAudioTrack(local_track.get(), kSsrcOfTrack);
zhihuang6ba3b192016-05-13 18:46:351548
1549 // Create a remote stream with a remote audio track and adds it to the stats.
Steve Anton3871f6f2018-01-26 18:25:531550 rtc::scoped_refptr<MediaStream> remote_stream(
Seth Hampson845e8782018-03-02 19:34:101551 MediaStream::Create("remotestreamid"));
Harald Alvestrand2f7ad282022-04-21 11:35:431552 rtc::scoped_refptr<AudioTrackInterface> remote_track =
Tommi87f70902021-04-27 12:43:081553 rtc::make_ref_counted<FakeAudioTrackWithInitValue>(kRemoteTrackId);
Harald Alvestrand2f7ad282022-04-21 11:35:431554 remote_stream->AddTrack(remote_track);
Steve Antonefe4c922019-03-27 17:26:061555 pc->AddReceiver(CreateMockReceiver(remote_track, kSsrcOfTrack));
Harald Alvestrand75ceef22018-01-04 14:26:131556 if (GetParam()) {
Niels Möllerafb246b2022-04-20 12:26:501557 stats->AddStream(remote_stream.get());
Harald Alvestrand75ceef22018-01-04 14:26:131558 }
zhihuang6ba3b192016-05-13 18:46:351559
Steve Anton3871f6f2018-01-26 18:25:531560 VoiceSenderInfo voice_sender_info;
zhihuang6ba3b192016-05-13 18:46:351561 voice_sender_info.add_ssrc(kSsrcOfTrack);
1562 // These values are set to -1 initially in audio_send_stream.
1563 // The voice_sender_info will read the values from audio_send_stream.
1564 voice_sender_info.rtt_ms = -1;
1565 voice_sender_info.packets_lost = -1;
1566 voice_sender_info.jitter_ms = -1;
1567
Artem Titov880fa812021-07-30 20:30:231568 // Some of the contents in `voice_sender_info` needs to be updated from the
1569 // `audio_track_`.
Ivo Creusen56d460902017-11-24 16:29:591570 UpdateVoiceSenderInfoFromAudioTrack(local_track.get(), &voice_sender_info,
1571 true);
zhihuang6ba3b192016-05-13 18:46:351572
Steve Anton3871f6f2018-01-26 18:25:531573 VoiceReceiverInfo voice_receiver_info;
zhihuang6ba3b192016-05-13 18:46:351574 voice_receiver_info.add_ssrc(kSsrcOfTrack);
1575 voice_receiver_info.capture_start_ntp_time_ms = -1;
1576 voice_receiver_info.audio_level = -1;
1577
1578 // Constructs an ssrc stats update.
Steve Anton3871f6f2018-01-26 18:25:531579 VoiceMediaInfo voice_info;
1580 voice_info.senders.push_back(voice_sender_info);
1581 voice_info.receivers.push_back(voice_receiver_info);
zhihuang6ba3b192016-05-13 18:46:351582
Harald Alvestrand2f553702023-03-07 10:10:031583 auto voice_media_channels = pc->AddVoiceChannel("voice", "transport");
1584 voice_media_channels.first->SetStats(voice_info);
1585 voice_media_channels.second->SetStats(voice_info);
zhihuang6ba3b192016-05-13 18:46:351586
Steve Anton3871f6f2018-01-26 18:25:531587 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
zhihuang6ba3b192016-05-13 18:46:351588
1589 // Get stats for the local track.
Steve Anton3871f6f2018-01-26 18:25:531590 StatsReports reports;
1591 stats->GetStats(local_track.get(), &reports);
zhihuang6ba3b192016-05-13 18:46:351592 const StatsReport* report =
1593 FindNthReportByType(reports, StatsReport::kStatsReportTypeSsrc, 1);
Harald Alvestrand75ceef22018-01-04 14:26:131594 ASSERT_TRUE(report);
zhihuang6ba3b192016-05-13 18:46:351595 // The -1 will not be added to the stats report.
1596 std::string value_in_report;
1597 EXPECT_FALSE(
1598 GetValue(report, StatsReport::kStatsValueNameRtt, &value_in_report));
1599 EXPECT_FALSE(GetValue(report, StatsReport::kStatsValueNamePacketsLost,
1600 &value_in_report));
1601 EXPECT_FALSE(GetValue(report, StatsReport::kStatsValueNameJitterReceived,
1602 &value_in_report));
zhihuang6ba3b192016-05-13 18:46:351603 EXPECT_FALSE(GetValue(report, StatsReport::kStatsValueNameEchoDelayMedian,
1604 &value_in_report));
1605 EXPECT_FALSE(GetValue(report, StatsReport::kStatsValueNameEchoDelayStdDev,
1606 &value_in_report));
1607
1608 // Get stats for the remote track.
1609 reports.clear();
Steve Anton3871f6f2018-01-26 18:25:531610 stats->GetStats(remote_track.get(), &reports);
zhihuang6ba3b192016-05-13 18:46:351611 report = FindNthReportByType(reports, StatsReport::kStatsReportTypeSsrc, 1);
Harald Alvestrand75ceef22018-01-04 14:26:131612 ASSERT_TRUE(report);
zhihuang6ba3b192016-05-13 18:46:351613 EXPECT_FALSE(GetValue(report,
1614 StatsReport::kStatsValueNameCaptureStartNtpTimeMs,
1615 &value_in_report));
1616 EXPECT_FALSE(GetValue(report, StatsReport::kStatsValueNameAudioInputLevel,
1617 &value_in_report));
1618}
1619
henrike@webrtc.org40b3b682014-03-03 18:30:111620// This test verifies that a local stats object can get statistics via
1621// AudioTrackInterface::GetStats() method.
Harald Alvestrand75ceef22018-01-04 14:26:131622TEST_P(StatsCollectorTrackTest, GetStatsFromLocalAudioTrack) {
Steve Anton3871f6f2018-01-26 18:25:531623 auto pc = CreatePeerConnection();
Niels Möllerafb246b2022-04-20 12:26:501624 auto stats = CreateStatsCollector(pc.get());
decurtis@webrtc.org487a4442015-01-15 22:55:071625
Niels Möllerafb246b2022-04-20 12:26:501626 AddOutgoingAudioTrack(pc.get(), stats.get());
1627 stats->AddLocalAudioTrack(audio_track_.get(), kSsrcOfTrack);
tommi@webrtc.org242068d2014-07-14 20:19:561628
Steve Anton3871f6f2018-01-26 18:25:531629 VoiceSenderInfo voice_sender_info;
xians@webrtc.org4cb01282014-06-12 14:57:051630 InitVoiceSenderInfo(&voice_sender_info);
Niels Möllerafb246b2022-04-20 12:26:501631 UpdateVoiceSenderInfoFromAudioTrack(audio_track_.get(), &voice_sender_info,
1632 false);
Steve Anton3871f6f2018-01-26 18:25:531633 VoiceMediaInfo voice_info;
1634 voice_info.senders.push_back(voice_sender_info);
Steve Anton5b387312018-02-03 00:00:201635
Harald Alvestrand2f553702023-03-07 10:10:031636 auto voice_media_channels = pc->AddVoiceChannel("audio", "transport");
1637 voice_media_channels.first->SetStats(voice_info);
1638 voice_media_channels.second->SetStats(voice_info);
henrike@webrtc.org40b3b682014-03-03 18:30:111639
henrike@webrtc.org40b3b682014-03-03 18:30:111640 StatsReports reports; // returned values.
Niels Möllerafb246b2022-04-20 12:26:501641 VerifyAudioTrackStats(audio_track_.get(), stats.get(), voice_info, &reports);
henrike@webrtc.org40b3b682014-03-03 18:30:111642
xians@webrtc.org4cb01282014-06-12 14:57:051643 // Verify that there is no remote report for the local audio track because
1644 // we did not set it up.
Yves Gerey665174f2018-06-19 13:03:051645 const StatsReport* remote_report =
1646 FindNthReportByType(reports, StatsReport::kStatsReportTypeRemoteSsrc, 1);
xians@webrtc.org4cb01282014-06-12 14:57:051647 EXPECT_TRUE(remote_report == NULL);
1648}
buildbot@webrtc.org3e01e0b2014-05-13 17:54:101649
1650// This test verifies that audio receive streams populate stats reports
1651// correctly.
Harald Alvestrand75ceef22018-01-04 14:26:131652TEST_P(StatsCollectorTrackTest, GetStatsFromRemoteStream) {
Steve Anton3871f6f2018-01-26 18:25:531653 auto pc = CreatePeerConnection();
Niels Möllerafb246b2022-04-20 12:26:501654 auto stats = CreateStatsCollector(pc.get());
decurtis@webrtc.org487a4442015-01-15 22:55:071655
Niels Möllerafb246b2022-04-20 12:26:501656 AddIncomingAudioTrack(pc.get(), stats.get());
deadbeefcbecd352015-09-23 18:50:271657
Steve Anton3871f6f2018-01-26 18:25:531658 VoiceReceiverInfo voice_receiver_info;
xians@webrtc.org4cb01282014-06-12 14:57:051659 InitVoiceReceiverInfo(&voice_receiver_info);
buildbot@webrtc.org7e71b772014-06-13 01:14:011660 voice_receiver_info.codec_name = "fake_codec";
Steve Anton3871f6f2018-01-26 18:25:531661 VoiceMediaInfo voice_info;
1662 voice_info.receivers.push_back(voice_receiver_info);
Steve Anton5b387312018-02-03 00:00:201663
Harald Alvestrand2f553702023-03-07 10:10:031664 auto voice_media_channels = pc->AddVoiceChannel("audio", "transport");
1665 voice_media_channels.first->SetStats(voice_info);
1666 voice_media_channels.second->SetStats(voice_info);
buildbot@webrtc.org3e01e0b2014-05-13 17:54:101667
buildbot@webrtc.org3e01e0b2014-05-13 17:54:101668 StatsReports reports; // returned values.
Niels Möllerafb246b2022-04-20 12:26:501669 VerifyAudioTrackStats(audio_track_.get(), stats.get(), voice_info, &reports);
buildbot@webrtc.org3e01e0b2014-05-13 17:54:101670}
1671
henrike@webrtc.org40b3b682014-03-03 18:30:111672// This test verifies that a local stats object won't update its statistics
1673// after a RemoveLocalAudioTrack() call.
Harald Alvestrand75ceef22018-01-04 14:26:131674TEST_P(StatsCollectorTrackTest, GetStatsAfterRemoveAudioStream) {
Steve Anton3871f6f2018-01-26 18:25:531675 auto pc = CreatePeerConnection();
Niels Möllerafb246b2022-04-20 12:26:501676 auto stats = CreateStatsCollector(pc.get());
decurtis@webrtc.org487a4442015-01-15 22:55:071677
Niels Möllerafb246b2022-04-20 12:26:501678 AddOutgoingAudioTrack(pc.get(), stats.get());
Steve Anton3871f6f2018-01-26 18:25:531679 stats->AddLocalAudioTrack(audio_track_.get(), kSsrcOfTrack);
deadbeefcbecd352015-09-23 18:50:271680
Steve Anton3871f6f2018-01-26 18:25:531681 VoiceSenderInfo voice_sender_info;
xians@webrtc.org4cb01282014-06-12 14:57:051682 InitVoiceSenderInfo(&voice_sender_info);
Steve Anton3871f6f2018-01-26 18:25:531683 VoiceMediaInfo voice_info;
1684 voice_info.senders.push_back(voice_sender_info);
henrike@webrtc.org40b3b682014-03-03 18:30:111685
Harald Alvestrand2f553702023-03-07 10:10:031686 auto voice_media_channels = pc->AddVoiceChannel("audio", "transport");
1687 voice_media_channels.first->SetStats(voice_info);
1688 voice_media_channels.second->SetStats(voice_info);
henrike@webrtc.org40b3b682014-03-03 18:30:111689
Steve Anton3871f6f2018-01-26 18:25:531690 stats->RemoveLocalAudioTrack(audio_track_.get(), kSsrcOfTrack);
henrike@webrtc.org40b3b682014-03-03 18:30:111691
Steve Anton3871f6f2018-01-26 18:25:531692 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1693 StatsReports reports;
1694 stats->GetStats(nullptr, &reports);
henrike@webrtc.org40b3b682014-03-03 18:30:111695
1696 // The report will exist since we don't remove them in RemoveStream().
Yves Gerey665174f2018-06-19 13:03:051697 const StatsReport* report =
1698 FindNthReportByType(reports, StatsReport::kStatsReportTypeSsrc, 1);
Steve Anton3871f6f2018-01-26 18:25:531699 ASSERT_TRUE(report);
1700 EXPECT_EQ(stats->GetTimeNow(), report->timestamp());
Yves Gerey665174f2018-06-19 13:03:051701 std::string track_id =
1702 ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameTrackId);
xians@webrtc.org4cb01282014-06-12 14:57:051703 EXPECT_EQ(kLocalTrackId, track_id);
Yves Gerey665174f2018-06-19 13:03:051704 std::string ssrc_id =
1705 ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameSsrc);
Jonas Olsson6b1985d2018-07-05 09:59:481706 EXPECT_EQ(rtc::ToString(kSsrcOfTrack), ssrc_id);
henrike@webrtc.org40b3b682014-03-03 18:30:111707
1708 // Verifies the values in the track report, no value will be changed by the
1709 // AudioTrackInterface::GetSignalValue() and
Sam Zackrisson28127632018-11-01 10:37:151710 // AudioProcessorInterface::GetStats();
henrike@webrtc.org40b3b682014-03-03 18:30:111711 VerifyVoiceSenderInfoReport(report, voice_sender_info);
1712}
1713
xians@webrtc.org4cb01282014-06-12 14:57:051714// This test verifies that when ongoing and incoming audio tracks are using
1715// the same ssrc, they populate stats reports correctly.
Harald Alvestrand75ceef22018-01-04 14:26:131716TEST_P(StatsCollectorTrackTest, LocalAndRemoteTracksWithSameSsrc) {
Steve Anton3871f6f2018-01-26 18:25:531717 auto pc = CreatePeerConnection();
Niels Möllerafb246b2022-04-20 12:26:501718 auto stats = CreateStatsCollector(pc.get());
xians@webrtc.org4cb01282014-06-12 14:57:051719
1720 // Create a local stream with a local audio track and adds it to the stats.
Niels Möllerafb246b2022-04-20 12:26:501721 AddOutgoingAudioTrack(pc.get(), stats.get());
Steve Anton3871f6f2018-01-26 18:25:531722 stats->AddLocalAudioTrack(audio_track_.get(), kSsrcOfTrack);
xians@webrtc.org4cb01282014-06-12 14:57:051723
1724 // Create a remote stream with a remote audio track and adds it to the stats.
Steve Anton3871f6f2018-01-26 18:25:531725 rtc::scoped_refptr<MediaStream> remote_stream(
Seth Hampson845e8782018-03-02 19:34:101726 MediaStream::Create("remotestreamid"));
Harald Alvestrand2f7ad282022-04-21 11:35:431727 rtc::scoped_refptr<AudioTrackInterface> remote_track =
1728 rtc::make_ref_counted<FakeAudioTrack>(kRemoteTrackId);
Steve Antonefe4c922019-03-27 17:26:061729 pc->AddReceiver(CreateMockReceiver(remote_track, kSsrcOfTrack));
Harald Alvestrand2f7ad282022-04-21 11:35:431730 remote_stream->AddTrack(remote_track);
Niels Möllerafb246b2022-04-20 12:26:501731 stats->AddStream(remote_stream.get());
xians@webrtc.org4cb01282014-06-12 14:57:051732
Steve Anton3871f6f2018-01-26 18:25:531733 VoiceSenderInfo voice_sender_info;
xians@webrtc.org4cb01282014-06-12 14:57:051734 InitVoiceSenderInfo(&voice_sender_info);
Artem Titov880fa812021-07-30 20:30:231735 // Some of the contents in `voice_sender_info` needs to be updated from the
1736 // `audio_track_`.
Ivo Creusen56d460902017-11-24 16:29:591737 UpdateVoiceSenderInfoFromAudioTrack(audio_track_.get(), &voice_sender_info,
1738 true);
xians@webrtc.org4cb01282014-06-12 14:57:051739
Steve Anton3871f6f2018-01-26 18:25:531740 VoiceReceiverInfo voice_receiver_info;
xians@webrtc.org4cb01282014-06-12 14:57:051741 InitVoiceReceiverInfo(&voice_receiver_info);
1742
1743 // Constructs an ssrc stats update.
Steve Anton3871f6f2018-01-26 18:25:531744 VoiceMediaInfo voice_info;
1745 voice_info.senders.push_back(voice_sender_info);
1746 voice_info.receivers.push_back(voice_receiver_info);
xians@webrtc.org4cb01282014-06-12 14:57:051747
Steve Anton3871f6f2018-01-26 18:25:531748 // Instruct the session to return stats containing the transport channel.
Harald Alvestrand2f553702023-03-07 10:10:031749 auto voice_media_channels = pc->AddVoiceChannel("audio", "transport");
1750 voice_media_channels.first->SetStats(voice_info);
1751 voice_media_channels.second->SetStats(voice_info);
xians@webrtc.org4cb01282014-06-12 14:57:051752
Steve Anton3871f6f2018-01-26 18:25:531753 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
xians@webrtc.org4cb01282014-06-12 14:57:051754
1755 // Get stats for the local track.
Steve Anton3871f6f2018-01-26 18:25:531756 StatsReports reports; // returned values.
1757 stats->GetStats(audio_track_.get(), &reports);
1758
Yves Gerey665174f2018-06-19 13:03:051759 const StatsReport* track_report =
1760 FindNthReportByType(reports, StatsReport::kStatsReportTypeSsrc, 1);
Harald Alvestrand75ceef22018-01-04 14:26:131761 ASSERT_TRUE(track_report);
Steve Anton3871f6f2018-01-26 18:25:531762 EXPECT_EQ(stats->GetTimeNow(), track_report->timestamp());
Yves Gerey665174f2018-06-19 13:03:051763 std::string track_id =
1764 ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameTrackId);
xians@webrtc.org4cb01282014-06-12 14:57:051765 EXPECT_EQ(kLocalTrackId, track_id);
1766 VerifyVoiceSenderInfoReport(track_report, voice_sender_info);
1767
1768 // Get stats for the remote track.
tommi@webrtc.org5b06b062014-08-15 08:38:301769 reports.clear();
Steve Anton3871f6f2018-01-26 18:25:531770 stats->GetStats(remote_track.get(), &reports);
Yves Gerey665174f2018-06-19 13:03:051771 track_report =
1772 FindNthReportByType(reports, StatsReport::kStatsReportTypeSsrc, 1);
Harald Alvestrand75ceef22018-01-04 14:26:131773 ASSERT_TRUE(track_report);
Steve Anton3871f6f2018-01-26 18:25:531774 EXPECT_EQ(stats->GetTimeNow(), track_report->timestamp());
Yves Gerey665174f2018-06-19 13:03:051775 track_id =
1776 ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameTrackId);
xians@webrtc.org4cb01282014-06-12 14:57:051777 EXPECT_EQ(kRemoteTrackId, track_id);
1778 VerifyVoiceReceiverInfoReport(track_report, voice_receiver_info);
1779}
1780
xians@webrtc.org01bda202014-07-09 07:38:381781// This test verifies that when two outgoing audio tracks are using the same
1782// ssrc at different times, they populate stats reports correctly.
1783// TODO(xians): Figure out if it is possible to encapsulate the setup and
1784// avoid duplication of code in test cases.
Harald Alvestrand75ceef22018-01-04 14:26:131785TEST_P(StatsCollectorTrackTest, TwoLocalTracksWithSameSsrc) {
Harald Alvestrand75ceef22018-01-04 14:26:131786 // This test only makes sense when we're using streams.
Steve Anton3871f6f2018-01-26 18:25:531787 if (!GetParam()) {
Harald Alvestrand75ceef22018-01-04 14:26:131788 return;
Steve Anton3871f6f2018-01-26 18:25:531789 }
Harald Alvestrand75ceef22018-01-04 14:26:131790
Steve Anton3871f6f2018-01-26 18:25:531791 auto pc = CreatePeerConnection();
Niels Möllerafb246b2022-04-20 12:26:501792 auto stats = CreateStatsCollector(pc.get());
xians@webrtc.org01bda202014-07-09 07:38:381793
1794 // Create a local stream with a local audio track and adds it to the stats.
Niels Möllerafb246b2022-04-20 12:26:501795 auto sender = AddOutgoingAudioTrack(pc.get(), stats.get());
1796 stats->AddLocalAudioTrack(audio_track_.get(), kSsrcOfTrack);
xians@webrtc.org01bda202014-07-09 07:38:381797
Steve Anton3871f6f2018-01-26 18:25:531798 VoiceSenderInfo voice_sender_info;
ivoce1198e02017-09-08 15:13:191799 InitVoiceSenderInfo(&voice_sender_info);
Niels Möllerafb246b2022-04-20 12:26:501800 UpdateVoiceSenderInfoFromAudioTrack(audio_track_.get(), &voice_sender_info,
1801 false);
xians@webrtc.org01bda202014-07-09 07:38:381802 voice_sender_info.add_ssrc(kSsrcOfTrack);
Steve Anton3871f6f2018-01-26 18:25:531803 VoiceMediaInfo voice_info;
1804 voice_info.senders.push_back(voice_sender_info);
Steve Anton5b387312018-02-03 00:00:201805
Harald Alvestrand2f553702023-03-07 10:10:031806 auto voice_media_channels = pc->AddVoiceChannel("voice", "transport");
1807 voice_media_channels.first->SetStats(voice_info);
1808 voice_media_channels.second->SetStats(voice_info);
xians@webrtc.org01bda202014-07-09 07:38:381809
xians@webrtc.org01bda202014-07-09 07:38:381810 StatsReports reports; // returned values.
Niels Möllerafb246b2022-04-20 12:26:501811 VerifyAudioTrackStats(audio_track_.get(), stats.get(), voice_info, &reports);
xians@webrtc.org01bda202014-07-09 07:38:381812
1813 // Remove the previous audio track from the stream.
Harald Alvestrand2f7ad282022-04-21 11:35:431814 stream_->RemoveTrack(audio_track());
Steve Anton3871f6f2018-01-26 18:25:531815 stats->RemoveLocalAudioTrack(audio_track_.get(), kSsrcOfTrack);
Steve Antonefe4c922019-03-27 17:26:061816 pc->RemoveSender(sender);
xians@webrtc.org01bda202014-07-09 07:38:381817
1818 // Create a new audio track and adds it to the stream and stats.
1819 static const std::string kNewTrackId = "new_track_id";
Tommi87f70902021-04-27 12:43:081820 auto new_audio_track = rtc::make_ref_counted<FakeAudioTrack>(kNewTrackId);
Steve Antonefe4c922019-03-27 17:26:061821 pc->AddSender(CreateMockSender(new_audio_track, kSsrcOfTrack));
Harald Alvestrand2f7ad282022-04-21 11:35:431822 stream_->AddTrack(
1823 rtc::scoped_refptr<AudioTrackInterface>(new_audio_track.get()));
xians@webrtc.org01bda202014-07-09 07:38:381824
Niels Möllerafb246b2022-04-20 12:26:501825 stats->AddLocalAudioTrack(new_audio_track.get(), kSsrcOfTrack);
Tommic811ab52022-01-11 15:33:231826 stats->InvalidateCache();
Steve Anton3871f6f2018-01-26 18:25:531827
1828 VoiceSenderInfo new_voice_sender_info;
xians@webrtc.org01bda202014-07-09 07:38:381829 InitVoiceSenderInfo(&new_voice_sender_info);
Niels Möllerafb246b2022-04-20 12:26:501830 UpdateVoiceSenderInfoFromAudioTrack(new_audio_track.get(),
1831 &new_voice_sender_info, false);
Steve Anton3871f6f2018-01-26 18:25:531832 VoiceMediaInfo new_voice_info;
1833 new_voice_info.senders.push_back(new_voice_sender_info);
Harald Alvestrand2f553702023-03-07 10:10:031834 voice_media_channels.first->SetStats(new_voice_info);
1835 voice_media_channels.second->SetStats(new_voice_info);
Steve Anton3871f6f2018-01-26 18:25:531836
tommi@webrtc.org5b06b062014-08-15 08:38:301837 reports.clear();
Niels Möllerafb246b2022-04-20 12:26:501838 VerifyAudioTrackStats(new_audio_track.get(), stats.get(), new_voice_info,
1839 &reports);
xians@webrtc.org01bda202014-07-09 07:38:381840}
1841
Steve Antonefe4c922019-03-27 17:26:061842// Test that if there are two local senders with the same track then two SSRC
1843// reports will be created, one for each sender, with the same track ID and one
1844// track report will be created for the shared track.
1845TEST_P(StatsCollectorTrackTest, TwoLocalSendersWithSameTrack) {
1846 constexpr uint32_t kFirstSsrc = 22;
1847 constexpr uint32_t kSecondSsrc = 33;
1848
1849 auto pc = CreatePeerConnection();
Niels Möllerafb246b2022-04-20 12:26:501850 auto stats = CreateStatsCollector(pc.get());
Steve Antonefe4c922019-03-27 17:26:061851
Tommi87f70902021-04-27 12:43:081852 auto local_track =
1853 rtc::make_ref_counted<FakeAudioTrackWithInitValue>(kLocalTrackId);
Steve Antonefe4c922019-03-27 17:26:061854 pc->AddSender(CreateMockSender(local_track, kFirstSsrc));
1855 stats->AddLocalAudioTrack(local_track.get(), kFirstSsrc);
1856 pc->AddSender(CreateMockSender(local_track, kSecondSsrc));
1857 stats->AddLocalAudioTrack(local_track.get(), kSecondSsrc);
1858
1859 VoiceSenderInfo first_sender_info;
1860 InitVoiceSenderInfo(&first_sender_info, kFirstSsrc);
1861 UpdateVoiceSenderInfoFromAudioTrack(local_track.get(), &first_sender_info,
1862 false);
1863
1864 VoiceSenderInfo second_sender_info;
1865 InitVoiceSenderInfo(&second_sender_info, kSecondSsrc);
1866 UpdateVoiceSenderInfoFromAudioTrack(local_track.get(), &second_sender_info,
1867 false);
1868
1869 VoiceMediaInfo voice_info;
1870 voice_info.senders.push_back(first_sender_info);
1871 voice_info.senders.push_back(second_sender_info);
1872
Harald Alvestrand2f553702023-03-07 10:10:031873 auto voice_media_channels = pc->AddVoiceChannel("voice", "transport");
1874 voice_media_channels.first->SetStats(voice_info);
1875 voice_media_channels.second->SetStats(voice_info);
Steve Antonefe4c922019-03-27 17:26:061876
1877 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1878
1879 StatsReports reports;
1880 stats->GetStats(local_track.get(), &reports);
Steve Antonefe4c922019-03-27 17:26:061881
1882 // Both SSRC reports have the same track ID.
1883 EXPECT_EQ(kLocalTrackId, GetValueInNthReportByType(
1884 reports, StatsReport::kStatsReportTypeSsrc,
1885 StatsReport::kStatsValueNameTrackId, 1));
1886 EXPECT_EQ(kLocalTrackId, GetValueInNthReportByType(
1887 reports, StatsReport::kStatsReportTypeSsrc,
1888 StatsReport::kStatsValueNameTrackId, 2));
1889
1890 // The SSRC in each SSRC report is different and correspond to the sender
1891 // SSRC.
1892 std::vector<absl::optional<std::string>> ssrcs = {
1893 GetValueInNthReportByType(reports, StatsReport::kStatsReportTypeSsrc,
1894 StatsReport::kStatsValueNameSsrc, 1),
1895 GetValueInNthReportByType(reports, StatsReport::kStatsReportTypeSsrc,
1896 StatsReport::kStatsValueNameSsrc, 2)};
1897 EXPECT_THAT(ssrcs, UnorderedElementsAre(rtc::ToString(kFirstSsrc),
1898 rtc::ToString(kSecondSsrc)));
1899
1900 // There is one track report with the same track ID as the SSRC reports.
1901 EXPECT_EQ(
1902 1u, GetReportsByType(reports, StatsReport::kStatsReportTypeTrack).size());
1903 EXPECT_EQ(kLocalTrackId, GetValueInNthReportByType(
1904 reports, StatsReport::kStatsReportTypeTrack,
1905 StatsReport::kStatsValueNameTrackId, 1));
1906}
1907
sakal43536c32016-10-24 08:46:431908// This test verifies that stats are correctly set in video send ssrc stats.
Harald Alvestrand75ceef22018-01-04 14:26:131909TEST_P(StatsCollectorTrackTest, VerifyVideoSendSsrcStats) {
Steve Anton3871f6f2018-01-26 18:25:531910 auto pc = CreatePeerConnection();
Niels Möllerafb246b2022-04-20 12:26:501911 auto stats = CreateStatsCollector(pc.get());
sakal43536c32016-10-24 08:46:431912
Niels Möllerafb246b2022-04-20 12:26:501913 AddOutgoingVideoTrack(pc.get(), stats.get());
sakal43536c32016-10-24 08:46:431914
Steve Anton3871f6f2018-01-26 18:25:531915 VideoSenderInfo video_sender_info;
sakal43536c32016-10-24 08:46:431916 video_sender_info.add_ssrc(1234);
1917 video_sender_info.frames_encoded = 10;
Oskar Sundbom36f8f3e2017-11-16 09:54:271918 video_sender_info.qp_sum = 11;
Steve Anton3871f6f2018-01-26 18:25:531919 VideoMediaInfo video_info;
Henrik Boströma0ff50c2020-05-05 13:54:461920 video_info.aggregated_senders.push_back(video_sender_info);
Steve Anton5b387312018-02-03 00:00:201921
Tommi19015512022-02-02 10:49:351922 pc->AddVideoChannel("video", "transport", video_info);
sakal43536c32016-10-24 08:46:431923
Steve Anton3871f6f2018-01-26 18:25:531924 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1925 StatsReports reports;
1926 stats->GetStats(nullptr, &reports);
1927
sakal43536c32016-10-24 08:46:431928 EXPECT_EQ(rtc::ToString(video_sender_info.frames_encoded),
1929 ExtractSsrcStatsValue(reports,
1930 StatsReport::kStatsValueNameFramesEncoded));
sakal87da4042016-10-31 13:53:471931 EXPECT_EQ(rtc::ToString(*video_sender_info.qp_sum),
1932 ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameQpSum));
sakal43536c32016-10-24 08:46:431933}
1934
sakale5ba44e2016-10-26 14:09:241935// This test verifies that stats are correctly set in video receive ssrc stats.
Steve Anton3871f6f2018-01-26 18:25:531936TEST_P(StatsCollectorTrackTest, VerifyVideoReceiveSsrcStatsNew) {
1937 auto pc = CreatePeerConnection();
Niels Möllerafb246b2022-04-20 12:26:501938 auto stats = CreateStatsCollector(pc.get());
sakale5ba44e2016-10-26 14:09:241939
Niels Möllerafb246b2022-04-20 12:26:501940 AddIncomingVideoTrack(pc.get(), stats.get());
sakale5ba44e2016-10-26 14:09:241941
Steve Anton3871f6f2018-01-26 18:25:531942 VideoReceiverInfo video_receiver_info;
sakale5ba44e2016-10-26 14:09:241943 video_receiver_info.add_ssrc(1234);
1944 video_receiver_info.frames_decoded = 10;
Artem Titov8a3ab0e2018-07-27 14:52:571945 video_receiver_info.qp_sum = 11;
Steve Anton3871f6f2018-01-26 18:25:531946 VideoMediaInfo video_info;
1947 video_info.receivers.push_back(video_receiver_info);
Steve Anton5b387312018-02-03 00:00:201948
Tommi19015512022-02-02 10:49:351949 pc->AddVideoChannel("video", "transport", video_info);
sakale5ba44e2016-10-26 14:09:241950
Steve Anton3871f6f2018-01-26 18:25:531951 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1952 StatsReports reports;
1953 stats->GetStats(nullptr, &reports);
1954
sakale5ba44e2016-10-26 14:09:241955 EXPECT_EQ(rtc::ToString(video_receiver_info.frames_decoded),
1956 ExtractSsrcStatsValue(reports,
1957 StatsReport::kStatsValueNameFramesDecoded));
sakalcc452e12017-02-09 12:53:451958 EXPECT_EQ(rtc::ToString(*video_receiver_info.qp_sum),
1959 ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameQpSum));
sakale5ba44e2016-10-26 14:09:241960}
1961
Mirko Bonadeic84f6612019-01-31 11:20:571962INSTANTIATE_TEST_SUITE_P(HasStream, StatsCollectorTrackTest, ::testing::Bool());
Harald Alvestrand75ceef22018-01-04 14:26:131963
guoweis@webrtc.org950c5182014-12-16 23:01:311964} // namespace webrtc