blob: fffc42ce0dc1f4cd14b905fb8bc81736fc89bd73 [file] [log] [blame]
sakale5ba44e2016-10-26 07:09:24 -07001/*
2 * Copyright 2016 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "video/receive_statistics_proxy.h"
sakale5ba44e2016-10-26 07:09:24 -070012
asapersson2077f2f2017-05-11 05:37:35 -070013#include <limits>
sakale5ba44e2016-10-26 07:09:24 -070014#include <memory>
Yves Gerey3e707812018-11-28 16:47:49 +010015#include <string>
Sergey Silkin02371062019-01-31 16:45:42 +010016#include <tuple>
17#include <utility>
sakale5ba44e2016-10-26 07:09:24 -070018
Mirko Bonadeid9708072019-01-25 20:26:48 +010019#include "api/scoped_refptr.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "api/video/i420_buffer.h"
21#include "api/video/video_frame.h"
Yves Gerey3e707812018-11-28 16:47:49 +010022#include "api/video/video_frame_buffer.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020023#include "api/video/video_rotation.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020024#include "system_wrappers/include/metrics.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020025#include "test/gtest.h"
sakale5ba44e2016-10-26 07:09:24 -070026
27namespace webrtc {
asaperssonde9e5ff2016-11-02 07:14:03 -070028namespace {
29const int64_t kFreqOffsetProcessIntervalInMs = 40000;
asapersson46c4e3c2016-11-03 06:48:19 -070030const uint32_t kLocalSsrc = 123;
31const uint32_t kRemoteSsrc = 456;
32const int kMinRequiredSamples = 200;
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +020033const int kWidth = 1280;
34const int kHeight = 720;
asaperssonde9e5ff2016-11-02 07:14:03 -070035} // namespace
sakale5ba44e2016-10-26 07:09:24 -070036
37// TODO(sakal): ReceiveStatisticsProxy is lacking unittesting.
Sergey Silkin02371062019-01-31 16:45:42 +010038class ReceiveStatisticsProxyTest : public ::testing::Test {
sakale5ba44e2016-10-26 07:09:24 -070039 public:
40 ReceiveStatisticsProxyTest() : fake_clock_(1234), config_(GetTestConfig()) {}
41 virtual ~ReceiveStatisticsProxyTest() {}
42
43 protected:
44 virtual void SetUp() {
asaperssonde9e5ff2016-11-02 07:14:03 -070045 metrics::Reset();
sakale5ba44e2016-10-26 07:09:24 -070046 statistics_proxy_.reset(new ReceiveStatisticsProxy(&config_, &fake_clock_));
47 }
48
49 VideoReceiveStream::Config GetTestConfig() {
50 VideoReceiveStream::Config config(nullptr);
asapersson46c4e3c2016-11-03 06:48:19 -070051 config.rtp.local_ssrc = kLocalSsrc;
52 config.rtp.remote_ssrc = kRemoteSsrc;
sakale5ba44e2016-10-26 07:09:24 -070053 return config;
54 }
55
asapersson2077f2f2017-05-11 05:37:35 -070056 VideoFrame CreateFrame(int width, int height) {
Åsa Persson81327d52018-06-05 13:34:33 +020057 return CreateVideoFrame(width, height, 0);
58 }
59
60 VideoFrame CreateFrameWithRenderTimeMs(int64_t render_time_ms) {
61 return CreateVideoFrame(kWidth, kHeight, render_time_ms);
62 }
63
64 VideoFrame CreateVideoFrame(int width, int height, int64_t render_time_ms) {
Artem Titov1ebfb6a2019-01-03 23:49:37 +010065 VideoFrame frame =
66 VideoFrame::Builder()
67 .set_video_frame_buffer(I420Buffer::Create(width, height))
68 .set_timestamp_rtp(0)
69 .set_timestamp_ms(render_time_ms)
70 .set_rotation(kVideoRotation_0)
71 .build();
asapersson2077f2f2017-05-11 05:37:35 -070072 frame.set_ntp_time_ms(fake_clock_.CurrentNtpInMilliseconds());
73 return frame;
74 }
75
sakale5ba44e2016-10-26 07:09:24 -070076 SimulatedClock fake_clock_;
asaperssonde9e5ff2016-11-02 07:14:03 -070077 const VideoReceiveStream::Config config_;
sakale5ba44e2016-10-26 07:09:24 -070078 std::unique_ptr<ReceiveStatisticsProxy> statistics_proxy_;
sakale5ba44e2016-10-26 07:09:24 -070079};
80
81TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameIncreasesFramesDecoded) {
82 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_decoded);
Sergey Silkin278f8252019-01-09 14:37:40 +010083 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
sakale5ba44e2016-10-26 07:09:24 -070084 for (uint32_t i = 1; i <= 3; ++i) {
Johannes Kronbfd343b2019-07-01 10:07:50 +020085 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
ilnik00d802b2017-04-11 10:34:31 -070086 VideoContentType::UNSPECIFIED);
sakale5ba44e2016-10-26 07:09:24 -070087 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_decoded);
88 }
89}
90
Åsa Perssonb9b07ea2018-01-24 17:04:07 +010091TEST_F(ReceiveStatisticsProxyTest, DecodedFpsIsReported) {
92 const int kFps = 20;
93 const int kRequiredSamples = metrics::kMinRunTimeInSeconds * kFps;
Sergey Silkin278f8252019-01-09 14:37:40 +010094 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Åsa Perssonb9b07ea2018-01-24 17:04:07 +010095 for (int i = 0; i < kRequiredSamples; ++i) {
Johannes Kronbfd343b2019-07-01 10:07:50 +020096 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Sergey Silkin278f8252019-01-09 14:37:40 +010097 VideoContentType::UNSPECIFIED);
Åsa Perssonb9b07ea2018-01-24 17:04:07 +010098 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
99 }
Niels Möllerd7819652019-08-13 14:43:02 +0200100 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
101 nullptr);
Åsa Perssonb9b07ea2018-01-24 17:04:07 +0100102 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
103 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DecodedFramesPerSecond", kFps));
104}
105
106TEST_F(ReceiveStatisticsProxyTest, DecodedFpsIsNotReportedForTooFewSamples) {
107 const int kFps = 20;
108 const int kRequiredSamples = metrics::kMinRunTimeInSeconds * kFps;
Sergey Silkin278f8252019-01-09 14:37:40 +0100109 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Åsa Perssonb9b07ea2018-01-24 17:04:07 +0100110 for (int i = 0; i < kRequiredSamples - 1; ++i) {
Johannes Kronbfd343b2019-07-01 10:07:50 +0200111 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Sergey Silkin278f8252019-01-09 14:37:40 +0100112 VideoContentType::UNSPECIFIED);
Åsa Perssonb9b07ea2018-01-24 17:04:07 +0100113 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
114 }
Niels Möllerd7819652019-08-13 14:43:02 +0200115 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
116 nullptr);
Åsa Perssonb9b07ea2018-01-24 17:04:07 +0100117 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
118}
119
Johannes Kronbfd343b2019-07-01 10:07:50 +0200120TEST_F(ReceiveStatisticsProxyTest,
121 OnDecodedFrameWithQpDoesNotResetFramesDecodedOrTotalDecodeTime) {
sakalcc452e12017-02-09 04:53:45 -0800122 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_decoded);
Sergey Silkin278f8252019-01-09 14:37:40 +0100123 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200124 unsigned int expected_total_decode_time_ms = 0;
125 unsigned int expected_frames_decoded = 0;
sakalcc452e12017-02-09 04:53:45 -0800126 for (uint32_t i = 1; i <= 3; ++i) {
Johannes Kronbfd343b2019-07-01 10:07:50 +0200127 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 1,
ilnik00d802b2017-04-11 10:34:31 -0700128 VideoContentType::UNSPECIFIED);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200129 expected_total_decode_time_ms += 1;
130 ++expected_frames_decoded;
131 EXPECT_EQ(expected_frames_decoded,
132 statistics_proxy_->GetStats().frames_decoded);
133 EXPECT_EQ(expected_total_decode_time_ms,
134 statistics_proxy_->GetStats().total_decode_time_ms);
sakalcc452e12017-02-09 04:53:45 -0800135 }
Johannes Kronbfd343b2019-07-01 10:07:50 +0200136 statistics_proxy_->OnDecodedFrame(frame, 1u, 3,
137 VideoContentType::UNSPECIFIED);
138 ++expected_frames_decoded;
139 expected_total_decode_time_ms += 3;
140 EXPECT_EQ(expected_frames_decoded,
141 statistics_proxy_->GetStats().frames_decoded);
142 EXPECT_EQ(expected_total_decode_time_ms,
143 statistics_proxy_->GetStats().total_decode_time_ms);
sakalcc452e12017-02-09 04:53:45 -0800144}
145
146TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameIncreasesQpSum) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200147 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
Sergey Silkin278f8252019-01-09 14:37:40 +0100148 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200149 statistics_proxy_->OnDecodedFrame(frame, 3u, 0,
150 VideoContentType::UNSPECIFIED);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100151 EXPECT_EQ(3u, statistics_proxy_->GetStats().qp_sum);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200152 statistics_proxy_->OnDecodedFrame(frame, 127u, 0,
153 VideoContentType::UNSPECIFIED);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100154 EXPECT_EQ(130u, statistics_proxy_->GetStats().qp_sum);
sakalcc452e12017-02-09 04:53:45 -0800155}
156
Johannes Kronbfd343b2019-07-01 10:07:50 +0200157TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameIncreasesTotalDecodeTime) {
158 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
159 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
160 statistics_proxy_->OnDecodedFrame(frame, 3u, 4,
161 VideoContentType::UNSPECIFIED);
162 EXPECT_EQ(4u, statistics_proxy_->GetStats().total_decode_time_ms);
163 statistics_proxy_->OnDecodedFrame(frame, 127u, 7,
164 VideoContentType::UNSPECIFIED);
165 EXPECT_EQ(11u, statistics_proxy_->GetStats().total_decode_time_ms);
166}
167
ilnik2e1b40b2017-09-04 07:57:17 -0700168TEST_F(ReceiveStatisticsProxyTest, ReportsContentType) {
169 const std::string kRealtimeString("realtime");
170 const std::string kScreenshareString("screen");
Sergey Silkin278f8252019-01-09 14:37:40 +0100171 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
ilnik2e1b40b2017-09-04 07:57:17 -0700172 EXPECT_EQ(kRealtimeString, videocontenttypehelpers::ToString(
Sergey Silkin02371062019-01-31 16:45:42 +0100173 statistics_proxy_->GetStats().content_type));
Johannes Kronbfd343b2019-07-01 10:07:50 +0200174 statistics_proxy_->OnDecodedFrame(frame, 3u, 0,
175 VideoContentType::SCREENSHARE);
Sergey Silkin02371062019-01-31 16:45:42 +0100176 EXPECT_EQ(kScreenshareString,
177 videocontenttypehelpers::ToString(
178 statistics_proxy_->GetStats().content_type));
Johannes Kronbfd343b2019-07-01 10:07:50 +0200179 statistics_proxy_->OnDecodedFrame(frame, 3u, 0,
180 VideoContentType::UNSPECIFIED);
ilnik2e1b40b2017-09-04 07:57:17 -0700181 EXPECT_EQ(kRealtimeString, videocontenttypehelpers::ToString(
Sergey Silkin02371062019-01-31 16:45:42 +0100182 statistics_proxy_->GetStats().content_type));
ilnik2e1b40b2017-09-04 07:57:17 -0700183}
184
ilnika79cc282017-08-23 05:24:10 -0700185TEST_F(ReceiveStatisticsProxyTest, ReportsMaxInterframeDelay) {
Sergey Silkin278f8252019-01-09 14:37:40 +0100186 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
ilnika79cc282017-08-23 05:24:10 -0700187 const int64_t kInterframeDelayMs1 = 100;
188 const int64_t kInterframeDelayMs2 = 200;
189 const int64_t kInterframeDelayMs3 = 100;
190 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200191 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200192 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700193 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
ilnikf04afde2017-07-07 01:26:24 -0700194
195 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs1);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200196 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200197 VideoContentType::UNSPECIFIED);
ilnikf04afde2017-07-07 01:26:24 -0700198 EXPECT_EQ(kInterframeDelayMs1,
ilnika79cc282017-08-23 05:24:10 -0700199 statistics_proxy_->GetStats().interframe_delay_max_ms);
ilnikf04afde2017-07-07 01:26:24 -0700200
201 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs2);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200202 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200203 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700204 EXPECT_EQ(kInterframeDelayMs2,
205 statistics_proxy_->GetStats().interframe_delay_max_ms);
206
207 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs3);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200208 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200209 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700210 // kInterframeDelayMs3 is smaller than kInterframeDelayMs2.
211 EXPECT_EQ(kInterframeDelayMs2,
212 statistics_proxy_->GetStats().interframe_delay_max_ms);
213}
214
215TEST_F(ReceiveStatisticsProxyTest, ReportInterframeDelayInWindow) {
Sergey Silkin278f8252019-01-09 14:37:40 +0100216 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Ilya Nikolaevskiyb06b3582017-10-16 17:59:12 +0200217 const int64_t kInterframeDelayMs1 = 900;
218 const int64_t kInterframeDelayMs2 = 750;
219 const int64_t kInterframeDelayMs3 = 700;
ilnika79cc282017-08-23 05:24:10 -0700220 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200221 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200222 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700223 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
224
225 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs1);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200226 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200227 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700228 EXPECT_EQ(kInterframeDelayMs1,
229 statistics_proxy_->GetStats().interframe_delay_max_ms);
230
231 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs2);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200232 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200233 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700234 // Still first delay is the maximum
235 EXPECT_EQ(kInterframeDelayMs1,
236 statistics_proxy_->GetStats().interframe_delay_max_ms);
237
238 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs3);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200239 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200240 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700241 // Now the first sample is out of the window, so the second is the maximum.
242 EXPECT_EQ(kInterframeDelayMs2,
243 statistics_proxy_->GetStats().interframe_delay_max_ms);
ilnikf04afde2017-07-07 01:26:24 -0700244}
245
Sergey Silkin02371062019-01-31 16:45:42 +0100246TEST_F(ReceiveStatisticsProxyTest, ReportsFreezeMetrics) {
247 const int64_t kFreezeDurationMs = 1000;
248
249 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
250 EXPECT_EQ(0u, stats.freeze_count);
251 EXPECT_FALSE(stats.total_freezes_duration_ms);
252
253 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
254 for (size_t i = 0; i < VideoQualityObserver::kMinFrameSamplesToDetectFreeze;
255 ++i) {
256 fake_clock_.AdvanceTimeMilliseconds(30);
257 statistics_proxy_->OnRenderedFrame(frame);
258 }
259
260 // Freeze.
261 fake_clock_.AdvanceTimeMilliseconds(kFreezeDurationMs);
262 statistics_proxy_->OnRenderedFrame(frame);
263
264 stats = statistics_proxy_->GetStats();
265 EXPECT_EQ(1u, stats.freeze_count);
266 EXPECT_EQ(kFreezeDurationMs, stats.total_freezes_duration_ms);
267}
268
269TEST_F(ReceiveStatisticsProxyTest, ReportsPauseMetrics) {
270 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
271 ASSERT_EQ(0u, stats.pause_count);
272 ASSERT_EQ(0u, stats.total_pauses_duration_ms);
273
274 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
275 statistics_proxy_->OnRenderedFrame(frame);
276
277 // Pause.
278 fake_clock_.AdvanceTimeMilliseconds(5432);
279 statistics_proxy_->OnStreamInactive();
280 statistics_proxy_->OnRenderedFrame(frame);
281
282 stats = statistics_proxy_->GetStats();
283 EXPECT_EQ(1u, stats.pause_count);
284 EXPECT_EQ(5432u, stats.total_pauses_duration_ms);
285}
286
287TEST_F(ReceiveStatisticsProxyTest, PauseBeforeFirstAndAfterLastFrameIgnored) {
288 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
289 ASSERT_EQ(0u, stats.pause_count);
290 ASSERT_EQ(0u, stats.total_pauses_duration_ms);
291
292 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
293
294 // Pause -> Frame -> Pause
295 fake_clock_.AdvanceTimeMilliseconds(5000);
296 statistics_proxy_->OnStreamInactive();
297 statistics_proxy_->OnRenderedFrame(frame);
298
299 fake_clock_.AdvanceTimeMilliseconds(30);
300 statistics_proxy_->OnRenderedFrame(frame);
301
302 fake_clock_.AdvanceTimeMilliseconds(5000);
303 statistics_proxy_->OnStreamInactive();
304
305 stats = statistics_proxy_->GetStats();
306 EXPECT_EQ(0u, stats.pause_count);
307 EXPECT_EQ(0u, stats.total_pauses_duration_ms);
308}
309
310TEST_F(ReceiveStatisticsProxyTest, ReportsFramesDuration) {
311 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
312 ASSERT_EQ(0u, stats.total_frames_duration_ms);
313
314 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
315
316 // Emulate delay before first frame is rendered. This is needed to ensure
317 // that frame duration only covers time since first frame is rendered and
318 // not the total time.
319 fake_clock_.AdvanceTimeMilliseconds(5432);
320
321 for (int i = 0; i <= 10; ++i) {
322 fake_clock_.AdvanceTimeMilliseconds(30);
323 statistics_proxy_->OnRenderedFrame(frame);
324 }
325
326 stats = statistics_proxy_->GetStats();
327 EXPECT_EQ(10 * 30u, stats.total_frames_duration_ms);
328}
329
330TEST_F(ReceiveStatisticsProxyTest, ReportsSumSquaredFrameDurations) {
331 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
332 ASSERT_EQ(0u, stats.sum_squared_frame_durations);
333
334 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
335 for (int i = 0; i <= 10; ++i) {
336 fake_clock_.AdvanceTimeMilliseconds(30);
337 statistics_proxy_->OnRenderedFrame(frame);
338 }
339
340 stats = statistics_proxy_->GetStats();
341 const double kExpectedSumSquaredFrameDurationsSecs =
342 10 * (30 / 1000.0 * 30 / 1000.0);
343 EXPECT_EQ(kExpectedSumSquaredFrameDurationsSecs,
344 stats.sum_squared_frame_durations);
345}
346
sakalcc452e12017-02-09 04:53:45 -0800347TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameWithoutQpQpSumWontExist) {
Sergey Silkin278f8252019-01-09 14:37:40 +0100348 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200349 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200350 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
ilnik00d802b2017-04-11 10:34:31 -0700351 VideoContentType::UNSPECIFIED);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200352 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakalcc452e12017-02-09 04:53:45 -0800353}
354
Mirta Dvornicic608083b2019-10-03 15:52:36 +0200355TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameWithoutQpResetsQpSum) {
Sergey Silkin278f8252019-01-09 14:37:40 +0100356 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200357 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200358 statistics_proxy_->OnDecodedFrame(frame, 3u, 0,
ilnik00d802b2017-04-11 10:34:31 -0700359 VideoContentType::UNSPECIFIED);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200360 EXPECT_EQ(3u, statistics_proxy_->GetStats().qp_sum);
361 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
362 VideoContentType::UNSPECIFIED);
Mirta Dvornicic608083b2019-10-03 15:52:36 +0200363 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakalcc452e12017-02-09 04:53:45 -0800364}
365
hbos50cfe1f2017-01-23 07:21:55 -0800366TEST_F(ReceiveStatisticsProxyTest, OnRenderedFrameIncreasesFramesRendered) {
367 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_rendered);
Sergey Silkin278f8252019-01-09 14:37:40 +0100368 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
hbos50cfe1f2017-01-23 07:21:55 -0800369 for (uint32_t i = 1; i <= 3; ++i) {
370 statistics_proxy_->OnRenderedFrame(frame);
371 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_rendered);
372 }
373}
374
asapersson46c4e3c2016-11-03 06:48:19 -0700375TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsSsrc) {
376 EXPECT_EQ(kRemoteSsrc, statistics_proxy_->GetStats().ssrc);
377}
378
379TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsIncomingPayloadType) {
380 const int kPayloadType = 111;
381 statistics_proxy_->OnIncomingPayloadType(kPayloadType);
382 EXPECT_EQ(kPayloadType, statistics_proxy_->GetStats().current_payload_type);
383}
384
asapersson6966bd52017-01-03 00:44:06 -0800385TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsDecoderImplementationName) {
386 const char* kName = "decoderName";
387 statistics_proxy_->OnDecoderImplementationName(kName);
388 EXPECT_STREQ(
389 kName, statistics_proxy_->GetStats().decoder_implementation_name.c_str());
390}
391
philipela45102f2017-02-22 05:30:39 -0800392TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsOnCompleteFrame) {
393 const int kFrameSizeBytes = 1000;
ilnik6d5b4d62017-08-30 03:32:14 -0700394 statistics_proxy_->OnCompleteFrame(true, kFrameSizeBytes,
395 VideoContentType::UNSPECIFIED);
philipela45102f2017-02-22 05:30:39 -0800396 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
397 EXPECT_EQ(1, stats.network_frame_rate);
philipela45102f2017-02-22 05:30:39 -0800398 EXPECT_EQ(1, stats.frame_counts.key_frames);
399 EXPECT_EQ(0, stats.frame_counts.delta_frames);
asapersson46c4e3c2016-11-03 06:48:19 -0700400}
401
Johannes Kron0c141c52019-08-26 15:04:43 +0200402TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsOnDroppedFrame) {
403 unsigned int dropped_frames = 0;
404 for (int i = 0; i < 10; ++i) {
405 statistics_proxy_->OnDroppedFrames(i);
406 dropped_frames += i;
407 }
408 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
409 EXPECT_EQ(dropped_frames, stats.frames_dropped);
410}
411
asapersson46c4e3c2016-11-03 06:48:19 -0700412TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsDecodeTimingStats) {
asapersson46c4e3c2016-11-03 06:48:19 -0700413 const int kMaxDecodeMs = 2;
414 const int kCurrentDelayMs = 3;
415 const int kTargetDelayMs = 4;
416 const int kJitterBufferMs = 5;
417 const int kMinPlayoutDelayMs = 6;
418 const int kRenderDelayMs = 7;
419 const int64_t kRttMs = 8;
philipela45102f2017-02-22 05:30:39 -0800420 statistics_proxy_->OnRttUpdate(kRttMs, 0);
421 statistics_proxy_->OnFrameBufferTimingsUpdated(
Johannes Kronbfd343b2019-07-01 10:07:50 +0200422 kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs, kJitterBufferMs,
philipela45102f2017-02-22 05:30:39 -0800423 kMinPlayoutDelayMs, kRenderDelayMs);
asapersson46c4e3c2016-11-03 06:48:19 -0700424 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
asapersson46c4e3c2016-11-03 06:48:19 -0700425 EXPECT_EQ(kMaxDecodeMs, stats.max_decode_ms);
426 EXPECT_EQ(kCurrentDelayMs, stats.current_delay_ms);
427 EXPECT_EQ(kTargetDelayMs, stats.target_delay_ms);
428 EXPECT_EQ(kJitterBufferMs, stats.jitter_buffer_ms);
429 EXPECT_EQ(kMinPlayoutDelayMs, stats.min_playout_delay_ms);
430 EXPECT_EQ(kRenderDelayMs, stats.render_delay_ms);
431}
432
asapersson6966bd52017-01-03 00:44:06 -0800433TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsRtcpPacketTypeCounts) {
434 const uint32_t kFirPackets = 33;
435 const uint32_t kPliPackets = 44;
436 const uint32_t kNackPackets = 55;
437 RtcpPacketTypeCounter counter;
438 counter.fir_packets = kFirPackets;
439 counter.pli_packets = kPliPackets;
440 counter.nack_packets = kNackPackets;
441 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
442 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
443 EXPECT_EQ(kFirPackets, stats.rtcp_packet_type_counts.fir_packets);
444 EXPECT_EQ(kPliPackets, stats.rtcp_packet_type_counts.pli_packets);
445 EXPECT_EQ(kNackPackets, stats.rtcp_packet_type_counts.nack_packets);
446}
447
448TEST_F(ReceiveStatisticsProxyTest,
449 GetStatsReportsNoRtcpPacketTypeCountsForUnknownSsrc) {
450 RtcpPacketTypeCounter counter;
451 counter.fir_packets = 33;
452 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc + 1, counter);
453 EXPECT_EQ(0u,
454 statistics_proxy_->GetStats().rtcp_packet_type_counts.fir_packets);
455}
456
457TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsFrameCounts) {
458 const int kKeyFrames = 3;
459 const int kDeltaFrames = 22;
Niels Möllerdd41da62019-03-28 08:59:07 +0100460 for (int i = 0; i < kKeyFrames; i++) {
461 statistics_proxy_->OnCompleteFrame(true, 0, VideoContentType::UNSPECIFIED);
462 }
463 for (int i = 0; i < kDeltaFrames; i++) {
464 statistics_proxy_->OnCompleteFrame(false, 0, VideoContentType::UNSPECIFIED);
465 }
466
asapersson6966bd52017-01-03 00:44:06 -0800467 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
468 EXPECT_EQ(kKeyFrames, stats.frame_counts.key_frames);
469 EXPECT_EQ(kDeltaFrames, stats.frame_counts.delta_frames);
470}
471
asapersson6966bd52017-01-03 00:44:06 -0800472TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsCName) {
473 const char* kName = "cName";
Niels Möller4d7c4052019-08-05 12:45:19 +0200474 statistics_proxy_->OnCname(kRemoteSsrc, kName);
asapersson6966bd52017-01-03 00:44:06 -0800475 EXPECT_STREQ(kName, statistics_proxy_->GetStats().c_name.c_str());
476}
477
478TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsNoCNameForUnknownSsrc) {
479 const char* kName = "cName";
Niels Möller4d7c4052019-08-05 12:45:19 +0200480 statistics_proxy_->OnCname(kRemoteSsrc + 1, kName);
asapersson6966bd52017-01-03 00:44:06 -0800481 EXPECT_STREQ("", statistics_proxy_->GetStats().c_name.c_str());
482}
483
Jonas Olssona4d87372019-07-05 19:08:33 +0200484TEST_F(ReceiveStatisticsProxyTest, ReportsLongestTimingFrameInfo) {
ilnik2edc6842017-07-06 03:06:50 -0700485 const int64_t kShortEndToEndDelay = 10;
486 const int64_t kMedEndToEndDelay = 20;
487 const int64_t kLongEndToEndDelay = 100;
488 const uint32_t kExpectedRtpTimestamp = 2;
489 TimingFrameInfo info;
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200490 absl::optional<TimingFrameInfo> result;
ilnik2edc6842017-07-06 03:06:50 -0700491 info.rtp_timestamp = kExpectedRtpTimestamp - 1;
492 info.capture_time_ms = 0;
493 info.decode_finish_ms = kShortEndToEndDelay;
494 statistics_proxy_->OnTimingFrameInfoUpdated(info);
495 info.rtp_timestamp =
496 kExpectedRtpTimestamp; // this frame should be reported in the end.
497 info.capture_time_ms = 0;
498 info.decode_finish_ms = kLongEndToEndDelay;
499 statistics_proxy_->OnTimingFrameInfoUpdated(info);
500 info.rtp_timestamp = kExpectedRtpTimestamp + 1;
501 info.capture_time_ms = 0;
502 info.decode_finish_ms = kMedEndToEndDelay;
503 statistics_proxy_->OnTimingFrameInfoUpdated(info);
ilnik75204c52017-09-04 03:35:40 -0700504 result = statistics_proxy_->GetStats().timing_frame_info;
ilnik2edc6842017-07-06 03:06:50 -0700505 EXPECT_TRUE(result);
506 EXPECT_EQ(kExpectedRtpTimestamp, result->rtp_timestamp);
507}
508
ilnik75204c52017-09-04 03:35:40 -0700509TEST_F(ReceiveStatisticsProxyTest, RespectsReportingIntervalForTimingFrames) {
510 TimingFrameInfo info;
ilnik2edc6842017-07-06 03:06:50 -0700511 const int64_t kShortEndToEndDelay = 10;
512 const uint32_t kExpectedRtpTimestamp = 2;
ilnik75204c52017-09-04 03:35:40 -0700513 const int64_t kShortDelayMs = 1000;
514 const int64_t kLongDelayMs = 10000;
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200515 absl::optional<TimingFrameInfo> result;
ilnik2edc6842017-07-06 03:06:50 -0700516 info.rtp_timestamp = kExpectedRtpTimestamp;
517 info.capture_time_ms = 0;
518 info.decode_finish_ms = kShortEndToEndDelay;
519 statistics_proxy_->OnTimingFrameInfoUpdated(info);
ilnik75204c52017-09-04 03:35:40 -0700520 fake_clock_.AdvanceTimeMilliseconds(kShortDelayMs);
521 result = statistics_proxy_->GetStats().timing_frame_info;
ilnik2edc6842017-07-06 03:06:50 -0700522 EXPECT_TRUE(result);
523 EXPECT_EQ(kExpectedRtpTimestamp, result->rtp_timestamp);
ilnik75204c52017-09-04 03:35:40 -0700524 fake_clock_.AdvanceTimeMilliseconds(kLongDelayMs);
525 result = statistics_proxy_->GetStats().timing_frame_info;
ilnik2edc6842017-07-06 03:06:50 -0700526 EXPECT_FALSE(result);
527}
528
asapersson46c4e3c2016-11-03 06:48:19 -0700529TEST_F(ReceiveStatisticsProxyTest, LifetimeHistogramIsUpdated) {
530 const int64_t kTimeSec = 3;
531 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
ilnik6d5b4d62017-08-30 03:32:14 -0700532 // Need at least one frame to report stream lifetime.
533 statistics_proxy_->OnCompleteFrame(true, 1000, VideoContentType::UNSPECIFIED);
Niels Möllerd7819652019-08-13 14:43:02 +0200534 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
535 nullptr);
asapersson46c4e3c2016-11-03 06:48:19 -0700536 EXPECT_EQ(1,
537 metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
538 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceiveStreamLifetimeInSeconds",
539 kTimeSec));
540}
541
ilnik6d5b4d62017-08-30 03:32:14 -0700542TEST_F(ReceiveStatisticsProxyTest,
543 LifetimeHistogramNotReportedForEmptyStreams) {
544 const int64_t kTimeSec = 3;
545 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
546 // No frames received.
Niels Möllerd7819652019-08-13 14:43:02 +0200547 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
548 nullptr);
ilnik6d5b4d62017-08-30 03:32:14 -0700549 EXPECT_EQ(0,
550 metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
551}
552
palmkvista40672a2017-01-13 05:58:34 -0800553TEST_F(ReceiveStatisticsProxyTest, BadCallHistogramsAreUpdated) {
554 // Based on the tuning parameters this will produce 7 uncertain states,
555 // then 10 certainly bad states. There has to be 10 certain states before
556 // any histograms are recorded.
557 const int kNumBadSamples = 17;
Niels Möller9b0b1e02019-03-22 13:56:46 +0100558 // We only count one sample per second.
559 const int kBadFameIntervalMs = 1100;
palmkvista40672a2017-01-13 05:58:34 -0800560
561 StreamDataCounters counters;
562 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
palmkvista40672a2017-01-13 05:58:34 -0800563
Niels Möller9b0b1e02019-03-22 13:56:46 +0100564 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
565
palmkvista40672a2017-01-13 05:58:34 -0800566 for (int i = 0; i < kNumBadSamples; ++i) {
Niels Möller9b0b1e02019-03-22 13:56:46 +0100567 fake_clock_.AdvanceTimeMilliseconds(kBadFameIntervalMs);
568 statistics_proxy_->OnRenderedFrame(frame);
palmkvista40672a2017-01-13 05:58:34 -0800569 }
Niels Möllerd7819652019-08-13 14:43:02 +0200570 statistics_proxy_->UpdateHistograms(absl::nullopt, counters, nullptr);
palmkvista40672a2017-01-13 05:58:34 -0800571 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BadCall.Any"));
572 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BadCall.Any", 100));
573
574 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BadCall.FrameRate"));
575 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BadCall.FrameRate", 100));
576
577 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.BadCall.FrameRateVariance"));
578
579 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.BadCall.Qp"));
580}
581
asapersson0c43f772016-11-30 01:42:26 -0800582TEST_F(ReceiveStatisticsProxyTest, PacketLossHistogramIsUpdated) {
Niels Möllerd7819652019-08-13 14:43:02 +0200583 statistics_proxy_->UpdateHistograms(10, StreamDataCounters(), nullptr);
asapersson0c43f772016-11-30 01:42:26 -0800584 EXPECT_EQ(0,
585 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
586
Niels Möller9a9f18a2019-08-02 13:52:37 +0200587 // Restart
asapersson0c43f772016-11-30 01:42:26 -0800588 SetUp();
Niels Möller9a9f18a2019-08-02 13:52:37 +0200589
590 // Min run time has passed.
591 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
Niels Möllerd7819652019-08-13 14:43:02 +0200592 statistics_proxy_->UpdateHistograms(10, StreamDataCounters(), nullptr);
asapersson0c43f772016-11-30 01:42:26 -0800593 EXPECT_EQ(1,
594 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
Niels Möller9a9f18a2019-08-02 13:52:37 +0200595 EXPECT_EQ(
596 1, metrics::NumEvents("WebRTC.Video.ReceivedPacketsLostInPercent", 10));
asapersson0c43f772016-11-30 01:42:26 -0800597}
598
asapersson2077f2f2017-05-11 05:37:35 -0700599TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsAvSyncOffset) {
600 const int64_t kSyncOffsetMs = 22;
601 const double kFreqKhz = 90.0;
602 EXPECT_EQ(std::numeric_limits<int>::max(),
603 statistics_proxy_->GetStats().sync_offset_ms);
604 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
605 EXPECT_EQ(kSyncOffsetMs, statistics_proxy_->GetStats().sync_offset_ms);
606}
607
asapersson46c4e3c2016-11-03 06:48:19 -0700608TEST_F(ReceiveStatisticsProxyTest, AvSyncOffsetHistogramIsUpdated) {
609 const int64_t kSyncOffsetMs = 22;
610 const double kFreqKhz = 90.0;
611 for (int i = 0; i < kMinRequiredSamples; ++i)
612 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
Niels Möllerd7819652019-08-13 14:43:02 +0200613 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
614 nullptr);
asapersson46c4e3c2016-11-03 06:48:19 -0700615 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AVSyncOffsetInMs"));
616 EXPECT_EQ(1,
617 metrics::NumEvents("WebRTC.Video.AVSyncOffsetInMs", kSyncOffsetMs));
618}
619
asaperssonde9e5ff2016-11-02 07:14:03 -0700620TEST_F(ReceiveStatisticsProxyTest, RtpToNtpFrequencyOffsetHistogramIsUpdated) {
621 const int64_t kSyncOffsetMs = 22;
622 const double kFreqKhz = 90.0;
623 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
624 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz + 2.2);
625 fake_clock_.AdvanceTimeMilliseconds(kFreqOffsetProcessIntervalInMs);
626 // Process interval passed, max diff: 2.
627 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz + 1.1);
628 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz - 4.2);
629 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz - 0.9);
630 fake_clock_.AdvanceTimeMilliseconds(kFreqOffsetProcessIntervalInMs);
631 // Process interval passed, max diff: 4.
632 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
Niels Möllerd7819652019-08-13 14:43:02 +0200633 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
634 nullptr);
asaperssonde9e5ff2016-11-02 07:14:03 -0700635 // Average reported: (2 + 4) / 2 = 3.
636 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtpToNtpFreqOffsetInKhz"));
637 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtpToNtpFreqOffsetInKhz", 3));
638}
639
asapersson6966bd52017-01-03 00:44:06 -0800640TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsUpdated) {
641 const int kQp = 22;
asapersson6966bd52017-01-03 00:44:06 -0800642
643 for (int i = 0; i < kMinRequiredSamples; ++i)
Niels Möller147013a2018-10-01 15:56:33 +0200644 statistics_proxy_->OnPreDecode(kVideoCodecVP8, kQp);
asapersson6966bd52017-01-03 00:44:06 -0800645
Niels Möllerd7819652019-08-13 14:43:02 +0200646 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
647 nullptr);
asapersson6966bd52017-01-03 00:44:06 -0800648 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
649 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Decoded.Vp8.Qp", kQp));
650}
651
652TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsNotUpdatedForTooFewSamples) {
Niels Möller147013a2018-10-01 15:56:33 +0200653 const int kQp = 22;
asapersson6966bd52017-01-03 00:44:06 -0800654
655 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
Niels Möller147013a2018-10-01 15:56:33 +0200656 statistics_proxy_->OnPreDecode(kVideoCodecVP8, kQp);
asapersson6966bd52017-01-03 00:44:06 -0800657
Niels Möllerd7819652019-08-13 14:43:02 +0200658 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
659 nullptr);
asapersson6966bd52017-01-03 00:44:06 -0800660 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
661}
662
663TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsNotUpdatedIfNoQpValue) {
asapersson6966bd52017-01-03 00:44:06 -0800664 for (int i = 0; i < kMinRequiredSamples; ++i)
Niels Möller147013a2018-10-01 15:56:33 +0200665 statistics_proxy_->OnPreDecode(kVideoCodecVP8, -1);
asapersson6966bd52017-01-03 00:44:06 -0800666
Niels Möllerd7819652019-08-13 14:43:02 +0200667 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
668 nullptr);
asapersson6966bd52017-01-03 00:44:06 -0800669 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
670}
671
asaperssonb99baf82017-04-20 04:05:43 -0700672TEST_F(ReceiveStatisticsProxyTest,
673 KeyFrameHistogramNotUpdatedForTooFewSamples) {
674 const bool kIsKeyFrame = false;
675 const int kFrameSizeBytes = 1000;
676
677 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
ilnik6d5b4d62017-08-30 03:32:14 -0700678 statistics_proxy_->OnCompleteFrame(kIsKeyFrame, kFrameSizeBytes,
679 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 04:05:43 -0700680
681 EXPECT_EQ(0, statistics_proxy_->GetStats().frame_counts.key_frames);
682 EXPECT_EQ(kMinRequiredSamples - 1,
683 statistics_proxy_->GetStats().frame_counts.delta_frames);
684
Niels Möllerd7819652019-08-13 14:43:02 +0200685 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
686 nullptr);
asaperssonb99baf82017-04-20 04:05:43 -0700687 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
688}
689
690TEST_F(ReceiveStatisticsProxyTest,
691 KeyFrameHistogramUpdatedForMinRequiredSamples) {
692 const bool kIsKeyFrame = false;
693 const int kFrameSizeBytes = 1000;
694
695 for (int i = 0; i < kMinRequiredSamples; ++i)
ilnik6d5b4d62017-08-30 03:32:14 -0700696 statistics_proxy_->OnCompleteFrame(kIsKeyFrame, kFrameSizeBytes,
697 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 04:05:43 -0700698
699 EXPECT_EQ(0, statistics_proxy_->GetStats().frame_counts.key_frames);
700 EXPECT_EQ(kMinRequiredSamples,
701 statistics_proxy_->GetStats().frame_counts.delta_frames);
702
Niels Möllerd7819652019-08-13 14:43:02 +0200703 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
704 nullptr);
asaperssonb99baf82017-04-20 04:05:43 -0700705 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
706 EXPECT_EQ(1,
707 metrics::NumEvents("WebRTC.Video.KeyFramesReceivedInPermille", 0));
708}
709
710TEST_F(ReceiveStatisticsProxyTest, KeyFrameHistogramIsUpdated) {
711 const int kFrameSizeBytes = 1000;
712
713 for (int i = 0; i < kMinRequiredSamples; ++i)
ilnik6d5b4d62017-08-30 03:32:14 -0700714 statistics_proxy_->OnCompleteFrame(true, kFrameSizeBytes,
715 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 04:05:43 -0700716
717 for (int i = 0; i < kMinRequiredSamples; ++i)
ilnik6d5b4d62017-08-30 03:32:14 -0700718 statistics_proxy_->OnCompleteFrame(false, kFrameSizeBytes,
719 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 04:05:43 -0700720
721 EXPECT_EQ(kMinRequiredSamples,
722 statistics_proxy_->GetStats().frame_counts.key_frames);
723 EXPECT_EQ(kMinRequiredSamples,
724 statistics_proxy_->GetStats().frame_counts.delta_frames);
725
Niels Möllerd7819652019-08-13 14:43:02 +0200726 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
727 nullptr);
asaperssonb99baf82017-04-20 04:05:43 -0700728 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
729 EXPECT_EQ(
730 1, metrics::NumEvents("WebRTC.Video.KeyFramesReceivedInPermille", 500));
731}
732
733TEST_F(ReceiveStatisticsProxyTest, TimingHistogramsNotUpdatedForTooFewSamples) {
asaperssonb99baf82017-04-20 04:05:43 -0700734 const int kMaxDecodeMs = 2;
735 const int kCurrentDelayMs = 3;
736 const int kTargetDelayMs = 4;
737 const int kJitterBufferMs = 5;
738 const int kMinPlayoutDelayMs = 6;
739 const int kRenderDelayMs = 7;
740
741 for (int i = 0; i < kMinRequiredSamples - 1; ++i) {
742 statistics_proxy_->OnFrameBufferTimingsUpdated(
Johannes Kronbfd343b2019-07-01 10:07:50 +0200743 kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs, kJitterBufferMs,
744 kMinPlayoutDelayMs, kRenderDelayMs);
asaperssonb99baf82017-04-20 04:05:43 -0700745 }
746
Niels Möllerd7819652019-08-13 14:43:02 +0200747 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
748 nullptr);
asaperssonb99baf82017-04-20 04:05:43 -0700749 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
750 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
751 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
752 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
753 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
754}
755
756TEST_F(ReceiveStatisticsProxyTest, TimingHistogramsAreUpdated) {
asaperssonb99baf82017-04-20 04:05:43 -0700757 const int kMaxDecodeMs = 2;
758 const int kCurrentDelayMs = 3;
759 const int kTargetDelayMs = 4;
760 const int kJitterBufferMs = 5;
761 const int kMinPlayoutDelayMs = 6;
762 const int kRenderDelayMs = 7;
763
764 for (int i = 0; i < kMinRequiredSamples; ++i) {
765 statistics_proxy_->OnFrameBufferTimingsUpdated(
Johannes Kronbfd343b2019-07-01 10:07:50 +0200766 kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs, kJitterBufferMs,
767 kMinPlayoutDelayMs, kRenderDelayMs);
asaperssonb99baf82017-04-20 04:05:43 -0700768 }
769
Niels Möllerd7819652019-08-13 14:43:02 +0200770 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
771 nullptr);
asaperssonb99baf82017-04-20 04:05:43 -0700772 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
773 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
774 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
775 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
776
asaperssonb99baf82017-04-20 04:05:43 -0700777 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.JitterBufferDelayInMs",
778 kJitterBufferMs));
779 EXPECT_EQ(1,
780 metrics::NumEvents("WebRTC.Video.TargetDelayInMs", kTargetDelayMs));
781 EXPECT_EQ(
782 1, metrics::NumEvents("WebRTC.Video.CurrentDelayInMs", kCurrentDelayMs));
783 EXPECT_EQ(1,
784 metrics::NumEvents("WebRTC.Video.OnewayDelayInMs", kTargetDelayMs));
785}
786
sprang948b2752017-05-04 02:47:13 -0700787TEST_F(ReceiveStatisticsProxyTest, DoesNotReportStaleFramerates) {
788 const int kDefaultFps = 30;
Sergey Silkin278f8252019-01-09 14:37:40 +0100789 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
sprang948b2752017-05-04 02:47:13 -0700790
791 for (int i = 0; i < kDefaultFps; ++i) {
792 // Since OnRenderedFrame is never called the fps in each sample will be 0,
793 // i.e. bad
794 frame.set_ntp_time_ms(fake_clock_.CurrentNtpInMilliseconds());
Johannes Kronbfd343b2019-07-01 10:07:50 +0200795 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
sprang948b2752017-05-04 02:47:13 -0700796 VideoContentType::UNSPECIFIED);
797 statistics_proxy_->OnRenderedFrame(frame);
798 fake_clock_.AdvanceTimeMilliseconds(1000 / kDefaultFps);
799 }
800
801 EXPECT_EQ(kDefaultFps, statistics_proxy_->GetStats().decode_frame_rate);
802 EXPECT_EQ(kDefaultFps, statistics_proxy_->GetStats().render_frame_rate);
803
804 // FPS trackers in stats proxy have a 1000ms sliding window.
805 fake_clock_.AdvanceTimeMilliseconds(1000);
806 EXPECT_EQ(0, statistics_proxy_->GetStats().decode_frame_rate);
807 EXPECT_EQ(0, statistics_proxy_->GetStats().render_frame_rate);
808}
809
asapersson2077f2f2017-05-11 05:37:35 -0700810TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsReceivedFrameStats) {
asapersson2077f2f2017-05-11 05:37:35 -0700811 EXPECT_EQ(0, statistics_proxy_->GetStats().width);
812 EXPECT_EQ(0, statistics_proxy_->GetStats().height);
813 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_rendered);
814
815 statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight));
816
817 EXPECT_EQ(kWidth, statistics_proxy_->GetStats().width);
818 EXPECT_EQ(kHeight, statistics_proxy_->GetStats().height);
819 EXPECT_EQ(1u, statistics_proxy_->GetStats().frames_rendered);
820}
821
822TEST_F(ReceiveStatisticsProxyTest,
823 ReceivedFrameHistogramsAreNotUpdatedForTooFewSamples) {
asapersson2077f2f2017-05-11 05:37:35 -0700824 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
825 statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight));
826
Niels Möllerd7819652019-08-13 14:43:02 +0200827 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
828 nullptr);
asapersson2077f2f2017-05-11 05:37:35 -0700829 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
830 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
831 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
832 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
833}
834
835TEST_F(ReceiveStatisticsProxyTest, ReceivedFrameHistogramsAreUpdated) {
asapersson2077f2f2017-05-11 05:37:35 -0700836 for (int i = 0; i < kMinRequiredSamples; ++i)
837 statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight));
838
Niels Möllerd7819652019-08-13 14:43:02 +0200839 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
840 nullptr);
asapersson2077f2f2017-05-11 05:37:35 -0700841 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
842 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
843 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
844 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
845 EXPECT_EQ(1,
846 metrics::NumEvents("WebRTC.Video.ReceivedWidthInPixels", kWidth));
847 EXPECT_EQ(1,
848 metrics::NumEvents("WebRTC.Video.ReceivedHeightInPixels", kHeight));
849}
850
Åsa Persson81327d52018-06-05 13:34:33 +0200851TEST_F(ReceiveStatisticsProxyTest, ZeroDelayReportedIfFrameNotDelayed) {
Sergey Silkin278f8252019-01-09 14:37:40 +0100852 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200853 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Åsa Persson81327d52018-06-05 13:34:33 +0200854 VideoContentType::UNSPECIFIED);
855
856 // Frame not delayed, delayed frames to render: 0%.
857 const int64_t kNowMs = fake_clock_.TimeInMilliseconds();
858 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs));
859
860 // Min run time has passed.
861 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
Niels Möllerd7819652019-08-13 14:43:02 +0200862 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
863 nullptr);
Åsa Persson81327d52018-06-05 13:34:33 +0200864 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
865 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 0));
866 EXPECT_EQ(0, metrics::NumSamples(
867 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
868}
869
870TEST_F(ReceiveStatisticsProxyTest,
871 DelayedFrameHistogramsAreNotUpdatedIfMinRuntimeHasNotPassed) {
Sergey Silkin278f8252019-01-09 14:37:40 +0100872 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200873 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Åsa Persson81327d52018-06-05 13:34:33 +0200874 VideoContentType::UNSPECIFIED);
875
876 // Frame not delayed, delayed frames to render: 0%.
877 const int64_t kNowMs = fake_clock_.TimeInMilliseconds();
878 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs));
879
880 // Min run time has not passed.
881 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000) -
882 1);
Niels Möllerd7819652019-08-13 14:43:02 +0200883 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
884 nullptr);
Åsa Persson81327d52018-06-05 13:34:33 +0200885 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
886 EXPECT_EQ(0, metrics::NumSamples(
887 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
888}
889
890TEST_F(ReceiveStatisticsProxyTest,
891 DelayedFramesHistogramsAreNotUpdatedIfNoRenderedFrames) {
Sergey Silkin278f8252019-01-09 14:37:40 +0100892 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200893 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Åsa Persson81327d52018-06-05 13:34:33 +0200894 VideoContentType::UNSPECIFIED);
895
896 // Min run time has passed. No rendered frames.
897 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
Niels Möllerd7819652019-08-13 14:43:02 +0200898 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
899 nullptr);
Åsa Persson81327d52018-06-05 13:34:33 +0200900 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
901 EXPECT_EQ(0, metrics::NumSamples(
902 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
903}
904
905TEST_F(ReceiveStatisticsProxyTest, DelayReportedIfFrameIsDelayed) {
Sergey Silkin278f8252019-01-09 14:37:40 +0100906 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200907 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Åsa Persson81327d52018-06-05 13:34:33 +0200908 VideoContentType::UNSPECIFIED);
909
910 // Frame delayed 1 ms, delayed frames to render: 100%.
911 const int64_t kNowMs = fake_clock_.TimeInMilliseconds();
912 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs - 1));
913
914 // Min run time has passed.
915 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
Niels Möllerd7819652019-08-13 14:43:02 +0200916 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
917 nullptr);
Åsa Persson81327d52018-06-05 13:34:33 +0200918 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
919 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 100));
920 EXPECT_EQ(1, metrics::NumSamples(
921 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
922 EXPECT_EQ(1, metrics::NumEvents(
923 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs", 1));
924}
925
926TEST_F(ReceiveStatisticsProxyTest, AverageDelayOfDelayedFramesIsReported) {
Sergey Silkin278f8252019-01-09 14:37:40 +0100927 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200928 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Åsa Persson81327d52018-06-05 13:34:33 +0200929 VideoContentType::UNSPECIFIED);
930
931 // Two frames delayed (6 ms, 10 ms), delayed frames to render: 50%.
932 const int64_t kNowMs = fake_clock_.TimeInMilliseconds();
933 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs - 10));
934 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs - 6));
935 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs));
936 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs + 1));
937
938 // Min run time has passed.
939 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
Niels Möllerd7819652019-08-13 14:43:02 +0200940 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
941 nullptr);
Åsa Persson81327d52018-06-05 13:34:33 +0200942 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
943 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 50));
944 EXPECT_EQ(1, metrics::NumSamples(
945 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
946 EXPECT_EQ(1, metrics::NumEvents(
947 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs", 8));
948}
949
asapersson2077f2f2017-05-11 05:37:35 -0700950TEST_F(ReceiveStatisticsProxyTest,
951 RtcpHistogramsNotUpdatedIfMinRuntimeHasNotPassed) {
Niels Möllerd7819652019-08-13 14:43:02 +0200952 StreamDataCounters data_counters;
953 data_counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
954
asapersson2077f2f2017-05-11 05:37:35 -0700955 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000) -
956 1);
957
958 RtcpPacketTypeCounter counter;
959 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
960
Niels Möllerd7819652019-08-13 14:43:02 +0200961 statistics_proxy_->UpdateHistograms(absl::nullopt, data_counters, nullptr);
asapersson2077f2f2017-05-11 05:37:35 -0700962 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
963 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
964 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
965}
966
967TEST_F(ReceiveStatisticsProxyTest, RtcpHistogramsAreUpdated) {
Niels Möllerd7819652019-08-13 14:43:02 +0200968 StreamDataCounters data_counters;
969 data_counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
asapersson2077f2f2017-05-11 05:37:35 -0700970 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
971
972 const uint32_t kFirPackets = 100;
973 const uint32_t kPliPackets = 200;
974 const uint32_t kNackPackets = 300;
975
976 RtcpPacketTypeCounter counter;
977 counter.fir_packets = kFirPackets;
978 counter.pli_packets = kPliPackets;
979 counter.nack_packets = kNackPackets;
980 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
981
Niels Möllerd7819652019-08-13 14:43:02 +0200982 statistics_proxy_->UpdateHistograms(absl::nullopt, data_counters, nullptr);
asapersson2077f2f2017-05-11 05:37:35 -0700983 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
984 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
985 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
986 EXPECT_EQ(
987 1, metrics::NumEvents("WebRTC.Video.FirPacketsSentPerMinute",
988 kFirPackets * 60 / metrics::kMinRunTimeInSeconds));
989 EXPECT_EQ(
990 1, metrics::NumEvents("WebRTC.Video.PliPacketsSentPerMinute",
991 kPliPackets * 60 / metrics::kMinRunTimeInSeconds));
992 EXPECT_EQ(
993 1, metrics::NumEvents("WebRTC.Video.NackPacketsSentPerMinute",
994 kNackPackets * 60 / metrics::kMinRunTimeInSeconds));
995}
996
Sergey Silkin02371062019-01-31 16:45:42 +0100997class ReceiveStatisticsProxyTestWithFreezeDuration
998 : public ReceiveStatisticsProxyTest,
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200999 public ::testing::WithParamInterface<
Sergey Silkin02371062019-01-31 16:45:42 +01001000 std::tuple<uint32_t, uint32_t, uint32_t>> {
1001 protected:
1002 const uint32_t frame_duration_ms_ = {std::get<0>(GetParam())};
1003 const uint32_t freeze_duration_ms_ = {std::get<1>(GetParam())};
1004 const uint32_t expected_freeze_count_ = {std::get<2>(GetParam())};
1005};
sprang892dab52017-08-15 05:00:33 -07001006
Sergey Silkin02371062019-01-31 16:45:42 +01001007// It is a freeze if:
1008// frame_duration_ms >= max(3 * avg_frame_duration, avg_frame_duration + 150)
1009// where avg_frame_duration is average duration of last 30 frames including
1010// the current one.
1011//
1012// Condition 1: 3 * avg_frame_duration > avg_frame_duration + 150
1013const auto kFreezeDetectionCond1Freeze = std::make_tuple(150, 483, 1);
1014const auto kFreezeDetectionCond1NotFreeze = std::make_tuple(150, 482, 0);
1015// Condition 2: 3 * avg_frame_duration < avg_frame_duration + 150
1016const auto kFreezeDetectionCond2Freeze = std::make_tuple(30, 185, 1);
1017const auto kFreezeDetectionCond2NotFreeze = std::make_tuple(30, 184, 0);
1018
Mirko Bonadei12d12852019-02-05 17:04:04 +01001019INSTANTIATE_TEST_SUITE_P(_,
1020 ReceiveStatisticsProxyTestWithFreezeDuration,
1021 ::testing::Values(kFreezeDetectionCond1Freeze,
1022 kFreezeDetectionCond1NotFreeze,
1023 kFreezeDetectionCond2Freeze,
1024 kFreezeDetectionCond2NotFreeze));
Sergey Silkin02371062019-01-31 16:45:42 +01001025
1026TEST_P(ReceiveStatisticsProxyTestWithFreezeDuration, FreezeDetection) {
1027 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
1028 EXPECT_EQ(0u, stats.freeze_count);
1029 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1030
1031 // Add a very long frame. This is need to verify that average frame
1032 // duration, which is supposed to be calculated as mean of durations of
1033 // last 30 frames, is calculated correctly.
1034 statistics_proxy_->OnRenderedFrame(frame);
1035 fake_clock_.AdvanceTimeMilliseconds(2000);
1036
1037 for (size_t i = 0;
1038 i <= VideoQualityObserver::kAvgInterframeDelaysWindowSizeFrames; ++i) {
1039 fake_clock_.AdvanceTimeMilliseconds(frame_duration_ms_);
1040 statistics_proxy_->OnRenderedFrame(frame);
1041 }
1042
1043 fake_clock_.AdvanceTimeMilliseconds(freeze_duration_ms_);
1044 statistics_proxy_->OnRenderedFrame(frame);
1045
1046 stats = statistics_proxy_->GetStats();
1047 EXPECT_EQ(stats.freeze_count, expected_freeze_count_);
1048}
1049
1050class ReceiveStatisticsProxyTestWithContent
1051 : public ReceiveStatisticsProxyTest,
1052 public ::testing::WithParamInterface<webrtc::VideoContentType> {
1053 protected:
1054 const webrtc::VideoContentType content_type_{GetParam()};
1055};
1056
Mirko Bonadei12d12852019-02-05 17:04:04 +01001057INSTANTIATE_TEST_SUITE_P(ContentTypes,
1058 ReceiveStatisticsProxyTestWithContent,
1059 ::testing::Values(VideoContentType::UNSPECIFIED,
1060 VideoContentType::SCREENSHARE));
Sergey Silkin02371062019-01-31 16:45:42 +01001061
1062TEST_P(ReceiveStatisticsProxyTestWithContent, InterFrameDelaysAreReported) {
sprang892dab52017-08-15 05:00:33 -07001063 const int kInterFrameDelayMs = 33;
Sergey Silkin278f8252019-01-09 14:37:40 +01001064 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1065
sprang892dab52017-08-15 05:00:33 -07001066 for (int i = 0; i < kMinRequiredSamples; ++i) {
Johannes Kronbfd343b2019-07-01 10:07:50 +02001067 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
sprang892dab52017-08-15 05:00:33 -07001068 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1069 }
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001070 // One extra with double the interval.
sprang892dab52017-08-15 05:00:33 -07001071 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
Johannes Kronbfd343b2019-07-01 10:07:50 +02001072 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
sprang892dab52017-08-15 05:00:33 -07001073
Niels Möllerd7819652019-08-13 14:43:02 +02001074 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1075 nullptr);
sprang892dab52017-08-15 05:00:33 -07001076 const int kExpectedInterFrame =
1077 (kInterFrameDelayMs * (kMinRequiredSamples - 1) +
1078 kInterFrameDelayMs * 2) /
1079 kMinRequiredSamples;
Sergey Silkin02371062019-01-31 16:45:42 +01001080 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
ilnik6d5b4d62017-08-30 03:32:14 -07001081 EXPECT_EQ(
1082 kExpectedInterFrame,
1083 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1084 EXPECT_EQ(
1085 kInterFrameDelayMs * 2,
1086 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1087 } else {
1088 EXPECT_EQ(kExpectedInterFrame,
1089 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
1090 EXPECT_EQ(kInterFrameDelayMs * 2,
1091 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
sprang892dab52017-08-15 05:00:33 -07001092 }
1093}
1094
Sergey Silkin02371062019-01-31 16:45:42 +01001095TEST_P(ReceiveStatisticsProxyTestWithContent,
1096 InterFrameDelaysPercentilesAreReported) {
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001097 const int kInterFrameDelayMs = 33;
1098 const int kLastFivePercentsSamples = kMinRequiredSamples * 5 / 100;
Sergey Silkin278f8252019-01-09 14:37:40 +01001099 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1100
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001101 for (int i = 0; i <= kMinRequiredSamples - kLastFivePercentsSamples; ++i) {
1102 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
Johannes Kronbfd343b2019-07-01 10:07:50 +02001103 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001104 }
1105 // Last 5% of intervals are double in size.
1106 for (int i = 0; i < kLastFivePercentsSamples; ++i) {
1107 fake_clock_.AdvanceTimeMilliseconds(2 * kInterFrameDelayMs);
Johannes Kronbfd343b2019-07-01 10:07:50 +02001108 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001109 }
1110 // Final sample is outlier and 10 times as big.
1111 fake_clock_.AdvanceTimeMilliseconds(10 * kInterFrameDelayMs);
Johannes Kronbfd343b2019-07-01 10:07:50 +02001112 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001113
Niels Möllerd7819652019-08-13 14:43:02 +02001114 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1115 nullptr);
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001116 const int kExpectedInterFrame = kInterFrameDelayMs * 2;
Sergey Silkin02371062019-01-31 16:45:42 +01001117 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001118 EXPECT_EQ(kExpectedInterFrame,
1119 metrics::MinSample(
1120 "WebRTC.Video.Screenshare.InterframeDelay95PercentileInMs"));
1121 } else {
1122 EXPECT_EQ(
1123 kExpectedInterFrame,
1124 metrics::MinSample("WebRTC.Video.InterframeDelay95PercentileInMs"));
1125 }
1126}
1127
Sergey Silkin02371062019-01-31 16:45:42 +01001128TEST_P(ReceiveStatisticsProxyTestWithContent,
1129 MaxInterFrameDelayOnlyWithValidAverage) {
sprang892dab52017-08-15 05:00:33 -07001130 const int kInterFrameDelayMs = 33;
Sergey Silkin278f8252019-01-09 14:37:40 +01001131 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1132
sprang892dab52017-08-15 05:00:33 -07001133 for (int i = 0; i < kMinRequiredSamples; ++i) {
Johannes Kronbfd343b2019-07-01 10:07:50 +02001134 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
sprang892dab52017-08-15 05:00:33 -07001135 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1136 }
1137
1138 // |kMinRequiredSamples| samples, and thereby intervals, is required. That
1139 // means we're one frame short of having a valid data set.
Niels Möllerd7819652019-08-13 14:43:02 +02001140 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1141 nullptr);
sprang892dab52017-08-15 05:00:33 -07001142 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
1143 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
1144 EXPECT_EQ(
1145 0, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1146 EXPECT_EQ(0, metrics::NumSamples(
1147 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1148}
1149
Sergey Silkin02371062019-01-31 16:45:42 +01001150TEST_P(ReceiveStatisticsProxyTestWithContent, MaxInterFrameDelayOnlyWithPause) {
sprang3e86e7e2017-08-22 09:23:28 -07001151 const int kInterFrameDelayMs = 33;
Sergey Silkin278f8252019-01-09 14:37:40 +01001152 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1153
sprang3e86e7e2017-08-22 09:23:28 -07001154 for (int i = 0; i <= kMinRequiredSamples; ++i) {
Johannes Kronbfd343b2019-07-01 10:07:50 +02001155 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
sprang3e86e7e2017-08-22 09:23:28 -07001156 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1157 }
1158
1159 // At this state, we should have a valid inter-frame delay.
1160 // Indicate stream paused and make a large jump in time.
1161 statistics_proxy_->OnStreamInactive();
1162 fake_clock_.AdvanceTimeMilliseconds(5000);
1163
1164 // Insert two more frames. The interval during the pause should be disregarded
1165 // in the stats.
Johannes Kronbfd343b2019-07-01 10:07:50 +02001166 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
sprang3e86e7e2017-08-22 09:23:28 -07001167 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
Johannes Kronbfd343b2019-07-01 10:07:50 +02001168 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
sprang3e86e7e2017-08-22 09:23:28 -07001169
Niels Möllerd7819652019-08-13 14:43:02 +02001170 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1171 nullptr);
Sergey Silkin02371062019-01-31 16:45:42 +01001172 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
sprang3e86e7e2017-08-22 09:23:28 -07001173 EXPECT_EQ(
1174 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1175 EXPECT_EQ(1, metrics::NumSamples(
1176 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1177 EXPECT_EQ(
1178 kInterFrameDelayMs,
1179 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1180 EXPECT_EQ(
1181 kInterFrameDelayMs,
1182 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1183 } else {
1184 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
1185 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
1186 EXPECT_EQ(kInterFrameDelayMs,
1187 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
1188 EXPECT_EQ(kInterFrameDelayMs,
1189 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
1190 }
1191}
1192
Sergey Silkin02371062019-01-31 16:45:42 +01001193TEST_P(ReceiveStatisticsProxyTestWithContent, FreezesAreReported) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001194 const int kInterFrameDelayMs = 33;
1195 const int kFreezeDelayMs = 200;
Sergey Silkinbea18ca2018-10-02 16:22:46 +02001196 const int kCallDurationMs =
1197 kMinRequiredSamples * kInterFrameDelayMs + kFreezeDelayMs;
Sergey Silkin278f8252019-01-09 14:37:40 +01001198 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1199
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001200 for (int i = 0; i < kMinRequiredSamples; ++i) {
Johannes Kronbfd343b2019-07-01 10:07:50 +02001201 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Ilya Nikolaevskiycdc959f2018-10-10 13:15:09 +02001202 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001203 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1204 }
1205 // Add extra freeze.
1206 fake_clock_.AdvanceTimeMilliseconds(kFreezeDelayMs);
Johannes Kronbfd343b2019-07-01 10:07:50 +02001207 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Ilya Nikolaevskiycdc959f2018-10-10 13:15:09 +02001208 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001209
Niels Möllerd7819652019-08-13 14:43:02 +02001210 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1211 nullptr);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001212 const int kExpectedTimeBetweenFreezes =
1213 kInterFrameDelayMs * (kMinRequiredSamples - 1);
Sergey Silkinbea18ca2018-10-02 16:22:46 +02001214 const int kExpectedNumberFreezesPerMinute = 60 * 1000 / kCallDurationMs;
Sergey Silkin02371062019-01-31 16:45:42 +01001215 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001216 EXPECT_EQ(
1217 kFreezeDelayMs + kInterFrameDelayMs,
1218 metrics::MinSample("WebRTC.Video.Screenshare.MeanFreezeDurationMs"));
1219 EXPECT_EQ(kExpectedTimeBetweenFreezes,
1220 metrics::MinSample(
1221 "WebRTC.Video.Screenshare.MeanTimeBetweenFreezesMs"));
Sergey Silkinbea18ca2018-10-02 16:22:46 +02001222 EXPECT_EQ(
1223 kExpectedNumberFreezesPerMinute,
1224 metrics::MinSample("WebRTC.Video.Screenshare.NumberFreezesPerMinute"));
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001225 } else {
1226 EXPECT_EQ(kFreezeDelayMs + kInterFrameDelayMs,
1227 metrics::MinSample("WebRTC.Video.MeanFreezeDurationMs"));
1228 EXPECT_EQ(kExpectedTimeBetweenFreezes,
1229 metrics::MinSample("WebRTC.Video.MeanTimeBetweenFreezesMs"));
Sergey Silkinbea18ca2018-10-02 16:22:46 +02001230 EXPECT_EQ(kExpectedNumberFreezesPerMinute,
1231 metrics::MinSample("WebRTC.Video.NumberFreezesPerMinute"));
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001232 }
1233}
1234
Sergey Silkin02371062019-01-31 16:45:42 +01001235TEST_P(ReceiveStatisticsProxyTestWithContent, HarmonicFrameRateIsReported) {
Sergey Silkinfc6f3e52019-04-03 10:57:26 +02001236 const int kFrameDurationMs = 33;
1237 const int kFreezeDurationMs = 200;
1238 const int kPauseDurationMs = 10000;
1239 const int kCallDurationMs = kMinRequiredSamples * kFrameDurationMs +
1240 kFreezeDurationMs + kPauseDurationMs;
Sergey Silkin50e77452019-01-16 13:41:46 +01001241 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1242
1243 for (int i = 0; i < kMinRequiredSamples; ++i) {
Sergey Silkinfc6f3e52019-04-03 10:57:26 +02001244 fake_clock_.AdvanceTimeMilliseconds(kFrameDurationMs);
Johannes Kronbfd343b2019-07-01 10:07:50 +02001245 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Sergey Silkin50e77452019-01-16 13:41:46 +01001246 statistics_proxy_->OnRenderedFrame(frame);
1247 }
Sergey Silkinfc6f3e52019-04-03 10:57:26 +02001248
1249 // Freezes and pauses should be included into harmonic frame rate.
1250 // Add freeze.
1251 fake_clock_.AdvanceTimeMilliseconds(kFreezeDurationMs);
Johannes Kronbfd343b2019-07-01 10:07:50 +02001252 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Sergey Silkinfc6f3e52019-04-03 10:57:26 +02001253 statistics_proxy_->OnRenderedFrame(frame);
1254
1255 // Add pause.
1256 fake_clock_.AdvanceTimeMilliseconds(kPauseDurationMs);
1257 statistics_proxy_->OnStreamInactive();
Johannes Kronbfd343b2019-07-01 10:07:50 +02001258 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Sergey Silkin50e77452019-01-16 13:41:46 +01001259 statistics_proxy_->OnRenderedFrame(frame);
1260
Niels Möllerd7819652019-08-13 14:43:02 +02001261 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1262 nullptr);
Sergey Silkinfc6f3e52019-04-03 10:57:26 +02001263 double kSumSquaredFrameDurationSecs =
Sergey Silkin50e77452019-01-16 13:41:46 +01001264 (kMinRequiredSamples - 1) *
Sergey Silkinfc6f3e52019-04-03 10:57:26 +02001265 (kFrameDurationMs / 1000.0 * kFrameDurationMs / 1000.0);
1266 kSumSquaredFrameDurationSecs +=
1267 kFreezeDurationMs / 1000.0 * kFreezeDurationMs / 1000.0;
1268 kSumSquaredFrameDurationSecs +=
1269 kPauseDurationMs / 1000.0 * kPauseDurationMs / 1000.0;
Sergey Silkin50e77452019-01-16 13:41:46 +01001270 const int kExpectedHarmonicFrameRateFps =
Sergey Silkinfc6f3e52019-04-03 10:57:26 +02001271 std::round(kCallDurationMs / (1000 * kSumSquaredFrameDurationSecs));
Sergey Silkin02371062019-01-31 16:45:42 +01001272 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Sergey Silkin50e77452019-01-16 13:41:46 +01001273 EXPECT_EQ(kExpectedHarmonicFrameRateFps,
1274 metrics::MinSample("WebRTC.Video.Screenshare.HarmonicFrameRate"));
1275 } else {
1276 EXPECT_EQ(kExpectedHarmonicFrameRateFps,
1277 metrics::MinSample("WebRTC.Video.HarmonicFrameRate"));
1278 }
1279}
1280
Sergey Silkin02371062019-01-31 16:45:42 +01001281TEST_P(ReceiveStatisticsProxyTestWithContent, PausesAreIgnored) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001282 const int kInterFrameDelayMs = 33;
1283 const int kPauseDurationMs = 10000;
Sergey Silkin278f8252019-01-09 14:37:40 +01001284 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1285
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001286 for (int i = 0; i <= kMinRequiredSamples; ++i) {
Johannes Kronbfd343b2019-07-01 10:07:50 +02001287 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Ilya Nikolaevskiycdc959f2018-10-10 13:15:09 +02001288 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001289 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1290 }
1291 // Add a pause.
1292 fake_clock_.AdvanceTimeMilliseconds(kPauseDurationMs);
1293 statistics_proxy_->OnStreamInactive();
1294
1295 // Second playback interval with triple the length.
1296 for (int i = 0; i <= kMinRequiredSamples * 3; ++i) {
Johannes Kronbfd343b2019-07-01 10:07:50 +02001297 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Ilya Nikolaevskiycdc959f2018-10-10 13:15:09 +02001298 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001299 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1300 }
1301
Niels Möllerd7819652019-08-13 14:43:02 +02001302 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1303 nullptr);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001304 // Average of two playback intervals.
1305 const int kExpectedTimeBetweenFreezes =
1306 kInterFrameDelayMs * kMinRequiredSamples * 2;
Sergey Silkin02371062019-01-31 16:45:42 +01001307 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001308 EXPECT_EQ(-1, metrics::MinSample(
1309 "WebRTC.Video.Screenshare.MeanFreezeDurationMs"));
1310 EXPECT_EQ(kExpectedTimeBetweenFreezes,
1311 metrics::MinSample(
1312 "WebRTC.Video.Screenshare.MeanTimeBetweenFreezesMs"));
1313 } else {
1314 EXPECT_EQ(-1, metrics::MinSample("WebRTC.Video.MeanFreezeDurationMs"));
1315 EXPECT_EQ(kExpectedTimeBetweenFreezes,
1316 metrics::MinSample("WebRTC.Video.MeanTimeBetweenFreezesMs"));
1317 }
1318}
1319
Sergey Silkin02371062019-01-31 16:45:42 +01001320TEST_P(ReceiveStatisticsProxyTestWithContent, ManyPausesAtTheBeginning) {
Ilya Nikolaevskiy879f5a32018-05-31 09:47:17 +02001321 const int kInterFrameDelayMs = 33;
1322 const int kPauseDurationMs = 10000;
Sergey Silkin278f8252019-01-09 14:37:40 +01001323 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1324
Ilya Nikolaevskiy879f5a32018-05-31 09:47:17 +02001325 for (int i = 0; i <= kMinRequiredSamples; ++i) {
Johannes Kronbfd343b2019-07-01 10:07:50 +02001326 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Ilya Nikolaevskiy879f5a32018-05-31 09:47:17 +02001327 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1328
1329 statistics_proxy_->OnStreamInactive();
1330 fake_clock_.AdvanceTimeMilliseconds(kPauseDurationMs);
1331
Johannes Kronbfd343b2019-07-01 10:07:50 +02001332 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Ilya Nikolaevskiy879f5a32018-05-31 09:47:17 +02001333 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1334 }
1335
Niels Möllerd7819652019-08-13 14:43:02 +02001336 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1337 nullptr);
Ilya Nikolaevskiy879f5a32018-05-31 09:47:17 +02001338 // No freezes should be detected, as all long inter-frame delays were pauses.
Sergey Silkin02371062019-01-31 16:45:42 +01001339 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiy879f5a32018-05-31 09:47:17 +02001340 EXPECT_EQ(-1, metrics::MinSample(
1341 "WebRTC.Video.Screenshare.MeanFreezeDurationMs"));
1342 } else {
1343 EXPECT_EQ(-1, metrics::MinSample("WebRTC.Video.MeanFreezeDurationMs"));
1344 }
1345}
1346
Sergey Silkin02371062019-01-31 16:45:42 +01001347TEST_P(ReceiveStatisticsProxyTestWithContent, TimeInHdReported) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001348 const int kInterFrameDelayMs = 20;
Sergey Silkin278f8252019-01-09 14:37:40 +01001349 webrtc::VideoFrame frame_hd = CreateFrame(1280, 720);
1350 webrtc::VideoFrame frame_sd = CreateFrame(640, 360);
1351
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001352 // HD frames.
1353 for (int i = 0; i < kMinRequiredSamples; ++i) {
Johannes Kronbfd343b2019-07-01 10:07:50 +02001354 statistics_proxy_->OnDecodedFrame(frame_hd, absl::nullopt, 0,
1355 content_type_);
Sergey Silkin278f8252019-01-09 14:37:40 +01001356 statistics_proxy_->OnRenderedFrame(frame_hd);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001357 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1358 }
1359 // SD frames.
1360 for (int i = 0; i < 2 * kMinRequiredSamples; ++i) {
Johannes Kronbfd343b2019-07-01 10:07:50 +02001361 statistics_proxy_->OnDecodedFrame(frame_sd, absl::nullopt, 0,
1362 content_type_);
Sergey Silkin278f8252019-01-09 14:37:40 +01001363 statistics_proxy_->OnRenderedFrame(frame_sd);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001364 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1365 }
1366 // Extra last frame.
Sergey Silkin278f8252019-01-09 14:37:40 +01001367 statistics_proxy_->OnRenderedFrame(frame_sd);
1368
Niels Möllerd7819652019-08-13 14:43:02 +02001369 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1370 nullptr);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001371 const int kExpectedTimeInHdPercents = 33;
Sergey Silkin02371062019-01-31 16:45:42 +01001372 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001373 EXPECT_EQ(
1374 kExpectedTimeInHdPercents,
1375 metrics::MinSample("WebRTC.Video.Screenshare.TimeInHdPercentage"));
1376 } else {
1377 EXPECT_EQ(kExpectedTimeInHdPercents,
1378 metrics::MinSample("WebRTC.Video.TimeInHdPercentage"));
1379 }
1380}
1381
Sergey Silkin02371062019-01-31 16:45:42 +01001382TEST_P(ReceiveStatisticsProxyTestWithContent, TimeInBlockyVideoReported) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001383 const int kInterFrameDelayMs = 20;
1384 const int kHighQp = 80;
1385 const int kLowQp = 30;
Sergey Silkin278f8252019-01-09 14:37:40 +01001386 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1387
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001388 // High quality frames.
1389 for (int i = 0; i < kMinRequiredSamples; ++i) {
Johannes Kronbfd343b2019-07-01 10:07:50 +02001390 statistics_proxy_->OnDecodedFrame(frame, kLowQp, 0, content_type_);
Sergey Silkin278f8252019-01-09 14:37:40 +01001391 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001392 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1393 }
1394 // Blocky frames.
1395 for (int i = 0; i < 2 * kMinRequiredSamples; ++i) {
Johannes Kronbfd343b2019-07-01 10:07:50 +02001396 statistics_proxy_->OnDecodedFrame(frame, kHighQp, 0, content_type_);
Sergey Silkin278f8252019-01-09 14:37:40 +01001397 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001398 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1399 }
1400 // Extra last frame.
Johannes Kronbfd343b2019-07-01 10:07:50 +02001401 statistics_proxy_->OnDecodedFrame(frame, kHighQp, 0, content_type_);
Sergey Silkin278f8252019-01-09 14:37:40 +01001402 statistics_proxy_->OnRenderedFrame(frame);
1403
Niels Möllerd7819652019-08-13 14:43:02 +02001404 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1405 nullptr);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001406 const int kExpectedTimeInHdPercents = 66;
Sergey Silkin02371062019-01-31 16:45:42 +01001407 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001408 EXPECT_EQ(kExpectedTimeInHdPercents,
1409 metrics::MinSample(
1410 "WebRTC.Video.Screenshare.TimeInBlockyVideoPercentage"));
1411 } else {
1412 EXPECT_EQ(kExpectedTimeInHdPercents,
1413 metrics::MinSample("WebRTC.Video.TimeInBlockyVideoPercentage"));
1414 }
1415}
1416
Sergey Silkin02371062019-01-31 16:45:42 +01001417TEST_P(ReceiveStatisticsProxyTestWithContent, DownscalesReported) {
Sergey Silkin278f8252019-01-09 14:37:40 +01001418 const int kInterFrameDelayMs = 2000; // To ensure long enough call duration.
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001419
Sergey Silkin278f8252019-01-09 14:37:40 +01001420 webrtc::VideoFrame frame_hd = CreateFrame(1280, 720);
1421 webrtc::VideoFrame frame_sd = CreateFrame(640, 360);
1422 webrtc::VideoFrame frame_ld = CreateFrame(320, 180);
1423
1424 // Call once to pass content type.
Johannes Kronbfd343b2019-07-01 10:07:50 +02001425 statistics_proxy_->OnDecodedFrame(frame_hd, absl::nullopt, 0, content_type_);
Sergey Silkin278f8252019-01-09 14:37:40 +01001426
1427 statistics_proxy_->OnRenderedFrame(frame_hd);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001428 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1429
1430 // Downscale.
Sergey Silkin278f8252019-01-09 14:37:40 +01001431 statistics_proxy_->OnRenderedFrame(frame_sd);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001432 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1433
1434 // Downscale.
Sergey Silkin278f8252019-01-09 14:37:40 +01001435 statistics_proxy_->OnRenderedFrame(frame_ld);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001436 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1437
Niels Möllerd7819652019-08-13 14:43:02 +02001438 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1439 nullptr);
Sergey Silkin278f8252019-01-09 14:37:40 +01001440 const int kExpectedDownscales = 30; // 2 per 4 seconds = 30 per minute.
Sergey Silkin02371062019-01-31 16:45:42 +01001441 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001442 EXPECT_EQ(
1443 kExpectedDownscales,
1444 metrics::MinSample(
1445 "WebRTC.Video.Screenshare.NumberResolutionDownswitchesPerMinute"));
1446 } else {
1447 EXPECT_EQ(kExpectedDownscales,
1448 metrics::MinSample(
1449 "WebRTC.Video.NumberResolutionDownswitchesPerMinute"));
1450 }
1451}
1452
Johannes Kronbfd343b2019-07-01 10:07:50 +02001453TEST_P(ReceiveStatisticsProxyTestWithContent, DecodeTimeReported) {
1454 const int kInterFrameDelayMs = 20;
1455 const int kLowQp = 30;
1456 const int kDecodeMs = 7;
1457
1458 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1459
1460 for (int i = 0; i < kMinRequiredSamples; ++i) {
1461 statistics_proxy_->OnDecodedFrame(frame, kLowQp, kDecodeMs, content_type_);
1462 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1463 }
Niels Möllerd7819652019-08-13 14:43:02 +02001464 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1465 nullptr);
Johannes Kronbfd343b2019-07-01 10:07:50 +02001466 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DecodeTimeInMs", kDecodeMs));
1467}
1468
Sergey Silkin02371062019-01-31 16:45:42 +01001469TEST_P(ReceiveStatisticsProxyTestWithContent,
1470 StatsAreSlicedOnSimulcastAndExperiment) {
ilnik6d5b4d62017-08-30 03:32:14 -07001471 const uint8_t experiment_id = 1;
Sergey Silkin02371062019-01-31 16:45:42 +01001472 webrtc::VideoContentType content_type = content_type_;
ilnik6d5b4d62017-08-30 03:32:14 -07001473 videocontenttypehelpers::SetExperimentId(&content_type, experiment_id);
1474 const int kInterFrameDelayMs1 = 30;
1475 const int kInterFrameDelayMs2 = 50;
Sergey Silkin278f8252019-01-09 14:37:40 +01001476 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
ilnik6d5b4d62017-08-30 03:32:14 -07001477
1478 videocontenttypehelpers::SetSimulcastId(&content_type, 1);
1479 for (int i = 0; i <= kMinRequiredSamples; ++i) {
1480 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs1);
Johannes Kronbfd343b2019-07-01 10:07:50 +02001481 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type);
ilnik6d5b4d62017-08-30 03:32:14 -07001482 }
1483
1484 videocontenttypehelpers::SetSimulcastId(&content_type, 2);
1485 for (int i = 0; i <= kMinRequiredSamples; ++i) {
1486 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs2);
Johannes Kronbfd343b2019-07-01 10:07:50 +02001487 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type);
ilnik6d5b4d62017-08-30 03:32:14 -07001488 }
Niels Möllerd7819652019-08-13 14:43:02 +02001489 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1490 nullptr);
ilnik6d5b4d62017-08-30 03:32:14 -07001491
1492 if (videocontenttypehelpers::IsScreenshare(content_type)) {
1493 EXPECT_EQ(
1494 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1495 EXPECT_EQ(1, metrics::NumSamples(
1496 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1497 EXPECT_EQ(1, metrics::NumSamples(
1498 "WebRTC.Video.Screenshare.InterframeDelayInMs.S0"));
1499 EXPECT_EQ(1, metrics::NumSamples(
1500 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs.S0"));
1501 EXPECT_EQ(1, metrics::NumSamples(
1502 "WebRTC.Video.Screenshare.InterframeDelayInMs.S1"));
1503 EXPECT_EQ(1, metrics::NumSamples(
1504 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs.S1"));
1505 EXPECT_EQ(1,
1506 metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"
1507 ".ExperimentGroup0"));
1508 EXPECT_EQ(
1509 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"
1510 ".ExperimentGroup0"));
1511 EXPECT_EQ(
1512 kInterFrameDelayMs1,
1513 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs.S0"));
1514 EXPECT_EQ(
1515 kInterFrameDelayMs2,
1516 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs.S1"));
1517 EXPECT_EQ(
1518 (kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1519 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1520 EXPECT_EQ(
1521 kInterFrameDelayMs2,
1522 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1523 EXPECT_EQ(
1524 (kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1525 metrics::MinSample(
1526 "WebRTC.Video.Screenshare.InterframeDelayInMs.ExperimentGroup0"));
1527 } else {
1528 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
1529 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
1530 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs.S0"));
1531 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs.S0"));
1532 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs.S1"));
1533 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs.S1"));
1534 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"
1535 ".ExperimentGroup0"));
1536 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"
1537 ".ExperimentGroup0"));
1538 EXPECT_EQ(kInterFrameDelayMs1,
1539 metrics::MinSample("WebRTC.Video.InterframeDelayInMs.S0"));
1540 EXPECT_EQ(kInterFrameDelayMs2,
1541 metrics::MinSample("WebRTC.Video.InterframeDelayInMs.S1"));
1542 EXPECT_EQ((kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1543 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
1544 EXPECT_EQ(kInterFrameDelayMs2,
1545 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
1546 EXPECT_EQ((kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1547 metrics::MinSample(
1548 "WebRTC.Video.InterframeDelayInMs.ExperimentGroup0"));
1549 }
1550}
sakale5ba44e2016-10-26 07:09:24 -07001551} // namespace webrtc