blob: 9af5db43f03aa3a3131440dfe8989fbf88ca669f [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 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 13:34:33 +020063 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 23:49:37 +010071 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 05:37:35 -070078 frame.set_ntp_time_ms(fake_clock_.CurrentNtpInMilliseconds());
79 return frame;
80 }
81
sakale5ba44e2016-10-26 07:09:24 -070082 SimulatedClock fake_clock_;
asaperssonde9e5ff2016-11-02 07:14:03 -070083 const VideoReceiveStream::Config config_;
sakale5ba44e2016-10-26 07:09:24 -070084 std::unique_ptr<ReceiveStatisticsProxy> statistics_proxy_;
sakale5ba44e2016-10-26 07:09:24 -070085};
86
87TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameIncreasesFramesDecoded) {
88 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_decoded);
Sergey Silkin278f8252019-01-09 14:37:40 +010089 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
sakale5ba44e2016-10-26 07:09:24 -070090 for (uint32_t i = 1; i <= 3; ++i) {
Sergey Silkin278f8252019-01-09 14:37:40 +010091 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
ilnik00d802b2017-04-11 10:34:31 -070092 VideoContentType::UNSPECIFIED);
sakale5ba44e2016-10-26 07:09:24 -070093 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_decoded);
94 }
95}
96
Åsa Perssonb9b07ea2018-01-24 17:04:07 +010097TEST_F(ReceiveStatisticsProxyTest, DecodedFpsIsReported) {
98 const int kFps = 20;
99 const int kRequiredSamples = metrics::kMinRunTimeInSeconds * kFps;
Sergey Silkin278f8252019-01-09 14:37:40 +0100100 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Åsa Perssonb9b07ea2018-01-24 17:04:07 +0100101 for (int i = 0; i < kRequiredSamples; ++i) {
Sergey Silkin278f8252019-01-09 14:37:40 +0100102 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
103 VideoContentType::UNSPECIFIED);
Åsa Perssonb9b07ea2018-01-24 17:04:07 +0100104 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 14:37:40 +0100114 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Åsa Perssonb9b07ea2018-01-24 17:04:07 +0100115 for (int i = 0; i < kRequiredSamples - 1; ++i) {
Sergey Silkin278f8252019-01-09 14:37:40 +0100116 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
117 VideoContentType::UNSPECIFIED);
Åsa Perssonb9b07ea2018-01-24 17:04:07 +0100118 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
119 }
120 statistics_proxy_.reset();
121 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
122}
123
124TEST_F(ReceiveStatisticsProxyTest, DecodedFpsIsReportedWithQpReset) {
125 const int kFps1 = 10;
Sergey Silkin278f8252019-01-09 14:37:40 +0100126 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Åsa Perssonb9b07ea2018-01-24 17:04:07 +0100127 for (int i = 0; i < metrics::kMinRunTimeInSeconds * kFps1; ++i) {
Sergey Silkin278f8252019-01-09 14:37:40 +0100128 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
129 VideoContentType::UNSPECIFIED);
Åsa Perssonb9b07ea2018-01-24 17:04:07 +0100130 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps1);
131 }
132 // First QP value received, resets frames decoded.
133 const int kFps2 = 20;
134 for (int i = 0; i < metrics::kMinRunTimeInSeconds * kFps2; ++i) {
Sergey Silkin278f8252019-01-09 14:37:40 +0100135 statistics_proxy_->OnDecodedFrame(frame, 1u, VideoContentType::UNSPECIFIED);
Åsa Perssonb9b07ea2018-01-24 17:04:07 +0100136 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps2);
137 }
138 statistics_proxy_.reset();
139 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
140 EXPECT_EQ(1,
141 metrics::NumEvents("WebRTC.Video.DecodedFramesPerSecond", kFps2));
142}
143
sakalcc452e12017-02-09 04:53:45 -0800144TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameWithQpResetsFramesDecoded) {
145 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_decoded);
Sergey Silkin278f8252019-01-09 14:37:40 +0100146 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
sakalcc452e12017-02-09 04:53:45 -0800147 for (uint32_t i = 1; i <= 3; ++i) {
Sergey Silkin278f8252019-01-09 14:37:40 +0100148 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
ilnik00d802b2017-04-11 10:34:31 -0700149 VideoContentType::UNSPECIFIED);
sakalcc452e12017-02-09 04:53:45 -0800150 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_decoded);
151 }
Sergey Silkin278f8252019-01-09 14:37:40 +0100152 statistics_proxy_->OnDecodedFrame(frame, 1u, VideoContentType::UNSPECIFIED);
sakalcc452e12017-02-09 04:53:45 -0800153 EXPECT_EQ(1u, statistics_proxy_->GetStats().frames_decoded);
154}
155
156TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameIncreasesQpSum) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200157 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
Sergey Silkin278f8252019-01-09 14:37:40 +0100158 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
159 statistics_proxy_->OnDecodedFrame(frame, 3u, VideoContentType::UNSPECIFIED);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100160 EXPECT_EQ(3u, statistics_proxy_->GetStats().qp_sum);
Sergey Silkin278f8252019-01-09 14:37:40 +0100161 statistics_proxy_->OnDecodedFrame(frame, 127u, VideoContentType::UNSPECIFIED);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100162 EXPECT_EQ(130u, statistics_proxy_->GetStats().qp_sum);
sakalcc452e12017-02-09 04:53:45 -0800163}
164
ilnik2e1b40b2017-09-04 07:57:17 -0700165TEST_F(ReceiveStatisticsProxyTest, ReportsContentType) {
166 const std::string kRealtimeString("realtime");
167 const std::string kScreenshareString("screen");
Sergey Silkin278f8252019-01-09 14:37:40 +0100168 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
ilnik2e1b40b2017-09-04 07:57:17 -0700169 EXPECT_EQ(kRealtimeString, videocontenttypehelpers::ToString(
Sergey Silkin02371062019-01-31 16:45:42 +0100170 statistics_proxy_->GetStats().content_type));
Sergey Silkin278f8252019-01-09 14:37:40 +0100171 statistics_proxy_->OnDecodedFrame(frame, 3u, VideoContentType::SCREENSHARE);
Sergey Silkin02371062019-01-31 16:45:42 +0100172 EXPECT_EQ(kScreenshareString,
173 videocontenttypehelpers::ToString(
174 statistics_proxy_->GetStats().content_type));
Sergey Silkin278f8252019-01-09 14:37:40 +0100175 statistics_proxy_->OnDecodedFrame(frame, 3u, VideoContentType::UNSPECIFIED);
ilnik2e1b40b2017-09-04 07:57:17 -0700176 EXPECT_EQ(kRealtimeString, videocontenttypehelpers::ToString(
Sergey Silkin02371062019-01-31 16:45:42 +0100177 statistics_proxy_->GetStats().content_type));
ilnik2e1b40b2017-09-04 07:57:17 -0700178}
179
ilnika79cc282017-08-23 05:24:10 -0700180TEST_F(ReceiveStatisticsProxyTest, ReportsMaxInterframeDelay) {
Sergey Silkin278f8252019-01-09 14:37:40 +0100181 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
ilnika79cc282017-08-23 05:24:10 -0700182 const int64_t kInterframeDelayMs1 = 100;
183 const int64_t kInterframeDelayMs2 = 200;
184 const int64_t kInterframeDelayMs3 = 100;
185 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
Sergey Silkin278f8252019-01-09 14:37:40 +0100186 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200187 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700188 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
ilnikf04afde2017-07-07 01:26:24 -0700189
190 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs1);
Sergey Silkin278f8252019-01-09 14:37:40 +0100191 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200192 VideoContentType::UNSPECIFIED);
ilnikf04afde2017-07-07 01:26:24 -0700193 EXPECT_EQ(kInterframeDelayMs1,
ilnika79cc282017-08-23 05:24:10 -0700194 statistics_proxy_->GetStats().interframe_delay_max_ms);
ilnikf04afde2017-07-07 01:26:24 -0700195
196 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs2);
Sergey Silkin278f8252019-01-09 14:37:40 +0100197 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200198 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700199 EXPECT_EQ(kInterframeDelayMs2,
200 statistics_proxy_->GetStats().interframe_delay_max_ms);
201
202 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs3);
Sergey Silkin278f8252019-01-09 14:37:40 +0100203 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200204 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700205 // kInterframeDelayMs3 is smaller than kInterframeDelayMs2.
206 EXPECT_EQ(kInterframeDelayMs2,
207 statistics_proxy_->GetStats().interframe_delay_max_ms);
208}
209
210TEST_F(ReceiveStatisticsProxyTest, ReportInterframeDelayInWindow) {
Sergey Silkin278f8252019-01-09 14:37:40 +0100211 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Ilya Nikolaevskiyb06b3582017-10-16 17:59:12 +0200212 const int64_t kInterframeDelayMs1 = 900;
213 const int64_t kInterframeDelayMs2 = 750;
214 const int64_t kInterframeDelayMs3 = 700;
ilnika79cc282017-08-23 05:24:10 -0700215 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
Sergey Silkin278f8252019-01-09 14:37:40 +0100216 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200217 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700218 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
219
220 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs1);
Sergey Silkin278f8252019-01-09 14:37:40 +0100221 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200222 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700223 EXPECT_EQ(kInterframeDelayMs1,
224 statistics_proxy_->GetStats().interframe_delay_max_ms);
225
226 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs2);
Sergey Silkin278f8252019-01-09 14:37:40 +0100227 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200228 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700229 // Still first delay is the maximum
230 EXPECT_EQ(kInterframeDelayMs1,
231 statistics_proxy_->GetStats().interframe_delay_max_ms);
232
233 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs3);
Sergey Silkin278f8252019-01-09 14:37:40 +0100234 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200235 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700236 // Now the first sample is out of the window, so the second is the maximum.
237 EXPECT_EQ(kInterframeDelayMs2,
238 statistics_proxy_->GetStats().interframe_delay_max_ms);
ilnikf04afde2017-07-07 01:26:24 -0700239}
240
Sergey Silkin02371062019-01-31 16:45:42 +0100241TEST_F(ReceiveStatisticsProxyTest, ReportsFreezeMetrics) {
242 const int64_t kFreezeDurationMs = 1000;
243
244 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
245 EXPECT_EQ(0u, stats.freeze_count);
246 EXPECT_FALSE(stats.total_freezes_duration_ms);
247
248 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
249 for (size_t i = 0; i < VideoQualityObserver::kMinFrameSamplesToDetectFreeze;
250 ++i) {
251 fake_clock_.AdvanceTimeMilliseconds(30);
252 statistics_proxy_->OnRenderedFrame(frame);
253 }
254
255 // Freeze.
256 fake_clock_.AdvanceTimeMilliseconds(kFreezeDurationMs);
257 statistics_proxy_->OnRenderedFrame(frame);
258
259 stats = statistics_proxy_->GetStats();
260 EXPECT_EQ(1u, stats.freeze_count);
261 EXPECT_EQ(kFreezeDurationMs, stats.total_freezes_duration_ms);
262}
263
264TEST_F(ReceiveStatisticsProxyTest, ReportsPauseMetrics) {
265 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
266 ASSERT_EQ(0u, stats.pause_count);
267 ASSERT_EQ(0u, stats.total_pauses_duration_ms);
268
269 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
270 statistics_proxy_->OnRenderedFrame(frame);
271
272 // Pause.
273 fake_clock_.AdvanceTimeMilliseconds(5432);
274 statistics_proxy_->OnStreamInactive();
275 statistics_proxy_->OnRenderedFrame(frame);
276
277 stats = statistics_proxy_->GetStats();
278 EXPECT_EQ(1u, stats.pause_count);
279 EXPECT_EQ(5432u, stats.total_pauses_duration_ms);
280}
281
282TEST_F(ReceiveStatisticsProxyTest, PauseBeforeFirstAndAfterLastFrameIgnored) {
283 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
284 ASSERT_EQ(0u, stats.pause_count);
285 ASSERT_EQ(0u, stats.total_pauses_duration_ms);
286
287 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
288
289 // Pause -> Frame -> Pause
290 fake_clock_.AdvanceTimeMilliseconds(5000);
291 statistics_proxy_->OnStreamInactive();
292 statistics_proxy_->OnRenderedFrame(frame);
293
294 fake_clock_.AdvanceTimeMilliseconds(30);
295 statistics_proxy_->OnRenderedFrame(frame);
296
297 fake_clock_.AdvanceTimeMilliseconds(5000);
298 statistics_proxy_->OnStreamInactive();
299
300 stats = statistics_proxy_->GetStats();
301 EXPECT_EQ(0u, stats.pause_count);
302 EXPECT_EQ(0u, stats.total_pauses_duration_ms);
303}
304
305TEST_F(ReceiveStatisticsProxyTest, ReportsFramesDuration) {
306 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
307 ASSERT_EQ(0u, stats.total_frames_duration_ms);
308
309 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
310
311 // Emulate delay before first frame is rendered. This is needed to ensure
312 // that frame duration only covers time since first frame is rendered and
313 // not the total time.
314 fake_clock_.AdvanceTimeMilliseconds(5432);
315
316 for (int i = 0; i <= 10; ++i) {
317 fake_clock_.AdvanceTimeMilliseconds(30);
318 statistics_proxy_->OnRenderedFrame(frame);
319 }
320
321 stats = statistics_proxy_->GetStats();
322 EXPECT_EQ(10 * 30u, stats.total_frames_duration_ms);
323}
324
325TEST_F(ReceiveStatisticsProxyTest, ReportsSumSquaredFrameDurations) {
326 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
327 ASSERT_EQ(0u, stats.sum_squared_frame_durations);
328
329 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
330 for (int i = 0; i <= 10; ++i) {
331 fake_clock_.AdvanceTimeMilliseconds(30);
332 statistics_proxy_->OnRenderedFrame(frame);
333 }
334
335 stats = statistics_proxy_->GetStats();
336 const double kExpectedSumSquaredFrameDurationsSecs =
337 10 * (30 / 1000.0 * 30 / 1000.0);
338 EXPECT_EQ(kExpectedSumSquaredFrameDurationsSecs,
339 stats.sum_squared_frame_durations);
340}
341
sakalcc452e12017-02-09 04:53:45 -0800342TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameWithoutQpQpSumWontExist) {
Sergey Silkin278f8252019-01-09 14:37:40 +0100343 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200344 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
Sergey Silkin278f8252019-01-09 14:37:40 +0100345 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
ilnik00d802b2017-04-11 10:34:31 -0700346 VideoContentType::UNSPECIFIED);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200347 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakalcc452e12017-02-09 04:53:45 -0800348}
349
350TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameWithoutQpResetsQpSum) {
Sergey Silkin278f8252019-01-09 14:37:40 +0100351 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200352 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
Sergey Silkin278f8252019-01-09 14:37:40 +0100353 statistics_proxy_->OnDecodedFrame(frame, 3u, VideoContentType::UNSPECIFIED);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100354 EXPECT_EQ(3u, statistics_proxy_->GetStats().qp_sum);
Sergey Silkin278f8252019-01-09 14:37:40 +0100355 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
ilnik00d802b2017-04-11 10:34:31 -0700356 VideoContentType::UNSPECIFIED);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200357 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakalcc452e12017-02-09 04:53:45 -0800358}
359
hbos50cfe1f2017-01-23 07:21:55 -0800360TEST_F(ReceiveStatisticsProxyTest, OnRenderedFrameIncreasesFramesRendered) {
361 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_rendered);
Sergey Silkin278f8252019-01-09 14:37:40 +0100362 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
hbos50cfe1f2017-01-23 07:21:55 -0800363 for (uint32_t i = 1; i <= 3; ++i) {
364 statistics_proxy_->OnRenderedFrame(frame);
365 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_rendered);
366 }
367}
368
asapersson46c4e3c2016-11-03 06:48:19 -0700369TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsSsrc) {
370 EXPECT_EQ(kRemoteSsrc, statistics_proxy_->GetStats().ssrc);
371}
372
373TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsIncomingPayloadType) {
374 const int kPayloadType = 111;
375 statistics_proxy_->OnIncomingPayloadType(kPayloadType);
376 EXPECT_EQ(kPayloadType, statistics_proxy_->GetStats().current_payload_type);
377}
378
asapersson6966bd52017-01-03 00:44:06 -0800379TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsDecoderImplementationName) {
380 const char* kName = "decoderName";
381 statistics_proxy_->OnDecoderImplementationName(kName);
382 EXPECT_STREQ(
383 kName, statistics_proxy_->GetStats().decoder_implementation_name.c_str());
384}
385
philipela45102f2017-02-22 05:30:39 -0800386TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsOnCompleteFrame) {
387 const int kFrameSizeBytes = 1000;
ilnik6d5b4d62017-08-30 03:32:14 -0700388 statistics_proxy_->OnCompleteFrame(true, kFrameSizeBytes,
389 VideoContentType::UNSPECIFIED);
philipela45102f2017-02-22 05:30:39 -0800390 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
391 EXPECT_EQ(1, stats.network_frame_rate);
philipela45102f2017-02-22 05:30:39 -0800392 EXPECT_EQ(1, stats.frame_counts.key_frames);
393 EXPECT_EQ(0, stats.frame_counts.delta_frames);
asapersson46c4e3c2016-11-03 06:48:19 -0700394}
395
396TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsDecodeTimingStats) {
397 const int kDecodeMs = 1;
398 const int kMaxDecodeMs = 2;
399 const int kCurrentDelayMs = 3;
400 const int kTargetDelayMs = 4;
401 const int kJitterBufferMs = 5;
402 const int kMinPlayoutDelayMs = 6;
403 const int kRenderDelayMs = 7;
404 const int64_t kRttMs = 8;
philipela45102f2017-02-22 05:30:39 -0800405 statistics_proxy_->OnRttUpdate(kRttMs, 0);
406 statistics_proxy_->OnFrameBufferTimingsUpdated(
asapersson46c4e3c2016-11-03 06:48:19 -0700407 kDecodeMs, kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs, kJitterBufferMs,
philipela45102f2017-02-22 05:30:39 -0800408 kMinPlayoutDelayMs, kRenderDelayMs);
asapersson46c4e3c2016-11-03 06:48:19 -0700409 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
410 EXPECT_EQ(kDecodeMs, stats.decode_ms);
411 EXPECT_EQ(kMaxDecodeMs, stats.max_decode_ms);
412 EXPECT_EQ(kCurrentDelayMs, stats.current_delay_ms);
413 EXPECT_EQ(kTargetDelayMs, stats.target_delay_ms);
414 EXPECT_EQ(kJitterBufferMs, stats.jitter_buffer_ms);
415 EXPECT_EQ(kMinPlayoutDelayMs, stats.min_playout_delay_ms);
416 EXPECT_EQ(kRenderDelayMs, stats.render_delay_ms);
417}
418
asapersson6966bd52017-01-03 00:44:06 -0800419TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsRtcpPacketTypeCounts) {
420 const uint32_t kFirPackets = 33;
421 const uint32_t kPliPackets = 44;
422 const uint32_t kNackPackets = 55;
423 RtcpPacketTypeCounter counter;
424 counter.fir_packets = kFirPackets;
425 counter.pli_packets = kPliPackets;
426 counter.nack_packets = kNackPackets;
427 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
428 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
429 EXPECT_EQ(kFirPackets, stats.rtcp_packet_type_counts.fir_packets);
430 EXPECT_EQ(kPliPackets, stats.rtcp_packet_type_counts.pli_packets);
431 EXPECT_EQ(kNackPackets, stats.rtcp_packet_type_counts.nack_packets);
432}
433
434TEST_F(ReceiveStatisticsProxyTest,
435 GetStatsReportsNoRtcpPacketTypeCountsForUnknownSsrc) {
436 RtcpPacketTypeCounter counter;
437 counter.fir_packets = 33;
438 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc + 1, counter);
439 EXPECT_EQ(0u,
440 statistics_proxy_->GetStats().rtcp_packet_type_counts.fir_packets);
441}
442
443TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsFrameCounts) {
444 const int kKeyFrames = 3;
445 const int kDeltaFrames = 22;
446 FrameCounts frame_counts;
447 frame_counts.key_frames = kKeyFrames;
448 frame_counts.delta_frames = kDeltaFrames;
449 statistics_proxy_->OnFrameCountsUpdated(frame_counts);
450 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
451 EXPECT_EQ(kKeyFrames, stats.frame_counts.key_frames);
452 EXPECT_EQ(kDeltaFrames, stats.frame_counts.delta_frames);
453}
454
asapersson46c4e3c2016-11-03 06:48:19 -0700455TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsDiscardedPackets) {
456 const int kDiscardedPackets = 12;
457 statistics_proxy_->OnDiscardedPacketsUpdated(kDiscardedPackets);
458 EXPECT_EQ(kDiscardedPackets, statistics_proxy_->GetStats().discarded_packets);
459}
460
asapersson6966bd52017-01-03 00:44:06 -0800461TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsRtcpStats) {
462 const uint8_t kFracLost = 0;
Harald Alvestrandc7c41912017-12-08 09:59:34 +0100463 const int32_t kCumLost = 1;
asapersson6966bd52017-01-03 00:44:06 -0800464 const uint32_t kExtSeqNum = 10;
465 const uint32_t kJitter = 4;
466
467 RtcpStatistics rtcp_stats;
468 rtcp_stats.fraction_lost = kFracLost;
srte186d9c32017-08-04 05:03:53 -0700469 rtcp_stats.packets_lost = kCumLost;
470 rtcp_stats.extended_highest_sequence_number = kExtSeqNum;
asapersson6966bd52017-01-03 00:44:06 -0800471 rtcp_stats.jitter = kJitter;
472 statistics_proxy_->StatisticsUpdated(rtcp_stats, kRemoteSsrc);
473
474 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
475 EXPECT_EQ(kFracLost, stats.rtcp_stats.fraction_lost);
srte186d9c32017-08-04 05:03:53 -0700476 EXPECT_EQ(kCumLost, stats.rtcp_stats.packets_lost);
477 EXPECT_EQ(kExtSeqNum, stats.rtcp_stats.extended_highest_sequence_number);
asapersson6966bd52017-01-03 00:44:06 -0800478 EXPECT_EQ(kJitter, stats.rtcp_stats.jitter);
479}
480
481TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsCName) {
482 const char* kName = "cName";
483 statistics_proxy_->CNameChanged(kName, kRemoteSsrc);
484 EXPECT_STREQ(kName, statistics_proxy_->GetStats().c_name.c_str());
485}
486
487TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsNoCNameForUnknownSsrc) {
488 const char* kName = "cName";
489 statistics_proxy_->CNameChanged(kName, kRemoteSsrc + 1);
490 EXPECT_STREQ("", statistics_proxy_->GetStats().c_name.c_str());
491}
492
ilnik2edc6842017-07-06 03:06:50 -0700493TEST_F(ReceiveStatisticsProxyTest,
ilnik75204c52017-09-04 03:35:40 -0700494 ReportsLongestTimingFrameInfo) {
ilnik2edc6842017-07-06 03:06:50 -0700495 const int64_t kShortEndToEndDelay = 10;
496 const int64_t kMedEndToEndDelay = 20;
497 const int64_t kLongEndToEndDelay = 100;
498 const uint32_t kExpectedRtpTimestamp = 2;
499 TimingFrameInfo info;
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200500 absl::optional<TimingFrameInfo> result;
ilnik2edc6842017-07-06 03:06:50 -0700501 info.rtp_timestamp = kExpectedRtpTimestamp - 1;
502 info.capture_time_ms = 0;
503 info.decode_finish_ms = kShortEndToEndDelay;
504 statistics_proxy_->OnTimingFrameInfoUpdated(info);
505 info.rtp_timestamp =
506 kExpectedRtpTimestamp; // this frame should be reported in the end.
507 info.capture_time_ms = 0;
508 info.decode_finish_ms = kLongEndToEndDelay;
509 statistics_proxy_->OnTimingFrameInfoUpdated(info);
510 info.rtp_timestamp = kExpectedRtpTimestamp + 1;
511 info.capture_time_ms = 0;
512 info.decode_finish_ms = kMedEndToEndDelay;
513 statistics_proxy_->OnTimingFrameInfoUpdated(info);
ilnik75204c52017-09-04 03:35:40 -0700514 result = statistics_proxy_->GetStats().timing_frame_info;
ilnik2edc6842017-07-06 03:06:50 -0700515 EXPECT_TRUE(result);
516 EXPECT_EQ(kExpectedRtpTimestamp, result->rtp_timestamp);
517}
518
ilnik75204c52017-09-04 03:35:40 -0700519TEST_F(ReceiveStatisticsProxyTest, RespectsReportingIntervalForTimingFrames) {
520 TimingFrameInfo info;
ilnik2edc6842017-07-06 03:06:50 -0700521 const int64_t kShortEndToEndDelay = 10;
522 const uint32_t kExpectedRtpTimestamp = 2;
ilnik75204c52017-09-04 03:35:40 -0700523 const int64_t kShortDelayMs = 1000;
524 const int64_t kLongDelayMs = 10000;
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200525 absl::optional<TimingFrameInfo> result;
ilnik2edc6842017-07-06 03:06:50 -0700526 info.rtp_timestamp = kExpectedRtpTimestamp;
527 info.capture_time_ms = 0;
528 info.decode_finish_ms = kShortEndToEndDelay;
529 statistics_proxy_->OnTimingFrameInfoUpdated(info);
ilnik75204c52017-09-04 03:35:40 -0700530 fake_clock_.AdvanceTimeMilliseconds(kShortDelayMs);
531 result = statistics_proxy_->GetStats().timing_frame_info;
ilnik2edc6842017-07-06 03:06:50 -0700532 EXPECT_TRUE(result);
533 EXPECT_EQ(kExpectedRtpTimestamp, result->rtp_timestamp);
ilnik75204c52017-09-04 03:35:40 -0700534 fake_clock_.AdvanceTimeMilliseconds(kLongDelayMs);
535 result = statistics_proxy_->GetStats().timing_frame_info;
ilnik2edc6842017-07-06 03:06:50 -0700536 EXPECT_FALSE(result);
537}
538
asapersson46c4e3c2016-11-03 06:48:19 -0700539TEST_F(ReceiveStatisticsProxyTest, LifetimeHistogramIsUpdated) {
540 const int64_t kTimeSec = 3;
541 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
ilnik6d5b4d62017-08-30 03:32:14 -0700542 // Need at least one frame to report stream lifetime.
543 statistics_proxy_->OnCompleteFrame(true, 1000, VideoContentType::UNSPECIFIED);
asapersson46c4e3c2016-11-03 06:48:19 -0700544 // Histograms are updated when the statistics_proxy_ is deleted.
545 statistics_proxy_.reset();
546 EXPECT_EQ(1,
547 metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
548 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceiveStreamLifetimeInSeconds",
549 kTimeSec));
550}
551
ilnik6d5b4d62017-08-30 03:32:14 -0700552TEST_F(ReceiveStatisticsProxyTest,
553 LifetimeHistogramNotReportedForEmptyStreams) {
554 const int64_t kTimeSec = 3;
555 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
556 // No frames received.
557 // Histograms are updated when the statistics_proxy_ is deleted.
558 statistics_proxy_.reset();
559 EXPECT_EQ(0,
560 metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
561}
562
palmkvista40672a2017-01-13 05:58:34 -0800563TEST_F(ReceiveStatisticsProxyTest, BadCallHistogramsAreUpdated) {
564 // Based on the tuning parameters this will produce 7 uncertain states,
565 // then 10 certainly bad states. There has to be 10 certain states before
566 // any histograms are recorded.
567 const int kNumBadSamples = 17;
Niels Möller9b0b1e02019-03-22 13:56:46 +0100568 // We only count one sample per second.
569 const int kBadFameIntervalMs = 1100;
palmkvista40672a2017-01-13 05:58:34 -0800570
571 StreamDataCounters counters;
572 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
573 statistics_proxy_->DataCountersUpdated(counters, config_.rtp.remote_ssrc);
574
Niels Möller9b0b1e02019-03-22 13:56:46 +0100575 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
576
palmkvista40672a2017-01-13 05:58:34 -0800577 for (int i = 0; i < kNumBadSamples; ++i) {
Niels Möller9b0b1e02019-03-22 13:56:46 +0100578 fake_clock_.AdvanceTimeMilliseconds(kBadFameIntervalMs);
579 statistics_proxy_->OnRenderedFrame(frame);
palmkvista40672a2017-01-13 05:58:34 -0800580 }
581 // Histograms are updated when the statistics_proxy_ is deleted.
582 statistics_proxy_.reset();
583 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BadCall.Any"));
584 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BadCall.Any", 100));
585
586 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BadCall.FrameRate"));
587 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BadCall.FrameRate", 100));
588
589 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.BadCall.FrameRateVariance"));
590
591 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.BadCall.Qp"));
592}
593
asapersson0c43f772016-11-30 01:42:26 -0800594TEST_F(ReceiveStatisticsProxyTest, PacketLossHistogramIsUpdated) {
595 const uint32_t kCumLost1 = 1;
596 const uint32_t kExtSeqNum1 = 10;
597 const uint32_t kCumLost2 = 2;
598 const uint32_t kExtSeqNum2 = 20;
599
600 // One report block received.
601 RtcpStatistics rtcp_stats1;
srte186d9c32017-08-04 05:03:53 -0700602 rtcp_stats1.packets_lost = kCumLost1;
603 rtcp_stats1.extended_highest_sequence_number = kExtSeqNum1;
asapersson0c43f772016-11-30 01:42:26 -0800604 statistics_proxy_->StatisticsUpdated(rtcp_stats1, kRemoteSsrc);
605
606 // Two report blocks received.
607 RtcpStatistics rtcp_stats2;
srte186d9c32017-08-04 05:03:53 -0700608 rtcp_stats2.packets_lost = kCumLost2;
609 rtcp_stats2.extended_highest_sequence_number = kExtSeqNum2;
asapersson0c43f772016-11-30 01:42:26 -0800610 statistics_proxy_->StatisticsUpdated(rtcp_stats2, kRemoteSsrc);
611
612 // Two received report blocks but min run time has not passed.
613 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
614 SetUp(); // Reset stat proxy causes histograms to be updated.
615 EXPECT_EQ(0,
616 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
617
618 // Two report blocks received.
619 statistics_proxy_->StatisticsUpdated(rtcp_stats1, kRemoteSsrc);
620 statistics_proxy_->StatisticsUpdated(rtcp_stats2, kRemoteSsrc);
621
622 // Two received report blocks and min run time has passed.
623 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
624 SetUp();
625 EXPECT_EQ(1,
626 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
627 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceivedPacketsLostInPercent",
628 (kCumLost2 - kCumLost1) * 100 /
629 (kExtSeqNum2 - kExtSeqNum1)));
630}
631
632TEST_F(ReceiveStatisticsProxyTest,
633 PacketLossHistogramIsNotUpdatedIfLessThanTwoReportBlocksAreReceived) {
634 RtcpStatistics rtcp_stats1;
srte186d9c32017-08-04 05:03:53 -0700635 rtcp_stats1.packets_lost = 1;
636 rtcp_stats1.extended_highest_sequence_number = 10;
asapersson0c43f772016-11-30 01:42:26 -0800637
638 // Min run time has passed but no received report block.
639 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
640 SetUp(); // Reset stat proxy causes histograms to be updated.
641 EXPECT_EQ(0,
642 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
643
644 // Min run time has passed but only one received report block.
645 statistics_proxy_->StatisticsUpdated(rtcp_stats1, kRemoteSsrc);
646 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
647 SetUp();
648 EXPECT_EQ(0,
649 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
650}
651
asapersson2077f2f2017-05-11 05:37:35 -0700652TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsAvSyncOffset) {
653 const int64_t kSyncOffsetMs = 22;
654 const double kFreqKhz = 90.0;
655 EXPECT_EQ(std::numeric_limits<int>::max(),
656 statistics_proxy_->GetStats().sync_offset_ms);
657 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
658 EXPECT_EQ(kSyncOffsetMs, statistics_proxy_->GetStats().sync_offset_ms);
659}
660
asapersson46c4e3c2016-11-03 06:48:19 -0700661TEST_F(ReceiveStatisticsProxyTest, AvSyncOffsetHistogramIsUpdated) {
662 const int64_t kSyncOffsetMs = 22;
663 const double kFreqKhz = 90.0;
664 for (int i = 0; i < kMinRequiredSamples; ++i)
665 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
666 // Histograms are updated when the statistics_proxy_ is deleted.
667 statistics_proxy_.reset();
668 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AVSyncOffsetInMs"));
669 EXPECT_EQ(1,
670 metrics::NumEvents("WebRTC.Video.AVSyncOffsetInMs", kSyncOffsetMs));
671}
672
asaperssonde9e5ff2016-11-02 07:14:03 -0700673TEST_F(ReceiveStatisticsProxyTest, RtpToNtpFrequencyOffsetHistogramIsUpdated) {
674 const int64_t kSyncOffsetMs = 22;
675 const double kFreqKhz = 90.0;
676 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
677 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz + 2.2);
678 fake_clock_.AdvanceTimeMilliseconds(kFreqOffsetProcessIntervalInMs);
679 // Process interval passed, max diff: 2.
680 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz + 1.1);
681 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz - 4.2);
682 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz - 0.9);
683 fake_clock_.AdvanceTimeMilliseconds(kFreqOffsetProcessIntervalInMs);
684 // Process interval passed, max diff: 4.
685 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
686 statistics_proxy_.reset();
687 // Average reported: (2 + 4) / 2 = 3.
688 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtpToNtpFreqOffsetInKhz"));
689 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtpToNtpFreqOffsetInKhz", 3));
690}
691
asapersson6966bd52017-01-03 00:44:06 -0800692TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsUpdated) {
693 const int kQp = 22;
asapersson6966bd52017-01-03 00:44:06 -0800694
695 for (int i = 0; i < kMinRequiredSamples; ++i)
Niels Möller147013a2018-10-01 15:56:33 +0200696 statistics_proxy_->OnPreDecode(kVideoCodecVP8, kQp);
asapersson6966bd52017-01-03 00:44:06 -0800697
698 statistics_proxy_.reset();
699 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
700 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Decoded.Vp8.Qp", kQp));
701}
702
703TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsNotUpdatedForTooFewSamples) {
Niels Möller147013a2018-10-01 15:56:33 +0200704 const int kQp = 22;
asapersson6966bd52017-01-03 00:44:06 -0800705
706 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
Niels Möller147013a2018-10-01 15:56:33 +0200707 statistics_proxy_->OnPreDecode(kVideoCodecVP8, kQp);
asapersson6966bd52017-01-03 00:44:06 -0800708
709 statistics_proxy_.reset();
710 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
711}
712
713TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsNotUpdatedIfNoQpValue) {
asapersson6966bd52017-01-03 00:44:06 -0800714 for (int i = 0; i < kMinRequiredSamples; ++i)
Niels Möller147013a2018-10-01 15:56:33 +0200715 statistics_proxy_->OnPreDecode(kVideoCodecVP8, -1);
asapersson6966bd52017-01-03 00:44:06 -0800716
717 statistics_proxy_.reset();
718 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
719}
720
asaperssonb99baf82017-04-20 04:05:43 -0700721TEST_F(ReceiveStatisticsProxyTest,
722 KeyFrameHistogramNotUpdatedForTooFewSamples) {
723 const bool kIsKeyFrame = false;
724 const int kFrameSizeBytes = 1000;
725
726 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
ilnik6d5b4d62017-08-30 03:32:14 -0700727 statistics_proxy_->OnCompleteFrame(kIsKeyFrame, kFrameSizeBytes,
728 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 04:05:43 -0700729
730 EXPECT_EQ(0, statistics_proxy_->GetStats().frame_counts.key_frames);
731 EXPECT_EQ(kMinRequiredSamples - 1,
732 statistics_proxy_->GetStats().frame_counts.delta_frames);
733
734 statistics_proxy_.reset();
735 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
736}
737
738TEST_F(ReceiveStatisticsProxyTest,
739 KeyFrameHistogramUpdatedForMinRequiredSamples) {
740 const bool kIsKeyFrame = false;
741 const int kFrameSizeBytes = 1000;
742
743 for (int i = 0; i < kMinRequiredSamples; ++i)
ilnik6d5b4d62017-08-30 03:32:14 -0700744 statistics_proxy_->OnCompleteFrame(kIsKeyFrame, kFrameSizeBytes,
745 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 04:05:43 -0700746
747 EXPECT_EQ(0, statistics_proxy_->GetStats().frame_counts.key_frames);
748 EXPECT_EQ(kMinRequiredSamples,
749 statistics_proxy_->GetStats().frame_counts.delta_frames);
750
751 statistics_proxy_.reset();
752 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
753 EXPECT_EQ(1,
754 metrics::NumEvents("WebRTC.Video.KeyFramesReceivedInPermille", 0));
755}
756
757TEST_F(ReceiveStatisticsProxyTest, KeyFrameHistogramIsUpdated) {
758 const int kFrameSizeBytes = 1000;
759
760 for (int i = 0; i < kMinRequiredSamples; ++i)
ilnik6d5b4d62017-08-30 03:32:14 -0700761 statistics_proxy_->OnCompleteFrame(true, kFrameSizeBytes,
762 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 04:05:43 -0700763
764 for (int i = 0; i < kMinRequiredSamples; ++i)
ilnik6d5b4d62017-08-30 03:32:14 -0700765 statistics_proxy_->OnCompleteFrame(false, kFrameSizeBytes,
766 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 04:05:43 -0700767
768 EXPECT_EQ(kMinRequiredSamples,
769 statistics_proxy_->GetStats().frame_counts.key_frames);
770 EXPECT_EQ(kMinRequiredSamples,
771 statistics_proxy_->GetStats().frame_counts.delta_frames);
772
773 statistics_proxy_.reset();
774 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
775 EXPECT_EQ(
776 1, metrics::NumEvents("WebRTC.Video.KeyFramesReceivedInPermille", 500));
777}
778
779TEST_F(ReceiveStatisticsProxyTest, TimingHistogramsNotUpdatedForTooFewSamples) {
780 const int kDecodeMs = 1;
781 const int kMaxDecodeMs = 2;
782 const int kCurrentDelayMs = 3;
783 const int kTargetDelayMs = 4;
784 const int kJitterBufferMs = 5;
785 const int kMinPlayoutDelayMs = 6;
786 const int kRenderDelayMs = 7;
787
788 for (int i = 0; i < kMinRequiredSamples - 1; ++i) {
789 statistics_proxy_->OnFrameBufferTimingsUpdated(
790 kDecodeMs, kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs,
791 kJitterBufferMs, kMinPlayoutDelayMs, kRenderDelayMs);
792 }
793
794 statistics_proxy_.reset();
795 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
796 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
797 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
798 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
799 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
800}
801
802TEST_F(ReceiveStatisticsProxyTest, TimingHistogramsAreUpdated) {
803 const int kDecodeMs = 1;
804 const int kMaxDecodeMs = 2;
805 const int kCurrentDelayMs = 3;
806 const int kTargetDelayMs = 4;
807 const int kJitterBufferMs = 5;
808 const int kMinPlayoutDelayMs = 6;
809 const int kRenderDelayMs = 7;
810
811 for (int i = 0; i < kMinRequiredSamples; ++i) {
812 statistics_proxy_->OnFrameBufferTimingsUpdated(
813 kDecodeMs, kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs,
814 kJitterBufferMs, kMinPlayoutDelayMs, kRenderDelayMs);
815 }
816
817 statistics_proxy_.reset();
818 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
819 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
820 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
821 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
822 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
823
824 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DecodeTimeInMs", kDecodeMs));
825 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 02:47:13 -0700835TEST_F(ReceiveStatisticsProxyTest, DoesNotReportStaleFramerates) {
836 const int kDefaultFps = 30;
Sergey Silkin278f8252019-01-09 14:37:40 +0100837 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
sprang948b2752017-05-04 02:47:13 -0700838
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());
Sergey Silkin278f8252019-01-09 14:37:40 +0100843 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
sprang948b2752017-05-04 02:47:13 -0700844 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 05:37:35 -0700858TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsReceivedFrameStats) {
asapersson2077f2f2017-05-11 05:37:35 -0700859 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 05:37:35 -0700872 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 05:37:35 -0700883 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 13:34:33 +0200897TEST_F(ReceiveStatisticsProxyTest, ZeroDelayReportedIfFrameNotDelayed) {
Sergey Silkin278f8252019-01-09 14:37:40 +0100898 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
899 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
Åsa Persson81327d52018-06-05 13:34:33 +0200900 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 14:37:40 +0100917 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
918 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
Åsa Persson81327d52018-06-05 13:34:33 +0200919 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 14:37:40 +0100936 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
937 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
Åsa Persson81327d52018-06-05 13:34:33 +0200938 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 14:37:40 +0100949 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
950 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
Åsa Persson81327d52018-06-05 13:34:33 +0200951 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 14:37:40 +0100969 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
970 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
Åsa Persson81327d52018-06-05 13:34:33 +0200971 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 05:37:35 -0700991TEST_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 16:45:42 +01001035class ReceiveStatisticsProxyTestWithFreezeDuration
1036 : public ReceiveStatisticsProxyTest,
1037 public testing::WithParamInterface<
1038 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 05:00:33 -07001044
Sergey Silkin02371062019-01-31 16:45:42 +01001045// 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 17:04:04 +01001057INSTANTIATE_TEST_SUITE_P(_,
1058 ReceiveStatisticsProxyTestWithFreezeDuration,
1059 ::testing::Values(kFreezeDetectionCond1Freeze,
1060 kFreezeDetectionCond1NotFreeze,
1061 kFreezeDetectionCond2Freeze,
1062 kFreezeDetectionCond2NotFreeze));
Sergey Silkin02371062019-01-31 16:45:42 +01001063
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 17:04:04 +01001095INSTANTIATE_TEST_SUITE_P(ContentTypes,
1096 ReceiveStatisticsProxyTestWithContent,
1097 ::testing::Values(VideoContentType::UNSPECIFIED,
1098 VideoContentType::SCREENSHARE));
Sergey Silkin02371062019-01-31 16:45:42 +01001099
1100TEST_P(ReceiveStatisticsProxyTestWithContent, InterFrameDelaysAreReported) {
sprang892dab52017-08-15 05:00:33 -07001101 const int kInterFrameDelayMs = 33;
Sergey Silkin278f8252019-01-09 14:37:40 +01001102 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1103
sprang892dab52017-08-15 05:00:33 -07001104 for (int i = 0; i < kMinRequiredSamples; ++i) {
Sergey Silkin02371062019-01-31 16:45:42 +01001105 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
sprang892dab52017-08-15 05:00:33 -07001106 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1107 }
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001108 // One extra with double the interval.
sprang892dab52017-08-15 05:00:33 -07001109 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
Sergey Silkin02371062019-01-31 16:45:42 +01001110 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
sprang892dab52017-08-15 05:00:33 -07001111
1112 statistics_proxy_.reset();
1113 const int kExpectedInterFrame =
1114 (kInterFrameDelayMs * (kMinRequiredSamples - 1) +
1115 kInterFrameDelayMs * 2) /
1116 kMinRequiredSamples;
Sergey Silkin02371062019-01-31 16:45:42 +01001117 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
ilnik6d5b4d62017-08-30 03:32:14 -07001118 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 05:00:33 -07001129 }
1130}
1131
Sergey Silkin02371062019-01-31 16:45:42 +01001132TEST_P(ReceiveStatisticsProxyTestWithContent,
1133 InterFrameDelaysPercentilesAreReported) {
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001134 const int kInterFrameDelayMs = 33;
1135 const int kLastFivePercentsSamples = kMinRequiredSamples * 5 / 100;
Sergey Silkin278f8252019-01-09 14:37:40 +01001136 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1137
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001138 for (int i = 0; i <= kMinRequiredSamples - kLastFivePercentsSamples; ++i) {
1139 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
Sergey Silkin02371062019-01-31 16:45:42 +01001140 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001141 }
1142 // Last 5% of intervals are double in size.
1143 for (int i = 0; i < kLastFivePercentsSamples; ++i) {
1144 fake_clock_.AdvanceTimeMilliseconds(2 * kInterFrameDelayMs);
Sergey Silkin02371062019-01-31 16:45:42 +01001145 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001146 }
1147 // Final sample is outlier and 10 times as big.
1148 fake_clock_.AdvanceTimeMilliseconds(10 * kInterFrameDelayMs);
Sergey Silkin02371062019-01-31 16:45:42 +01001149 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001150
1151 statistics_proxy_.reset();
1152 const int kExpectedInterFrame = kInterFrameDelayMs * 2;
Sergey Silkin02371062019-01-31 16:45:42 +01001153 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001154 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 16:45:42 +01001164TEST_P(ReceiveStatisticsProxyTestWithContent,
1165 MaxInterFrameDelayOnlyWithValidAverage) {
sprang892dab52017-08-15 05:00:33 -07001166 const int kInterFrameDelayMs = 33;
Sergey Silkin278f8252019-01-09 14:37:40 +01001167 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1168
sprang892dab52017-08-15 05:00:33 -07001169 for (int i = 0; i < kMinRequiredSamples; ++i) {
Sergey Silkin02371062019-01-31 16:45:42 +01001170 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
sprang892dab52017-08-15 05:00:33 -07001171 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 16:45:42 +01001185TEST_P(ReceiveStatisticsProxyTestWithContent, MaxInterFrameDelayOnlyWithPause) {
sprang3e86e7e2017-08-22 09:23:28 -07001186 const int kInterFrameDelayMs = 33;
Sergey Silkin278f8252019-01-09 14:37:40 +01001187 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1188
sprang3e86e7e2017-08-22 09:23:28 -07001189 for (int i = 0; i <= kMinRequiredSamples; ++i) {
Sergey Silkin02371062019-01-31 16:45:42 +01001190 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
sprang3e86e7e2017-08-22 09:23:28 -07001191 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.
Sergey Silkin02371062019-01-31 16:45:42 +01001201 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
sprang3e86e7e2017-08-22 09:23:28 -07001202 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
Sergey Silkin02371062019-01-31 16:45:42 +01001203 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
sprang3e86e7e2017-08-22 09:23:28 -07001204
1205 statistics_proxy_.reset();
Sergey Silkin02371062019-01-31 16:45:42 +01001206 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
sprang3e86e7e2017-08-22 09:23:28 -07001207 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 16:45:42 +01001227TEST_P(ReceiveStatisticsProxyTestWithContent, FreezesAreReported) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001228 const int kInterFrameDelayMs = 33;
1229 const int kFreezeDelayMs = 200;
Sergey Silkinbea18ca2018-10-02 16:22:46 +02001230 const int kCallDurationMs =
1231 kMinRequiredSamples * kInterFrameDelayMs + kFreezeDelayMs;
Sergey Silkin278f8252019-01-09 14:37:40 +01001232 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1233
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001234 for (int i = 0; i < kMinRequiredSamples; ++i) {
Sergey Silkin02371062019-01-31 16:45:42 +01001235 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
Ilya Nikolaevskiycdc959f2018-10-10 13:15:09 +02001236 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001237 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1238 }
1239 // Add extra freeze.
1240 fake_clock_.AdvanceTimeMilliseconds(kFreezeDelayMs);
Sergey Silkin02371062019-01-31 16:45:42 +01001241 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
Ilya Nikolaevskiycdc959f2018-10-10 13:15:09 +02001242 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001243
1244 statistics_proxy_.reset();
1245 const int kExpectedTimeBetweenFreezes =
1246 kInterFrameDelayMs * (kMinRequiredSamples - 1);
Sergey Silkinbea18ca2018-10-02 16:22:46 +02001247 const int kExpectedNumberFreezesPerMinute = 60 * 1000 / kCallDurationMs;
Sergey Silkin02371062019-01-31 16:45:42 +01001248 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001249 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 16:22:46 +02001255 EXPECT_EQ(
1256 kExpectedNumberFreezesPerMinute,
1257 metrics::MinSample("WebRTC.Video.Screenshare.NumberFreezesPerMinute"));
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001258 } 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 16:22:46 +02001263 EXPECT_EQ(kExpectedNumberFreezesPerMinute,
1264 metrics::MinSample("WebRTC.Video.NumberFreezesPerMinute"));
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001265 }
1266}
1267
Sergey Silkin02371062019-01-31 16:45:42 +01001268TEST_P(ReceiveStatisticsProxyTestWithContent, HarmonicFrameRateIsReported) {
Sergey Silkin50e77452019-01-16 13:41:46 +01001269 const int kInterFrameDelayMs = 33;
1270 const int kFreezeDelayMs = 200;
1271 const int kCallDurationMs =
1272 kMinRequiredSamples * kInterFrameDelayMs + kFreezeDelayMs;
1273 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1274
1275 for (int i = 0; i < kMinRequiredSamples; ++i) {
1276 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
Sergey Silkin02371062019-01-31 16:45:42 +01001277 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
Sergey Silkin50e77452019-01-16 13:41:46 +01001278 statistics_proxy_->OnRenderedFrame(frame);
1279 }
1280 // Add extra freeze.
1281 fake_clock_.AdvanceTimeMilliseconds(kFreezeDelayMs);
Sergey Silkin02371062019-01-31 16:45:42 +01001282 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
Sergey Silkin50e77452019-01-16 13:41:46 +01001283 statistics_proxy_->OnRenderedFrame(frame);
1284
1285 statistics_proxy_.reset();
1286 double kSumSquaredInterframeDelaysSecs =
1287 (kMinRequiredSamples - 1) *
1288 (kInterFrameDelayMs / 1000.0 * kInterFrameDelayMs / 1000.0);
1289 kSumSquaredInterframeDelaysSecs +=
1290 kFreezeDelayMs / 1000.0 * kFreezeDelayMs / 1000.0;
1291 const int kExpectedHarmonicFrameRateFps =
1292 std::round(kCallDurationMs / (1000 * kSumSquaredInterframeDelaysSecs));
Sergey Silkin02371062019-01-31 16:45:42 +01001293 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Sergey Silkin50e77452019-01-16 13:41:46 +01001294 EXPECT_EQ(kExpectedHarmonicFrameRateFps,
1295 metrics::MinSample("WebRTC.Video.Screenshare.HarmonicFrameRate"));
1296 } else {
1297 EXPECT_EQ(kExpectedHarmonicFrameRateFps,
1298 metrics::MinSample("WebRTC.Video.HarmonicFrameRate"));
1299 }
1300}
1301
Sergey Silkin02371062019-01-31 16:45:42 +01001302TEST_P(ReceiveStatisticsProxyTestWithContent, PausesAreIgnored) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001303 const int kInterFrameDelayMs = 33;
1304 const int kPauseDurationMs = 10000;
Sergey Silkin278f8252019-01-09 14:37:40 +01001305 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1306
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001307 for (int i = 0; i <= kMinRequiredSamples; ++i) {
Sergey Silkin02371062019-01-31 16:45:42 +01001308 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
Ilya Nikolaevskiycdc959f2018-10-10 13:15:09 +02001309 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001310 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1311 }
1312 // Add a pause.
1313 fake_clock_.AdvanceTimeMilliseconds(kPauseDurationMs);
1314 statistics_proxy_->OnStreamInactive();
1315
1316 // Second playback interval with triple the length.
1317 for (int i = 0; i <= kMinRequiredSamples * 3; ++i) {
Sergey Silkin02371062019-01-31 16:45:42 +01001318 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
Ilya Nikolaevskiycdc959f2018-10-10 13:15:09 +02001319 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001320 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1321 }
1322
1323 statistics_proxy_.reset();
1324 // Average of two playback intervals.
1325 const int kExpectedTimeBetweenFreezes =
1326 kInterFrameDelayMs * kMinRequiredSamples * 2;
Sergey Silkin02371062019-01-31 16:45:42 +01001327 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001328 EXPECT_EQ(-1, metrics::MinSample(
1329 "WebRTC.Video.Screenshare.MeanFreezeDurationMs"));
1330 EXPECT_EQ(kExpectedTimeBetweenFreezes,
1331 metrics::MinSample(
1332 "WebRTC.Video.Screenshare.MeanTimeBetweenFreezesMs"));
1333 } else {
1334 EXPECT_EQ(-1, metrics::MinSample("WebRTC.Video.MeanFreezeDurationMs"));
1335 EXPECT_EQ(kExpectedTimeBetweenFreezes,
1336 metrics::MinSample("WebRTC.Video.MeanTimeBetweenFreezesMs"));
1337 }
1338}
1339
Sergey Silkin02371062019-01-31 16:45:42 +01001340TEST_P(ReceiveStatisticsProxyTestWithContent, ManyPausesAtTheBeginning) {
Ilya Nikolaevskiy879f5a32018-05-31 09:47:17 +02001341 const int kInterFrameDelayMs = 33;
1342 const int kPauseDurationMs = 10000;
Sergey Silkin278f8252019-01-09 14:37:40 +01001343 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1344
Ilya Nikolaevskiy879f5a32018-05-31 09:47:17 +02001345 for (int i = 0; i <= kMinRequiredSamples; ++i) {
Sergey Silkin02371062019-01-31 16:45:42 +01001346 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
Ilya Nikolaevskiy879f5a32018-05-31 09:47:17 +02001347 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1348
1349 statistics_proxy_->OnStreamInactive();
1350 fake_clock_.AdvanceTimeMilliseconds(kPauseDurationMs);
1351
Sergey Silkin02371062019-01-31 16:45:42 +01001352 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
Ilya Nikolaevskiy879f5a32018-05-31 09:47:17 +02001353 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1354 }
1355
1356 statistics_proxy_.reset();
1357 // No freezes should be detected, as all long inter-frame delays were pauses.
Sergey Silkin02371062019-01-31 16:45:42 +01001358 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiy879f5a32018-05-31 09:47:17 +02001359 EXPECT_EQ(-1, metrics::MinSample(
1360 "WebRTC.Video.Screenshare.MeanFreezeDurationMs"));
1361 } else {
1362 EXPECT_EQ(-1, metrics::MinSample("WebRTC.Video.MeanFreezeDurationMs"));
1363 }
1364}
1365
Sergey Silkin02371062019-01-31 16:45:42 +01001366TEST_P(ReceiveStatisticsProxyTestWithContent, TimeInHdReported) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001367 const int kInterFrameDelayMs = 20;
Sergey Silkin278f8252019-01-09 14:37:40 +01001368 webrtc::VideoFrame frame_hd = CreateFrame(1280, 720);
1369 webrtc::VideoFrame frame_sd = CreateFrame(640, 360);
1370
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001371 // HD frames.
1372 for (int i = 0; i < kMinRequiredSamples; ++i) {
Sergey Silkin02371062019-01-31 16:45:42 +01001373 statistics_proxy_->OnDecodedFrame(frame_hd, absl::nullopt, content_type_);
Sergey Silkin278f8252019-01-09 14:37:40 +01001374 statistics_proxy_->OnRenderedFrame(frame_hd);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001375 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1376 }
1377 // SD frames.
1378 for (int i = 0; i < 2 * kMinRequiredSamples; ++i) {
Sergey Silkin02371062019-01-31 16:45:42 +01001379 statistics_proxy_->OnDecodedFrame(frame_sd, absl::nullopt, content_type_);
Sergey Silkin278f8252019-01-09 14:37:40 +01001380 statistics_proxy_->OnRenderedFrame(frame_sd);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001381 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1382 }
1383 // Extra last frame.
Sergey Silkin278f8252019-01-09 14:37:40 +01001384 statistics_proxy_->OnRenderedFrame(frame_sd);
1385
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001386 statistics_proxy_.reset();
1387 const int kExpectedTimeInHdPercents = 33;
Sergey Silkin02371062019-01-31 16:45:42 +01001388 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001389 EXPECT_EQ(
1390 kExpectedTimeInHdPercents,
1391 metrics::MinSample("WebRTC.Video.Screenshare.TimeInHdPercentage"));
1392 } else {
1393 EXPECT_EQ(kExpectedTimeInHdPercents,
1394 metrics::MinSample("WebRTC.Video.TimeInHdPercentage"));
1395 }
1396}
1397
Sergey Silkin02371062019-01-31 16:45:42 +01001398TEST_P(ReceiveStatisticsProxyTestWithContent, TimeInBlockyVideoReported) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001399 const int kInterFrameDelayMs = 20;
1400 const int kHighQp = 80;
1401 const int kLowQp = 30;
Sergey Silkin278f8252019-01-09 14:37:40 +01001402 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1403
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001404 // High quality frames.
1405 for (int i = 0; i < kMinRequiredSamples; ++i) {
Sergey Silkin02371062019-01-31 16:45:42 +01001406 statistics_proxy_->OnDecodedFrame(frame, kLowQp, content_type_);
Sergey Silkin278f8252019-01-09 14:37:40 +01001407 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001408 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1409 }
1410 // Blocky frames.
1411 for (int i = 0; i < 2 * kMinRequiredSamples; ++i) {
Sergey Silkin02371062019-01-31 16:45:42 +01001412 statistics_proxy_->OnDecodedFrame(frame, kHighQp, content_type_);
Sergey Silkin278f8252019-01-09 14:37:40 +01001413 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001414 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1415 }
1416 // Extra last frame.
Sergey Silkin02371062019-01-31 16:45:42 +01001417 statistics_proxy_->OnDecodedFrame(frame, kHighQp, content_type_);
Sergey Silkin278f8252019-01-09 14:37:40 +01001418 statistics_proxy_->OnRenderedFrame(frame);
1419
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001420 statistics_proxy_.reset();
1421 const int kExpectedTimeInHdPercents = 66;
Sergey Silkin02371062019-01-31 16:45:42 +01001422 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001423 EXPECT_EQ(kExpectedTimeInHdPercents,
1424 metrics::MinSample(
1425 "WebRTC.Video.Screenshare.TimeInBlockyVideoPercentage"));
1426 } else {
1427 EXPECT_EQ(kExpectedTimeInHdPercents,
1428 metrics::MinSample("WebRTC.Video.TimeInBlockyVideoPercentage"));
1429 }
1430}
1431
Sergey Silkin02371062019-01-31 16:45:42 +01001432TEST_P(ReceiveStatisticsProxyTestWithContent, DownscalesReported) {
Sergey Silkin278f8252019-01-09 14:37:40 +01001433 const int kInterFrameDelayMs = 2000; // To ensure long enough call duration.
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001434
Sergey Silkin278f8252019-01-09 14:37:40 +01001435 webrtc::VideoFrame frame_hd = CreateFrame(1280, 720);
1436 webrtc::VideoFrame frame_sd = CreateFrame(640, 360);
1437 webrtc::VideoFrame frame_ld = CreateFrame(320, 180);
1438
1439 // Call once to pass content type.
Sergey Silkin02371062019-01-31 16:45:42 +01001440 statistics_proxy_->OnDecodedFrame(frame_hd, absl::nullopt, content_type_);
Sergey Silkin278f8252019-01-09 14:37:40 +01001441
1442 statistics_proxy_->OnRenderedFrame(frame_hd);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001443 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1444
1445 // Downscale.
Sergey Silkin278f8252019-01-09 14:37:40 +01001446 statistics_proxy_->OnRenderedFrame(frame_sd);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001447 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1448
1449 // Downscale.
Sergey Silkin278f8252019-01-09 14:37:40 +01001450 statistics_proxy_->OnRenderedFrame(frame_ld);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001451 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1452
1453 statistics_proxy_.reset();
Sergey Silkin278f8252019-01-09 14:37:40 +01001454 const int kExpectedDownscales = 30; // 2 per 4 seconds = 30 per minute.
Sergey Silkin02371062019-01-31 16:45:42 +01001455 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001456 EXPECT_EQ(
1457 kExpectedDownscales,
1458 metrics::MinSample(
1459 "WebRTC.Video.Screenshare.NumberResolutionDownswitchesPerMinute"));
1460 } else {
1461 EXPECT_EQ(kExpectedDownscales,
1462 metrics::MinSample(
1463 "WebRTC.Video.NumberResolutionDownswitchesPerMinute"));
1464 }
1465}
1466
Sergey Silkin02371062019-01-31 16:45:42 +01001467TEST_P(ReceiveStatisticsProxyTestWithContent,
1468 StatsAreSlicedOnSimulcastAndExperiment) {
ilnik6d5b4d62017-08-30 03:32:14 -07001469 const uint8_t experiment_id = 1;
Sergey Silkin02371062019-01-31 16:45:42 +01001470 webrtc::VideoContentType content_type = content_type_;
ilnik6d5b4d62017-08-30 03:32:14 -07001471 videocontenttypehelpers::SetExperimentId(&content_type, experiment_id);
1472 const int kInterFrameDelayMs1 = 30;
1473 const int kInterFrameDelayMs2 = 50;
Sergey Silkin278f8252019-01-09 14:37:40 +01001474 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
ilnik6d5b4d62017-08-30 03:32:14 -07001475
1476 videocontenttypehelpers::SetSimulcastId(&content_type, 1);
1477 for (int i = 0; i <= kMinRequiredSamples; ++i) {
1478 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs1);
Sergey Silkin278f8252019-01-09 14:37:40 +01001479 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type);
ilnik6d5b4d62017-08-30 03:32:14 -07001480 }
1481
1482 videocontenttypehelpers::SetSimulcastId(&content_type, 2);
1483 for (int i = 0; i <= kMinRequiredSamples; ++i) {
1484 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs2);
Sergey Silkin278f8252019-01-09 14:37:40 +01001485 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type);
ilnik6d5b4d62017-08-30 03:32:14 -07001486 }
1487 statistics_proxy_.reset();
1488
1489 if (videocontenttypehelpers::IsScreenshare(content_type)) {
1490 EXPECT_EQ(
1491 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1492 EXPECT_EQ(1, metrics::NumSamples(
1493 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1494 EXPECT_EQ(1, metrics::NumSamples(
1495 "WebRTC.Video.Screenshare.InterframeDelayInMs.S0"));
1496 EXPECT_EQ(1, metrics::NumSamples(
1497 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs.S0"));
1498 EXPECT_EQ(1, metrics::NumSamples(
1499 "WebRTC.Video.Screenshare.InterframeDelayInMs.S1"));
1500 EXPECT_EQ(1, metrics::NumSamples(
1501 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs.S1"));
1502 EXPECT_EQ(1,
1503 metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"
1504 ".ExperimentGroup0"));
1505 EXPECT_EQ(
1506 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"
1507 ".ExperimentGroup0"));
1508 EXPECT_EQ(
1509 kInterFrameDelayMs1,
1510 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs.S0"));
1511 EXPECT_EQ(
1512 kInterFrameDelayMs2,
1513 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs.S1"));
1514 EXPECT_EQ(
1515 (kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1516 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1517 EXPECT_EQ(
1518 kInterFrameDelayMs2,
1519 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1520 EXPECT_EQ(
1521 (kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1522 metrics::MinSample(
1523 "WebRTC.Video.Screenshare.InterframeDelayInMs.ExperimentGroup0"));
1524 } else {
1525 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
1526 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
1527 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs.S0"));
1528 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs.S0"));
1529 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs.S1"));
1530 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs.S1"));
1531 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"
1532 ".ExperimentGroup0"));
1533 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"
1534 ".ExperimentGroup0"));
1535 EXPECT_EQ(kInterFrameDelayMs1,
1536 metrics::MinSample("WebRTC.Video.InterframeDelayInMs.S0"));
1537 EXPECT_EQ(kInterFrameDelayMs2,
1538 metrics::MinSample("WebRTC.Video.InterframeDelayInMs.S1"));
1539 EXPECT_EQ((kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1540 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
1541 EXPECT_EQ(kInterFrameDelayMs2,
1542 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
1543 EXPECT_EQ((kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1544 metrics::MinSample(
1545 "WebRTC.Video.InterframeDelayInMs.ExperimentGroup0"));
1546 }
1547}
sakale5ba44e2016-10-26 07:09:24 -07001548} // namespace webrtc