blob: af9f6747b632a3f1ba32c6cb6835f577e4beebb7 [file] [log] [blame]
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001/*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "video/send_statistics_proxy.h"
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000012
13#include <map>
kwiberg27f982b2016-03-01 11:52:33 -080014#include <memory>
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000015#include <string>
16#include <vector>
17
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "system_wrappers/include/metrics.h"
19#include "system_wrappers/include/metrics_default.h"
asapersson8d75ac72017-09-15 06:41:15 -070020#include "test/field_trial.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020021#include "test/gtest.h"
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000022
23namespace webrtc {
asapersson5265fed2016-04-18 02:58:47 -070024namespace {
25const uint32_t kFirstSsrc = 17;
26const uint32_t kSecondSsrc = 42;
27const uint32_t kFirstRtxSsrc = 18;
28const uint32_t kSecondRtxSsrc = 43;
asaperssona6a699a2016-11-25 03:52:46 -080029const uint32_t kFlexFecSsrc = 55;
asapersson320e45a2016-11-29 01:40:35 -080030const int kFpsPeriodicIntervalMs = 2000;
31const int kWidth = 640;
32const int kHeight = 480;
asapersson5265fed2016-04-18 02:58:47 -070033const int kQpIdx0 = 21;
34const int kQpIdx1 = 39;
asapersson8d75ac72017-09-15 06:41:15 -070035const int kMinFirstFallbackIntervalMs = 1500;
kthelgason0cd27ba2016-12-19 06:32:16 -080036const CodecSpecificInfo kDefaultCodecInfo = []() {
37 CodecSpecificInfo codec_info;
38 codec_info.codecType = kVideoCodecVP8;
39 codec_info.codecSpecific.VP8.simulcastIdx = 0;
40 return codec_info;
41}();
asapersson5265fed2016-04-18 02:58:47 -070042} // namespace
sprang07fb9be2016-02-24 07:55:00 -080043
stefan@webrtc.org168f23f2014-07-11 13:44:02 +000044class SendStatisticsProxyTest : public ::testing::Test {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000045 public:
asapersson8d75ac72017-09-15 06:41:15 -070046 SendStatisticsProxyTest() : SendStatisticsProxyTest("") {}
47 explicit SendStatisticsProxyTest(const std::string& field_trials)
48 : override_field_trials_(field_trials),
49 fake_clock_(1234),
50 config_(GetTestConfig()),
51 avg_delay_ms_(0),
solenberg4fbae2b2015-08-28 04:07:10 -070052 max_delay_ms_(0) {}
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000053 virtual ~SendStatisticsProxyTest() {}
54
55 protected:
56 virtual void SetUp() {
asapersson01d70a32016-05-20 06:29:46 -070057 metrics::Reset();
sprangb4a1ae52015-12-03 08:10:08 -080058 statistics_proxy_.reset(new SendStatisticsProxy(
59 &fake_clock_, GetTestConfig(),
60 VideoEncoderConfig::ContentType::kRealtimeVideo));
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000061 expected_ = VideoSendStream::Stats();
asapersson2e5cfcd2016-08-11 08:41:18 -070062 for (const auto& ssrc : config_.rtp.ssrcs)
63 expected_.substreams[ssrc].is_rtx = false;
64 for (const auto& ssrc : config_.rtp.rtx.ssrcs)
65 expected_.substreams[ssrc].is_rtx = true;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000066 }
67
68 VideoSendStream::Config GetTestConfig() {
solenberg4fbae2b2015-08-28 04:07:10 -070069 VideoSendStream::Config config(nullptr);
sprang07fb9be2016-02-24 07:55:00 -080070 config.rtp.ssrcs.push_back(kFirstSsrc);
71 config.rtp.ssrcs.push_back(kSecondSsrc);
72 config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
73 config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
brandtrb5f2c3f2016-10-04 23:28:39 -070074 config.rtp.ulpfec.red_payload_type = 17;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000075 return config;
76 }
77
asaperssona6a699a2016-11-25 03:52:46 -080078 VideoSendStream::Config GetTestConfigWithFlexFec() {
79 VideoSendStream::Config config(nullptr);
80 config.rtp.ssrcs.push_back(kFirstSsrc);
81 config.rtp.ssrcs.push_back(kSecondSsrc);
82 config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
83 config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
brandtr3d200bd2017-01-16 06:59:19 -080084 config.rtp.flexfec.payload_type = 50;
85 config.rtp.flexfec.ssrc = kFlexFecSsrc;
asaperssona6a699a2016-11-25 03:52:46 -080086 return config;
87 }
88
89 VideoSendStream::StreamStats GetStreamStats(uint32_t ssrc) {
90 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
91 std::map<uint32_t, VideoSendStream::StreamStats>::iterator it =
92 stats.substreams.find(ssrc);
93 EXPECT_NE(it, stats.substreams.end());
94 return it->second;
95 }
96
asapersson66d4b372016-12-19 06:50:53 -080097 void UpdateDataCounters(uint32_t ssrc) {
98 StreamDataCountersCallback* proxy =
99 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
100 StreamDataCounters counters;
101 proxy->DataCountersUpdated(counters, ssrc);
102 }
103
sprang@webrtc.org09315702014-02-07 12:06:29 +0000104 void ExpectEqual(VideoSendStream::Stats one, VideoSendStream::Stats other) {
sprang@webrtc.org09315702014-02-07 12:06:29 +0000105 EXPECT_EQ(one.input_frame_rate, other.input_frame_rate);
106 EXPECT_EQ(one.encode_frame_rate, other.encode_frame_rate);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000107 EXPECT_EQ(one.media_bitrate_bps, other.media_bitrate_bps);
Pera48ddb72016-09-29 11:48:50 +0200108 EXPECT_EQ(one.preferred_media_bitrate_bps,
109 other.preferred_media_bitrate_bps);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000110 EXPECT_EQ(one.suspended, other.suspended);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000111
112 EXPECT_EQ(one.substreams.size(), other.substreams.size());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000113 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
sprang@webrtc.org09315702014-02-07 12:06:29 +0000114 one.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000115 it != one.substreams.end(); ++it) {
116 std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator
117 corresponding_it = other.substreams.find(it->first);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000118 ASSERT_TRUE(corresponding_it != other.substreams.end());
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000119 const VideoSendStream::StreamStats& a = it->second;
120 const VideoSendStream::StreamStats& b = corresponding_it->second;
sprang@webrtc.org09315702014-02-07 12:06:29 +0000121
asapersson2e5cfcd2016-08-11 08:41:18 -0700122 EXPECT_EQ(a.is_rtx, b.is_rtx);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000123 EXPECT_EQ(a.frame_counts.key_frames, b.frame_counts.key_frames);
124 EXPECT_EQ(a.frame_counts.delta_frames, b.frame_counts.delta_frames);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000125 EXPECT_EQ(a.total_bitrate_bps, b.total_bitrate_bps);
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000126 EXPECT_EQ(a.avg_delay_ms, b.avg_delay_ms);
127 EXPECT_EQ(a.max_delay_ms, b.max_delay_ms);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000128
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000129 EXPECT_EQ(a.rtp_stats.transmitted.payload_bytes,
130 b.rtp_stats.transmitted.payload_bytes);
131 EXPECT_EQ(a.rtp_stats.transmitted.header_bytes,
132 b.rtp_stats.transmitted.header_bytes);
133 EXPECT_EQ(a.rtp_stats.transmitted.padding_bytes,
134 b.rtp_stats.transmitted.padding_bytes);
135 EXPECT_EQ(a.rtp_stats.transmitted.packets,
136 b.rtp_stats.transmitted.packets);
137 EXPECT_EQ(a.rtp_stats.retransmitted.packets,
138 b.rtp_stats.retransmitted.packets);
139 EXPECT_EQ(a.rtp_stats.fec.packets, b.rtp_stats.fec.packets);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000140
141 EXPECT_EQ(a.rtcp_stats.fraction_lost, b.rtcp_stats.fraction_lost);
srte186d9c32017-08-04 05:03:53 -0700142 EXPECT_EQ(a.rtcp_stats.packets_lost, b.rtcp_stats.packets_lost);
143 EXPECT_EQ(a.rtcp_stats.extended_highest_sequence_number,
144 b.rtcp_stats.extended_highest_sequence_number);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000145 EXPECT_EQ(a.rtcp_stats.jitter, b.rtcp_stats.jitter);
146 }
147 }
148
asapersson8d75ac72017-09-15 06:41:15 -0700149 test::ScopedFieldTrials override_field_trials_;
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000150 SimulatedClock fake_clock_;
kwiberg27f982b2016-03-01 11:52:33 -0800151 std::unique_ptr<SendStatisticsProxy> statistics_proxy_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000152 VideoSendStream::Config config_;
153 int avg_delay_ms_;
154 int max_delay_ms_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000155 VideoSendStream::Stats expected_;
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000156 typedef std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator
157 StreamIterator;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000158};
159
160TEST_F(SendStatisticsProxyTest, RtcpStatistics) {
161 RtcpStatisticsCallback* callback = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700162 for (const auto& ssrc : config_.rtp.ssrcs) {
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000163 VideoSendStream::StreamStats& ssrc_stats = expected_.substreams[ssrc];
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000164
165 // Add statistics with some arbitrary, but unique, numbers.
166 uint32_t offset = ssrc * sizeof(RtcpStatistics);
srte186d9c32017-08-04 05:03:53 -0700167 ssrc_stats.rtcp_stats.packets_lost = offset;
168 ssrc_stats.rtcp_stats.extended_highest_sequence_number = offset + 1;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000169 ssrc_stats.rtcp_stats.fraction_lost = offset + 2;
170 ssrc_stats.rtcp_stats.jitter = offset + 3;
171 callback->StatisticsUpdated(ssrc_stats.rtcp_stats, ssrc);
172 }
asapersson35151f32016-05-02 23:44:01 -0700173 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000174 VideoSendStream::StreamStats& ssrc_stats = expected_.substreams[ssrc];
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000175
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000176 // Add statistics with some arbitrary, but unique, numbers.
177 uint32_t offset = ssrc * sizeof(RtcpStatistics);
srte186d9c32017-08-04 05:03:53 -0700178 ssrc_stats.rtcp_stats.packets_lost = offset;
179 ssrc_stats.rtcp_stats.extended_highest_sequence_number = offset + 1;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000180 ssrc_stats.rtcp_stats.fraction_lost = offset + 2;
181 ssrc_stats.rtcp_stats.jitter = offset + 3;
182 callback->StatisticsUpdated(ssrc_stats.rtcp_stats, ssrc);
183 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000184 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000185 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000186}
187
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000188TEST_F(SendStatisticsProxyTest, EncodedBitrateAndFramerate) {
Peter Boström7083e112015-09-22 16:28:51 +0200189 int media_bitrate_bps = 500;
190 int encode_fps = 29;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000191
perkj275afc52016-09-01 00:21:16 -0700192 statistics_proxy_->OnEncoderStatsUpdate(encode_fps, media_bitrate_bps);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000193
194 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
195 EXPECT_EQ(media_bitrate_bps, stats.media_bitrate_bps);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000196 EXPECT_EQ(encode_fps, stats.encode_frame_rate);
197}
198
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000199TEST_F(SendStatisticsProxyTest, Suspended) {
200 // Verify that the value is false by default.
201 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
202
203 // Verify that we can set it to true.
Peter Boström7083e112015-09-22 16:28:51 +0200204 statistics_proxy_->OnSuspendChange(true);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000205 EXPECT_TRUE(statistics_proxy_->GetStats().suspended);
206
207 // Verify that we can set it back to false again.
Peter Boström7083e112015-09-22 16:28:51 +0200208 statistics_proxy_->OnSuspendChange(false);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000209 EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
210}
211
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000212TEST_F(SendStatisticsProxyTest, FrameCounts) {
213 FrameCountObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700214 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000215 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000216 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
217 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000218 FrameCounts frame_counts;
219 frame_counts.key_frames = offset;
220 frame_counts.delta_frames = offset + 1;
221 stats.frame_counts = frame_counts;
222 observer->FrameCountUpdated(frame_counts, ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000223 }
asapersson35151f32016-05-02 23:44:01 -0700224 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000225 // Add statistics with some arbitrary, but unique, numbers.
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000226 VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
227 uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000228 FrameCounts frame_counts;
229 frame_counts.key_frames = offset;
230 frame_counts.delta_frames = offset + 1;
231 stats.frame_counts = frame_counts;
232 observer->FrameCountUpdated(frame_counts, ssrc);
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000233 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000234
235 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000236 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000237}
238
239TEST_F(SendStatisticsProxyTest, DataCounters) {
240 StreamDataCountersCallback* callback = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700241 for (const auto& ssrc : config_.rtp.ssrcs) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000242 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
243 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000244 size_t offset = ssrc * sizeof(StreamDataCounters);
245 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000246 counters.transmitted.payload_bytes = offset;
247 counters.transmitted.header_bytes = offset + 1;
248 counters.fec.packets = offset_uint32 + 2;
249 counters.transmitted.padding_bytes = offset + 3;
250 counters.retransmitted.packets = offset_uint32 + 4;
251 counters.transmitted.packets = offset_uint32 + 5;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000252 callback->DataCountersUpdated(counters, ssrc);
253 }
asapersson35151f32016-05-02 23:44:01 -0700254 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000255 StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
256 // Add statistics with some arbitrary, but unique, numbers.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000257 size_t offset = ssrc * sizeof(StreamDataCounters);
258 uint32_t offset_uint32 = static_cast<uint32_t>(offset);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000259 counters.transmitted.payload_bytes = offset;
260 counters.transmitted.header_bytes = offset + 1;
261 counters.fec.packets = offset_uint32 + 2;
262 counters.transmitted.padding_bytes = offset + 3;
263 counters.retransmitted.packets = offset_uint32 + 4;
264 counters.transmitted.packets = offset_uint32 + 5;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000265 callback->DataCountersUpdated(counters, ssrc);
266 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000267
268 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000269 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000270}
271
272TEST_F(SendStatisticsProxyTest, Bitrate) {
273 BitrateStatisticsObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700274 for (const auto& ssrc : config_.rtp.ssrcs) {
sprangcd349d92016-07-13 09:11:28 -0700275 uint32_t total;
276 uint32_t retransmit;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000277 // Use ssrc as bitrate_bps to get a unique value for each stream.
sprangcd349d92016-07-13 09:11:28 -0700278 total = ssrc;
279 retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000280 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700281 expected_.substreams[ssrc].total_bitrate_bps = total;
282 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000283 }
asapersson35151f32016-05-02 23:44:01 -0700284 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
sprangcd349d92016-07-13 09:11:28 -0700285 uint32_t total;
286 uint32_t retransmit;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000287 // Use ssrc as bitrate_bps to get a unique value for each stream.
sprangcd349d92016-07-13 09:11:28 -0700288 total = ssrc;
289 retransmit = ssrc + 1;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000290 observer->Notify(total, retransmit, ssrc);
sprangcd349d92016-07-13 09:11:28 -0700291 expected_.substreams[ssrc].total_bitrate_bps = total;
292 expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000293 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000294
295 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprang@webrtc.org09315702014-02-07 12:06:29 +0000296 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000297}
298
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000299TEST_F(SendStatisticsProxyTest, SendSideDelay) {
300 SendSideDelayObserver* observer = statistics_proxy_.get();
asapersson35151f32016-05-02 23:44:01 -0700301 for (const auto& ssrc : config_.rtp.ssrcs) {
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000302 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
303 // stream.
304 int avg_delay_ms = ssrc;
305 int max_delay_ms = ssrc + 1;
306 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms, ssrc);
307 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
308 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
309 }
asapersson35151f32016-05-02 23:44:01 -0700310 for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000311 // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
312 // stream.
313 int avg_delay_ms = ssrc;
314 int max_delay_ms = ssrc + 1;
315 observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms, ssrc);
316 expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
317 expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
318 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000319 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000320 ExpectEqual(expected_, stats);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000321}
322
Peter Boströme4499152016-02-05 11:13:28 +0100323TEST_F(SendStatisticsProxyTest, OnEncodedFrameTimeMeasured) {
asapersson1aa420b2015-12-07 03:12:22 -0800324 const int kEncodeTimeMs = 11;
Peter Boströme4499152016-02-05 11:13:28 +0100325 CpuOveruseMetrics metrics;
326 metrics.encode_usage_percent = 80;
327 statistics_proxy_->OnEncodedFrameTimeMeasured(kEncodeTimeMs, metrics);
asapersson1aa420b2015-12-07 03:12:22 -0800328
329 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
330 EXPECT_EQ(kEncodeTimeMs, stats.avg_encode_time_ms);
Peter Boströme4499152016-02-05 11:13:28 +0100331 EXPECT_EQ(metrics.encode_usage_percent, stats.encode_usage_percent);
asapersson1aa420b2015-12-07 03:12:22 -0800332}
333
Pera48ddb72016-09-29 11:48:50 +0200334TEST_F(SendStatisticsProxyTest, OnEncoderReconfiguredChangePreferredBitrate) {
335 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
336 EXPECT_EQ(0, stats.preferred_media_bitrate_bps);
337 const int kPreferredMediaBitrateBps = 50;
338
339 VideoEncoderConfig config;
340 statistics_proxy_->OnEncoderReconfigured(config, kPreferredMediaBitrateBps);
341 stats = statistics_proxy_->GetStats();
342 EXPECT_EQ(kPreferredMediaBitrateBps, stats.preferred_media_bitrate_bps);
343}
344
sakal43536c32016-10-24 01:46:43 -0700345TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesFramesEncoded) {
346 EncodedImage encoded_image;
347 CodecSpecificInfo codec_info;
348 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_encoded);
349 for (uint32_t i = 1; i <= 3; ++i) {
350 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
351 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_encoded);
352 }
353}
354
sakal87da4042016-10-31 06:53:47 -0700355TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesQpSum) {
356 EncodedImage encoded_image;
357 CodecSpecificInfo codec_info;
358 EXPECT_EQ(rtc::Optional<uint64_t>(), statistics_proxy_->GetStats().qp_sum);
359 encoded_image.qp_ = 3;
360 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
361 EXPECT_EQ(rtc::Optional<uint64_t>(3u), statistics_proxy_->GetStats().qp_sum);
362 encoded_image.qp_ = 127;
363 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
364 EXPECT_EQ(rtc::Optional<uint64_t>(130u),
365 statistics_proxy_->GetStats().qp_sum);
366}
367
368TEST_F(SendStatisticsProxyTest, OnSendEncodedImageWithoutQpQpSumWontExist) {
369 EncodedImage encoded_image;
370 CodecSpecificInfo codec_info;
371 encoded_image.qp_ = -1;
372 EXPECT_EQ(rtc::Optional<uint64_t>(), statistics_proxy_->GetStats().qp_sum);
373 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
374 EXPECT_EQ(rtc::Optional<uint64_t>(), statistics_proxy_->GetStats().qp_sum);
375}
376
asapersson09f05612017-05-15 23:40:18 -0700377TEST_F(SendStatisticsProxyTest, GetCpuAdaptationStats) {
mflodmancc3d4422017-08-03 08:27:51 -0700378 VideoStreamEncoder::AdaptCounts cpu_counts;
379 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700380 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700381 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700382 cpu_counts.fps = 1;
383 cpu_counts.resolution = 0;
384 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
385 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson36e9eb42017-03-31 05:29:12 -0700386 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700387 cpu_counts.fps = 0;
388 cpu_counts.resolution = 1;
389 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
390 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asapersson6eca98b2017-04-04 23:40:50 -0700391 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700392 cpu_counts.fps = 1;
393 cpu_counts.resolution = -1;
394 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
395 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700396 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700397 cpu_counts.fps = -1;
398 cpu_counts.resolution = -1;
399 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
400 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
401 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
402}
403
404TEST_F(SendStatisticsProxyTest, GetQualityAdaptationStats) {
mflodmancc3d4422017-08-03 08:27:51 -0700405 VideoStreamEncoder::AdaptCounts cpu_counts;
406 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700407 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
408 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
409 quality_counts.fps = 1;
410 quality_counts.resolution = 0;
411 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
412 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
413 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
414 quality_counts.fps = 0;
415 quality_counts.resolution = 1;
416 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
417 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
418 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
419 quality_counts.fps = 1;
420 quality_counts.resolution = -1;
421 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
422 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
423 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
424 quality_counts.fps = -1;
425 quality_counts.resolution = -1;
426 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
427 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
428 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
429}
430
431TEST_F(SendStatisticsProxyTest, GetStatsReportsCpuAdaptChanges) {
mflodmancc3d4422017-08-03 08:27:51 -0700432 VideoStreamEncoder::AdaptCounts cpu_counts;
433 VideoStreamEncoder::AdaptCounts quality_counts;
asaperssonfab67072017-04-04 05:51:49 -0700434 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
435
asapersson09f05612017-05-15 23:40:18 -0700436 cpu_counts.resolution = 1;
437 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
438 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700439 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
440 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
441
asapersson09f05612017-05-15 23:40:18 -0700442 cpu_counts.resolution = 2;
443 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
444 EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
445 EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700446 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asapersson09f05612017-05-15 23:40:18 -0700447 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700448}
449
asapersson09f05612017-05-15 23:40:18 -0700450TEST_F(SendStatisticsProxyTest, GetStatsReportsQualityAdaptChanges) {
mflodmancc3d4422017-08-03 08:27:51 -0700451 VideoStreamEncoder::AdaptCounts cpu_counts;
452 VideoStreamEncoder::AdaptCounts quality_counts;
asaperssonfab67072017-04-04 05:51:49 -0700453 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
454
asapersson09f05612017-05-15 23:40:18 -0700455 quality_counts.fps = 1;
456 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
457 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
458 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asaperssonfab67072017-04-04 05:51:49 -0700459 EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
460
asapersson09f05612017-05-15 23:40:18 -0700461 quality_counts.fps = 0;
462 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
463 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
asaperssonfab67072017-04-04 05:51:49 -0700464 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
asapersson09f05612017-05-15 23:40:18 -0700465 EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
466 EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
asaperssonfab67072017-04-04 05:51:49 -0700467}
468
asapersson09f05612017-05-15 23:40:18 -0700469TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_AdaptationNotEnabled) {
asapersson0944a802017-04-07 00:57:58 -0700470 // First RTP packet sent.
471 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700472 // Min runtime has passed.
473 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
474 statistics_proxy_.reset();
475 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
476 EXPECT_EQ(0,
477 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
478}
479
480TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_MinRuntimeNotPassed) {
asapersson0944a802017-04-07 00:57:58 -0700481 // First RTP packet sent.
482 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700483 // Enable adaptation.
mflodmancc3d4422017-08-03 08:27:51 -0700484 VideoStreamEncoder::AdaptCounts cpu_counts;
485 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700486 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700487 // Min runtime has not passed.
488 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
489 statistics_proxy_.reset();
490 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
491 EXPECT_EQ(0,
492 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
493}
494
asapersson09f05612017-05-15 23:40:18 -0700495TEST_F(SendStatisticsProxyTest, ZeroAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700496 // First RTP packet sent.
497 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700498 // Enable adaptation.
mflodmancc3d4422017-08-03 08:27:51 -0700499 VideoStreamEncoder::AdaptCounts cpu_counts;
500 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700501 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700502 // Min runtime has passed.
503 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
504 statistics_proxy_.reset();
505 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
506 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 0));
asapersson6eca98b2017-04-04 23:40:50 -0700507 EXPECT_EQ(1,
508 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
509 EXPECT_EQ(
510 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
511}
512
513TEST_F(SendStatisticsProxyTest, CpuAdaptChangesReported) {
asapersson0944a802017-04-07 00:57:58 -0700514 // First RTP packet sent.
515 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700516 // Enable adaptation.
mflodmancc3d4422017-08-03 08:27:51 -0700517 VideoStreamEncoder::AdaptCounts cpu_counts;
518 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700519 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700520 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
asapersson09f05612017-05-15 23:40:18 -0700521 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700522 fake_clock_.AdvanceTimeMilliseconds(10000);
523 statistics_proxy_.reset();
524 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
525 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
526}
527
528TEST_F(SendStatisticsProxyTest, AdaptChangesStatsExcludesDisabledTime) {
asapersson0944a802017-04-07 00:57:58 -0700529 // First RTP packet sent.
530 UpdateDataCounters(kFirstSsrc);
531
asapersson09f05612017-05-15 23:40:18 -0700532 // Disable quality adaptation.
mflodmancc3d4422017-08-03 08:27:51 -0700533 VideoStreamEncoder::AdaptCounts cpu_counts;
534 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700535 quality_counts.fps = -1;
536 quality_counts.resolution = -1;
537 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700538 fake_clock_.AdvanceTimeMilliseconds(10000);
539
asapersson09f05612017-05-15 23:40:18 -0700540 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700541 // Adapt changes: 2, elapsed time: 20 sec.
asapersson09f05612017-05-15 23:40:18 -0700542 quality_counts.fps = 0;
543 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700544 fake_clock_.AdvanceTimeMilliseconds(5000);
asapersson09f05612017-05-15 23:40:18 -0700545 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700546 fake_clock_.AdvanceTimeMilliseconds(9000);
asapersson09f05612017-05-15 23:40:18 -0700547 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700548 fake_clock_.AdvanceTimeMilliseconds(6000);
asapersson09f05612017-05-15 23:40:18 -0700549 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700550
asapersson09f05612017-05-15 23:40:18 -0700551 // Disable quality adaptation.
552 quality_counts.fps = -1;
553 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700554 fake_clock_.AdvanceTimeMilliseconds(30000);
555
asapersson09f05612017-05-15 23:40:18 -0700556 // Enable quality adaptation.
asapersson0944a802017-04-07 00:57:58 -0700557 // Adapt changes: 1, elapsed time: 10 sec.
asapersson09f05612017-05-15 23:40:18 -0700558 quality_counts.resolution = 0;
559 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
560 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700561 fake_clock_.AdvanceTimeMilliseconds(10000);
562
asapersson09f05612017-05-15 23:40:18 -0700563 // Disable quality adaptation.
564 quality_counts.resolution = -1;
565 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700566 fake_clock_.AdvanceTimeMilliseconds(5000);
asapersson09f05612017-05-15 23:40:18 -0700567 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700568 fake_clock_.AdvanceTimeMilliseconds(20000);
569
asapersson0944a802017-04-07 00:57:58 -0700570 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700571 statistics_proxy_.reset();
572 EXPECT_EQ(1,
573 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
574 EXPECT_EQ(
575 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
576}
577
asapersson0944a802017-04-07 00:57:58 -0700578TEST_F(SendStatisticsProxyTest,
579 AdaptChangesNotReported_ScalingNotEnabledVideoResumed) {
580 // First RTP packet sent.
581 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700582
asapersson0944a802017-04-07 00:57:58 -0700583 // Suspend and resume video.
584 statistics_proxy_->OnSuspendChange(true);
585 fake_clock_.AdvanceTimeMilliseconds(5000);
586 statistics_proxy_->OnSuspendChange(false);
587
588 // Min runtime has passed but scaling not enabled.
589 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
590 statistics_proxy_.reset();
591 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
592 EXPECT_EQ(0,
593 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
594}
595
596TEST_F(SendStatisticsProxyTest, QualityAdaptChangesStatsExcludesSuspendedTime) {
597 // First RTP packet sent.
598 UpdateDataCounters(kFirstSsrc);
599
asapersson09f05612017-05-15 23:40:18 -0700600 // Enable adaptation.
mflodmancc3d4422017-08-03 08:27:51 -0700601 VideoStreamEncoder::AdaptCounts cpu_counts;
602 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700603 // Adapt changes: 2, elapsed time: 20 sec.
asapersson09f05612017-05-15 23:40:18 -0700604 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700605 fake_clock_.AdvanceTimeMilliseconds(20000);
asapersson09f05612017-05-15 23:40:18 -0700606 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
607 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700608
609 // Suspend and resume video.
610 statistics_proxy_->OnSuspendChange(true);
611 fake_clock_.AdvanceTimeMilliseconds(30000);
612 statistics_proxy_->OnSuspendChange(false);
613
614 // Adapt changes: 1, elapsed time: 10 sec.
asapersson09f05612017-05-15 23:40:18 -0700615 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700616 fake_clock_.AdvanceTimeMilliseconds(10000);
617
618 // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
619 statistics_proxy_.reset();
620 EXPECT_EQ(1,
621 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
622 EXPECT_EQ(
623 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
624}
625
626TEST_F(SendStatisticsProxyTest, CpuAdaptChangesStatsExcludesSuspendedTime) {
627 // First RTP packet sent.
628 UpdateDataCounters(kFirstSsrc);
629
630 // Video not suspended.
631 statistics_proxy_->OnSuspendChange(false);
632 fake_clock_.AdvanceTimeMilliseconds(30000);
633
asapersson09f05612017-05-15 23:40:18 -0700634 // Enable adaptation.
mflodmancc3d4422017-08-03 08:27:51 -0700635 VideoStreamEncoder::AdaptCounts cpu_counts;
636 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson0944a802017-04-07 00:57:58 -0700637 // Adapt changes: 1, elapsed time: 20 sec.
asapersson09f05612017-05-15 23:40:18 -0700638 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700639 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson09f05612017-05-15 23:40:18 -0700640 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700641
642 // Video not suspended, stats time already started.
643 statistics_proxy_->OnSuspendChange(false);
644 fake_clock_.AdvanceTimeMilliseconds(10000);
645
asapersson09f05612017-05-15 23:40:18 -0700646 // Disable adaptation.
647 cpu_counts.fps = -1;
648 cpu_counts.resolution = -1;
649 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700650 fake_clock_.AdvanceTimeMilliseconds(30000);
651
652 // Suspend and resume video, stats time not started when scaling not enabled.
653 statistics_proxy_->OnSuspendChange(true);
654 fake_clock_.AdvanceTimeMilliseconds(30000);
655 statistics_proxy_->OnSuspendChange(false);
656 fake_clock_.AdvanceTimeMilliseconds(30000);
657
asapersson09f05612017-05-15 23:40:18 -0700658 // Enable adaptation.
asapersson0944a802017-04-07 00:57:58 -0700659 // Adapt changes: 1, elapsed time: 10 sec.
asapersson09f05612017-05-15 23:40:18 -0700660 cpu_counts.fps = 0;
661 cpu_counts.resolution = 0;
662 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700663 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson09f05612017-05-15 23:40:18 -0700664 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700665
666 // Adapt changes: 2, elapsed time: 30 sec => 4 per minute.
667 statistics_proxy_.reset();
668 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
669 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 4));
670}
671
672TEST_F(SendStatisticsProxyTest, AdaptChangesStatsNotStartedIfVideoSuspended) {
673 // First RTP packet sent.
674 UpdateDataCounters(kFirstSsrc);
675
676 // Video suspended.
677 statistics_proxy_->OnSuspendChange(true);
678
asapersson09f05612017-05-15 23:40:18 -0700679 // Enable adaptation, stats time not started when suspended.
mflodmancc3d4422017-08-03 08:27:51 -0700680 VideoStreamEncoder::AdaptCounts cpu_counts;
681 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700682 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700683 fake_clock_.AdvanceTimeMilliseconds(10000);
684
685 // Resume video, stats time started.
686 // Adapt changes: 1, elapsed time: 10 sec.
687 statistics_proxy_->OnSuspendChange(false);
688 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson09f05612017-05-15 23:40:18 -0700689 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700690
691 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
692 statistics_proxy_.reset();
693 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
694 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
695}
696
697TEST_F(SendStatisticsProxyTest, AdaptChangesStatsRestartsOnFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -0700698 // Send first packet, adaptation enabled.
asapersson6eca98b2017-04-04 23:40:50 -0700699 // Elapsed time before first packet is sent should be excluded.
mflodmancc3d4422017-08-03 08:27:51 -0700700 VideoStreamEncoder::AdaptCounts cpu_counts;
701 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700702 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700703 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -0700704 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700705
asapersson0944a802017-04-07 00:57:58 -0700706 // Adapt changes: 1, elapsed time: 10 sec.
asapersson6eca98b2017-04-04 23:40:50 -0700707 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson09f05612017-05-15 23:40:18 -0700708 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
asapersson0944a802017-04-07 00:57:58 -0700709 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700710
asapersson0944a802017-04-07 00:57:58 -0700711 // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700712 statistics_proxy_.reset();
713 EXPECT_EQ(1,
714 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
715 EXPECT_EQ(
716 1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
717}
718
719TEST_F(SendStatisticsProxyTest, AdaptChangesStatsStartedAfterFirstSentPacket) {
asapersson09f05612017-05-15 23:40:18 -0700720 // Enable and disable adaptation.
mflodmancc3d4422017-08-03 08:27:51 -0700721 VideoStreamEncoder::AdaptCounts cpu_counts;
722 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700723 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700724 fake_clock_.AdvanceTimeMilliseconds(60000);
asapersson09f05612017-05-15 23:40:18 -0700725 cpu_counts.fps = -1;
726 cpu_counts.resolution = -1;
727 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700728
729 // Send first packet, scaling disabled.
730 // Elapsed time before first packet is sent should be excluded.
asapersson0944a802017-04-07 00:57:58 -0700731 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700732 fake_clock_.AdvanceTimeMilliseconds(60000);
733
asapersson09f05612017-05-15 23:40:18 -0700734 // Enable adaptation.
735 cpu_counts.resolution = 0;
736 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700737 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson0944a802017-04-07 00:57:58 -0700738 UpdateDataCounters(kFirstSsrc);
asapersson6eca98b2017-04-04 23:40:50 -0700739
asapersson0944a802017-04-07 00:57:58 -0700740 // Adapt changes: 1, elapsed time: 20 sec.
asapersson6eca98b2017-04-04 23:40:50 -0700741 fake_clock_.AdvanceTimeMilliseconds(10000);
asapersson09f05612017-05-15 23:40:18 -0700742 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700743
asapersson0944a802017-04-07 00:57:58 -0700744 // Adapt changes: 1, elapsed time: 20 sec => 3 per minute.
asapersson6eca98b2017-04-04 23:40:50 -0700745 statistics_proxy_.reset();
746 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
747 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 3));
748}
749
750TEST_F(SendStatisticsProxyTest, AdaptChangesReportedAfterContentSwitch) {
asapersson09f05612017-05-15 23:40:18 -0700751 // First RTP packet sent, cpu adaptation enabled.
asapersson0944a802017-04-07 00:57:58 -0700752 UpdateDataCounters(kFirstSsrc);
mflodmancc3d4422017-08-03 08:27:51 -0700753 VideoStreamEncoder::AdaptCounts cpu_counts;
754 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700755 quality_counts.fps = -1;
756 quality_counts.resolution = -1;
757 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700758
asapersson0944a802017-04-07 00:57:58 -0700759 // Adapt changes: 2, elapsed time: 15 sec => 8 per minute.
asapersson09f05612017-05-15 23:40:18 -0700760 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700761 fake_clock_.AdvanceTimeMilliseconds(6000);
asapersson09f05612017-05-15 23:40:18 -0700762 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700763 fake_clock_.AdvanceTimeMilliseconds(9000);
764
765 // Switch content type, real-time stats should be updated.
766 VideoEncoderConfig config;
767 config.content_type = VideoEncoderConfig::ContentType::kScreen;
768 statistics_proxy_->OnEncoderReconfigured(config, 50);
769 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
770 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 8));
771 EXPECT_EQ(0,
772 metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
773
asapersson0944a802017-04-07 00:57:58 -0700774 // First RTP packet sent, scaling enabled.
775 UpdateDataCounters(kFirstSsrc);
asapersson09f05612017-05-15 23:40:18 -0700776 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700777
asapersson0944a802017-04-07 00:57:58 -0700778 // Adapt changes: 4, elapsed time: 120 sec => 2 per minute.
asapersson09f05612017-05-15 23:40:18 -0700779 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
780 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
781 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
782 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
asapersson6eca98b2017-04-04 23:40:50 -0700783 fake_clock_.AdvanceTimeMilliseconds(120000);
784
785 statistics_proxy_.reset();
786 EXPECT_EQ(1, metrics::NumSamples(
787 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu"));
788 EXPECT_EQ(1, metrics::NumEvents(
789 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu", 2));
790 EXPECT_EQ(0, metrics::NumSamples(
791 "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Quality"));
792}
793
asapersson59bac1a2016-01-07 23:36:00 -0800794TEST_F(SendStatisticsProxyTest, SwitchContentTypeUpdatesHistograms) {
perkj803d97f2016-11-01 11:45:46 -0700795 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
asapersson59bac1a2016-01-07 23:36:00 -0800796 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
797
Pera48ddb72016-09-29 11:48:50 +0200798 // No switch, stats should not be updated.
799 VideoEncoderConfig config;
800 config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
801 statistics_proxy_->OnEncoderReconfigured(config, 50);
asapersson01d70a32016-05-20 06:29:46 -0700802 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -0800803
804 // Switch to screenshare, real-time stats should be updated.
Pera48ddb72016-09-29 11:48:50 +0200805 config.content_type = VideoEncoderConfig::ContentType::kScreen;
806 statistics_proxy_->OnEncoderReconfigured(config, 50);
asapersson01d70a32016-05-20 06:29:46 -0700807 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
asapersson59bac1a2016-01-07 23:36:00 -0800808}
809
asapersson320e45a2016-11-29 01:40:35 -0800810TEST_F(SendStatisticsProxyTest, InputResolutionHistogramsAreUpdated) {
811 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
812 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
perkj803d97f2016-11-01 11:45:46 -0700813
asapersson320e45a2016-11-29 01:40:35 -0800814 statistics_proxy_.reset();
815 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
816 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputWidthInPixels", kWidth));
817 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputHeightInPixels"));
818 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputHeightInPixels", kHeight));
819}
820
821TEST_F(SendStatisticsProxyTest, SentResolutionHistogramsAreUpdated) {
822 EncodedImage encoded_image;
823 encoded_image._encodedWidth = kWidth;
824 encoded_image._encodedHeight = kHeight;
825 for (int i = 0; i <= SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
826 encoded_image._timeStamp = i + 1;
827 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
828 }
829 statistics_proxy_.reset();
830 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
831 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentWidthInPixels", kWidth));
832 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
833 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentHeightInPixels", kHeight));
834}
835
836TEST_F(SendStatisticsProxyTest, InputFpsHistogramIsUpdated) {
837 const int kFps = 20;
838 const int kMinPeriodicSamples = 6;
839 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
840 for (int i = 0; i <= frames; ++i) {
841 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
842 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
843 }
844 statistics_proxy_.reset();
845 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
846 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
847}
848
849TEST_F(SendStatisticsProxyTest, SentFpsHistogramIsUpdated) {
850 EncodedImage encoded_image;
851 const int kFps = 20;
852 const int kMinPeriodicSamples = 6;
853 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000 + 1;
854 for (int i = 0; i <= frames; ++i) {
855 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
856 encoded_image._timeStamp = i + 1;
857 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
858 }
859 statistics_proxy_.reset();
860 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
861 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
862}
863
864TEST_F(SendStatisticsProxyTest, InputFpsHistogramExcludesSuspendedTime) {
865 const int kFps = 20;
866 const int kSuspendTimeMs = 10000;
867 const int kMinPeriodicSamples = 6;
868 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
869 for (int i = 0; i < frames; ++i) {
870 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
871 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
872 }
873 // Suspend.
874 statistics_proxy_->OnSuspendChange(true);
875 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
876
877 for (int i = 0; i < frames; ++i) {
878 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
879 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
880 }
881 // Suspended time interval should not affect the framerate.
882 statistics_proxy_.reset();
883 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
884 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
885}
886
887TEST_F(SendStatisticsProxyTest, SentFpsHistogramExcludesSuspendedTime) {
888 EncodedImage encoded_image;
889 const int kFps = 20;
890 const int kSuspendTimeMs = 10000;
891 const int kMinPeriodicSamples = 6;
892 int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
893 for (int i = 0; i <= frames; ++i) {
894 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
895 encoded_image._timeStamp = i + 1;
896 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
897 }
898 // Suspend.
899 statistics_proxy_->OnSuspendChange(true);
900 fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
901
902 for (int i = 0; i <= frames; ++i) {
903 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
904 encoded_image._timeStamp = i + 1;
905 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
906 }
907 // Suspended time interval should not affect the framerate.
908 statistics_proxy_.reset();
909 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
910 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
911}
912
asaperssonf4e44af2017-04-19 02:01:06 -0700913TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramNotUpdatedWhenDisabled) {
mflodmancc3d4422017-08-03 08:27:51 -0700914 VideoStreamEncoder::AdaptCounts cpu_counts;
915 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700916 cpu_counts.resolution = -1;
917 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asaperssonf4e44af2017-04-19 02:01:06 -0700918
919 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
920 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
921
922 statistics_proxy_.reset();
923 EXPECT_EQ(0,
924 metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
925}
926
927TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramUpdated) {
mflodmancc3d4422017-08-03 08:27:51 -0700928 VideoStreamEncoder::AdaptCounts cpu_counts;
929 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -0700930 cpu_counts.resolution = 0;
931 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asaperssonf4e44af2017-04-19 02:01:06 -0700932
perkj803d97f2016-11-01 11:45:46 -0700933 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
934 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
935
asapersson09f05612017-05-15 23:40:18 -0700936 cpu_counts.resolution = 1;
937 statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
perkj803d97f2016-11-01 11:45:46 -0700938
939 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
940 statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
941
942 statistics_proxy_.reset();
943 EXPECT_EQ(1,
944 metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
945 EXPECT_EQ(
946 1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50));
947}
948
asapersson4374a092016-07-27 00:39:09 -0700949TEST_F(SendStatisticsProxyTest, LifetimeHistogramIsUpdated) {
950 const int64_t kTimeSec = 3;
951 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
952 statistics_proxy_.reset();
953 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
954 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.SendStreamLifetimeInSeconds",
955 kTimeSec));
956}
957
958TEST_F(SendStatisticsProxyTest, CodecTypeHistogramIsUpdated) {
959 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
960 statistics_proxy_.reset();
961 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoder.CodecType"));
962}
963
asapersson66d4b372016-12-19 06:50:53 -0800964TEST_F(SendStatisticsProxyTest, PauseEventHistogramIsUpdated) {
965 // First RTP packet sent.
966 UpdateDataCounters(kFirstSsrc);
967
968 // Min runtime has passed.
969 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
970 statistics_proxy_.reset();
971 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
972 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
973}
974
975TEST_F(SendStatisticsProxyTest,
976 PauseEventHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
977 // First RTP packet sent.
978 UpdateDataCounters(kFirstSsrc);
979
980 // Min runtime has not passed.
981 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
982 statistics_proxy_.reset();
983 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
984 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
985}
986
987TEST_F(SendStatisticsProxyTest,
988 PauseEventHistogramIsNotUpdatedIfNoMediaIsSent) {
989 // First RTP packet not sent.
990 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
991 statistics_proxy_.reset();
992 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
993}
994
995TEST_F(SendStatisticsProxyTest, NoPauseEvent) {
996 // First RTP packet sent and min runtime passed.
997 UpdateDataCounters(kFirstSsrc);
998
999 // No change. Video: 10000 ms, paused: 0 ms (0%).
1000 statistics_proxy_->OnSetEncoderTargetRate(50000);
1001 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1002 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1003
1004 statistics_proxy_.reset();
1005 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1006 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
1007 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1008 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 0));
1009}
1010
1011TEST_F(SendStatisticsProxyTest, OnePauseEvent) {
1012 // First RTP packet sent and min runtime passed.
1013 UpdateDataCounters(kFirstSsrc);
1014
1015 // One change. Video: 7000 ms, paused: 3000 ms (30%).
1016 statistics_proxy_->OnSetEncoderTargetRate(50000);
1017 fake_clock_.AdvanceTimeMilliseconds(7000);
1018 statistics_proxy_->OnSetEncoderTargetRate(0);
1019 fake_clock_.AdvanceTimeMilliseconds(3000);
1020 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1021
1022 statistics_proxy_.reset();
1023 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1024 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 1));
1025 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1026 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 30));
1027}
1028
1029TEST_F(SendStatisticsProxyTest, TwoPauseEvents) {
1030 // First RTP packet sent.
1031 UpdateDataCounters(kFirstSsrc);
1032
1033 // Two changes. Video: 19000 ms, paused: 1000 ms (5%).
1034 statistics_proxy_->OnSetEncoderTargetRate(0);
1035 fake_clock_.AdvanceTimeMilliseconds(1000);
1036 statistics_proxy_->OnSetEncoderTargetRate(50000); // Starts on bitrate > 0.
1037 fake_clock_.AdvanceTimeMilliseconds(7000);
1038 statistics_proxy_->OnSetEncoderTargetRate(60000);
1039 fake_clock_.AdvanceTimeMilliseconds(3000);
1040 statistics_proxy_->OnSetEncoderTargetRate(0);
1041 fake_clock_.AdvanceTimeMilliseconds(250);
1042 statistics_proxy_->OnSetEncoderTargetRate(0);
1043 fake_clock_.AdvanceTimeMilliseconds(750);
1044 statistics_proxy_->OnSetEncoderTargetRate(60000);
1045 fake_clock_.AdvanceTimeMilliseconds(5000);
1046 statistics_proxy_->OnSetEncoderTargetRate(50000);
1047 fake_clock_.AdvanceTimeMilliseconds(4000);
1048 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1049
1050 statistics_proxy_.reset();
1051 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1052 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 2));
1053 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1054 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 5));
1055}
1056
1057TEST_F(SendStatisticsProxyTest,
1058 PausedTimeHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1059 // First RTP packet sent.
1060 UpdateDataCounters(kFirstSsrc);
1061 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1062
1063 // Min runtime has not passed.
1064 statistics_proxy_->OnSetEncoderTargetRate(50000);
1065 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1066 statistics_proxy_->OnSetEncoderTargetRate(0); // VideoSendStream::Stop
1067
1068 statistics_proxy_.reset();
1069 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1070}
1071
asapersson118ef002016-03-31 00:00:19 -07001072TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8) {
asapersson118ef002016-03-31 00:00:19 -07001073 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001074 CodecSpecificInfo codec_info;
1075 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001076
perkj803d97f2016-11-01 11:45:46 -07001077 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
kjellander02b3d272016-04-20 05:05:54 -07001078 codec_info.codecSpecific.VP8.simulcastIdx = 0;
asapersson118ef002016-03-31 00:00:19 -07001079 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001080 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
1081 codec_info.codecSpecific.VP8.simulcastIdx = 1;
asapersson118ef002016-03-31 00:00:19 -07001082 encoded_image.qp_ = kQpIdx1;
kjellander02b3d272016-04-20 05:05:54 -07001083 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001084 }
1085 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001086 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S0"));
1087 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S0", kQpIdx0));
1088 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S1"));
1089 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S1", kQpIdx1));
asapersson118ef002016-03-31 00:00:19 -07001090}
1091
1092TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8OneSsrc) {
1093 VideoSendStream::Config config(nullptr);
1094 config.rtp.ssrcs.push_back(kFirstSsrc);
1095 statistics_proxy_.reset(new SendStatisticsProxy(
1096 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1097
asapersson118ef002016-03-31 00:00:19 -07001098 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001099 CodecSpecificInfo codec_info;
1100 codec_info.codecType = kVideoCodecVP8;
asapersson118ef002016-03-31 00:00:19 -07001101
perkj803d97f2016-11-01 11:45:46 -07001102 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
kjellander02b3d272016-04-20 05:05:54 -07001103 codec_info.codecSpecific.VP8.simulcastIdx = 0;
asapersson118ef002016-03-31 00:00:19 -07001104 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001105 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson118ef002016-03-31 00:00:19 -07001106 }
1107 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001108 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8"));
1109 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8", kQpIdx0));
asapersson118ef002016-03-31 00:00:19 -07001110}
1111
asapersson5265fed2016-04-18 02:58:47 -07001112TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9) {
asapersson5265fed2016-04-18 02:58:47 -07001113 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001114 CodecSpecificInfo codec_info;
1115 codec_info.codecType = kVideoCodecVP9;
1116 codec_info.codecSpecific.VP9.num_spatial_layers = 2;
asapersson5265fed2016-04-18 02:58:47 -07001117
perkj803d97f2016-11-01 11:45:46 -07001118 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001119 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001120 codec_info.codecSpecific.VP9.spatial_idx = 0;
1121 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001122 encoded_image.qp_ = kQpIdx1;
kjellander02b3d272016-04-20 05:05:54 -07001123 codec_info.codecSpecific.VP9.spatial_idx = 1;
1124 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001125 }
1126 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001127 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S0"));
1128 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S0", kQpIdx0));
1129 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S1"));
1130 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S1", kQpIdx1));
asapersson5265fed2016-04-18 02:58:47 -07001131}
1132
1133TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9OneSpatialLayer) {
1134 VideoSendStream::Config config(nullptr);
1135 config.rtp.ssrcs.push_back(kFirstSsrc);
1136 statistics_proxy_.reset(new SendStatisticsProxy(
1137 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1138
asapersson5265fed2016-04-18 02:58:47 -07001139 EncodedImage encoded_image;
kjellander02b3d272016-04-20 05:05:54 -07001140 CodecSpecificInfo codec_info;
1141 codec_info.codecType = kVideoCodecVP9;
1142 codec_info.codecSpecific.VP9.num_spatial_layers = 1;
asapersson5265fed2016-04-18 02:58:47 -07001143
perkj803d97f2016-11-01 11:45:46 -07001144 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
asapersson5265fed2016-04-18 02:58:47 -07001145 encoded_image.qp_ = kQpIdx0;
kjellander02b3d272016-04-20 05:05:54 -07001146 codec_info.codecSpecific.VP9.spatial_idx = 0;
1147 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
asapersson5265fed2016-04-18 02:58:47 -07001148 }
1149 statistics_proxy_.reset();
asapersson01d70a32016-05-20 06:29:46 -07001150 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9"));
1151 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9", kQpIdx0));
asapersson5265fed2016-04-18 02:58:47 -07001152}
1153
asapersson827cab32016-11-02 09:08:47 -07001154TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_H264) {
1155 EncodedImage encoded_image;
1156 CodecSpecificInfo codec_info;
1157 codec_info.codecType = kVideoCodecH264;
1158
1159 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
1160 encoded_image.qp_ = kQpIdx0;
1161 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
1162 }
1163 statistics_proxy_.reset();
1164 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264"));
1165 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264", kQpIdx0));
1166}
1167
asapersson4ee70462016-10-31 04:05:12 -07001168TEST_F(SendStatisticsProxyTest,
1169 BandwidthLimitedHistogramsNotUpdatedWhenDisabled) {
1170 EncodedImage encoded_image;
1171 // encoded_image.adapt_reason_.bw_resolutions_disabled by default: -1
perkj803d97f2016-11-01 11:45:46 -07001172 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
asapersson4ee70462016-10-31 04:05:12 -07001173 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1174
1175 // Histograms are updated when the statistics_proxy_ is deleted.
1176 statistics_proxy_.reset();
1177 EXPECT_EQ(0, metrics::NumSamples(
1178 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1179 EXPECT_EQ(0, metrics::NumSamples(
1180 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
1181}
1182
1183TEST_F(SendStatisticsProxyTest,
1184 BandwidthLimitedHistogramsUpdatedWhenEnabled_NoResolutionDisabled) {
1185 const int kResolutionsDisabled = 0;
1186 EncodedImage encoded_image;
1187 encoded_image.adapt_reason_.bw_resolutions_disabled = kResolutionsDisabled;
perkj803d97f2016-11-01 11:45:46 -07001188 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
asapersson4ee70462016-10-31 04:05:12 -07001189 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1190
1191 // Histograms are updated when the statistics_proxy_ is deleted.
1192 statistics_proxy_.reset();
1193 EXPECT_EQ(1, metrics::NumSamples(
1194 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1195 EXPECT_EQ(1, metrics::NumEvents(
1196 "WebRTC.Video.BandwidthLimitedResolutionInPercent", 0));
1197 // No resolution disabled.
1198 EXPECT_EQ(0, metrics::NumSamples(
1199 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
1200}
1201
1202TEST_F(SendStatisticsProxyTest,
1203 BandwidthLimitedHistogramsUpdatedWhenEnabled_OneResolutionDisabled) {
1204 const int kResolutionsDisabled = 1;
1205 EncodedImage encoded_image;
1206 encoded_image.adapt_reason_.bw_resolutions_disabled = kResolutionsDisabled;
perkj803d97f2016-11-01 11:45:46 -07001207 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
asapersson4ee70462016-10-31 04:05:12 -07001208 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1209
1210 // Histograms are updated when the statistics_proxy_ is deleted.
1211 statistics_proxy_.reset();
1212 EXPECT_EQ(1, metrics::NumSamples(
1213 "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
1214 EXPECT_EQ(1, metrics::NumEvents(
1215 "WebRTC.Video.BandwidthLimitedResolutionInPercent", 100));
1216 // Resolutions disabled.
1217 EXPECT_EQ(1, metrics::NumSamples(
1218 "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
1219 EXPECT_EQ(
1220 1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionsDisabled",
1221 kResolutionsDisabled));
1222}
1223
1224TEST_F(SendStatisticsProxyTest,
1225 QualityLimitedHistogramsNotUpdatedWhenDisabled) {
mflodmancc3d4422017-08-03 08:27:51 -07001226 VideoStreamEncoder::AdaptCounts cpu_counts;
1227 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -07001228 quality_counts.resolution = -1;
1229 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001230 EncodedImage encoded_image;
perkj803d97f2016-11-01 11:45:46 -07001231 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08001232 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07001233
1234 // Histograms are updated when the statistics_proxy_ is deleted.
1235 statistics_proxy_.reset();
1236 EXPECT_EQ(
1237 0, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
1238 EXPECT_EQ(0, metrics::NumSamples(
1239 "WebRTC.Video.QualityLimitedResolutionDownscales"));
1240}
1241
1242TEST_F(SendStatisticsProxyTest,
1243 QualityLimitedHistogramsUpdatedWhenEnabled_NoResolutionDownscale) {
mflodmancc3d4422017-08-03 08:27:51 -07001244 VideoStreamEncoder::AdaptCounts cpu_counts;
1245 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -07001246 quality_counts.resolution = 0;
1247 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001248 EncodedImage encoded_image;
perkj803d97f2016-11-01 11:45:46 -07001249 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08001250 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07001251
1252 // Histograms are updated when the statistics_proxy_ is deleted.
1253 statistics_proxy_.reset();
1254 EXPECT_EQ(
1255 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
1256 EXPECT_EQ(1, metrics::NumEvents(
1257 "WebRTC.Video.QualityLimitedResolutionInPercent", 0));
1258 // No resolution downscale.
1259 EXPECT_EQ(0, metrics::NumSamples(
1260 "WebRTC.Video.QualityLimitedResolutionDownscales"));
1261}
1262
1263TEST_F(SendStatisticsProxyTest,
1264 QualityLimitedHistogramsUpdatedWhenEnabled_TwoResolutionDownscales) {
1265 const int kDownscales = 2;
mflodmancc3d4422017-08-03 08:27:51 -07001266 VideoStreamEncoder::AdaptCounts cpu_counts;
1267 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -07001268 quality_counts.resolution = kDownscales;
1269 statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001270 EncodedImage encoded_image;
perkj803d97f2016-11-01 11:45:46 -07001271 for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
kthelgason0cd27ba2016-12-19 06:32:16 -08001272 statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
asapersson4ee70462016-10-31 04:05:12 -07001273 // Histograms are updated when the statistics_proxy_ is deleted.
1274 statistics_proxy_.reset();
1275 EXPECT_EQ(
1276 1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
1277 EXPECT_EQ(1, metrics::NumEvents(
1278 "WebRTC.Video.QualityLimitedResolutionInPercent", 100));
1279 // Resolution downscales.
1280 EXPECT_EQ(1, metrics::NumSamples(
1281 "WebRTC.Video.QualityLimitedResolutionDownscales"));
1282 EXPECT_EQ(
1283 1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionDownscales",
1284 kDownscales));
1285}
1286
1287TEST_F(SendStatisticsProxyTest, GetStatsReportsBandwidthLimitedResolution) {
1288 // Initially false.
1289 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1290 // No resolution scale by default.
1291 EncodedImage encoded_image;
1292 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1293 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
kthelgason0cd27ba2016-12-19 06:32:16 -08001294
1295 // Simulcast disabled resolutions
1296 encoded_image.adapt_reason_.bw_resolutions_disabled = 1;
1297 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1298 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1299
asapersson4ee70462016-10-31 04:05:12 -07001300 encoded_image.adapt_reason_.bw_resolutions_disabled = 0;
asapersson4ee70462016-10-31 04:05:12 -07001301 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1302 EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
kthelgason0cd27ba2016-12-19 06:32:16 -08001303
1304 // Resolution scaled due to quality.
mflodmancc3d4422017-08-03 08:27:51 -07001305 VideoStreamEncoder::AdaptCounts cpu_counts;
1306 VideoStreamEncoder::AdaptCounts quality_counts;
asapersson09f05612017-05-15 23:40:18 -07001307 quality_counts.resolution = 1;
1308 statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
asapersson4ee70462016-10-31 04:05:12 -07001309 statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1310 EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1311}
1312
asapersson66d4b372016-12-19 06:50:53 -08001313TEST_F(SendStatisticsProxyTest, GetStatsReportsTargetMediaBitrate) {
1314 // Initially zero.
1315 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
1316
1317 const int kBitrate = 100000;
1318 statistics_proxy_->OnSetEncoderTargetRate(kBitrate);
1319 EXPECT_EQ(kBitrate, statistics_proxy_->GetStats().target_media_bitrate_bps);
1320
1321 statistics_proxy_->OnSetEncoderTargetRate(0);
1322 EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
1323}
1324
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001325TEST_F(SendStatisticsProxyTest, NoSubstreams) {
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001326 uint32_t excluded_ssrc =
stefan@webrtc.org58e2d262014-08-14 15:10:49 +00001327 std::max(
1328 *std::max_element(config_.rtp.ssrcs.begin(), config_.rtp.ssrcs.end()),
1329 *std::max_element(config_.rtp.rtx.ssrcs.begin(),
1330 config_.rtp.rtx.ssrcs.end())) +
1331 1;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001332 // From RtcpStatisticsCallback.
1333 RtcpStatistics rtcp_stats;
1334 RtcpStatisticsCallback* rtcp_callback = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001335 rtcp_callback->StatisticsUpdated(rtcp_stats, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001336
1337 // From BitrateStatisticsObserver.
sprangcd349d92016-07-13 09:11:28 -07001338 uint32_t total = 0;
1339 uint32_t retransmit = 0;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001340 BitrateStatisticsObserver* bitrate_observer = statistics_proxy_.get();
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001341 bitrate_observer->Notify(total, retransmit, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001342
1343 // From FrameCountObserver.
1344 FrameCountObserver* fps_observer = statistics_proxy_.get();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00001345 FrameCounts frame_counts;
1346 frame_counts.key_frames = 1;
pbos@webrtc.org49096de2015-02-24 22:37:52 +00001347 fps_observer->FrameCountUpdated(frame_counts, excluded_ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001348
1349 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
1350 EXPECT_TRUE(stats.substreams.empty());
1351}
1352
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001353TEST_F(SendStatisticsProxyTest, EncodedResolutionTimesOut) {
1354 static const int kEncodedWidth = 123;
1355 static const int kEncodedHeight = 81;
1356 EncodedImage encoded_image;
1357 encoded_image._encodedWidth = kEncodedWidth;
1358 encoded_image._encodedHeight = kEncodedHeight;
1359
kjellander02b3d272016-04-20 05:05:54 -07001360 CodecSpecificInfo codec_info;
1361 codec_info.codecType = kVideoCodecVP8;
1362 codec_info.codecSpecific.VP8.simulcastIdx = 0;
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001363
kjellander02b3d272016-04-20 05:05:54 -07001364 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
1365 codec_info.codecSpecific.VP8.simulcastIdx = 1;
1366 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001367
1368 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001369 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
1370 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
1371 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
1372 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001373
1374 // Forward almost to timeout, this should not have removed stats.
1375 fake_clock_.AdvanceTimeMilliseconds(SendStatisticsProxy::kStatsTimeoutMs - 1);
1376 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001377 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
1378 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001379
1380 // Update the first SSRC with bogus RTCP stats to make sure that encoded
1381 // resolution still times out (no global timeout for all stats).
1382 RtcpStatistics rtcp_statistics;
1383 RtcpStatisticsCallback* rtcp_stats = statistics_proxy_.get();
1384 rtcp_stats->StatisticsUpdated(rtcp_statistics, config_.rtp.ssrcs[0]);
1385
1386 // Report stats for second SSRC to make sure it's not outdated along with the
1387 // first SSRC.
kjellander02b3d272016-04-20 05:05:54 -07001388 codec_info.codecSpecific.VP8.simulcastIdx = 1;
1389 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001390
1391 // Forward 1 ms, reach timeout, substream 0 should have no resolution
1392 // reported, but substream 1 should.
1393 fake_clock_.AdvanceTimeMilliseconds(1);
1394 stats = statistics_proxy_->GetStats();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001395 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].width);
1396 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].height);
1397 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
1398 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001399}
1400
Peter Boström20f3f942015-05-15 11:33:39 +02001401TEST_F(SendStatisticsProxyTest, ClearsResolutionFromInactiveSsrcs) {
1402 static const int kEncodedWidth = 123;
1403 static const int kEncodedHeight = 81;
1404 EncodedImage encoded_image;
1405 encoded_image._encodedWidth = kEncodedWidth;
1406 encoded_image._encodedHeight = kEncodedHeight;
1407
kjellander02b3d272016-04-20 05:05:54 -07001408 CodecSpecificInfo codec_info;
1409 codec_info.codecType = kVideoCodecVP8;
1410 codec_info.codecSpecific.VP8.simulcastIdx = 0;
Peter Boström20f3f942015-05-15 11:33:39 +02001411
kjellander02b3d272016-04-20 05:05:54 -07001412 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
1413 codec_info.codecSpecific.VP8.simulcastIdx = 1;
1414 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
Peter Boström20f3f942015-05-15 11:33:39 +02001415
1416 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
1417 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
1418 EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
1419 EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
1420 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].width);
1421 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].height);
1422}
1423
1424TEST_F(SendStatisticsProxyTest, ClearsBitratesFromInactiveSsrcs) {
sprangcd349d92016-07-13 09:11:28 -07001425 uint32_t bitrate = 42;
Peter Boström20f3f942015-05-15 11:33:39 +02001426 BitrateStatisticsObserver* observer = statistics_proxy_.get();
1427 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[0]);
1428 observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[1]);
1429
1430 statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
1431
1432 VideoSendStream::Stats stats = statistics_proxy_->GetStats();
sprangcd349d92016-07-13 09:11:28 -07001433 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02001434 stats.substreams[config_.rtp.ssrcs[0]].total_bitrate_bps);
sprangcd349d92016-07-13 09:11:28 -07001435 EXPECT_EQ(static_cast<int>(bitrate),
Peter Boström20f3f942015-05-15 11:33:39 +02001436 stats.substreams[config_.rtp.ssrcs[0]].retransmit_bitrate_bps);
1437 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].total_bitrate_bps);
1438 EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].retransmit_bitrate_bps);
1439}
1440
sprang07fb9be2016-02-24 07:55:00 -08001441TEST_F(SendStatisticsProxyTest, ResetsRtcpCountersOnContentChange) {
1442 RtcpPacketTypeCounterObserver* proxy =
1443 static_cast<RtcpPacketTypeCounterObserver*>(statistics_proxy_.get());
1444 RtcpPacketTypeCounter counters;
1445 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
1446 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1447 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1448
1449 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
1450
1451 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
1452 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
1453 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
1454 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
1455 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
1456
1457 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1458 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1459
1460 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02001461 VideoEncoderConfig config;
1462 config.content_type = VideoEncoderConfig::ContentType::kScreen;
1463 statistics_proxy_->OnEncoderReconfigured(config, 50);
sprang07fb9be2016-02-24 07:55:00 -08001464
asapersson01d70a32016-05-20 06:29:46 -07001465 EXPECT_EQ(1,
1466 metrics::NumSamples("WebRTC.Video.NackPacketsReceivedPerMinute"));
1467 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsReceivedPerMinute"));
1468 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsReceivedPerMinute"));
1469 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001470 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
1471
1472 const int kRate = 60 * 2; // Packets per minute with two streams.
1473
asapersson01d70a32016-05-20 06:29:46 -07001474 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NackPacketsReceivedPerMinute",
1475 1 * kRate));
1476 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FirPacketsReceivedPerMinute",
1477 2 * kRate));
1478 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PliPacketsReceivedPerMinute",
1479 3 * kRate));
1480 EXPECT_EQ(
1481 1, metrics::NumEvents("WebRTC.Video.UniqueNackRequestsReceivedInPercent",
1482 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08001483
1484 // New start time but same counter values.
1485 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1486 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1487
1488 fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
1489
1490 counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
1491 counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
1492 counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
1493 counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
1494 counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
1495
1496 proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
1497 proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
1498
1499 SetUp(); // Reset stats proxy also causes histograms to be reported.
1500
asapersson01d70a32016-05-20 06:29:46 -07001501 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001502 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute"));
asapersson01d70a32016-05-20 06:29:46 -07001503 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001504 "WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute"));
asapersson01d70a32016-05-20 06:29:46 -07001505 EXPECT_EQ(1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001506 "WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute"));
1507 EXPECT_EQ(
asapersson01d70a32016-05-20 06:29:46 -07001508 1, metrics::NumSamples(
sprang07fb9be2016-02-24 07:55:00 -08001509 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent"));
1510
asapersson01d70a32016-05-20 06:29:46 -07001511 EXPECT_EQ(1, metrics::NumEvents(
1512 "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute",
1513 1 * kRate));
1514 EXPECT_EQ(1, metrics::NumEvents(
1515 "WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute",
1516 2 * kRate));
1517 EXPECT_EQ(1, metrics::NumEvents(
1518 "WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute",
1519 3 * kRate));
1520 EXPECT_EQ(1,
1521 metrics::NumEvents(
1522 "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent",
1523 4 * 100 / 5));
sprang07fb9be2016-02-24 07:55:00 -08001524}
1525
asaperssona6a699a2016-11-25 03:52:46 -08001526TEST_F(SendStatisticsProxyTest, GetStatsReportsIsFlexFec) {
1527 statistics_proxy_.reset(
1528 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
1529 VideoEncoderConfig::ContentType::kRealtimeVideo));
1530
1531 StreamDataCountersCallback* proxy =
1532 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
1533 StreamDataCounters counters;
1534 proxy->DataCountersUpdated(counters, kFirstSsrc);
1535 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
1536
1537 EXPECT_FALSE(GetStreamStats(kFirstSsrc).is_flexfec);
1538 EXPECT_TRUE(GetStreamStats(kFlexFecSsrc).is_flexfec);
1539}
1540
1541TEST_F(SendStatisticsProxyTest, SendBitratesAreReportedWithFlexFecEnabled) {
1542 statistics_proxy_.reset(
1543 new SendStatisticsProxy(&fake_clock_, GetTestConfigWithFlexFec(),
1544 VideoEncoderConfig::ContentType::kRealtimeVideo));
1545
1546 StreamDataCountersCallback* proxy =
1547 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
asaperssona6a699a2016-11-25 03:52:46 -08001548 StreamDataCounters counters;
1549 StreamDataCounters rtx_counters;
asaperssona6a699a2016-11-25 03:52:46 -08001550
asapersson93e1e232017-02-06 05:18:35 -08001551 const int kMinRequiredPeriodSamples = 8;
1552 const int kPeriodIntervalMs = 2000;
1553 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1554 counters.transmitted.packets += 20;
1555 counters.transmitted.header_bytes += 500;
1556 counters.transmitted.padding_bytes += 1000;
1557 counters.transmitted.payload_bytes += 2000;
1558 counters.retransmitted.packets += 2;
1559 counters.retransmitted.header_bytes += 25;
1560 counters.retransmitted.padding_bytes += 100;
1561 counters.retransmitted.payload_bytes += 250;
1562 counters.fec = counters.retransmitted;
1563 rtx_counters.transmitted = counters.transmitted;
1564 // Advance one interval and update counters.
1565 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1566 proxy->DataCountersUpdated(counters, kFirstSsrc);
1567 proxy->DataCountersUpdated(counters, kSecondSsrc);
1568 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
1569 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
1570 proxy->DataCountersUpdated(counters, kFlexFecSsrc);
1571 }
asaperssona6a699a2016-11-25 03:52:46 -08001572
asaperssona6a699a2016-11-25 03:52:46 -08001573 statistics_proxy_.reset();
asapersson93e1e232017-02-06 05:18:35 -08001574 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
asaperssona6a699a2016-11-25 03:52:46 -08001575 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001576 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
1577 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
1578 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
1579 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
1580 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
asaperssona6a699a2016-11-25 03:52:46 -08001581 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001582 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
1583 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
asaperssona6a699a2016-11-25 03:52:46 -08001584 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001585 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
1586 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
1587 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
1588 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
1589 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
asaperssona6a699a2016-11-25 03:52:46 -08001590 EXPECT_EQ(1,
1591 metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
asaperssona6a699a2016-11-25 03:52:46 -08001592 EXPECT_EQ(
asapersson93e1e232017-02-06 05:18:35 -08001593 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
asaperssona6a699a2016-11-25 03:52:46 -08001594}
1595
Erik Språng22c2b482016-03-01 09:40:42 +01001596TEST_F(SendStatisticsProxyTest, ResetsRtpCountersOnContentChange) {
1597 StreamDataCountersCallback* proxy =
1598 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
1599 StreamDataCounters counters;
1600 StreamDataCounters rtx_counters;
1601 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
Erik Språng22c2b482016-03-01 09:40:42 +01001602
asapersson93e1e232017-02-06 05:18:35 -08001603 const int kMinRequiredPeriodSamples = 8;
1604 const int kPeriodIntervalMs = 2000;
1605 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1606 counters.transmitted.packets += 20;
1607 counters.transmitted.header_bytes += 500;
1608 counters.transmitted.padding_bytes += 1000;
1609 counters.transmitted.payload_bytes += 2000;
1610 counters.retransmitted.packets += 2;
1611 counters.retransmitted.header_bytes += 25;
1612 counters.retransmitted.padding_bytes += 100;
1613 counters.retransmitted.payload_bytes += 250;
1614 counters.fec = counters.retransmitted;
1615 rtx_counters.transmitted = counters.transmitted;
1616 // Advance one interval and update counters.
1617 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1618 proxy->DataCountersUpdated(counters, kFirstSsrc);
1619 proxy->DataCountersUpdated(counters, kSecondSsrc);
1620 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
1621 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
1622 }
Erik Språng22c2b482016-03-01 09:40:42 +01001623
1624 // Changing content type causes histograms to be reported.
Pera48ddb72016-09-29 11:48:50 +02001625 VideoEncoderConfig config;
1626 config.content_type = VideoEncoderConfig::ContentType::kScreen;
asapersson93e1e232017-02-06 05:18:35 -08001627 statistics_proxy_->OnEncoderReconfigured(config, 50000);
Erik Språng22c2b482016-03-01 09:40:42 +01001628
asapersson93e1e232017-02-06 05:18:35 -08001629 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
asapersson01d70a32016-05-20 06:29:46 -07001630 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001631 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
1632 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
1633 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
1634 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
1635 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
asapersson01d70a32016-05-20 06:29:46 -07001636 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001637 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
1638 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
asapersson01d70a32016-05-20 06:29:46 -07001639 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001640 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
1641 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
1642 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
1643 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
1644 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
Erik Språng22c2b482016-03-01 09:40:42 +01001645 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07001646 metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01001647 EXPECT_EQ(
asapersson93e1e232017-02-06 05:18:35 -08001648 1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
Erik Språng22c2b482016-03-01 09:40:42 +01001649
asapersson93e1e232017-02-06 05:18:35 -08001650 // New metric counters but same data counters.
Erik Språng22c2b482016-03-01 09:40:42 +01001651 // Double counter values, this should result in the same counts as before but
1652 // with new histogram names.
asapersson93e1e232017-02-06 05:18:35 -08001653 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1654 counters.transmitted.packets += 20;
1655 counters.transmitted.header_bytes += 500;
1656 counters.transmitted.padding_bytes += 1000;
1657 counters.transmitted.payload_bytes += 2000;
1658 counters.retransmitted.packets += 2;
1659 counters.retransmitted.header_bytes += 25;
1660 counters.retransmitted.padding_bytes += 100;
1661 counters.retransmitted.payload_bytes += 250;
1662 counters.fec = counters.retransmitted;
1663 rtx_counters.transmitted = counters.transmitted;
1664 // Advance one interval and update counters.
1665 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1666 proxy->DataCountersUpdated(counters, kFirstSsrc);
1667 proxy->DataCountersUpdated(counters, kSecondSsrc);
1668 proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
1669 proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
1670 }
Erik Språng22c2b482016-03-01 09:40:42 +01001671
asapersson93e1e232017-02-06 05:18:35 -08001672 // Reset stats proxy also causes histograms to be reported.
1673 statistics_proxy_.reset();
Erik Språng22c2b482016-03-01 09:40:42 +01001674
asapersson93e1e232017-02-06 05:18:35 -08001675 // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
asapersson01d70a32016-05-20 06:29:46 -07001676 EXPECT_EQ(1,
1677 metrics::NumSamples("WebRTC.Video.Screenshare.BitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001678 EXPECT_EQ(
1679 1, metrics::NumEvents("WebRTC.Video.Screenshare.BitrateSentInKbps", 56));
1680 // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec = 28 kbps
1681 EXPECT_EQ(
1682 1, metrics::NumSamples("WebRTC.Video.Screenshare.RtxBitrateSentInKbps"));
1683 EXPECT_EQ(1, metrics::NumEvents(
1684 "WebRTC.Video.Screenshare.RtxBitrateSentInKbps", 28));
1685 // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec = 12 kbps
asapersson01d70a32016-05-20 06:29:46 -07001686 EXPECT_EQ(1, metrics::NumSamples(
Erik Språng22c2b482016-03-01 09:40:42 +01001687 "WebRTC.Video.Screenshare.MediaBitrateSentInKbps"));
asapersson01d70a32016-05-20 06:29:46 -07001688 EXPECT_EQ(1, metrics::NumEvents(
asapersson93e1e232017-02-06 05:18:35 -08001689 "WebRTC.Video.Screenshare.MediaBitrateSentInKbps", 12));
1690 // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
asapersson01d70a32016-05-20 06:29:46 -07001691 EXPECT_EQ(1, metrics::NumSamples(
Erik Språng22c2b482016-03-01 09:40:42 +01001692 "WebRTC.Video.Screenshare.PaddingBitrateSentInKbps"));
asapersson93e1e232017-02-06 05:18:35 -08001693 EXPECT_EQ(1, metrics::NumEvents(
1694 "WebRTC.Video.Screenshare.PaddingBitrateSentInKbps", 16));
1695 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
1696 EXPECT_EQ(
1697 1, metrics::NumSamples("WebRTC.Video.Screenshare.FecBitrateSentInKbps"));
1698 EXPECT_EQ(1, metrics::NumEvents(
1699 "WebRTC.Video.Screenshare.FecBitrateSentInKbps", 3));
1700 // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
asapersson01d70a32016-05-20 06:29:46 -07001701 EXPECT_EQ(1, metrics::NumSamples(
Erik Språng22c2b482016-03-01 09:40:42 +01001702 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps"));
asapersson01d70a32016-05-20 06:29:46 -07001703 EXPECT_EQ(1,
1704 metrics::NumEvents(
asapersson93e1e232017-02-06 05:18:35 -08001705 "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps", 3));
1706}
Erik Språng22c2b482016-03-01 09:40:42 +01001707
asapersson93e1e232017-02-06 05:18:35 -08001708TEST_F(SendStatisticsProxyTest, RtxBitrateIsZeroWhenEnabledAndNoRtxDataIsSent) {
1709 StreamDataCountersCallback* proxy =
1710 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
1711 StreamDataCounters counters;
1712 StreamDataCounters rtx_counters;
Erik Språng22c2b482016-03-01 09:40:42 +01001713
asapersson93e1e232017-02-06 05:18:35 -08001714 const int kMinRequiredPeriodSamples = 8;
1715 const int kPeriodIntervalMs = 2000;
1716 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1717 counters.transmitted.packets += 20;
1718 counters.transmitted.header_bytes += 500;
1719 counters.transmitted.payload_bytes += 2000;
1720 counters.fec = counters.retransmitted;
1721 // Advance one interval and update counters.
1722 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1723 proxy->DataCountersUpdated(counters, kFirstSsrc);
1724 }
1725
1726 // RTX enabled. No data sent over RTX.
1727 statistics_proxy_.reset();
1728 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
1729 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 0));
1730}
1731
1732TEST_F(SendStatisticsProxyTest, RtxBitrateNotReportedWhenNotEnabled) {
1733 VideoSendStream::Config config(nullptr);
1734 config.rtp.ssrcs.push_back(kFirstSsrc); // RTX not configured.
1735 statistics_proxy_.reset(new SendStatisticsProxy(
1736 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1737
1738 StreamDataCountersCallback* proxy =
1739 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
1740 StreamDataCounters counters;
1741
1742 const int kMinRequiredPeriodSamples = 8;
1743 const int kPeriodIntervalMs = 2000;
1744 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1745 counters.transmitted.packets += 20;
1746 counters.transmitted.header_bytes += 500;
1747 counters.transmitted.payload_bytes += 2000;
1748 counters.fec = counters.retransmitted;
1749 // Advance one interval and update counters.
1750 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1751 proxy->DataCountersUpdated(counters, kFirstSsrc);
1752 }
1753
1754 // RTX not enabled.
1755 statistics_proxy_.reset();
1756 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
1757}
1758
1759TEST_F(SendStatisticsProxyTest, FecBitrateIsZeroWhenEnabledAndNoFecDataIsSent) {
1760 StreamDataCountersCallback* proxy =
1761 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
1762 StreamDataCounters counters;
1763 StreamDataCounters rtx_counters;
1764
1765 const int kMinRequiredPeriodSamples = 8;
1766 const int kPeriodIntervalMs = 2000;
1767 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1768 counters.transmitted.packets += 20;
1769 counters.transmitted.header_bytes += 500;
1770 counters.transmitted.payload_bytes += 2000;
1771 // Advance one interval and update counters.
1772 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1773 proxy->DataCountersUpdated(counters, kFirstSsrc);
1774 }
1775
1776 // FEC enabled. No FEC data sent.
1777 statistics_proxy_.reset();
1778 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
1779 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 0));
1780}
1781
1782TEST_F(SendStatisticsProxyTest, FecBitrateNotReportedWhenNotEnabled) {
1783 VideoSendStream::Config config(nullptr);
1784 config.rtp.ssrcs.push_back(kFirstSsrc); // FEC not configured.
1785 statistics_proxy_.reset(new SendStatisticsProxy(
1786 &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
1787
1788 StreamDataCountersCallback* proxy =
1789 static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
1790 StreamDataCounters counters;
1791
1792 const int kMinRequiredPeriodSamples = 8;
1793 const int kPeriodIntervalMs = 2000;
1794 for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
1795 counters.transmitted.packets += 20;
1796 counters.transmitted.header_bytes += 500;
1797 counters.transmitted.payload_bytes += 2000;
1798 counters.fec = counters.retransmitted;
1799 // Advance one interval and update counters.
1800 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
1801 proxy->DataCountersUpdated(counters, kFirstSsrc);
1802 }
1803
1804 // FEC not enabled.
1805 statistics_proxy_.reset();
1806 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
Erik Språng22c2b482016-03-01 09:40:42 +01001807}
1808
asapersson8d75ac72017-09-15 06:41:15 -07001809TEST_F(SendStatisticsProxyTest, GetStatsReportsEncoderImplementationName) {
1810 const char* kName = "encoderName";
1811 EncodedImage encoded_image;
1812 CodecSpecificInfo codec_info;
1813 codec_info.codec_name = kName;
1814 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
1815 EXPECT_STREQ(
1816 kName, statistics_proxy_->GetStats().encoder_implementation_name.c_str());
1817}
1818
1819class ForcedFallbackTest : public SendStatisticsProxyTest {
1820 public:
1821 explicit ForcedFallbackTest(const std::string& field_trials)
1822 : SendStatisticsProxyTest(field_trials) {
1823 codec_info_.codecType = kVideoCodecVP8;
1824 codec_info_.codecSpecific.VP8.simulcastIdx = 0;
1825 codec_info_.codecSpecific.VP8.temporalIdx = 0;
1826 codec_info_.codec_name = "fake_codec";
1827 }
1828
1829 ~ForcedFallbackTest() override {}
1830
1831 protected:
1832 void InsertEncodedFrames(int num_frames, int interval_ms) {
1833 // First frame is not updating stats, insert initial frame.
1834 if (statistics_proxy_->GetStats().frames_encoded == 0) {
1835 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
1836 }
1837 for (int i = 0; i < num_frames; ++i) {
1838 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
1839 fake_clock_.AdvanceTimeMilliseconds(interval_ms);
1840 }
1841 // Add frame to include last time interval.
1842 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
1843 }
1844
1845 EncodedImage encoded_image_;
1846 CodecSpecificInfo codec_info_;
1847 const std::string kPrefix = "WebRTC.Video.Encoder.ForcedSw";
1848 const int kFrameIntervalMs = 1000;
1849 const int kMinFrames = 20; // Min run time 20 sec.
1850};
1851
1852class ForcedFallbackDisabled : public ForcedFallbackTest {
1853 public:
1854 ForcedFallbackDisabled()
1855 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder/Disabled/") {}
1856};
1857
1858class ForcedFallbackEnabled : public ForcedFallbackTest {
1859 public:
1860 ForcedFallbackEnabled()
1861 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder/Enabled-1,2," +
1862 std::to_string(kMinFirstFallbackIntervalMs) +
1863 ",4/") {}
1864};
1865
1866TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfMinRunTimeHasNotPassed) {
1867 InsertEncodedFrames(kMinFrames, kFrameIntervalMs - 1);
1868 statistics_proxy_.reset();
1869 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
1870 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
1871}
1872
1873TEST_F(ForcedFallbackEnabled, StatsUpdated) {
1874 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
1875 statistics_proxy_.reset();
1876 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
1877 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 0));
1878 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
1879 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 0));
1880}
1881
1882TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfNotVp8) {
1883 codec_info_.codecType = kVideoCodecVP9;
1884 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
1885 statistics_proxy_.reset();
1886 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
1887 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
1888}
1889
1890TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForTemporalLayers) {
1891 codec_info_.codecSpecific.VP8.temporalIdx = 1;
1892 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
1893 statistics_proxy_.reset();
1894 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
1895 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
1896}
1897
1898TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForSimulcast) {
1899 codec_info_.codecSpecific.VP8.simulcastIdx = 1;
1900 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
1901 statistics_proxy_.reset();
1902 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
1903 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
1904}
1905
1906TEST_F(ForcedFallbackDisabled, StatsNotUpdatedIfNoFieldTrial) {
1907 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
1908 statistics_proxy_.reset();
1909 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
1910 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
1911}
1912
1913TEST_F(ForcedFallbackEnabled, OneFallbackEvent) {
1914 // One change. Video: 20000 ms, fallback: 5000 ms (25%).
1915 InsertEncodedFrames(15, 1000);
1916 codec_info_.codec_name = "libvpx";
1917 InsertEncodedFrames(5, 1000);
1918
1919 statistics_proxy_.reset();
1920 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
1921 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
1922 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
1923 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
1924}
1925
1926TEST_F(ForcedFallbackEnabled, ThreeFallbackEvents) {
1927 codec_info_.codecSpecific.VP8.temporalIdx = kNoTemporalIdx; // Should work.
1928 const int kMaxFrameDiffMs = 2000;
1929
1930 // Three changes. Video: 60000 ms, fallback: 15000 ms (25%).
1931 InsertEncodedFrames(10, 1000);
1932 codec_info_.codec_name = "libvpx";
1933 InsertEncodedFrames(15, 500);
1934 codec_info_.codec_name = "notlibvpx";
1935 InsertEncodedFrames(20, 1000);
1936 InsertEncodedFrames(3, kMaxFrameDiffMs); // Should not be included.
1937 InsertEncodedFrames(10, 1000);
1938 codec_info_.codec_name = "notlibvpx2";
1939 InsertEncodedFrames(10, 500);
1940 codec_info_.codec_name = "libvpx";
1941 InsertEncodedFrames(15, 500);
1942
1943 statistics_proxy_.reset();
1944 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
1945 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
1946 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
1947 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
1948}
1949
1950TEST_F(ForcedFallbackEnabled, NoFallbackIfMinIntervalHasNotPassed) {
1951 InsertEncodedFrames(1, kMinFirstFallbackIntervalMs - 1);
1952 codec_info_.codec_name = "libvpx";
1953 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
1954
1955 statistics_proxy_.reset();
1956 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
1957 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
1958}
1959
1960TEST_F(ForcedFallbackEnabled, FallbackIfMinIntervalPassed) {
1961 InsertEncodedFrames(1, kMinFirstFallbackIntervalMs);
1962 codec_info_.codec_name = "libvpx";
1963 InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
1964
1965 statistics_proxy_.reset();
1966 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
1967 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
1968}
1969
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001970} // namespace webrtc