blob: 276a059e4637cdc3b491eb3e560ddcf9c8397a0c [file] [log] [blame]
sakale5ba44e2016-10-26 14:09:241/*
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 04:47:3111#include "video/receive_statistics_proxy.h"
sakale5ba44e2016-10-26 14:09:2412
asapersson2077f2f2017-05-11 12:37:3513#include <limits>
sakale5ba44e2016-10-26 14:09:2414#include <memory>
Yves Gerey3e707812018-11-28 15:47:4915#include <string>
Sergey Silkin02371062019-01-31 15:45:4216#include <tuple>
17#include <utility>
sakale5ba44e2016-10-26 14:09:2418
Mirko Bonadeid9708072019-01-25 19:26:4819#include "api/scoped_refptr.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3120#include "api/video/i420_buffer.h"
21#include "api/video/video_frame.h"
Yves Gerey3e707812018-11-28 15:47:4922#include "api/video/video_frame_buffer.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3123#include "api/video/video_rotation.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3124#include "system_wrappers/include/metrics.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3125#include "test/gtest.h"
sakale5ba44e2016-10-26 14:09:2426
27namespace webrtc {
asaperssonde9e5ff2016-11-02 14:14:0328namespace {
29const int64_t kFreqOffsetProcessIntervalInMs = 40000;
asapersson46c4e3c2016-11-03 13:48:1930const uint32_t kLocalSsrc = 123;
31const uint32_t kRemoteSsrc = 456;
32const int kMinRequiredSamples = 200;
Ilya Nikolaevskiy94150ee2018-05-23 09:53:1933const int kWidth = 1280;
34const int kHeight = 720;
asaperssonde9e5ff2016-11-02 14:14:0335} // namespace
sakale5ba44e2016-10-26 14:09:2436
37// TODO(sakal): ReceiveStatisticsProxy is lacking unittesting.
Sergey Silkin02371062019-01-31 15:45:4238class ReceiveStatisticsProxyTest : public ::testing::Test {
sakale5ba44e2016-10-26 14:09:2439 public:
40 ReceiveStatisticsProxyTest() : fake_clock_(1234), config_(GetTestConfig()) {}
41 virtual ~ReceiveStatisticsProxyTest() {}
42
43 protected:
44 virtual void SetUp() {
asaperssonde9e5ff2016-11-02 14:14:0345 metrics::Reset();
sakale5ba44e2016-10-26 14:09:2446 statistics_proxy_.reset(new ReceiveStatisticsProxy(&config_, &fake_clock_));
47 }
48
49 VideoReceiveStream::Config GetTestConfig() {
50 VideoReceiveStream::Config config(nullptr);
asapersson46c4e3c2016-11-03 13:48:1951 config.rtp.local_ssrc = kLocalSsrc;
52 config.rtp.remote_ssrc = kRemoteSsrc;
sakale5ba44e2016-10-26 14:09:2453 return config;
54 }
55
asapersson2077f2f2017-05-11 12:37:3556 void InsertFirstRtpPacket(uint32_t ssrc) {
57 StreamDataCounters counters;
58 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
59 statistics_proxy_->DataCountersUpdated(counters, ssrc);
60 }
61
62 VideoFrame CreateFrame(int width, int height) {
Åsa Persson81327d52018-06-05 11:34:3363 return CreateVideoFrame(width, height, 0);
64 }
65
66 VideoFrame CreateFrameWithRenderTimeMs(int64_t render_time_ms) {
67 return CreateVideoFrame(kWidth, kHeight, render_time_ms);
68 }
69
70 VideoFrame CreateVideoFrame(int width, int height, int64_t render_time_ms) {
Artem Titov1ebfb6a2019-01-03 22:49:3771 VideoFrame frame =
72 VideoFrame::Builder()
73 .set_video_frame_buffer(I420Buffer::Create(width, height))
74 .set_timestamp_rtp(0)
75 .set_timestamp_ms(render_time_ms)
76 .set_rotation(kVideoRotation_0)
77 .build();
asapersson2077f2f2017-05-11 12:37:3578 frame.set_ntp_time_ms(fake_clock_.CurrentNtpInMilliseconds());
79 return frame;
80 }
81
sakale5ba44e2016-10-26 14:09:2482 SimulatedClock fake_clock_;
asaperssonde9e5ff2016-11-02 14:14:0383 const VideoReceiveStream::Config config_;
sakale5ba44e2016-10-26 14:09:2484 std::unique_ptr<ReceiveStatisticsProxy> statistics_proxy_;
sakale5ba44e2016-10-26 14:09:2485};
86
87TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameIncreasesFramesDecoded) {
88 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_decoded);
Sergey Silkin278f8252019-01-09 13:37:4089 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
sakale5ba44e2016-10-26 14:09:2490 for (uint32_t i = 1; i <= 3; ++i) {
Johannes Kronbfd343b2019-07-01 08:07:5091 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
ilnik00d802b2017-04-11 17:34:3192 VideoContentType::UNSPECIFIED);
sakale5ba44e2016-10-26 14:09:2493 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_decoded);
94 }
95}
96
Åsa Perssonb9b07ea2018-01-24 16:04:0797TEST_F(ReceiveStatisticsProxyTest, DecodedFpsIsReported) {
98 const int kFps = 20;
99 const int kRequiredSamples = metrics::kMinRunTimeInSeconds * kFps;
Sergey Silkin278f8252019-01-09 13:37:40100 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Åsa Perssonb9b07ea2018-01-24 16:04:07101 for (int i = 0; i < kRequiredSamples; ++i) {
Johannes Kronbfd343b2019-07-01 08:07:50102 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Sergey Silkin278f8252019-01-09 13:37:40103 VideoContentType::UNSPECIFIED);
Åsa Perssonb9b07ea2018-01-24 16:04:07104 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
105 }
106 statistics_proxy_.reset();
107 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
108 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DecodedFramesPerSecond", kFps));
109}
110
111TEST_F(ReceiveStatisticsProxyTest, DecodedFpsIsNotReportedForTooFewSamples) {
112 const int kFps = 20;
113 const int kRequiredSamples = metrics::kMinRunTimeInSeconds * kFps;
Sergey Silkin278f8252019-01-09 13:37:40114 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Åsa Perssonb9b07ea2018-01-24 16:04:07115 for (int i = 0; i < kRequiredSamples - 1; ++i) {
Johannes Kronbfd343b2019-07-01 08:07:50116 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Sergey Silkin278f8252019-01-09 13:37:40117 VideoContentType::UNSPECIFIED);
Åsa Perssonb9b07ea2018-01-24 16:04:07118 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
119 }
120 statistics_proxy_.reset();
121 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
122}
123
Johannes Kronbfd343b2019-07-01 08:07:50124TEST_F(ReceiveStatisticsProxyTest,
125 OnDecodedFrameWithQpDoesNotResetFramesDecodedOrTotalDecodeTime) {
sakalcc452e12017-02-09 12:53:45126 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_decoded);
Sergey Silkin278f8252019-01-09 13:37:40127 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Johannes Kronbfd343b2019-07-01 08:07:50128 unsigned int expected_total_decode_time_ms = 0;
129 unsigned int expected_frames_decoded = 0;
sakalcc452e12017-02-09 12:53:45130 for (uint32_t i = 1; i <= 3; ++i) {
Johannes Kronbfd343b2019-07-01 08:07:50131 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 1,
ilnik00d802b2017-04-11 17:34:31132 VideoContentType::UNSPECIFIED);
Johannes Kronbfd343b2019-07-01 08:07:50133 expected_total_decode_time_ms += 1;
134 ++expected_frames_decoded;
135 EXPECT_EQ(expected_frames_decoded,
136 statistics_proxy_->GetStats().frames_decoded);
137 EXPECT_EQ(expected_total_decode_time_ms,
138 statistics_proxy_->GetStats().total_decode_time_ms);
sakalcc452e12017-02-09 12:53:45139 }
Johannes Kronbfd343b2019-07-01 08:07:50140 statistics_proxy_->OnDecodedFrame(frame, 1u, 3,
141 VideoContentType::UNSPECIFIED);
142 ++expected_frames_decoded;
143 expected_total_decode_time_ms += 3;
144 EXPECT_EQ(expected_frames_decoded,
145 statistics_proxy_->GetStats().frames_decoded);
146 EXPECT_EQ(expected_total_decode_time_ms,
147 statistics_proxy_->GetStats().total_decode_time_ms);
sakalcc452e12017-02-09 12:53:45148}
149
150TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameIncreasesQpSum) {
Danil Chapovalovb9b146c2018-06-15 10:28:07151 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
Sergey Silkin278f8252019-01-09 13:37:40152 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Johannes Kronbfd343b2019-07-01 08:07:50153 statistics_proxy_->OnDecodedFrame(frame, 3u, 0,
154 VideoContentType::UNSPECIFIED);
Oskar Sundbom8e07c132018-01-08 15:45:42155 EXPECT_EQ(3u, statistics_proxy_->GetStats().qp_sum);
Johannes Kronbfd343b2019-07-01 08:07:50156 statistics_proxy_->OnDecodedFrame(frame, 127u, 0,
157 VideoContentType::UNSPECIFIED);
Oskar Sundbom8e07c132018-01-08 15:45:42158 EXPECT_EQ(130u, statistics_proxy_->GetStats().qp_sum);
sakalcc452e12017-02-09 12:53:45159}
160
Johannes Kronbfd343b2019-07-01 08:07:50161TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameIncreasesTotalDecodeTime) {
162 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
163 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
164 statistics_proxy_->OnDecodedFrame(frame, 3u, 4,
165 VideoContentType::UNSPECIFIED);
166 EXPECT_EQ(4u, statistics_proxy_->GetStats().total_decode_time_ms);
167 statistics_proxy_->OnDecodedFrame(frame, 127u, 7,
168 VideoContentType::UNSPECIFIED);
169 EXPECT_EQ(11u, statistics_proxy_->GetStats().total_decode_time_ms);
170}
171
ilnik2e1b40b2017-09-04 14:57:17172TEST_F(ReceiveStatisticsProxyTest, ReportsContentType) {
173 const std::string kRealtimeString("realtime");
174 const std::string kScreenshareString("screen");
Sergey Silkin278f8252019-01-09 13:37:40175 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
ilnik2e1b40b2017-09-04 14:57:17176 EXPECT_EQ(kRealtimeString, videocontenttypehelpers::ToString(
Sergey Silkin02371062019-01-31 15:45:42177 statistics_proxy_->GetStats().content_type));
Johannes Kronbfd343b2019-07-01 08:07:50178 statistics_proxy_->OnDecodedFrame(frame, 3u, 0,
179 VideoContentType::SCREENSHARE);
Sergey Silkin02371062019-01-31 15:45:42180 EXPECT_EQ(kScreenshareString,
181 videocontenttypehelpers::ToString(
182 statistics_proxy_->GetStats().content_type));
Johannes Kronbfd343b2019-07-01 08:07:50183 statistics_proxy_->OnDecodedFrame(frame, 3u, 0,
184 VideoContentType::UNSPECIFIED);
ilnik2e1b40b2017-09-04 14:57:17185 EXPECT_EQ(kRealtimeString, videocontenttypehelpers::ToString(
Sergey Silkin02371062019-01-31 15:45:42186 statistics_proxy_->GetStats().content_type));
ilnik2e1b40b2017-09-04 14:57:17187}
188
ilnika79cc282017-08-23 12:24:10189TEST_F(ReceiveStatisticsProxyTest, ReportsMaxInterframeDelay) {
Sergey Silkin278f8252019-01-09 13:37:40190 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
ilnika79cc282017-08-23 12:24:10191 const int64_t kInterframeDelayMs1 = 100;
192 const int64_t kInterframeDelayMs2 = 200;
193 const int64_t kInterframeDelayMs3 = 100;
194 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
Johannes Kronbfd343b2019-07-01 08:07:50195 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Ilya Nikolaevskiy94150ee2018-05-23 09:53:19196 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 12:24:10197 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
ilnikf04afde2017-07-07 08:26:24198
199 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs1);
Johannes Kronbfd343b2019-07-01 08:07:50200 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Ilya Nikolaevskiy94150ee2018-05-23 09:53:19201 VideoContentType::UNSPECIFIED);
ilnikf04afde2017-07-07 08:26:24202 EXPECT_EQ(kInterframeDelayMs1,
ilnika79cc282017-08-23 12:24:10203 statistics_proxy_->GetStats().interframe_delay_max_ms);
ilnikf04afde2017-07-07 08:26:24204
205 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs2);
Johannes Kronbfd343b2019-07-01 08:07:50206 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Ilya Nikolaevskiy94150ee2018-05-23 09:53:19207 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 12:24:10208 EXPECT_EQ(kInterframeDelayMs2,
209 statistics_proxy_->GetStats().interframe_delay_max_ms);
210
211 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs3);
Johannes Kronbfd343b2019-07-01 08:07:50212 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Ilya Nikolaevskiy94150ee2018-05-23 09:53:19213 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 12:24:10214 // kInterframeDelayMs3 is smaller than kInterframeDelayMs2.
215 EXPECT_EQ(kInterframeDelayMs2,
216 statistics_proxy_->GetStats().interframe_delay_max_ms);
217}
218
219TEST_F(ReceiveStatisticsProxyTest, ReportInterframeDelayInWindow) {
Sergey Silkin278f8252019-01-09 13:37:40220 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Ilya Nikolaevskiyb06b3582017-10-16 15:59:12221 const int64_t kInterframeDelayMs1 = 900;
222 const int64_t kInterframeDelayMs2 = 750;
223 const int64_t kInterframeDelayMs3 = 700;
ilnika79cc282017-08-23 12:24:10224 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
Johannes Kronbfd343b2019-07-01 08:07:50225 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Ilya Nikolaevskiy94150ee2018-05-23 09:53:19226 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 12:24:10227 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
228
229 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs1);
Johannes Kronbfd343b2019-07-01 08:07:50230 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Ilya Nikolaevskiy94150ee2018-05-23 09:53:19231 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 12:24:10232 EXPECT_EQ(kInterframeDelayMs1,
233 statistics_proxy_->GetStats().interframe_delay_max_ms);
234
235 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs2);
Johannes Kronbfd343b2019-07-01 08:07:50236 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Ilya Nikolaevskiy94150ee2018-05-23 09:53:19237 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 12:24:10238 // Still first delay is the maximum
239 EXPECT_EQ(kInterframeDelayMs1,
240 statistics_proxy_->GetStats().interframe_delay_max_ms);
241
242 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs3);
Johannes Kronbfd343b2019-07-01 08:07:50243 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Ilya Nikolaevskiy94150ee2018-05-23 09:53:19244 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 12:24:10245 // Now the first sample is out of the window, so the second is the maximum.
246 EXPECT_EQ(kInterframeDelayMs2,
247 statistics_proxy_->GetStats().interframe_delay_max_ms);
ilnikf04afde2017-07-07 08:26:24248}
249
Sergey Silkin02371062019-01-31 15:45:42250TEST_F(ReceiveStatisticsProxyTest, ReportsFreezeMetrics) {
251 const int64_t kFreezeDurationMs = 1000;
252
253 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
254 EXPECT_EQ(0u, stats.freeze_count);
255 EXPECT_FALSE(stats.total_freezes_duration_ms);
256
257 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
258 for (size_t i = 0; i < VideoQualityObserver::kMinFrameSamplesToDetectFreeze;
259 ++i) {
260 fake_clock_.AdvanceTimeMilliseconds(30);
261 statistics_proxy_->OnRenderedFrame(frame);
262 }
263
264 // Freeze.
265 fake_clock_.AdvanceTimeMilliseconds(kFreezeDurationMs);
266 statistics_proxy_->OnRenderedFrame(frame);
267
268 stats = statistics_proxy_->GetStats();
269 EXPECT_EQ(1u, stats.freeze_count);
270 EXPECT_EQ(kFreezeDurationMs, stats.total_freezes_duration_ms);
271}
272
273TEST_F(ReceiveStatisticsProxyTest, ReportsPauseMetrics) {
274 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
275 ASSERT_EQ(0u, stats.pause_count);
276 ASSERT_EQ(0u, stats.total_pauses_duration_ms);
277
278 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
279 statistics_proxy_->OnRenderedFrame(frame);
280
281 // Pause.
282 fake_clock_.AdvanceTimeMilliseconds(5432);
283 statistics_proxy_->OnStreamInactive();
284 statistics_proxy_->OnRenderedFrame(frame);
285
286 stats = statistics_proxy_->GetStats();
287 EXPECT_EQ(1u, stats.pause_count);
288 EXPECT_EQ(5432u, stats.total_pauses_duration_ms);
289}
290
291TEST_F(ReceiveStatisticsProxyTest, PauseBeforeFirstAndAfterLastFrameIgnored) {
292 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
293 ASSERT_EQ(0u, stats.pause_count);
294 ASSERT_EQ(0u, stats.total_pauses_duration_ms);
295
296 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
297
298 // Pause -> Frame -> Pause
299 fake_clock_.AdvanceTimeMilliseconds(5000);
300 statistics_proxy_->OnStreamInactive();
301 statistics_proxy_->OnRenderedFrame(frame);
302
303 fake_clock_.AdvanceTimeMilliseconds(30);
304 statistics_proxy_->OnRenderedFrame(frame);
305
306 fake_clock_.AdvanceTimeMilliseconds(5000);
307 statistics_proxy_->OnStreamInactive();
308
309 stats = statistics_proxy_->GetStats();
310 EXPECT_EQ(0u, stats.pause_count);
311 EXPECT_EQ(0u, stats.total_pauses_duration_ms);
312}
313
314TEST_F(ReceiveStatisticsProxyTest, ReportsFramesDuration) {
315 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
316 ASSERT_EQ(0u, stats.total_frames_duration_ms);
317
318 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
319
320 // Emulate delay before first frame is rendered. This is needed to ensure
321 // that frame duration only covers time since first frame is rendered and
322 // not the total time.
323 fake_clock_.AdvanceTimeMilliseconds(5432);
324
325 for (int i = 0; i <= 10; ++i) {
326 fake_clock_.AdvanceTimeMilliseconds(30);
327 statistics_proxy_->OnRenderedFrame(frame);
328 }
329
330 stats = statistics_proxy_->GetStats();
331 EXPECT_EQ(10 * 30u, stats.total_frames_duration_ms);
332}
333
334TEST_F(ReceiveStatisticsProxyTest, ReportsSumSquaredFrameDurations) {
335 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
336 ASSERT_EQ(0u, stats.sum_squared_frame_durations);
337
338 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
339 for (int i = 0; i <= 10; ++i) {
340 fake_clock_.AdvanceTimeMilliseconds(30);
341 statistics_proxy_->OnRenderedFrame(frame);
342 }
343
344 stats = statistics_proxy_->GetStats();
345 const double kExpectedSumSquaredFrameDurationsSecs =
346 10 * (30 / 1000.0 * 30 / 1000.0);
347 EXPECT_EQ(kExpectedSumSquaredFrameDurationsSecs,
348 stats.sum_squared_frame_durations);
349}
350
sakalcc452e12017-02-09 12:53:45351TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameWithoutQpQpSumWontExist) {
Sergey Silkin278f8252019-01-09 13:37:40352 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Danil Chapovalovb9b146c2018-06-15 10:28:07353 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
Johannes Kronbfd343b2019-07-01 08:07:50354 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
ilnik00d802b2017-04-11 17:34:31355 VideoContentType::UNSPECIFIED);
Danil Chapovalovb9b146c2018-06-15 10:28:07356 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakalcc452e12017-02-09 12:53:45357}
358
Johannes Kronbfd343b2019-07-01 08:07:50359TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameWithoutQpDoesNotResetQpSum) {
Sergey Silkin278f8252019-01-09 13:37:40360 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Danil Chapovalovb9b146c2018-06-15 10:28:07361 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
Johannes Kronbfd343b2019-07-01 08:07:50362 statistics_proxy_->OnDecodedFrame(frame, 3u, 0,
ilnik00d802b2017-04-11 17:34:31363 VideoContentType::UNSPECIFIED);
Johannes Kronbfd343b2019-07-01 08:07:50364 EXPECT_EQ(3u, statistics_proxy_->GetStats().qp_sum);
365 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
366 VideoContentType::UNSPECIFIED);
367 EXPECT_EQ(3u, statistics_proxy_->GetStats().qp_sum);
sakalcc452e12017-02-09 12:53:45368}
369
hbos50cfe1f2017-01-23 15:21:55370TEST_F(ReceiveStatisticsProxyTest, OnRenderedFrameIncreasesFramesRendered) {
371 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_rendered);
Sergey Silkin278f8252019-01-09 13:37:40372 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
hbos50cfe1f2017-01-23 15:21:55373 for (uint32_t i = 1; i <= 3; ++i) {
374 statistics_proxy_->OnRenderedFrame(frame);
375 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_rendered);
376 }
377}
378
asapersson46c4e3c2016-11-03 13:48:19379TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsSsrc) {
380 EXPECT_EQ(kRemoteSsrc, statistics_proxy_->GetStats().ssrc);
381}
382
383TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsIncomingPayloadType) {
384 const int kPayloadType = 111;
385 statistics_proxy_->OnIncomingPayloadType(kPayloadType);
386 EXPECT_EQ(kPayloadType, statistics_proxy_->GetStats().current_payload_type);
387}
388
asapersson6966bd52017-01-03 08:44:06389TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsDecoderImplementationName) {
390 const char* kName = "decoderName";
391 statistics_proxy_->OnDecoderImplementationName(kName);
392 EXPECT_STREQ(
393 kName, statistics_proxy_->GetStats().decoder_implementation_name.c_str());
394}
395
philipela45102f2017-02-22 13:30:39396TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsOnCompleteFrame) {
397 const int kFrameSizeBytes = 1000;
ilnik6d5b4d62017-08-30 10:32:14398 statistics_proxy_->OnCompleteFrame(true, kFrameSizeBytes,
399 VideoContentType::UNSPECIFIED);
philipela45102f2017-02-22 13:30:39400 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
401 EXPECT_EQ(1, stats.network_frame_rate);
philipela45102f2017-02-22 13:30:39402 EXPECT_EQ(1, stats.frame_counts.key_frames);
403 EXPECT_EQ(0, stats.frame_counts.delta_frames);
asapersson46c4e3c2016-11-03 13:48:19404}
405
406TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsDecodeTimingStats) {
asapersson46c4e3c2016-11-03 13:48:19407 const int kMaxDecodeMs = 2;
408 const int kCurrentDelayMs = 3;
409 const int kTargetDelayMs = 4;
410 const int kJitterBufferMs = 5;
411 const int kMinPlayoutDelayMs = 6;
412 const int kRenderDelayMs = 7;
413 const int64_t kRttMs = 8;
philipela45102f2017-02-22 13:30:39414 statistics_proxy_->OnRttUpdate(kRttMs, 0);
415 statistics_proxy_->OnFrameBufferTimingsUpdated(
Johannes Kronbfd343b2019-07-01 08:07:50416 kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs, kJitterBufferMs,
philipela45102f2017-02-22 13:30:39417 kMinPlayoutDelayMs, kRenderDelayMs);
asapersson46c4e3c2016-11-03 13:48:19418 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
asapersson46c4e3c2016-11-03 13:48:19419 EXPECT_EQ(kMaxDecodeMs, stats.max_decode_ms);
420 EXPECT_EQ(kCurrentDelayMs, stats.current_delay_ms);
421 EXPECT_EQ(kTargetDelayMs, stats.target_delay_ms);
422 EXPECT_EQ(kJitterBufferMs, stats.jitter_buffer_ms);
423 EXPECT_EQ(kMinPlayoutDelayMs, stats.min_playout_delay_ms);
424 EXPECT_EQ(kRenderDelayMs, stats.render_delay_ms);
425}
426
asapersson6966bd52017-01-03 08:44:06427TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsRtcpPacketTypeCounts) {
428 const uint32_t kFirPackets = 33;
429 const uint32_t kPliPackets = 44;
430 const uint32_t kNackPackets = 55;
431 RtcpPacketTypeCounter counter;
432 counter.fir_packets = kFirPackets;
433 counter.pli_packets = kPliPackets;
434 counter.nack_packets = kNackPackets;
435 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
436 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
437 EXPECT_EQ(kFirPackets, stats.rtcp_packet_type_counts.fir_packets);
438 EXPECT_EQ(kPliPackets, stats.rtcp_packet_type_counts.pli_packets);
439 EXPECT_EQ(kNackPackets, stats.rtcp_packet_type_counts.nack_packets);
440}
441
442TEST_F(ReceiveStatisticsProxyTest,
443 GetStatsReportsNoRtcpPacketTypeCountsForUnknownSsrc) {
444 RtcpPacketTypeCounter counter;
445 counter.fir_packets = 33;
446 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc + 1, counter);
447 EXPECT_EQ(0u,
448 statistics_proxy_->GetStats().rtcp_packet_type_counts.fir_packets);
449}
450
451TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsFrameCounts) {
452 const int kKeyFrames = 3;
453 const int kDeltaFrames = 22;
Niels Möllerdd41da62019-03-28 07:59:07454 for (int i = 0; i < kKeyFrames; i++) {
455 statistics_proxy_->OnCompleteFrame(true, 0, VideoContentType::UNSPECIFIED);
456 }
457 for (int i = 0; i < kDeltaFrames; i++) {
458 statistics_proxy_->OnCompleteFrame(false, 0, VideoContentType::UNSPECIFIED);
459 }
460
asapersson6966bd52017-01-03 08:44:06461 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
462 EXPECT_EQ(kKeyFrames, stats.frame_counts.key_frames);
463 EXPECT_EQ(kDeltaFrames, stats.frame_counts.delta_frames);
464}
465
asapersson6966bd52017-01-03 08:44:06466TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsRtcpStats) {
467 const uint8_t kFracLost = 0;
Harald Alvestrandc7c41912017-12-08 08:59:34468 const int32_t kCumLost = 1;
asapersson6966bd52017-01-03 08:44:06469 const uint32_t kExtSeqNum = 10;
470 const uint32_t kJitter = 4;
471
472 RtcpStatistics rtcp_stats;
473 rtcp_stats.fraction_lost = kFracLost;
srte186d9c32017-08-04 12:03:53474 rtcp_stats.packets_lost = kCumLost;
475 rtcp_stats.extended_highest_sequence_number = kExtSeqNum;
asapersson6966bd52017-01-03 08:44:06476 rtcp_stats.jitter = kJitter;
477 statistics_proxy_->StatisticsUpdated(rtcp_stats, kRemoteSsrc);
478
479 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
480 EXPECT_EQ(kFracLost, stats.rtcp_stats.fraction_lost);
srte186d9c32017-08-04 12:03:53481 EXPECT_EQ(kCumLost, stats.rtcp_stats.packets_lost);
482 EXPECT_EQ(kExtSeqNum, stats.rtcp_stats.extended_highest_sequence_number);
asapersson6966bd52017-01-03 08:44:06483 EXPECT_EQ(kJitter, stats.rtcp_stats.jitter);
484}
485
486TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsCName) {
487 const char* kName = "cName";
488 statistics_proxy_->CNameChanged(kName, kRemoteSsrc);
489 EXPECT_STREQ(kName, statistics_proxy_->GetStats().c_name.c_str());
490}
491
492TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsNoCNameForUnknownSsrc) {
493 const char* kName = "cName";
494 statistics_proxy_->CNameChanged(kName, kRemoteSsrc + 1);
495 EXPECT_STREQ("", statistics_proxy_->GetStats().c_name.c_str());
496}
497
Jonas Olssona4d87372019-07-05 17:08:33498TEST_F(ReceiveStatisticsProxyTest, ReportsLongestTimingFrameInfo) {
ilnik2edc6842017-07-06 10:06:50499 const int64_t kShortEndToEndDelay = 10;
500 const int64_t kMedEndToEndDelay = 20;
501 const int64_t kLongEndToEndDelay = 100;
502 const uint32_t kExpectedRtpTimestamp = 2;
503 TimingFrameInfo info;
Danil Chapovalovb9b146c2018-06-15 10:28:07504 absl::optional<TimingFrameInfo> result;
ilnik2edc6842017-07-06 10:06:50505 info.rtp_timestamp = kExpectedRtpTimestamp - 1;
506 info.capture_time_ms = 0;
507 info.decode_finish_ms = kShortEndToEndDelay;
508 statistics_proxy_->OnTimingFrameInfoUpdated(info);
509 info.rtp_timestamp =
510 kExpectedRtpTimestamp; // this frame should be reported in the end.
511 info.capture_time_ms = 0;
512 info.decode_finish_ms = kLongEndToEndDelay;
513 statistics_proxy_->OnTimingFrameInfoUpdated(info);
514 info.rtp_timestamp = kExpectedRtpTimestamp + 1;
515 info.capture_time_ms = 0;
516 info.decode_finish_ms = kMedEndToEndDelay;
517 statistics_proxy_->OnTimingFrameInfoUpdated(info);
ilnik75204c52017-09-04 10:35:40518 result = statistics_proxy_->GetStats().timing_frame_info;
ilnik2edc6842017-07-06 10:06:50519 EXPECT_TRUE(result);
520 EXPECT_EQ(kExpectedRtpTimestamp, result->rtp_timestamp);
521}
522
ilnik75204c52017-09-04 10:35:40523TEST_F(ReceiveStatisticsProxyTest, RespectsReportingIntervalForTimingFrames) {
524 TimingFrameInfo info;
ilnik2edc6842017-07-06 10:06:50525 const int64_t kShortEndToEndDelay = 10;
526 const uint32_t kExpectedRtpTimestamp = 2;
ilnik75204c52017-09-04 10:35:40527 const int64_t kShortDelayMs = 1000;
528 const int64_t kLongDelayMs = 10000;
Danil Chapovalovb9b146c2018-06-15 10:28:07529 absl::optional<TimingFrameInfo> result;
ilnik2edc6842017-07-06 10:06:50530 info.rtp_timestamp = kExpectedRtpTimestamp;
531 info.capture_time_ms = 0;
532 info.decode_finish_ms = kShortEndToEndDelay;
533 statistics_proxy_->OnTimingFrameInfoUpdated(info);
ilnik75204c52017-09-04 10:35:40534 fake_clock_.AdvanceTimeMilliseconds(kShortDelayMs);
535 result = statistics_proxy_->GetStats().timing_frame_info;
ilnik2edc6842017-07-06 10:06:50536 EXPECT_TRUE(result);
537 EXPECT_EQ(kExpectedRtpTimestamp, result->rtp_timestamp);
ilnik75204c52017-09-04 10:35:40538 fake_clock_.AdvanceTimeMilliseconds(kLongDelayMs);
539 result = statistics_proxy_->GetStats().timing_frame_info;
ilnik2edc6842017-07-06 10:06:50540 EXPECT_FALSE(result);
541}
542
asapersson46c4e3c2016-11-03 13:48:19543TEST_F(ReceiveStatisticsProxyTest, LifetimeHistogramIsUpdated) {
544 const int64_t kTimeSec = 3;
545 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
ilnik6d5b4d62017-08-30 10:32:14546 // Need at least one frame to report stream lifetime.
547 statistics_proxy_->OnCompleteFrame(true, 1000, VideoContentType::UNSPECIFIED);
asapersson46c4e3c2016-11-03 13:48:19548 // Histograms are updated when the statistics_proxy_ is deleted.
549 statistics_proxy_.reset();
550 EXPECT_EQ(1,
551 metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
552 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceiveStreamLifetimeInSeconds",
553 kTimeSec));
554}
555
ilnik6d5b4d62017-08-30 10:32:14556TEST_F(ReceiveStatisticsProxyTest,
557 LifetimeHistogramNotReportedForEmptyStreams) {
558 const int64_t kTimeSec = 3;
559 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
560 // No frames received.
561 // Histograms are updated when the statistics_proxy_ is deleted.
562 statistics_proxy_.reset();
563 EXPECT_EQ(0,
564 metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
565}
566
palmkvista40672a2017-01-13 13:58:34567TEST_F(ReceiveStatisticsProxyTest, BadCallHistogramsAreUpdated) {
568 // Based on the tuning parameters this will produce 7 uncertain states,
569 // then 10 certainly bad states. There has to be 10 certain states before
570 // any histograms are recorded.
571 const int kNumBadSamples = 17;
Niels Möller9b0b1e02019-03-22 12:56:46572 // We only count one sample per second.
573 const int kBadFameIntervalMs = 1100;
palmkvista40672a2017-01-13 13:58:34574
575 StreamDataCounters counters;
576 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
577 statistics_proxy_->DataCountersUpdated(counters, config_.rtp.remote_ssrc);
578
Niels Möller9b0b1e02019-03-22 12:56:46579 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
580
palmkvista40672a2017-01-13 13:58:34581 for (int i = 0; i < kNumBadSamples; ++i) {
Niels Möller9b0b1e02019-03-22 12:56:46582 fake_clock_.AdvanceTimeMilliseconds(kBadFameIntervalMs);
583 statistics_proxy_->OnRenderedFrame(frame);
palmkvista40672a2017-01-13 13:58:34584 }
585 // Histograms are updated when the statistics_proxy_ is deleted.
586 statistics_proxy_.reset();
587 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BadCall.Any"));
588 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BadCall.Any", 100));
589
590 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BadCall.FrameRate"));
591 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BadCall.FrameRate", 100));
592
593 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.BadCall.FrameRateVariance"));
594
595 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.BadCall.Qp"));
596}
597
asapersson0c43f772016-11-30 09:42:26598TEST_F(ReceiveStatisticsProxyTest, PacketLossHistogramIsUpdated) {
599 const uint32_t kCumLost1 = 1;
600 const uint32_t kExtSeqNum1 = 10;
601 const uint32_t kCumLost2 = 2;
602 const uint32_t kExtSeqNum2 = 20;
603
604 // One report block received.
605 RtcpStatistics rtcp_stats1;
srte186d9c32017-08-04 12:03:53606 rtcp_stats1.packets_lost = kCumLost1;
607 rtcp_stats1.extended_highest_sequence_number = kExtSeqNum1;
asapersson0c43f772016-11-30 09:42:26608 statistics_proxy_->StatisticsUpdated(rtcp_stats1, kRemoteSsrc);
609
610 // Two report blocks received.
611 RtcpStatistics rtcp_stats2;
srte186d9c32017-08-04 12:03:53612 rtcp_stats2.packets_lost = kCumLost2;
613 rtcp_stats2.extended_highest_sequence_number = kExtSeqNum2;
asapersson0c43f772016-11-30 09:42:26614 statistics_proxy_->StatisticsUpdated(rtcp_stats2, kRemoteSsrc);
615
616 // Two received report blocks but min run time has not passed.
617 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
618 SetUp(); // Reset stat proxy causes histograms to be updated.
619 EXPECT_EQ(0,
620 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
621
622 // Two report blocks received.
623 statistics_proxy_->StatisticsUpdated(rtcp_stats1, kRemoteSsrc);
624 statistics_proxy_->StatisticsUpdated(rtcp_stats2, kRemoteSsrc);
625
626 // Two received report blocks and min run time has passed.
627 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
628 SetUp();
629 EXPECT_EQ(1,
630 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
631 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceivedPacketsLostInPercent",
632 (kCumLost2 - kCumLost1) * 100 /
633 (kExtSeqNum2 - kExtSeqNum1)));
634}
635
636TEST_F(ReceiveStatisticsProxyTest,
637 PacketLossHistogramIsNotUpdatedIfLessThanTwoReportBlocksAreReceived) {
638 RtcpStatistics rtcp_stats1;
srte186d9c32017-08-04 12:03:53639 rtcp_stats1.packets_lost = 1;
640 rtcp_stats1.extended_highest_sequence_number = 10;
asapersson0c43f772016-11-30 09:42:26641
642 // Min run time has passed but no received report block.
643 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
644 SetUp(); // Reset stat proxy causes histograms to be updated.
645 EXPECT_EQ(0,
646 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
647
648 // Min run time has passed but only one received report block.
649 statistics_proxy_->StatisticsUpdated(rtcp_stats1, kRemoteSsrc);
650 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
651 SetUp();
652 EXPECT_EQ(0,
653 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
654}
655
asapersson2077f2f2017-05-11 12:37:35656TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsAvSyncOffset) {
657 const int64_t kSyncOffsetMs = 22;
658 const double kFreqKhz = 90.0;
659 EXPECT_EQ(std::numeric_limits<int>::max(),
660 statistics_proxy_->GetStats().sync_offset_ms);
661 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
662 EXPECT_EQ(kSyncOffsetMs, statistics_proxy_->GetStats().sync_offset_ms);
663}
664
asapersson46c4e3c2016-11-03 13:48:19665TEST_F(ReceiveStatisticsProxyTest, AvSyncOffsetHistogramIsUpdated) {
666 const int64_t kSyncOffsetMs = 22;
667 const double kFreqKhz = 90.0;
668 for (int i = 0; i < kMinRequiredSamples; ++i)
669 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
670 // Histograms are updated when the statistics_proxy_ is deleted.
671 statistics_proxy_.reset();
672 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AVSyncOffsetInMs"));
673 EXPECT_EQ(1,
674 metrics::NumEvents("WebRTC.Video.AVSyncOffsetInMs", kSyncOffsetMs));
675}
676
asaperssonde9e5ff2016-11-02 14:14:03677TEST_F(ReceiveStatisticsProxyTest, RtpToNtpFrequencyOffsetHistogramIsUpdated) {
678 const int64_t kSyncOffsetMs = 22;
679 const double kFreqKhz = 90.0;
680 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
681 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz + 2.2);
682 fake_clock_.AdvanceTimeMilliseconds(kFreqOffsetProcessIntervalInMs);
683 // Process interval passed, max diff: 2.
684 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz + 1.1);
685 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz - 4.2);
686 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz - 0.9);
687 fake_clock_.AdvanceTimeMilliseconds(kFreqOffsetProcessIntervalInMs);
688 // Process interval passed, max diff: 4.
689 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
690 statistics_proxy_.reset();
691 // Average reported: (2 + 4) / 2 = 3.
692 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtpToNtpFreqOffsetInKhz"));
693 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtpToNtpFreqOffsetInKhz", 3));
694}
695
asapersson6966bd52017-01-03 08:44:06696TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsUpdated) {
697 const int kQp = 22;
asapersson6966bd52017-01-03 08:44:06698
699 for (int i = 0; i < kMinRequiredSamples; ++i)
Niels Möller147013a2018-10-01 13:56:33700 statistics_proxy_->OnPreDecode(kVideoCodecVP8, kQp);
asapersson6966bd52017-01-03 08:44:06701
702 statistics_proxy_.reset();
703 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
704 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Decoded.Vp8.Qp", kQp));
705}
706
707TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsNotUpdatedForTooFewSamples) {
Niels Möller147013a2018-10-01 13:56:33708 const int kQp = 22;
asapersson6966bd52017-01-03 08:44:06709
710 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
Niels Möller147013a2018-10-01 13:56:33711 statistics_proxy_->OnPreDecode(kVideoCodecVP8, kQp);
asapersson6966bd52017-01-03 08:44:06712
713 statistics_proxy_.reset();
714 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
715}
716
717TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsNotUpdatedIfNoQpValue) {
asapersson6966bd52017-01-03 08:44:06718 for (int i = 0; i < kMinRequiredSamples; ++i)
Niels Möller147013a2018-10-01 13:56:33719 statistics_proxy_->OnPreDecode(kVideoCodecVP8, -1);
asapersson6966bd52017-01-03 08:44:06720
721 statistics_proxy_.reset();
722 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
723}
724
asaperssonb99baf82017-04-20 11:05:43725TEST_F(ReceiveStatisticsProxyTest,
726 KeyFrameHistogramNotUpdatedForTooFewSamples) {
727 const bool kIsKeyFrame = false;
728 const int kFrameSizeBytes = 1000;
729
730 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
ilnik6d5b4d62017-08-30 10:32:14731 statistics_proxy_->OnCompleteFrame(kIsKeyFrame, kFrameSizeBytes,
732 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 11:05:43733
734 EXPECT_EQ(0, statistics_proxy_->GetStats().frame_counts.key_frames);
735 EXPECT_EQ(kMinRequiredSamples - 1,
736 statistics_proxy_->GetStats().frame_counts.delta_frames);
737
738 statistics_proxy_.reset();
739 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
740}
741
742TEST_F(ReceiveStatisticsProxyTest,
743 KeyFrameHistogramUpdatedForMinRequiredSamples) {
744 const bool kIsKeyFrame = false;
745 const int kFrameSizeBytes = 1000;
746
747 for (int i = 0; i < kMinRequiredSamples; ++i)
ilnik6d5b4d62017-08-30 10:32:14748 statistics_proxy_->OnCompleteFrame(kIsKeyFrame, kFrameSizeBytes,
749 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 11:05:43750
751 EXPECT_EQ(0, statistics_proxy_->GetStats().frame_counts.key_frames);
752 EXPECT_EQ(kMinRequiredSamples,
753 statistics_proxy_->GetStats().frame_counts.delta_frames);
754
755 statistics_proxy_.reset();
756 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
757 EXPECT_EQ(1,
758 metrics::NumEvents("WebRTC.Video.KeyFramesReceivedInPermille", 0));
759}
760
761TEST_F(ReceiveStatisticsProxyTest, KeyFrameHistogramIsUpdated) {
762 const int kFrameSizeBytes = 1000;
763
764 for (int i = 0; i < kMinRequiredSamples; ++i)
ilnik6d5b4d62017-08-30 10:32:14765 statistics_proxy_->OnCompleteFrame(true, kFrameSizeBytes,
766 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 11:05:43767
768 for (int i = 0; i < kMinRequiredSamples; ++i)
ilnik6d5b4d62017-08-30 10:32:14769 statistics_proxy_->OnCompleteFrame(false, kFrameSizeBytes,
770 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 11:05:43771
772 EXPECT_EQ(kMinRequiredSamples,
773 statistics_proxy_->GetStats().frame_counts.key_frames);
774 EXPECT_EQ(kMinRequiredSamples,
775 statistics_proxy_->GetStats().frame_counts.delta_frames);
776
777 statistics_proxy_.reset();
778 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
779 EXPECT_EQ(
780 1, metrics::NumEvents("WebRTC.Video.KeyFramesReceivedInPermille", 500));
781}
782
783TEST_F(ReceiveStatisticsProxyTest, TimingHistogramsNotUpdatedForTooFewSamples) {
asaperssonb99baf82017-04-20 11:05:43784 const int kMaxDecodeMs = 2;
785 const int kCurrentDelayMs = 3;
786 const int kTargetDelayMs = 4;
787 const int kJitterBufferMs = 5;
788 const int kMinPlayoutDelayMs = 6;
789 const int kRenderDelayMs = 7;
790
791 for (int i = 0; i < kMinRequiredSamples - 1; ++i) {
792 statistics_proxy_->OnFrameBufferTimingsUpdated(
Johannes Kronbfd343b2019-07-01 08:07:50793 kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs, kJitterBufferMs,
794 kMinPlayoutDelayMs, kRenderDelayMs);
asaperssonb99baf82017-04-20 11:05:43795 }
796
797 statistics_proxy_.reset();
798 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
799 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
800 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
801 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
802 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
803}
804
805TEST_F(ReceiveStatisticsProxyTest, TimingHistogramsAreUpdated) {
asaperssonb99baf82017-04-20 11:05:43806 const int kMaxDecodeMs = 2;
807 const int kCurrentDelayMs = 3;
808 const int kTargetDelayMs = 4;
809 const int kJitterBufferMs = 5;
810 const int kMinPlayoutDelayMs = 6;
811 const int kRenderDelayMs = 7;
812
813 for (int i = 0; i < kMinRequiredSamples; ++i) {
814 statistics_proxy_->OnFrameBufferTimingsUpdated(
Johannes Kronbfd343b2019-07-01 08:07:50815 kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs, kJitterBufferMs,
816 kMinPlayoutDelayMs, kRenderDelayMs);
asaperssonb99baf82017-04-20 11:05:43817 }
818
819 statistics_proxy_.reset();
asaperssonb99baf82017-04-20 11:05:43820 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
821 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
822 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
823 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
824
asaperssonb99baf82017-04-20 11:05:43825 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.JitterBufferDelayInMs",
826 kJitterBufferMs));
827 EXPECT_EQ(1,
828 metrics::NumEvents("WebRTC.Video.TargetDelayInMs", kTargetDelayMs));
829 EXPECT_EQ(
830 1, metrics::NumEvents("WebRTC.Video.CurrentDelayInMs", kCurrentDelayMs));
831 EXPECT_EQ(1,
832 metrics::NumEvents("WebRTC.Video.OnewayDelayInMs", kTargetDelayMs));
833}
834
sprang948b2752017-05-04 09:47:13835TEST_F(ReceiveStatisticsProxyTest, DoesNotReportStaleFramerates) {
836 const int kDefaultFps = 30;
Sergey Silkin278f8252019-01-09 13:37:40837 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
sprang948b2752017-05-04 09:47:13838
839 for (int i = 0; i < kDefaultFps; ++i) {
840 // Since OnRenderedFrame is never called the fps in each sample will be 0,
841 // i.e. bad
842 frame.set_ntp_time_ms(fake_clock_.CurrentNtpInMilliseconds());
Johannes Kronbfd343b2019-07-01 08:07:50843 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
sprang948b2752017-05-04 09:47:13844 VideoContentType::UNSPECIFIED);
845 statistics_proxy_->OnRenderedFrame(frame);
846 fake_clock_.AdvanceTimeMilliseconds(1000 / kDefaultFps);
847 }
848
849 EXPECT_EQ(kDefaultFps, statistics_proxy_->GetStats().decode_frame_rate);
850 EXPECT_EQ(kDefaultFps, statistics_proxy_->GetStats().render_frame_rate);
851
852 // FPS trackers in stats proxy have a 1000ms sliding window.
853 fake_clock_.AdvanceTimeMilliseconds(1000);
854 EXPECT_EQ(0, statistics_proxy_->GetStats().decode_frame_rate);
855 EXPECT_EQ(0, statistics_proxy_->GetStats().render_frame_rate);
856}
857
asapersson2077f2f2017-05-11 12:37:35858TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsReceivedFrameStats) {
asapersson2077f2f2017-05-11 12:37:35859 EXPECT_EQ(0, statistics_proxy_->GetStats().width);
860 EXPECT_EQ(0, statistics_proxy_->GetStats().height);
861 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_rendered);
862
863 statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight));
864
865 EXPECT_EQ(kWidth, statistics_proxy_->GetStats().width);
866 EXPECT_EQ(kHeight, statistics_proxy_->GetStats().height);
867 EXPECT_EQ(1u, statistics_proxy_->GetStats().frames_rendered);
868}
869
870TEST_F(ReceiveStatisticsProxyTest,
871 ReceivedFrameHistogramsAreNotUpdatedForTooFewSamples) {
asapersson2077f2f2017-05-11 12:37:35872 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
873 statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight));
874
875 statistics_proxy_.reset();
876 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
877 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
878 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
879 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
880}
881
882TEST_F(ReceiveStatisticsProxyTest, ReceivedFrameHistogramsAreUpdated) {
asapersson2077f2f2017-05-11 12:37:35883 for (int i = 0; i < kMinRequiredSamples; ++i)
884 statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight));
885
886 statistics_proxy_.reset();
887 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
888 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
889 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
890 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
891 EXPECT_EQ(1,
892 metrics::NumEvents("WebRTC.Video.ReceivedWidthInPixels", kWidth));
893 EXPECT_EQ(1,
894 metrics::NumEvents("WebRTC.Video.ReceivedHeightInPixels", kHeight));
895}
896
Åsa Persson81327d52018-06-05 11:34:33897TEST_F(ReceiveStatisticsProxyTest, ZeroDelayReportedIfFrameNotDelayed) {
Sergey Silkin278f8252019-01-09 13:37:40898 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Johannes Kronbfd343b2019-07-01 08:07:50899 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Åsa Persson81327d52018-06-05 11:34:33900 VideoContentType::UNSPECIFIED);
901
902 // Frame not delayed, delayed frames to render: 0%.
903 const int64_t kNowMs = fake_clock_.TimeInMilliseconds();
904 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs));
905
906 // Min run time has passed.
907 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
908 statistics_proxy_.reset();
909 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
910 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 0));
911 EXPECT_EQ(0, metrics::NumSamples(
912 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
913}
914
915TEST_F(ReceiveStatisticsProxyTest,
916 DelayedFrameHistogramsAreNotUpdatedIfMinRuntimeHasNotPassed) {
Sergey Silkin278f8252019-01-09 13:37:40917 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Johannes Kronbfd343b2019-07-01 08:07:50918 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Åsa Persson81327d52018-06-05 11:34:33919 VideoContentType::UNSPECIFIED);
920
921 // Frame not delayed, delayed frames to render: 0%.
922 const int64_t kNowMs = fake_clock_.TimeInMilliseconds();
923 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs));
924
925 // Min run time has not passed.
926 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000) -
927 1);
928 statistics_proxy_.reset();
929 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
930 EXPECT_EQ(0, metrics::NumSamples(
931 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
932}
933
934TEST_F(ReceiveStatisticsProxyTest,
935 DelayedFramesHistogramsAreNotUpdatedIfNoRenderedFrames) {
Sergey Silkin278f8252019-01-09 13:37:40936 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Johannes Kronbfd343b2019-07-01 08:07:50937 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Åsa Persson81327d52018-06-05 11:34:33938 VideoContentType::UNSPECIFIED);
939
940 // Min run time has passed. No rendered frames.
941 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
942 statistics_proxy_.reset();
943 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
944 EXPECT_EQ(0, metrics::NumSamples(
945 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
946}
947
948TEST_F(ReceiveStatisticsProxyTest, DelayReportedIfFrameIsDelayed) {
Sergey Silkin278f8252019-01-09 13:37:40949 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Johannes Kronbfd343b2019-07-01 08:07:50950 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Åsa Persson81327d52018-06-05 11:34:33951 VideoContentType::UNSPECIFIED);
952
953 // Frame delayed 1 ms, delayed frames to render: 100%.
954 const int64_t kNowMs = fake_clock_.TimeInMilliseconds();
955 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs - 1));
956
957 // Min run time has passed.
958 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
959 statistics_proxy_.reset();
960 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
961 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 100));
962 EXPECT_EQ(1, metrics::NumSamples(
963 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
964 EXPECT_EQ(1, metrics::NumEvents(
965 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs", 1));
966}
967
968TEST_F(ReceiveStatisticsProxyTest, AverageDelayOfDelayedFramesIsReported) {
Sergey Silkin278f8252019-01-09 13:37:40969 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Johannes Kronbfd343b2019-07-01 08:07:50970 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Åsa Persson81327d52018-06-05 11:34:33971 VideoContentType::UNSPECIFIED);
972
973 // Two frames delayed (6 ms, 10 ms), delayed frames to render: 50%.
974 const int64_t kNowMs = fake_clock_.TimeInMilliseconds();
975 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs - 10));
976 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs - 6));
977 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs));
978 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs + 1));
979
980 // Min run time has passed.
981 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
982 statistics_proxy_.reset();
983 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
984 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 50));
985 EXPECT_EQ(1, metrics::NumSamples(
986 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
987 EXPECT_EQ(1, metrics::NumEvents(
988 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs", 8));
989}
990
asapersson2077f2f2017-05-11 12:37:35991TEST_F(ReceiveStatisticsProxyTest,
992 RtcpHistogramsNotUpdatedIfMinRuntimeHasNotPassed) {
993 InsertFirstRtpPacket(kRemoteSsrc);
994 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000) -
995 1);
996
997 RtcpPacketTypeCounter counter;
998 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
999
1000 statistics_proxy_.reset();
1001 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
1002 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
1003 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
1004}
1005
1006TEST_F(ReceiveStatisticsProxyTest, RtcpHistogramsAreUpdated) {
1007 InsertFirstRtpPacket(kRemoteSsrc);
1008 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1009
1010 const uint32_t kFirPackets = 100;
1011 const uint32_t kPliPackets = 200;
1012 const uint32_t kNackPackets = 300;
1013
1014 RtcpPacketTypeCounter counter;
1015 counter.fir_packets = kFirPackets;
1016 counter.pli_packets = kPliPackets;
1017 counter.nack_packets = kNackPackets;
1018 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
1019
1020 statistics_proxy_.reset();
1021 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
1022 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
1023 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
1024 EXPECT_EQ(
1025 1, metrics::NumEvents("WebRTC.Video.FirPacketsSentPerMinute",
1026 kFirPackets * 60 / metrics::kMinRunTimeInSeconds));
1027 EXPECT_EQ(
1028 1, metrics::NumEvents("WebRTC.Video.PliPacketsSentPerMinute",
1029 kPliPackets * 60 / metrics::kMinRunTimeInSeconds));
1030 EXPECT_EQ(
1031 1, metrics::NumEvents("WebRTC.Video.NackPacketsSentPerMinute",
1032 kNackPackets * 60 / metrics::kMinRunTimeInSeconds));
1033}
1034
Sergey Silkin02371062019-01-31 15:45:421035class ReceiveStatisticsProxyTestWithFreezeDuration
1036 : public ReceiveStatisticsProxyTest,
Mirko Bonadei6a489f22019-04-09 13:11:121037 public ::testing::WithParamInterface<
Sergey Silkin02371062019-01-31 15:45:421038 std::tuple<uint32_t, uint32_t, uint32_t>> {
1039 protected:
1040 const uint32_t frame_duration_ms_ = {std::get<0>(GetParam())};
1041 const uint32_t freeze_duration_ms_ = {std::get<1>(GetParam())};
1042 const uint32_t expected_freeze_count_ = {std::get<2>(GetParam())};
1043};
sprang892dab52017-08-15 12:00:331044
Sergey Silkin02371062019-01-31 15:45:421045// It is a freeze if:
1046// frame_duration_ms >= max(3 * avg_frame_duration, avg_frame_duration + 150)
1047// where avg_frame_duration is average duration of last 30 frames including
1048// the current one.
1049//
1050// Condition 1: 3 * avg_frame_duration > avg_frame_duration + 150
1051const auto kFreezeDetectionCond1Freeze = std::make_tuple(150, 483, 1);
1052const auto kFreezeDetectionCond1NotFreeze = std::make_tuple(150, 482, 0);
1053// Condition 2: 3 * avg_frame_duration < avg_frame_duration + 150
1054const auto kFreezeDetectionCond2Freeze = std::make_tuple(30, 185, 1);
1055const auto kFreezeDetectionCond2NotFreeze = std::make_tuple(30, 184, 0);
1056
Mirko Bonadei12d12852019-02-05 16:04:041057INSTANTIATE_TEST_SUITE_P(_,
1058 ReceiveStatisticsProxyTestWithFreezeDuration,
1059 ::testing::Values(kFreezeDetectionCond1Freeze,
1060 kFreezeDetectionCond1NotFreeze,
1061 kFreezeDetectionCond2Freeze,
1062 kFreezeDetectionCond2NotFreeze));
Sergey Silkin02371062019-01-31 15:45:421063
1064TEST_P(ReceiveStatisticsProxyTestWithFreezeDuration, FreezeDetection) {
1065 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
1066 EXPECT_EQ(0u, stats.freeze_count);
1067 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1068
1069 // Add a very long frame. This is need to verify that average frame
1070 // duration, which is supposed to be calculated as mean of durations of
1071 // last 30 frames, is calculated correctly.
1072 statistics_proxy_->OnRenderedFrame(frame);
1073 fake_clock_.AdvanceTimeMilliseconds(2000);
1074
1075 for (size_t i = 0;
1076 i <= VideoQualityObserver::kAvgInterframeDelaysWindowSizeFrames; ++i) {
1077 fake_clock_.AdvanceTimeMilliseconds(frame_duration_ms_);
1078 statistics_proxy_->OnRenderedFrame(frame);
1079 }
1080
1081 fake_clock_.AdvanceTimeMilliseconds(freeze_duration_ms_);
1082 statistics_proxy_->OnRenderedFrame(frame);
1083
1084 stats = statistics_proxy_->GetStats();
1085 EXPECT_EQ(stats.freeze_count, expected_freeze_count_);
1086}
1087
1088class ReceiveStatisticsProxyTestWithContent
1089 : public ReceiveStatisticsProxyTest,
1090 public ::testing::WithParamInterface<webrtc::VideoContentType> {
1091 protected:
1092 const webrtc::VideoContentType content_type_{GetParam()};
1093};
1094
Mirko Bonadei12d12852019-02-05 16:04:041095INSTANTIATE_TEST_SUITE_P(ContentTypes,
1096 ReceiveStatisticsProxyTestWithContent,
1097 ::testing::Values(VideoContentType::UNSPECIFIED,
1098 VideoContentType::SCREENSHARE));
Sergey Silkin02371062019-01-31 15:45:421099
1100TEST_P(ReceiveStatisticsProxyTestWithContent, InterFrameDelaysAreReported) {
sprang892dab52017-08-15 12:00:331101 const int kInterFrameDelayMs = 33;
Sergey Silkin278f8252019-01-09 13:37:401102 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1103
sprang892dab52017-08-15 12:00:331104 for (int i = 0; i < kMinRequiredSamples; ++i) {
Johannes Kronbfd343b2019-07-01 08:07:501105 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
sprang892dab52017-08-15 12:00:331106 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1107 }
Ilya Nikolaevskiydaa4f7a2017-10-06 10:29:471108 // One extra with double the interval.
sprang892dab52017-08-15 12:00:331109 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
Johannes Kronbfd343b2019-07-01 08:07:501110 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
sprang892dab52017-08-15 12:00:331111
1112 statistics_proxy_.reset();
1113 const int kExpectedInterFrame =
1114 (kInterFrameDelayMs * (kMinRequiredSamples - 1) +
1115 kInterFrameDelayMs * 2) /
1116 kMinRequiredSamples;
Sergey Silkin02371062019-01-31 15:45:421117 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
ilnik6d5b4d62017-08-30 10:32:141118 EXPECT_EQ(
1119 kExpectedInterFrame,
1120 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1121 EXPECT_EQ(
1122 kInterFrameDelayMs * 2,
1123 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1124 } else {
1125 EXPECT_EQ(kExpectedInterFrame,
1126 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
1127 EXPECT_EQ(kInterFrameDelayMs * 2,
1128 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
sprang892dab52017-08-15 12:00:331129 }
1130}
1131
Sergey Silkin02371062019-01-31 15:45:421132TEST_P(ReceiveStatisticsProxyTestWithContent,
1133 InterFrameDelaysPercentilesAreReported) {
Ilya Nikolaevskiydaa4f7a2017-10-06 10:29:471134 const int kInterFrameDelayMs = 33;
1135 const int kLastFivePercentsSamples = kMinRequiredSamples * 5 / 100;
Sergey Silkin278f8252019-01-09 13:37:401136 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1137
Ilya Nikolaevskiydaa4f7a2017-10-06 10:29:471138 for (int i = 0; i <= kMinRequiredSamples - kLastFivePercentsSamples; ++i) {
1139 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
Johannes Kronbfd343b2019-07-01 08:07:501140 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Ilya Nikolaevskiydaa4f7a2017-10-06 10:29:471141 }
1142 // Last 5% of intervals are double in size.
1143 for (int i = 0; i < kLastFivePercentsSamples; ++i) {
1144 fake_clock_.AdvanceTimeMilliseconds(2 * kInterFrameDelayMs);
Johannes Kronbfd343b2019-07-01 08:07:501145 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Ilya Nikolaevskiydaa4f7a2017-10-06 10:29:471146 }
1147 // Final sample is outlier and 10 times as big.
1148 fake_clock_.AdvanceTimeMilliseconds(10 * kInterFrameDelayMs);
Johannes Kronbfd343b2019-07-01 08:07:501149 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Ilya Nikolaevskiydaa4f7a2017-10-06 10:29:471150
1151 statistics_proxy_.reset();
1152 const int kExpectedInterFrame = kInterFrameDelayMs * 2;
Sergey Silkin02371062019-01-31 15:45:421153 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiydaa4f7a2017-10-06 10:29:471154 EXPECT_EQ(kExpectedInterFrame,
1155 metrics::MinSample(
1156 "WebRTC.Video.Screenshare.InterframeDelay95PercentileInMs"));
1157 } else {
1158 EXPECT_EQ(
1159 kExpectedInterFrame,
1160 metrics::MinSample("WebRTC.Video.InterframeDelay95PercentileInMs"));
1161 }
1162}
1163
Sergey Silkin02371062019-01-31 15:45:421164TEST_P(ReceiveStatisticsProxyTestWithContent,
1165 MaxInterFrameDelayOnlyWithValidAverage) {
sprang892dab52017-08-15 12:00:331166 const int kInterFrameDelayMs = 33;
Sergey Silkin278f8252019-01-09 13:37:401167 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1168
sprang892dab52017-08-15 12:00:331169 for (int i = 0; i < kMinRequiredSamples; ++i) {
Johannes Kronbfd343b2019-07-01 08:07:501170 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
sprang892dab52017-08-15 12:00:331171 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1172 }
1173
1174 // |kMinRequiredSamples| samples, and thereby intervals, is required. That
1175 // means we're one frame short of having a valid data set.
1176 statistics_proxy_.reset();
1177 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
1178 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
1179 EXPECT_EQ(
1180 0, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1181 EXPECT_EQ(0, metrics::NumSamples(
1182 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1183}
1184
Sergey Silkin02371062019-01-31 15:45:421185TEST_P(ReceiveStatisticsProxyTestWithContent, MaxInterFrameDelayOnlyWithPause) {
sprang3e86e7e2017-08-22 16:23:281186 const int kInterFrameDelayMs = 33;
Sergey Silkin278f8252019-01-09 13:37:401187 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1188
sprang3e86e7e2017-08-22 16:23:281189 for (int i = 0; i <= kMinRequiredSamples; ++i) {
Johannes Kronbfd343b2019-07-01 08:07:501190 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
sprang3e86e7e2017-08-22 16:23:281191 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1192 }
1193
1194 // At this state, we should have a valid inter-frame delay.
1195 // Indicate stream paused and make a large jump in time.
1196 statistics_proxy_->OnStreamInactive();
1197 fake_clock_.AdvanceTimeMilliseconds(5000);
1198
1199 // Insert two more frames. The interval during the pause should be disregarded
1200 // in the stats.
Johannes Kronbfd343b2019-07-01 08:07:501201 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
sprang3e86e7e2017-08-22 16:23:281202 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
Johannes Kronbfd343b2019-07-01 08:07:501203 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
sprang3e86e7e2017-08-22 16:23:281204
1205 statistics_proxy_.reset();
Sergey Silkin02371062019-01-31 15:45:421206 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
sprang3e86e7e2017-08-22 16:23:281207 EXPECT_EQ(
1208 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1209 EXPECT_EQ(1, metrics::NumSamples(
1210 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1211 EXPECT_EQ(
1212 kInterFrameDelayMs,
1213 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1214 EXPECT_EQ(
1215 kInterFrameDelayMs,
1216 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1217 } else {
1218 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
1219 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
1220 EXPECT_EQ(kInterFrameDelayMs,
1221 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
1222 EXPECT_EQ(kInterFrameDelayMs,
1223 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
1224 }
1225}
1226
Sergey Silkin02371062019-01-31 15:45:421227TEST_P(ReceiveStatisticsProxyTestWithContent, FreezesAreReported) {
Ilya Nikolaevskiy94150ee2018-05-23 09:53:191228 const int kInterFrameDelayMs = 33;
1229 const int kFreezeDelayMs = 200;
Sergey Silkinbea18ca2018-10-02 14:22:461230 const int kCallDurationMs =
1231 kMinRequiredSamples * kInterFrameDelayMs + kFreezeDelayMs;
Sergey Silkin278f8252019-01-09 13:37:401232 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1233
Ilya Nikolaevskiy94150ee2018-05-23 09:53:191234 for (int i = 0; i < kMinRequiredSamples; ++i) {
Johannes Kronbfd343b2019-07-01 08:07:501235 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Ilya Nikolaevskiycdc959f2018-10-10 11:15:091236 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 09:53:191237 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1238 }
1239 // Add extra freeze.
1240 fake_clock_.AdvanceTimeMilliseconds(kFreezeDelayMs);
Johannes Kronbfd343b2019-07-01 08:07:501241 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Ilya Nikolaevskiycdc959f2018-10-10 11:15:091242 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 09:53:191243
1244 statistics_proxy_.reset();
1245 const int kExpectedTimeBetweenFreezes =
1246 kInterFrameDelayMs * (kMinRequiredSamples - 1);
Sergey Silkinbea18ca2018-10-02 14:22:461247 const int kExpectedNumberFreezesPerMinute = 60 * 1000 / kCallDurationMs;
Sergey Silkin02371062019-01-31 15:45:421248 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiy94150ee2018-05-23 09:53:191249 EXPECT_EQ(
1250 kFreezeDelayMs + kInterFrameDelayMs,
1251 metrics::MinSample("WebRTC.Video.Screenshare.MeanFreezeDurationMs"));
1252 EXPECT_EQ(kExpectedTimeBetweenFreezes,
1253 metrics::MinSample(
1254 "WebRTC.Video.Screenshare.MeanTimeBetweenFreezesMs"));
Sergey Silkinbea18ca2018-10-02 14:22:461255 EXPECT_EQ(
1256 kExpectedNumberFreezesPerMinute,
1257 metrics::MinSample("WebRTC.Video.Screenshare.NumberFreezesPerMinute"));
Ilya Nikolaevskiy94150ee2018-05-23 09:53:191258 } else {
1259 EXPECT_EQ(kFreezeDelayMs + kInterFrameDelayMs,
1260 metrics::MinSample("WebRTC.Video.MeanFreezeDurationMs"));
1261 EXPECT_EQ(kExpectedTimeBetweenFreezes,
1262 metrics::MinSample("WebRTC.Video.MeanTimeBetweenFreezesMs"));
Sergey Silkinbea18ca2018-10-02 14:22:461263 EXPECT_EQ(kExpectedNumberFreezesPerMinute,
1264 metrics::MinSample("WebRTC.Video.NumberFreezesPerMinute"));
Ilya Nikolaevskiy94150ee2018-05-23 09:53:191265 }
1266}
1267
Sergey Silkin02371062019-01-31 15:45:421268TEST_P(ReceiveStatisticsProxyTestWithContent, HarmonicFrameRateIsReported) {
Sergey Silkinfc6f3e582019-04-03 08:57:261269 const int kFrameDurationMs = 33;
1270 const int kFreezeDurationMs = 200;
1271 const int kPauseDurationMs = 10000;
1272 const int kCallDurationMs = kMinRequiredSamples * kFrameDurationMs +
1273 kFreezeDurationMs + kPauseDurationMs;
Sergey Silkin50e77452019-01-16 12:41:461274 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1275
1276 for (int i = 0; i < kMinRequiredSamples; ++i) {
Sergey Silkinfc6f3e582019-04-03 08:57:261277 fake_clock_.AdvanceTimeMilliseconds(kFrameDurationMs);
Johannes Kronbfd343b2019-07-01 08:07:501278 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Sergey Silkin50e77452019-01-16 12:41:461279 statistics_proxy_->OnRenderedFrame(frame);
1280 }
Sergey Silkinfc6f3e582019-04-03 08:57:261281
1282 // Freezes and pauses should be included into harmonic frame rate.
1283 // Add freeze.
1284 fake_clock_.AdvanceTimeMilliseconds(kFreezeDurationMs);
Johannes Kronbfd343b2019-07-01 08:07:501285 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Sergey Silkinfc6f3e582019-04-03 08:57:261286 statistics_proxy_->OnRenderedFrame(frame);
1287
1288 // Add pause.
1289 fake_clock_.AdvanceTimeMilliseconds(kPauseDurationMs);
1290 statistics_proxy_->OnStreamInactive();
Johannes Kronbfd343b2019-07-01 08:07:501291 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Sergey Silkin50e77452019-01-16 12:41:461292 statistics_proxy_->OnRenderedFrame(frame);
1293
1294 statistics_proxy_.reset();
Sergey Silkinfc6f3e582019-04-03 08:57:261295 double kSumSquaredFrameDurationSecs =
Sergey Silkin50e77452019-01-16 12:41:461296 (kMinRequiredSamples - 1) *
Sergey Silkinfc6f3e582019-04-03 08:57:261297 (kFrameDurationMs / 1000.0 * kFrameDurationMs / 1000.0);
1298 kSumSquaredFrameDurationSecs +=
1299 kFreezeDurationMs / 1000.0 * kFreezeDurationMs / 1000.0;
1300 kSumSquaredFrameDurationSecs +=
1301 kPauseDurationMs / 1000.0 * kPauseDurationMs / 1000.0;
Sergey Silkin50e77452019-01-16 12:41:461302 const int kExpectedHarmonicFrameRateFps =
Sergey Silkinfc6f3e582019-04-03 08:57:261303 std::round(kCallDurationMs / (1000 * kSumSquaredFrameDurationSecs));
Sergey Silkin02371062019-01-31 15:45:421304 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Sergey Silkin50e77452019-01-16 12:41:461305 EXPECT_EQ(kExpectedHarmonicFrameRateFps,
1306 metrics::MinSample("WebRTC.Video.Screenshare.HarmonicFrameRate"));
1307 } else {
1308 EXPECT_EQ(kExpectedHarmonicFrameRateFps,
1309 metrics::MinSample("WebRTC.Video.HarmonicFrameRate"));
1310 }
1311}
1312
Sergey Silkin02371062019-01-31 15:45:421313TEST_P(ReceiveStatisticsProxyTestWithContent, PausesAreIgnored) {
Ilya Nikolaevskiy94150ee2018-05-23 09:53:191314 const int kInterFrameDelayMs = 33;
1315 const int kPauseDurationMs = 10000;
Sergey Silkin278f8252019-01-09 13:37:401316 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1317
Ilya Nikolaevskiy94150ee2018-05-23 09:53:191318 for (int i = 0; i <= kMinRequiredSamples; ++i) {
Johannes Kronbfd343b2019-07-01 08:07:501319 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Ilya Nikolaevskiycdc959f2018-10-10 11:15:091320 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 09:53:191321 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1322 }
1323 // Add a pause.
1324 fake_clock_.AdvanceTimeMilliseconds(kPauseDurationMs);
1325 statistics_proxy_->OnStreamInactive();
1326
1327 // Second playback interval with triple the length.
1328 for (int i = 0; i <= kMinRequiredSamples * 3; ++i) {
Johannes Kronbfd343b2019-07-01 08:07:501329 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Ilya Nikolaevskiycdc959f2018-10-10 11:15:091330 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 09:53:191331 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1332 }
1333
1334 statistics_proxy_.reset();
1335 // Average of two playback intervals.
1336 const int kExpectedTimeBetweenFreezes =
1337 kInterFrameDelayMs * kMinRequiredSamples * 2;
Sergey Silkin02371062019-01-31 15:45:421338 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiy94150ee2018-05-23 09:53:191339 EXPECT_EQ(-1, metrics::MinSample(
1340 "WebRTC.Video.Screenshare.MeanFreezeDurationMs"));
1341 EXPECT_EQ(kExpectedTimeBetweenFreezes,
1342 metrics::MinSample(
1343 "WebRTC.Video.Screenshare.MeanTimeBetweenFreezesMs"));
1344 } else {
1345 EXPECT_EQ(-1, metrics::MinSample("WebRTC.Video.MeanFreezeDurationMs"));
1346 EXPECT_EQ(kExpectedTimeBetweenFreezes,
1347 metrics::MinSample("WebRTC.Video.MeanTimeBetweenFreezesMs"));
1348 }
1349}
1350
Sergey Silkin02371062019-01-31 15:45:421351TEST_P(ReceiveStatisticsProxyTestWithContent, ManyPausesAtTheBeginning) {
Ilya Nikolaevskiy879f5a32018-05-31 07:47:171352 const int kInterFrameDelayMs = 33;
1353 const int kPauseDurationMs = 10000;
Sergey Silkin278f8252019-01-09 13:37:401354 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1355
Ilya Nikolaevskiy879f5a32018-05-31 07:47:171356 for (int i = 0; i <= kMinRequiredSamples; ++i) {
Johannes Kronbfd343b2019-07-01 08:07:501357 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Ilya Nikolaevskiy879f5a32018-05-31 07:47:171358 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1359
1360 statistics_proxy_->OnStreamInactive();
1361 fake_clock_.AdvanceTimeMilliseconds(kPauseDurationMs);
1362
Johannes Kronbfd343b2019-07-01 08:07:501363 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Ilya Nikolaevskiy879f5a32018-05-31 07:47:171364 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1365 }
1366
1367 statistics_proxy_.reset();
1368 // No freezes should be detected, as all long inter-frame delays were pauses.
Sergey Silkin02371062019-01-31 15:45:421369 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiy879f5a32018-05-31 07:47:171370 EXPECT_EQ(-1, metrics::MinSample(
1371 "WebRTC.Video.Screenshare.MeanFreezeDurationMs"));
1372 } else {
1373 EXPECT_EQ(-1, metrics::MinSample("WebRTC.Video.MeanFreezeDurationMs"));
1374 }
1375}
1376
Sergey Silkin02371062019-01-31 15:45:421377TEST_P(ReceiveStatisticsProxyTestWithContent, TimeInHdReported) {
Ilya Nikolaevskiy94150ee2018-05-23 09:53:191378 const int kInterFrameDelayMs = 20;
Sergey Silkin278f8252019-01-09 13:37:401379 webrtc::VideoFrame frame_hd = CreateFrame(1280, 720);
1380 webrtc::VideoFrame frame_sd = CreateFrame(640, 360);
1381
Ilya Nikolaevskiy94150ee2018-05-23 09:53:191382 // HD frames.
1383 for (int i = 0; i < kMinRequiredSamples; ++i) {
Johannes Kronbfd343b2019-07-01 08:07:501384 statistics_proxy_->OnDecodedFrame(frame_hd, absl::nullopt, 0,
1385 content_type_);
Sergey Silkin278f8252019-01-09 13:37:401386 statistics_proxy_->OnRenderedFrame(frame_hd);
Ilya Nikolaevskiy94150ee2018-05-23 09:53:191387 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1388 }
1389 // SD frames.
1390 for (int i = 0; i < 2 * kMinRequiredSamples; ++i) {
Johannes Kronbfd343b2019-07-01 08:07:501391 statistics_proxy_->OnDecodedFrame(frame_sd, absl::nullopt, 0,
1392 content_type_);
Sergey Silkin278f8252019-01-09 13:37:401393 statistics_proxy_->OnRenderedFrame(frame_sd);
Ilya Nikolaevskiy94150ee2018-05-23 09:53:191394 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1395 }
1396 // Extra last frame.
Sergey Silkin278f8252019-01-09 13:37:401397 statistics_proxy_->OnRenderedFrame(frame_sd);
1398
Ilya Nikolaevskiy94150ee2018-05-23 09:53:191399 statistics_proxy_.reset();
1400 const int kExpectedTimeInHdPercents = 33;
Sergey Silkin02371062019-01-31 15:45:421401 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiy94150ee2018-05-23 09:53:191402 EXPECT_EQ(
1403 kExpectedTimeInHdPercents,
1404 metrics::MinSample("WebRTC.Video.Screenshare.TimeInHdPercentage"));
1405 } else {
1406 EXPECT_EQ(kExpectedTimeInHdPercents,
1407 metrics::MinSample("WebRTC.Video.TimeInHdPercentage"));
1408 }
1409}
1410
Sergey Silkin02371062019-01-31 15:45:421411TEST_P(ReceiveStatisticsProxyTestWithContent, TimeInBlockyVideoReported) {
Ilya Nikolaevskiy94150ee2018-05-23 09:53:191412 const int kInterFrameDelayMs = 20;
1413 const int kHighQp = 80;
1414 const int kLowQp = 30;
Sergey Silkin278f8252019-01-09 13:37:401415 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1416
Ilya Nikolaevskiy94150ee2018-05-23 09:53:191417 // High quality frames.
1418 for (int i = 0; i < kMinRequiredSamples; ++i) {
Johannes Kronbfd343b2019-07-01 08:07:501419 statistics_proxy_->OnDecodedFrame(frame, kLowQp, 0, content_type_);
Sergey Silkin278f8252019-01-09 13:37:401420 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 09:53:191421 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1422 }
1423 // Blocky frames.
1424 for (int i = 0; i < 2 * kMinRequiredSamples; ++i) {
Johannes Kronbfd343b2019-07-01 08:07:501425 statistics_proxy_->OnDecodedFrame(frame, kHighQp, 0, content_type_);
Sergey Silkin278f8252019-01-09 13:37:401426 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 09:53:191427 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1428 }
1429 // Extra last frame.
Johannes Kronbfd343b2019-07-01 08:07:501430 statistics_proxy_->OnDecodedFrame(frame, kHighQp, 0, content_type_);
Sergey Silkin278f8252019-01-09 13:37:401431 statistics_proxy_->OnRenderedFrame(frame);
1432
Ilya Nikolaevskiy94150ee2018-05-23 09:53:191433 statistics_proxy_.reset();
1434 const int kExpectedTimeInHdPercents = 66;
Sergey Silkin02371062019-01-31 15:45:421435 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiy94150ee2018-05-23 09:53:191436 EXPECT_EQ(kExpectedTimeInHdPercents,
1437 metrics::MinSample(
1438 "WebRTC.Video.Screenshare.TimeInBlockyVideoPercentage"));
1439 } else {
1440 EXPECT_EQ(kExpectedTimeInHdPercents,
1441 metrics::MinSample("WebRTC.Video.TimeInBlockyVideoPercentage"));
1442 }
1443}
1444
Sergey Silkin02371062019-01-31 15:45:421445TEST_P(ReceiveStatisticsProxyTestWithContent, DownscalesReported) {
Sergey Silkin278f8252019-01-09 13:37:401446 const int kInterFrameDelayMs = 2000; // To ensure long enough call duration.
Ilya Nikolaevskiy94150ee2018-05-23 09:53:191447
Sergey Silkin278f8252019-01-09 13:37:401448 webrtc::VideoFrame frame_hd = CreateFrame(1280, 720);
1449 webrtc::VideoFrame frame_sd = CreateFrame(640, 360);
1450 webrtc::VideoFrame frame_ld = CreateFrame(320, 180);
1451
1452 // Call once to pass content type.
Johannes Kronbfd343b2019-07-01 08:07:501453 statistics_proxy_->OnDecodedFrame(frame_hd, absl::nullopt, 0, content_type_);
Sergey Silkin278f8252019-01-09 13:37:401454
1455 statistics_proxy_->OnRenderedFrame(frame_hd);
Ilya Nikolaevskiy94150ee2018-05-23 09:53:191456 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1457
1458 // Downscale.
Sergey Silkin278f8252019-01-09 13:37:401459 statistics_proxy_->OnRenderedFrame(frame_sd);
Ilya Nikolaevskiy94150ee2018-05-23 09:53:191460 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1461
1462 // Downscale.
Sergey Silkin278f8252019-01-09 13:37:401463 statistics_proxy_->OnRenderedFrame(frame_ld);
Ilya Nikolaevskiy94150ee2018-05-23 09:53:191464 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1465
1466 statistics_proxy_.reset();
Sergey Silkin278f8252019-01-09 13:37:401467 const int kExpectedDownscales = 30; // 2 per 4 seconds = 30 per minute.
Sergey Silkin02371062019-01-31 15:45:421468 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiy94150ee2018-05-23 09:53:191469 EXPECT_EQ(
1470 kExpectedDownscales,
1471 metrics::MinSample(
1472 "WebRTC.Video.Screenshare.NumberResolutionDownswitchesPerMinute"));
1473 } else {
1474 EXPECT_EQ(kExpectedDownscales,
1475 metrics::MinSample(
1476 "WebRTC.Video.NumberResolutionDownswitchesPerMinute"));
1477 }
1478}
1479
Johannes Kronbfd343b2019-07-01 08:07:501480TEST_P(ReceiveStatisticsProxyTestWithContent, DecodeTimeReported) {
1481 const int kInterFrameDelayMs = 20;
1482 const int kLowQp = 30;
1483 const int kDecodeMs = 7;
1484
1485 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1486
1487 for (int i = 0; i < kMinRequiredSamples; ++i) {
1488 statistics_proxy_->OnDecodedFrame(frame, kLowQp, kDecodeMs, content_type_);
1489 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1490 }
1491 statistics_proxy_.reset();
1492 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DecodeTimeInMs", kDecodeMs));
1493}
1494
Sergey Silkin02371062019-01-31 15:45:421495TEST_P(ReceiveStatisticsProxyTestWithContent,
1496 StatsAreSlicedOnSimulcastAndExperiment) {
ilnik6d5b4d62017-08-30 10:32:141497 const uint8_t experiment_id = 1;
Sergey Silkin02371062019-01-31 15:45:421498 webrtc::VideoContentType content_type = content_type_;
ilnik6d5b4d62017-08-30 10:32:141499 videocontenttypehelpers::SetExperimentId(&content_type, experiment_id);
1500 const int kInterFrameDelayMs1 = 30;
1501 const int kInterFrameDelayMs2 = 50;
Sergey Silkin278f8252019-01-09 13:37:401502 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
ilnik6d5b4d62017-08-30 10:32:141503
1504 videocontenttypehelpers::SetSimulcastId(&content_type, 1);
1505 for (int i = 0; i <= kMinRequiredSamples; ++i) {
1506 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs1);
Johannes Kronbfd343b2019-07-01 08:07:501507 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type);
ilnik6d5b4d62017-08-30 10:32:141508 }
1509
1510 videocontenttypehelpers::SetSimulcastId(&content_type, 2);
1511 for (int i = 0; i <= kMinRequiredSamples; ++i) {
1512 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs2);
Johannes Kronbfd343b2019-07-01 08:07:501513 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type);
ilnik6d5b4d62017-08-30 10:32:141514 }
1515 statistics_proxy_.reset();
1516
1517 if (videocontenttypehelpers::IsScreenshare(content_type)) {
1518 EXPECT_EQ(
1519 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1520 EXPECT_EQ(1, metrics::NumSamples(
1521 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1522 EXPECT_EQ(1, metrics::NumSamples(
1523 "WebRTC.Video.Screenshare.InterframeDelayInMs.S0"));
1524 EXPECT_EQ(1, metrics::NumSamples(
1525 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs.S0"));
1526 EXPECT_EQ(1, metrics::NumSamples(
1527 "WebRTC.Video.Screenshare.InterframeDelayInMs.S1"));
1528 EXPECT_EQ(1, metrics::NumSamples(
1529 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs.S1"));
1530 EXPECT_EQ(1,
1531 metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"
1532 ".ExperimentGroup0"));
1533 EXPECT_EQ(
1534 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"
1535 ".ExperimentGroup0"));
1536 EXPECT_EQ(
1537 kInterFrameDelayMs1,
1538 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs.S0"));
1539 EXPECT_EQ(
1540 kInterFrameDelayMs2,
1541 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs.S1"));
1542 EXPECT_EQ(
1543 (kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1544 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1545 EXPECT_EQ(
1546 kInterFrameDelayMs2,
1547 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1548 EXPECT_EQ(
1549 (kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1550 metrics::MinSample(
1551 "WebRTC.Video.Screenshare.InterframeDelayInMs.ExperimentGroup0"));
1552 } else {
1553 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
1554 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
1555 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs.S0"));
1556 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs.S0"));
1557 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs.S1"));
1558 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs.S1"));
1559 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"
1560 ".ExperimentGroup0"));
1561 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"
1562 ".ExperimentGroup0"));
1563 EXPECT_EQ(kInterFrameDelayMs1,
1564 metrics::MinSample("WebRTC.Video.InterframeDelayInMs.S0"));
1565 EXPECT_EQ(kInterFrameDelayMs2,
1566 metrics::MinSample("WebRTC.Video.InterframeDelayInMs.S1"));
1567 EXPECT_EQ((kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1568 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
1569 EXPECT_EQ(kInterFrameDelayMs2,
1570 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
1571 EXPECT_EQ((kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1572 metrics::MinSample(
1573 "WebRTC.Video.InterframeDelayInMs.ExperimentGroup0"));
1574 }
1575}
sakale5ba44e2016-10-26 14:09:241576} // namespace webrtc