blob: e050137462cbb8842d3d8d40defba322a056b506 [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;
Niels Möllerdd41da62019-03-28 08:59:07 +0100446 for (int i = 0; i < kKeyFrames; i++) {
447 statistics_proxy_->OnCompleteFrame(true, 0, VideoContentType::UNSPECIFIED);
448 }
449 for (int i = 0; i < kDeltaFrames; i++) {
450 statistics_proxy_->OnCompleteFrame(false, 0, VideoContentType::UNSPECIFIED);
451 }
452
asapersson6966bd52017-01-03 00:44:06 -0800453 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
454 EXPECT_EQ(kKeyFrames, stats.frame_counts.key_frames);
455 EXPECT_EQ(kDeltaFrames, stats.frame_counts.delta_frames);
456}
457
asapersson6966bd52017-01-03 00:44:06 -0800458TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsRtcpStats) {
459 const uint8_t kFracLost = 0;
Harald Alvestrandc7c41912017-12-08 09:59:34 +0100460 const int32_t kCumLost = 1;
asapersson6966bd52017-01-03 00:44:06 -0800461 const uint32_t kExtSeqNum = 10;
462 const uint32_t kJitter = 4;
463
464 RtcpStatistics rtcp_stats;
465 rtcp_stats.fraction_lost = kFracLost;
srte186d9c32017-08-04 05:03:53 -0700466 rtcp_stats.packets_lost = kCumLost;
467 rtcp_stats.extended_highest_sequence_number = kExtSeqNum;
asapersson6966bd52017-01-03 00:44:06 -0800468 rtcp_stats.jitter = kJitter;
469 statistics_proxy_->StatisticsUpdated(rtcp_stats, kRemoteSsrc);
470
471 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
472 EXPECT_EQ(kFracLost, stats.rtcp_stats.fraction_lost);
srte186d9c32017-08-04 05:03:53 -0700473 EXPECT_EQ(kCumLost, stats.rtcp_stats.packets_lost);
474 EXPECT_EQ(kExtSeqNum, stats.rtcp_stats.extended_highest_sequence_number);
asapersson6966bd52017-01-03 00:44:06 -0800475 EXPECT_EQ(kJitter, stats.rtcp_stats.jitter);
476}
477
478TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsCName) {
479 const char* kName = "cName";
480 statistics_proxy_->CNameChanged(kName, kRemoteSsrc);
481 EXPECT_STREQ(kName, statistics_proxy_->GetStats().c_name.c_str());
482}
483
484TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsNoCNameForUnknownSsrc) {
485 const char* kName = "cName";
486 statistics_proxy_->CNameChanged(kName, kRemoteSsrc + 1);
487 EXPECT_STREQ("", statistics_proxy_->GetStats().c_name.c_str());
488}
489
ilnik2edc6842017-07-06 03:06:50 -0700490TEST_F(ReceiveStatisticsProxyTest,
ilnik75204c52017-09-04 03:35:40 -0700491 ReportsLongestTimingFrameInfo) {
ilnik2edc6842017-07-06 03:06:50 -0700492 const int64_t kShortEndToEndDelay = 10;
493 const int64_t kMedEndToEndDelay = 20;
494 const int64_t kLongEndToEndDelay = 100;
495 const uint32_t kExpectedRtpTimestamp = 2;
496 TimingFrameInfo info;
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200497 absl::optional<TimingFrameInfo> result;
ilnik2edc6842017-07-06 03:06:50 -0700498 info.rtp_timestamp = kExpectedRtpTimestamp - 1;
499 info.capture_time_ms = 0;
500 info.decode_finish_ms = kShortEndToEndDelay;
501 statistics_proxy_->OnTimingFrameInfoUpdated(info);
502 info.rtp_timestamp =
503 kExpectedRtpTimestamp; // this frame should be reported in the end.
504 info.capture_time_ms = 0;
505 info.decode_finish_ms = kLongEndToEndDelay;
506 statistics_proxy_->OnTimingFrameInfoUpdated(info);
507 info.rtp_timestamp = kExpectedRtpTimestamp + 1;
508 info.capture_time_ms = 0;
509 info.decode_finish_ms = kMedEndToEndDelay;
510 statistics_proxy_->OnTimingFrameInfoUpdated(info);
ilnik75204c52017-09-04 03:35:40 -0700511 result = statistics_proxy_->GetStats().timing_frame_info;
ilnik2edc6842017-07-06 03:06:50 -0700512 EXPECT_TRUE(result);
513 EXPECT_EQ(kExpectedRtpTimestamp, result->rtp_timestamp);
514}
515
ilnik75204c52017-09-04 03:35:40 -0700516TEST_F(ReceiveStatisticsProxyTest, RespectsReportingIntervalForTimingFrames) {
517 TimingFrameInfo info;
ilnik2edc6842017-07-06 03:06:50 -0700518 const int64_t kShortEndToEndDelay = 10;
519 const uint32_t kExpectedRtpTimestamp = 2;
ilnik75204c52017-09-04 03:35:40 -0700520 const int64_t kShortDelayMs = 1000;
521 const int64_t kLongDelayMs = 10000;
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200522 absl::optional<TimingFrameInfo> result;
ilnik2edc6842017-07-06 03:06:50 -0700523 info.rtp_timestamp = kExpectedRtpTimestamp;
524 info.capture_time_ms = 0;
525 info.decode_finish_ms = kShortEndToEndDelay;
526 statistics_proxy_->OnTimingFrameInfoUpdated(info);
ilnik75204c52017-09-04 03:35:40 -0700527 fake_clock_.AdvanceTimeMilliseconds(kShortDelayMs);
528 result = statistics_proxy_->GetStats().timing_frame_info;
ilnik2edc6842017-07-06 03:06:50 -0700529 EXPECT_TRUE(result);
530 EXPECT_EQ(kExpectedRtpTimestamp, result->rtp_timestamp);
ilnik75204c52017-09-04 03:35:40 -0700531 fake_clock_.AdvanceTimeMilliseconds(kLongDelayMs);
532 result = statistics_proxy_->GetStats().timing_frame_info;
ilnik2edc6842017-07-06 03:06:50 -0700533 EXPECT_FALSE(result);
534}
535
asapersson46c4e3c2016-11-03 06:48:19 -0700536TEST_F(ReceiveStatisticsProxyTest, LifetimeHistogramIsUpdated) {
537 const int64_t kTimeSec = 3;
538 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
ilnik6d5b4d62017-08-30 03:32:14 -0700539 // Need at least one frame to report stream lifetime.
540 statistics_proxy_->OnCompleteFrame(true, 1000, VideoContentType::UNSPECIFIED);
asapersson46c4e3c2016-11-03 06:48:19 -0700541 // Histograms are updated when the statistics_proxy_ is deleted.
542 statistics_proxy_.reset();
543 EXPECT_EQ(1,
544 metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
545 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceiveStreamLifetimeInSeconds",
546 kTimeSec));
547}
548
ilnik6d5b4d62017-08-30 03:32:14 -0700549TEST_F(ReceiveStatisticsProxyTest,
550 LifetimeHistogramNotReportedForEmptyStreams) {
551 const int64_t kTimeSec = 3;
552 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
553 // No frames received.
554 // Histograms are updated when the statistics_proxy_ is deleted.
555 statistics_proxy_.reset();
556 EXPECT_EQ(0,
557 metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
558}
559
palmkvista40672a2017-01-13 05:58:34 -0800560TEST_F(ReceiveStatisticsProxyTest, BadCallHistogramsAreUpdated) {
561 // Based on the tuning parameters this will produce 7 uncertain states,
562 // then 10 certainly bad states. There has to be 10 certain states before
563 // any histograms are recorded.
564 const int kNumBadSamples = 17;
Niels Möller9b0b1e02019-03-22 13:56:46 +0100565 // We only count one sample per second.
566 const int kBadFameIntervalMs = 1100;
palmkvista40672a2017-01-13 05:58:34 -0800567
568 StreamDataCounters counters;
569 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
570 statistics_proxy_->DataCountersUpdated(counters, config_.rtp.remote_ssrc);
571
Niels Möller9b0b1e02019-03-22 13:56:46 +0100572 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
573
palmkvista40672a2017-01-13 05:58:34 -0800574 for (int i = 0; i < kNumBadSamples; ++i) {
Niels Möller9b0b1e02019-03-22 13:56:46 +0100575 fake_clock_.AdvanceTimeMilliseconds(kBadFameIntervalMs);
576 statistics_proxy_->OnRenderedFrame(frame);
palmkvista40672a2017-01-13 05:58:34 -0800577 }
578 // Histograms are updated when the statistics_proxy_ is deleted.
579 statistics_proxy_.reset();
580 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BadCall.Any"));
581 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BadCall.Any", 100));
582
583 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BadCall.FrameRate"));
584 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BadCall.FrameRate", 100));
585
586 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.BadCall.FrameRateVariance"));
587
588 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.BadCall.Qp"));
589}
590
asapersson0c43f772016-11-30 01:42:26 -0800591TEST_F(ReceiveStatisticsProxyTest, PacketLossHistogramIsUpdated) {
592 const uint32_t kCumLost1 = 1;
593 const uint32_t kExtSeqNum1 = 10;
594 const uint32_t kCumLost2 = 2;
595 const uint32_t kExtSeqNum2 = 20;
596
597 // One report block received.
598 RtcpStatistics rtcp_stats1;
srte186d9c32017-08-04 05:03:53 -0700599 rtcp_stats1.packets_lost = kCumLost1;
600 rtcp_stats1.extended_highest_sequence_number = kExtSeqNum1;
asapersson0c43f772016-11-30 01:42:26 -0800601 statistics_proxy_->StatisticsUpdated(rtcp_stats1, kRemoteSsrc);
602
603 // Two report blocks received.
604 RtcpStatistics rtcp_stats2;
srte186d9c32017-08-04 05:03:53 -0700605 rtcp_stats2.packets_lost = kCumLost2;
606 rtcp_stats2.extended_highest_sequence_number = kExtSeqNum2;
asapersson0c43f772016-11-30 01:42:26 -0800607 statistics_proxy_->StatisticsUpdated(rtcp_stats2, kRemoteSsrc);
608
609 // Two received report blocks but min run time has not passed.
610 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
611 SetUp(); // Reset stat proxy causes histograms to be updated.
612 EXPECT_EQ(0,
613 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
614
615 // Two report blocks received.
616 statistics_proxy_->StatisticsUpdated(rtcp_stats1, kRemoteSsrc);
617 statistics_proxy_->StatisticsUpdated(rtcp_stats2, kRemoteSsrc);
618
619 // Two received report blocks and min run time has passed.
620 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
621 SetUp();
622 EXPECT_EQ(1,
623 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
624 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceivedPacketsLostInPercent",
625 (kCumLost2 - kCumLost1) * 100 /
626 (kExtSeqNum2 - kExtSeqNum1)));
627}
628
629TEST_F(ReceiveStatisticsProxyTest,
630 PacketLossHistogramIsNotUpdatedIfLessThanTwoReportBlocksAreReceived) {
631 RtcpStatistics rtcp_stats1;
srte186d9c32017-08-04 05:03:53 -0700632 rtcp_stats1.packets_lost = 1;
633 rtcp_stats1.extended_highest_sequence_number = 10;
asapersson0c43f772016-11-30 01:42:26 -0800634
635 // Min run time has passed but no received report block.
636 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
637 SetUp(); // Reset stat proxy causes histograms to be updated.
638 EXPECT_EQ(0,
639 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
640
641 // Min run time has passed but only one received report block.
642 statistics_proxy_->StatisticsUpdated(rtcp_stats1, kRemoteSsrc);
643 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
644 SetUp();
645 EXPECT_EQ(0,
646 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
647}
648
asapersson2077f2f2017-05-11 05:37:35 -0700649TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsAvSyncOffset) {
650 const int64_t kSyncOffsetMs = 22;
651 const double kFreqKhz = 90.0;
652 EXPECT_EQ(std::numeric_limits<int>::max(),
653 statistics_proxy_->GetStats().sync_offset_ms);
654 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
655 EXPECT_EQ(kSyncOffsetMs, statistics_proxy_->GetStats().sync_offset_ms);
656}
657
asapersson46c4e3c2016-11-03 06:48:19 -0700658TEST_F(ReceiveStatisticsProxyTest, AvSyncOffsetHistogramIsUpdated) {
659 const int64_t kSyncOffsetMs = 22;
660 const double kFreqKhz = 90.0;
661 for (int i = 0; i < kMinRequiredSamples; ++i)
662 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
663 // Histograms are updated when the statistics_proxy_ is deleted.
664 statistics_proxy_.reset();
665 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AVSyncOffsetInMs"));
666 EXPECT_EQ(1,
667 metrics::NumEvents("WebRTC.Video.AVSyncOffsetInMs", kSyncOffsetMs));
668}
669
asaperssonde9e5ff2016-11-02 07:14:03 -0700670TEST_F(ReceiveStatisticsProxyTest, RtpToNtpFrequencyOffsetHistogramIsUpdated) {
671 const int64_t kSyncOffsetMs = 22;
672 const double kFreqKhz = 90.0;
673 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
674 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz + 2.2);
675 fake_clock_.AdvanceTimeMilliseconds(kFreqOffsetProcessIntervalInMs);
676 // Process interval passed, max diff: 2.
677 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz + 1.1);
678 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz - 4.2);
679 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz - 0.9);
680 fake_clock_.AdvanceTimeMilliseconds(kFreqOffsetProcessIntervalInMs);
681 // Process interval passed, max diff: 4.
682 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
683 statistics_proxy_.reset();
684 // Average reported: (2 + 4) / 2 = 3.
685 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtpToNtpFreqOffsetInKhz"));
686 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtpToNtpFreqOffsetInKhz", 3));
687}
688
asapersson6966bd52017-01-03 00:44:06 -0800689TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsUpdated) {
690 const int kQp = 22;
asapersson6966bd52017-01-03 00:44:06 -0800691
692 for (int i = 0; i < kMinRequiredSamples; ++i)
Niels Möller147013a2018-10-01 15:56:33 +0200693 statistics_proxy_->OnPreDecode(kVideoCodecVP8, kQp);
asapersson6966bd52017-01-03 00:44:06 -0800694
695 statistics_proxy_.reset();
696 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
697 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Decoded.Vp8.Qp", kQp));
698}
699
700TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsNotUpdatedForTooFewSamples) {
Niels Möller147013a2018-10-01 15:56:33 +0200701 const int kQp = 22;
asapersson6966bd52017-01-03 00:44:06 -0800702
703 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
Niels Möller147013a2018-10-01 15:56:33 +0200704 statistics_proxy_->OnPreDecode(kVideoCodecVP8, kQp);
asapersson6966bd52017-01-03 00:44:06 -0800705
706 statistics_proxy_.reset();
707 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
708}
709
710TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsNotUpdatedIfNoQpValue) {
asapersson6966bd52017-01-03 00:44:06 -0800711 for (int i = 0; i < kMinRequiredSamples; ++i)
Niels Möller147013a2018-10-01 15:56:33 +0200712 statistics_proxy_->OnPreDecode(kVideoCodecVP8, -1);
asapersson6966bd52017-01-03 00:44:06 -0800713
714 statistics_proxy_.reset();
715 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
716}
717
asaperssonb99baf82017-04-20 04:05:43 -0700718TEST_F(ReceiveStatisticsProxyTest,
719 KeyFrameHistogramNotUpdatedForTooFewSamples) {
720 const bool kIsKeyFrame = false;
721 const int kFrameSizeBytes = 1000;
722
723 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
ilnik6d5b4d62017-08-30 03:32:14 -0700724 statistics_proxy_->OnCompleteFrame(kIsKeyFrame, kFrameSizeBytes,
725 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 04:05:43 -0700726
727 EXPECT_EQ(0, statistics_proxy_->GetStats().frame_counts.key_frames);
728 EXPECT_EQ(kMinRequiredSamples - 1,
729 statistics_proxy_->GetStats().frame_counts.delta_frames);
730
731 statistics_proxy_.reset();
732 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
733}
734
735TEST_F(ReceiveStatisticsProxyTest,
736 KeyFrameHistogramUpdatedForMinRequiredSamples) {
737 const bool kIsKeyFrame = false;
738 const int kFrameSizeBytes = 1000;
739
740 for (int i = 0; i < kMinRequiredSamples; ++i)
ilnik6d5b4d62017-08-30 03:32:14 -0700741 statistics_proxy_->OnCompleteFrame(kIsKeyFrame, kFrameSizeBytes,
742 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 04:05:43 -0700743
744 EXPECT_EQ(0, statistics_proxy_->GetStats().frame_counts.key_frames);
745 EXPECT_EQ(kMinRequiredSamples,
746 statistics_proxy_->GetStats().frame_counts.delta_frames);
747
748 statistics_proxy_.reset();
749 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
750 EXPECT_EQ(1,
751 metrics::NumEvents("WebRTC.Video.KeyFramesReceivedInPermille", 0));
752}
753
754TEST_F(ReceiveStatisticsProxyTest, KeyFrameHistogramIsUpdated) {
755 const int kFrameSizeBytes = 1000;
756
757 for (int i = 0; i < kMinRequiredSamples; ++i)
ilnik6d5b4d62017-08-30 03:32:14 -0700758 statistics_proxy_->OnCompleteFrame(true, kFrameSizeBytes,
759 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 04:05:43 -0700760
761 for (int i = 0; i < kMinRequiredSamples; ++i)
ilnik6d5b4d62017-08-30 03:32:14 -0700762 statistics_proxy_->OnCompleteFrame(false, kFrameSizeBytes,
763 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 04:05:43 -0700764
765 EXPECT_EQ(kMinRequiredSamples,
766 statistics_proxy_->GetStats().frame_counts.key_frames);
767 EXPECT_EQ(kMinRequiredSamples,
768 statistics_proxy_->GetStats().frame_counts.delta_frames);
769
770 statistics_proxy_.reset();
771 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
772 EXPECT_EQ(
773 1, metrics::NumEvents("WebRTC.Video.KeyFramesReceivedInPermille", 500));
774}
775
776TEST_F(ReceiveStatisticsProxyTest, TimingHistogramsNotUpdatedForTooFewSamples) {
777 const int kDecodeMs = 1;
778 const int kMaxDecodeMs = 2;
779 const int kCurrentDelayMs = 3;
780 const int kTargetDelayMs = 4;
781 const int kJitterBufferMs = 5;
782 const int kMinPlayoutDelayMs = 6;
783 const int kRenderDelayMs = 7;
784
785 for (int i = 0; i < kMinRequiredSamples - 1; ++i) {
786 statistics_proxy_->OnFrameBufferTimingsUpdated(
787 kDecodeMs, kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs,
788 kJitterBufferMs, kMinPlayoutDelayMs, kRenderDelayMs);
789 }
790
791 statistics_proxy_.reset();
792 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
793 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
794 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
795 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
796 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
797}
798
799TEST_F(ReceiveStatisticsProxyTest, TimingHistogramsAreUpdated) {
800 const int kDecodeMs = 1;
801 const int kMaxDecodeMs = 2;
802 const int kCurrentDelayMs = 3;
803 const int kTargetDelayMs = 4;
804 const int kJitterBufferMs = 5;
805 const int kMinPlayoutDelayMs = 6;
806 const int kRenderDelayMs = 7;
807
808 for (int i = 0; i < kMinRequiredSamples; ++i) {
809 statistics_proxy_->OnFrameBufferTimingsUpdated(
810 kDecodeMs, kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs,
811 kJitterBufferMs, kMinPlayoutDelayMs, kRenderDelayMs);
812 }
813
814 statistics_proxy_.reset();
815 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
816 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
817 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
818 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
819 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
820
821 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DecodeTimeInMs", kDecodeMs));
822 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.JitterBufferDelayInMs",
823 kJitterBufferMs));
824 EXPECT_EQ(1,
825 metrics::NumEvents("WebRTC.Video.TargetDelayInMs", kTargetDelayMs));
826 EXPECT_EQ(
827 1, metrics::NumEvents("WebRTC.Video.CurrentDelayInMs", kCurrentDelayMs));
828 EXPECT_EQ(1,
829 metrics::NumEvents("WebRTC.Video.OnewayDelayInMs", kTargetDelayMs));
830}
831
sprang948b2752017-05-04 02:47:13 -0700832TEST_F(ReceiveStatisticsProxyTest, DoesNotReportStaleFramerates) {
833 const int kDefaultFps = 30;
Sergey Silkin278f8252019-01-09 14:37:40 +0100834 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
sprang948b2752017-05-04 02:47:13 -0700835
836 for (int i = 0; i < kDefaultFps; ++i) {
837 // Since OnRenderedFrame is never called the fps in each sample will be 0,
838 // i.e. bad
839 frame.set_ntp_time_ms(fake_clock_.CurrentNtpInMilliseconds());
Sergey Silkin278f8252019-01-09 14:37:40 +0100840 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
sprang948b2752017-05-04 02:47:13 -0700841 VideoContentType::UNSPECIFIED);
842 statistics_proxy_->OnRenderedFrame(frame);
843 fake_clock_.AdvanceTimeMilliseconds(1000 / kDefaultFps);
844 }
845
846 EXPECT_EQ(kDefaultFps, statistics_proxy_->GetStats().decode_frame_rate);
847 EXPECT_EQ(kDefaultFps, statistics_proxy_->GetStats().render_frame_rate);
848
849 // FPS trackers in stats proxy have a 1000ms sliding window.
850 fake_clock_.AdvanceTimeMilliseconds(1000);
851 EXPECT_EQ(0, statistics_proxy_->GetStats().decode_frame_rate);
852 EXPECT_EQ(0, statistics_proxy_->GetStats().render_frame_rate);
853}
854
asapersson2077f2f2017-05-11 05:37:35 -0700855TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsReceivedFrameStats) {
asapersson2077f2f2017-05-11 05:37:35 -0700856 EXPECT_EQ(0, statistics_proxy_->GetStats().width);
857 EXPECT_EQ(0, statistics_proxy_->GetStats().height);
858 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_rendered);
859
860 statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight));
861
862 EXPECT_EQ(kWidth, statistics_proxy_->GetStats().width);
863 EXPECT_EQ(kHeight, statistics_proxy_->GetStats().height);
864 EXPECT_EQ(1u, statistics_proxy_->GetStats().frames_rendered);
865}
866
867TEST_F(ReceiveStatisticsProxyTest,
868 ReceivedFrameHistogramsAreNotUpdatedForTooFewSamples) {
asapersson2077f2f2017-05-11 05:37:35 -0700869 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
870 statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight));
871
872 statistics_proxy_.reset();
873 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
874 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
875 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
876 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
877}
878
879TEST_F(ReceiveStatisticsProxyTest, ReceivedFrameHistogramsAreUpdated) {
asapersson2077f2f2017-05-11 05:37:35 -0700880 for (int i = 0; i < kMinRequiredSamples; ++i)
881 statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight));
882
883 statistics_proxy_.reset();
884 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
885 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
886 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
887 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
888 EXPECT_EQ(1,
889 metrics::NumEvents("WebRTC.Video.ReceivedWidthInPixels", kWidth));
890 EXPECT_EQ(1,
891 metrics::NumEvents("WebRTC.Video.ReceivedHeightInPixels", kHeight));
892}
893
Åsa Persson81327d52018-06-05 13:34:33 +0200894TEST_F(ReceiveStatisticsProxyTest, ZeroDelayReportedIfFrameNotDelayed) {
Sergey Silkin278f8252019-01-09 14:37:40 +0100895 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
896 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
Åsa Persson81327d52018-06-05 13:34:33 +0200897 VideoContentType::UNSPECIFIED);
898
899 // Frame not delayed, delayed frames to render: 0%.
900 const int64_t kNowMs = fake_clock_.TimeInMilliseconds();
901 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs));
902
903 // Min run time has passed.
904 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
905 statistics_proxy_.reset();
906 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
907 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 0));
908 EXPECT_EQ(0, metrics::NumSamples(
909 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
910}
911
912TEST_F(ReceiveStatisticsProxyTest,
913 DelayedFrameHistogramsAreNotUpdatedIfMinRuntimeHasNotPassed) {
Sergey Silkin278f8252019-01-09 14:37:40 +0100914 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
915 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
Åsa Persson81327d52018-06-05 13:34:33 +0200916 VideoContentType::UNSPECIFIED);
917
918 // Frame not delayed, delayed frames to render: 0%.
919 const int64_t kNowMs = fake_clock_.TimeInMilliseconds();
920 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs));
921
922 // Min run time has not passed.
923 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000) -
924 1);
925 statistics_proxy_.reset();
926 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
927 EXPECT_EQ(0, metrics::NumSamples(
928 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
929}
930
931TEST_F(ReceiveStatisticsProxyTest,
932 DelayedFramesHistogramsAreNotUpdatedIfNoRenderedFrames) {
Sergey Silkin278f8252019-01-09 14:37:40 +0100933 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
934 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
Åsa Persson81327d52018-06-05 13:34:33 +0200935 VideoContentType::UNSPECIFIED);
936
937 // Min run time has passed. No rendered frames.
938 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
939 statistics_proxy_.reset();
940 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
941 EXPECT_EQ(0, metrics::NumSamples(
942 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
943}
944
945TEST_F(ReceiveStatisticsProxyTest, DelayReportedIfFrameIsDelayed) {
Sergey Silkin278f8252019-01-09 14:37:40 +0100946 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
947 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
Åsa Persson81327d52018-06-05 13:34:33 +0200948 VideoContentType::UNSPECIFIED);
949
950 // Frame delayed 1 ms, delayed frames to render: 100%.
951 const int64_t kNowMs = fake_clock_.TimeInMilliseconds();
952 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs - 1));
953
954 // Min run time has passed.
955 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
956 statistics_proxy_.reset();
957 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
958 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 100));
959 EXPECT_EQ(1, metrics::NumSamples(
960 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
961 EXPECT_EQ(1, metrics::NumEvents(
962 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs", 1));
963}
964
965TEST_F(ReceiveStatisticsProxyTest, AverageDelayOfDelayedFramesIsReported) {
Sergey Silkin278f8252019-01-09 14:37:40 +0100966 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
967 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
Åsa Persson81327d52018-06-05 13:34:33 +0200968 VideoContentType::UNSPECIFIED);
969
970 // Two frames delayed (6 ms, 10 ms), delayed frames to render: 50%.
971 const int64_t kNowMs = fake_clock_.TimeInMilliseconds();
972 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs - 10));
973 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs - 6));
974 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs));
975 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs + 1));
976
977 // Min run time has passed.
978 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
979 statistics_proxy_.reset();
980 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
981 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 50));
982 EXPECT_EQ(1, metrics::NumSamples(
983 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
984 EXPECT_EQ(1, metrics::NumEvents(
985 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs", 8));
986}
987
asapersson2077f2f2017-05-11 05:37:35 -0700988TEST_F(ReceiveStatisticsProxyTest,
989 RtcpHistogramsNotUpdatedIfMinRuntimeHasNotPassed) {
990 InsertFirstRtpPacket(kRemoteSsrc);
991 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000) -
992 1);
993
994 RtcpPacketTypeCounter counter;
995 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
996
997 statistics_proxy_.reset();
998 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
999 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
1000 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
1001}
1002
1003TEST_F(ReceiveStatisticsProxyTest, RtcpHistogramsAreUpdated) {
1004 InsertFirstRtpPacket(kRemoteSsrc);
1005 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1006
1007 const uint32_t kFirPackets = 100;
1008 const uint32_t kPliPackets = 200;
1009 const uint32_t kNackPackets = 300;
1010
1011 RtcpPacketTypeCounter counter;
1012 counter.fir_packets = kFirPackets;
1013 counter.pli_packets = kPliPackets;
1014 counter.nack_packets = kNackPackets;
1015 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
1016
1017 statistics_proxy_.reset();
1018 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
1019 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
1020 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
1021 EXPECT_EQ(
1022 1, metrics::NumEvents("WebRTC.Video.FirPacketsSentPerMinute",
1023 kFirPackets * 60 / metrics::kMinRunTimeInSeconds));
1024 EXPECT_EQ(
1025 1, metrics::NumEvents("WebRTC.Video.PliPacketsSentPerMinute",
1026 kPliPackets * 60 / metrics::kMinRunTimeInSeconds));
1027 EXPECT_EQ(
1028 1, metrics::NumEvents("WebRTC.Video.NackPacketsSentPerMinute",
1029 kNackPackets * 60 / metrics::kMinRunTimeInSeconds));
1030}
1031
Sergey Silkin02371062019-01-31 16:45:42 +01001032class ReceiveStatisticsProxyTestWithFreezeDuration
1033 : public ReceiveStatisticsProxyTest,
1034 public testing::WithParamInterface<
1035 std::tuple<uint32_t, uint32_t, uint32_t>> {
1036 protected:
1037 const uint32_t frame_duration_ms_ = {std::get<0>(GetParam())};
1038 const uint32_t freeze_duration_ms_ = {std::get<1>(GetParam())};
1039 const uint32_t expected_freeze_count_ = {std::get<2>(GetParam())};
1040};
sprang892dab52017-08-15 05:00:33 -07001041
Sergey Silkin02371062019-01-31 16:45:42 +01001042// It is a freeze if:
1043// frame_duration_ms >= max(3 * avg_frame_duration, avg_frame_duration + 150)
1044// where avg_frame_duration is average duration of last 30 frames including
1045// the current one.
1046//
1047// Condition 1: 3 * avg_frame_duration > avg_frame_duration + 150
1048const auto kFreezeDetectionCond1Freeze = std::make_tuple(150, 483, 1);
1049const auto kFreezeDetectionCond1NotFreeze = std::make_tuple(150, 482, 0);
1050// Condition 2: 3 * avg_frame_duration < avg_frame_duration + 150
1051const auto kFreezeDetectionCond2Freeze = std::make_tuple(30, 185, 1);
1052const auto kFreezeDetectionCond2NotFreeze = std::make_tuple(30, 184, 0);
1053
Mirko Bonadei12d12852019-02-05 17:04:04 +01001054INSTANTIATE_TEST_SUITE_P(_,
1055 ReceiveStatisticsProxyTestWithFreezeDuration,
1056 ::testing::Values(kFreezeDetectionCond1Freeze,
1057 kFreezeDetectionCond1NotFreeze,
1058 kFreezeDetectionCond2Freeze,
1059 kFreezeDetectionCond2NotFreeze));
Sergey Silkin02371062019-01-31 16:45:42 +01001060
1061TEST_P(ReceiveStatisticsProxyTestWithFreezeDuration, FreezeDetection) {
1062 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
1063 EXPECT_EQ(0u, stats.freeze_count);
1064 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1065
1066 // Add a very long frame. This is need to verify that average frame
1067 // duration, which is supposed to be calculated as mean of durations of
1068 // last 30 frames, is calculated correctly.
1069 statistics_proxy_->OnRenderedFrame(frame);
1070 fake_clock_.AdvanceTimeMilliseconds(2000);
1071
1072 for (size_t i = 0;
1073 i <= VideoQualityObserver::kAvgInterframeDelaysWindowSizeFrames; ++i) {
1074 fake_clock_.AdvanceTimeMilliseconds(frame_duration_ms_);
1075 statistics_proxy_->OnRenderedFrame(frame);
1076 }
1077
1078 fake_clock_.AdvanceTimeMilliseconds(freeze_duration_ms_);
1079 statistics_proxy_->OnRenderedFrame(frame);
1080
1081 stats = statistics_proxy_->GetStats();
1082 EXPECT_EQ(stats.freeze_count, expected_freeze_count_);
1083}
1084
1085class ReceiveStatisticsProxyTestWithContent
1086 : public ReceiveStatisticsProxyTest,
1087 public ::testing::WithParamInterface<webrtc::VideoContentType> {
1088 protected:
1089 const webrtc::VideoContentType content_type_{GetParam()};
1090};
1091
Mirko Bonadei12d12852019-02-05 17:04:04 +01001092INSTANTIATE_TEST_SUITE_P(ContentTypes,
1093 ReceiveStatisticsProxyTestWithContent,
1094 ::testing::Values(VideoContentType::UNSPECIFIED,
1095 VideoContentType::SCREENSHARE));
Sergey Silkin02371062019-01-31 16:45:42 +01001096
1097TEST_P(ReceiveStatisticsProxyTestWithContent, InterFrameDelaysAreReported) {
sprang892dab52017-08-15 05:00:33 -07001098 const int kInterFrameDelayMs = 33;
Sergey Silkin278f8252019-01-09 14:37:40 +01001099 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1100
sprang892dab52017-08-15 05:00:33 -07001101 for (int i = 0; i < kMinRequiredSamples; ++i) {
Sergey Silkin02371062019-01-31 16:45:42 +01001102 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
sprang892dab52017-08-15 05:00:33 -07001103 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1104 }
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001105 // One extra with double the interval.
sprang892dab52017-08-15 05:00:33 -07001106 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
Sergey Silkin02371062019-01-31 16:45:42 +01001107 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
sprang892dab52017-08-15 05:00:33 -07001108
1109 statistics_proxy_.reset();
1110 const int kExpectedInterFrame =
1111 (kInterFrameDelayMs * (kMinRequiredSamples - 1) +
1112 kInterFrameDelayMs * 2) /
1113 kMinRequiredSamples;
Sergey Silkin02371062019-01-31 16:45:42 +01001114 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
ilnik6d5b4d62017-08-30 03:32:14 -07001115 EXPECT_EQ(
1116 kExpectedInterFrame,
1117 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1118 EXPECT_EQ(
1119 kInterFrameDelayMs * 2,
1120 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1121 } else {
1122 EXPECT_EQ(kExpectedInterFrame,
1123 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
1124 EXPECT_EQ(kInterFrameDelayMs * 2,
1125 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
sprang892dab52017-08-15 05:00:33 -07001126 }
1127}
1128
Sergey Silkin02371062019-01-31 16:45:42 +01001129TEST_P(ReceiveStatisticsProxyTestWithContent,
1130 InterFrameDelaysPercentilesAreReported) {
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001131 const int kInterFrameDelayMs = 33;
1132 const int kLastFivePercentsSamples = kMinRequiredSamples * 5 / 100;
Sergey Silkin278f8252019-01-09 14:37:40 +01001133 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1134
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001135 for (int i = 0; i <= kMinRequiredSamples - kLastFivePercentsSamples; ++i) {
1136 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
Sergey Silkin02371062019-01-31 16:45:42 +01001137 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001138 }
1139 // Last 5% of intervals are double in size.
1140 for (int i = 0; i < kLastFivePercentsSamples; ++i) {
1141 fake_clock_.AdvanceTimeMilliseconds(2 * kInterFrameDelayMs);
Sergey Silkin02371062019-01-31 16:45:42 +01001142 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001143 }
1144 // Final sample is outlier and 10 times as big.
1145 fake_clock_.AdvanceTimeMilliseconds(10 * kInterFrameDelayMs);
Sergey Silkin02371062019-01-31 16:45:42 +01001146 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001147
1148 statistics_proxy_.reset();
1149 const int kExpectedInterFrame = kInterFrameDelayMs * 2;
Sergey Silkin02371062019-01-31 16:45:42 +01001150 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001151 EXPECT_EQ(kExpectedInterFrame,
1152 metrics::MinSample(
1153 "WebRTC.Video.Screenshare.InterframeDelay95PercentileInMs"));
1154 } else {
1155 EXPECT_EQ(
1156 kExpectedInterFrame,
1157 metrics::MinSample("WebRTC.Video.InterframeDelay95PercentileInMs"));
1158 }
1159}
1160
Sergey Silkin02371062019-01-31 16:45:42 +01001161TEST_P(ReceiveStatisticsProxyTestWithContent,
1162 MaxInterFrameDelayOnlyWithValidAverage) {
sprang892dab52017-08-15 05:00:33 -07001163 const int kInterFrameDelayMs = 33;
Sergey Silkin278f8252019-01-09 14:37:40 +01001164 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1165
sprang892dab52017-08-15 05:00:33 -07001166 for (int i = 0; i < kMinRequiredSamples; ++i) {
Sergey Silkin02371062019-01-31 16:45:42 +01001167 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
sprang892dab52017-08-15 05:00:33 -07001168 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1169 }
1170
1171 // |kMinRequiredSamples| samples, and thereby intervals, is required. That
1172 // means we're one frame short of having a valid data set.
1173 statistics_proxy_.reset();
1174 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
1175 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
1176 EXPECT_EQ(
1177 0, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1178 EXPECT_EQ(0, metrics::NumSamples(
1179 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1180}
1181
Sergey Silkin02371062019-01-31 16:45:42 +01001182TEST_P(ReceiveStatisticsProxyTestWithContent, MaxInterFrameDelayOnlyWithPause) {
sprang3e86e7e2017-08-22 09:23:28 -07001183 const int kInterFrameDelayMs = 33;
Sergey Silkin278f8252019-01-09 14:37:40 +01001184 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1185
sprang3e86e7e2017-08-22 09:23:28 -07001186 for (int i = 0; i <= kMinRequiredSamples; ++i) {
Sergey Silkin02371062019-01-31 16:45:42 +01001187 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
sprang3e86e7e2017-08-22 09:23:28 -07001188 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1189 }
1190
1191 // At this state, we should have a valid inter-frame delay.
1192 // Indicate stream paused and make a large jump in time.
1193 statistics_proxy_->OnStreamInactive();
1194 fake_clock_.AdvanceTimeMilliseconds(5000);
1195
1196 // Insert two more frames. The interval during the pause should be disregarded
1197 // in the stats.
Sergey Silkin02371062019-01-31 16:45:42 +01001198 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
sprang3e86e7e2017-08-22 09:23:28 -07001199 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
Sergey Silkin02371062019-01-31 16:45:42 +01001200 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
sprang3e86e7e2017-08-22 09:23:28 -07001201
1202 statistics_proxy_.reset();
Sergey Silkin02371062019-01-31 16:45:42 +01001203 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
sprang3e86e7e2017-08-22 09:23:28 -07001204 EXPECT_EQ(
1205 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1206 EXPECT_EQ(1, metrics::NumSamples(
1207 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1208 EXPECT_EQ(
1209 kInterFrameDelayMs,
1210 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1211 EXPECT_EQ(
1212 kInterFrameDelayMs,
1213 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1214 } else {
1215 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
1216 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
1217 EXPECT_EQ(kInterFrameDelayMs,
1218 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
1219 EXPECT_EQ(kInterFrameDelayMs,
1220 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
1221 }
1222}
1223
Sergey Silkin02371062019-01-31 16:45:42 +01001224TEST_P(ReceiveStatisticsProxyTestWithContent, FreezesAreReported) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001225 const int kInterFrameDelayMs = 33;
1226 const int kFreezeDelayMs = 200;
Sergey Silkinbea18ca2018-10-02 16:22:46 +02001227 const int kCallDurationMs =
1228 kMinRequiredSamples * kInterFrameDelayMs + kFreezeDelayMs;
Sergey Silkin278f8252019-01-09 14:37:40 +01001229 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1230
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001231 for (int i = 0; i < kMinRequiredSamples; ++i) {
Sergey Silkin02371062019-01-31 16:45:42 +01001232 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
Ilya Nikolaevskiycdc959f2018-10-10 13:15:09 +02001233 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001234 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1235 }
1236 // Add extra freeze.
1237 fake_clock_.AdvanceTimeMilliseconds(kFreezeDelayMs);
Sergey Silkin02371062019-01-31 16:45:42 +01001238 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
Ilya Nikolaevskiycdc959f2018-10-10 13:15:09 +02001239 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001240
1241 statistics_proxy_.reset();
1242 const int kExpectedTimeBetweenFreezes =
1243 kInterFrameDelayMs * (kMinRequiredSamples - 1);
Sergey Silkinbea18ca2018-10-02 16:22:46 +02001244 const int kExpectedNumberFreezesPerMinute = 60 * 1000 / kCallDurationMs;
Sergey Silkin02371062019-01-31 16:45:42 +01001245 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001246 EXPECT_EQ(
1247 kFreezeDelayMs + kInterFrameDelayMs,
1248 metrics::MinSample("WebRTC.Video.Screenshare.MeanFreezeDurationMs"));
1249 EXPECT_EQ(kExpectedTimeBetweenFreezes,
1250 metrics::MinSample(
1251 "WebRTC.Video.Screenshare.MeanTimeBetweenFreezesMs"));
Sergey Silkinbea18ca2018-10-02 16:22:46 +02001252 EXPECT_EQ(
1253 kExpectedNumberFreezesPerMinute,
1254 metrics::MinSample("WebRTC.Video.Screenshare.NumberFreezesPerMinute"));
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001255 } else {
1256 EXPECT_EQ(kFreezeDelayMs + kInterFrameDelayMs,
1257 metrics::MinSample("WebRTC.Video.MeanFreezeDurationMs"));
1258 EXPECT_EQ(kExpectedTimeBetweenFreezes,
1259 metrics::MinSample("WebRTC.Video.MeanTimeBetweenFreezesMs"));
Sergey Silkinbea18ca2018-10-02 16:22:46 +02001260 EXPECT_EQ(kExpectedNumberFreezesPerMinute,
1261 metrics::MinSample("WebRTC.Video.NumberFreezesPerMinute"));
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001262 }
1263}
1264
Sergey Silkin02371062019-01-31 16:45:42 +01001265TEST_P(ReceiveStatisticsProxyTestWithContent, HarmonicFrameRateIsReported) {
Sergey Silkin50e77452019-01-16 13:41:46 +01001266 const int kInterFrameDelayMs = 33;
1267 const int kFreezeDelayMs = 200;
1268 const int kCallDurationMs =
1269 kMinRequiredSamples * kInterFrameDelayMs + kFreezeDelayMs;
1270 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1271
1272 for (int i = 0; i < kMinRequiredSamples; ++i) {
1273 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
Sergey Silkin02371062019-01-31 16:45:42 +01001274 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
Sergey Silkin50e77452019-01-16 13:41:46 +01001275 statistics_proxy_->OnRenderedFrame(frame);
1276 }
1277 // Add extra freeze.
1278 fake_clock_.AdvanceTimeMilliseconds(kFreezeDelayMs);
Sergey Silkin02371062019-01-31 16:45:42 +01001279 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
Sergey Silkin50e77452019-01-16 13:41:46 +01001280 statistics_proxy_->OnRenderedFrame(frame);
1281
1282 statistics_proxy_.reset();
1283 double kSumSquaredInterframeDelaysSecs =
1284 (kMinRequiredSamples - 1) *
1285 (kInterFrameDelayMs / 1000.0 * kInterFrameDelayMs / 1000.0);
1286 kSumSquaredInterframeDelaysSecs +=
1287 kFreezeDelayMs / 1000.0 * kFreezeDelayMs / 1000.0;
1288 const int kExpectedHarmonicFrameRateFps =
1289 std::round(kCallDurationMs / (1000 * kSumSquaredInterframeDelaysSecs));
Sergey Silkin02371062019-01-31 16:45:42 +01001290 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Sergey Silkin50e77452019-01-16 13:41:46 +01001291 EXPECT_EQ(kExpectedHarmonicFrameRateFps,
1292 metrics::MinSample("WebRTC.Video.Screenshare.HarmonicFrameRate"));
1293 } else {
1294 EXPECT_EQ(kExpectedHarmonicFrameRateFps,
1295 metrics::MinSample("WebRTC.Video.HarmonicFrameRate"));
1296 }
1297}
1298
Sergey Silkin02371062019-01-31 16:45:42 +01001299TEST_P(ReceiveStatisticsProxyTestWithContent, PausesAreIgnored) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001300 const int kInterFrameDelayMs = 33;
1301 const int kPauseDurationMs = 10000;
Sergey Silkin278f8252019-01-09 14:37:40 +01001302 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1303
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001304 for (int i = 0; i <= kMinRequiredSamples; ++i) {
Sergey Silkin02371062019-01-31 16:45:42 +01001305 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
Ilya Nikolaevskiycdc959f2018-10-10 13:15:09 +02001306 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001307 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1308 }
1309 // Add a pause.
1310 fake_clock_.AdvanceTimeMilliseconds(kPauseDurationMs);
1311 statistics_proxy_->OnStreamInactive();
1312
1313 // Second playback interval with triple the length.
1314 for (int i = 0; i <= kMinRequiredSamples * 3; ++i) {
Sergey Silkin02371062019-01-31 16:45:42 +01001315 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
Ilya Nikolaevskiycdc959f2018-10-10 13:15:09 +02001316 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001317 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1318 }
1319
1320 statistics_proxy_.reset();
1321 // Average of two playback intervals.
1322 const int kExpectedTimeBetweenFreezes =
1323 kInterFrameDelayMs * kMinRequiredSamples * 2;
Sergey Silkin02371062019-01-31 16:45:42 +01001324 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001325 EXPECT_EQ(-1, metrics::MinSample(
1326 "WebRTC.Video.Screenshare.MeanFreezeDurationMs"));
1327 EXPECT_EQ(kExpectedTimeBetweenFreezes,
1328 metrics::MinSample(
1329 "WebRTC.Video.Screenshare.MeanTimeBetweenFreezesMs"));
1330 } else {
1331 EXPECT_EQ(-1, metrics::MinSample("WebRTC.Video.MeanFreezeDurationMs"));
1332 EXPECT_EQ(kExpectedTimeBetweenFreezes,
1333 metrics::MinSample("WebRTC.Video.MeanTimeBetweenFreezesMs"));
1334 }
1335}
1336
Sergey Silkin02371062019-01-31 16:45:42 +01001337TEST_P(ReceiveStatisticsProxyTestWithContent, ManyPausesAtTheBeginning) {
Ilya Nikolaevskiy879f5a32018-05-31 09:47:17 +02001338 const int kInterFrameDelayMs = 33;
1339 const int kPauseDurationMs = 10000;
Sergey Silkin278f8252019-01-09 14:37:40 +01001340 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1341
Ilya Nikolaevskiy879f5a32018-05-31 09:47:17 +02001342 for (int i = 0; i <= kMinRequiredSamples; ++i) {
Sergey Silkin02371062019-01-31 16:45:42 +01001343 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
Ilya Nikolaevskiy879f5a32018-05-31 09:47:17 +02001344 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1345
1346 statistics_proxy_->OnStreamInactive();
1347 fake_clock_.AdvanceTimeMilliseconds(kPauseDurationMs);
1348
Sergey Silkin02371062019-01-31 16:45:42 +01001349 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
Ilya Nikolaevskiy879f5a32018-05-31 09:47:17 +02001350 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1351 }
1352
1353 statistics_proxy_.reset();
1354 // No freezes should be detected, as all long inter-frame delays were pauses.
Sergey Silkin02371062019-01-31 16:45:42 +01001355 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiy879f5a32018-05-31 09:47:17 +02001356 EXPECT_EQ(-1, metrics::MinSample(
1357 "WebRTC.Video.Screenshare.MeanFreezeDurationMs"));
1358 } else {
1359 EXPECT_EQ(-1, metrics::MinSample("WebRTC.Video.MeanFreezeDurationMs"));
1360 }
1361}
1362
Sergey Silkin02371062019-01-31 16:45:42 +01001363TEST_P(ReceiveStatisticsProxyTestWithContent, TimeInHdReported) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001364 const int kInterFrameDelayMs = 20;
Sergey Silkin278f8252019-01-09 14:37:40 +01001365 webrtc::VideoFrame frame_hd = CreateFrame(1280, 720);
1366 webrtc::VideoFrame frame_sd = CreateFrame(640, 360);
1367
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001368 // HD frames.
1369 for (int i = 0; i < kMinRequiredSamples; ++i) {
Sergey Silkin02371062019-01-31 16:45:42 +01001370 statistics_proxy_->OnDecodedFrame(frame_hd, absl::nullopt, content_type_);
Sergey Silkin278f8252019-01-09 14:37:40 +01001371 statistics_proxy_->OnRenderedFrame(frame_hd);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001372 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1373 }
1374 // SD frames.
1375 for (int i = 0; i < 2 * kMinRequiredSamples; ++i) {
Sergey Silkin02371062019-01-31 16:45:42 +01001376 statistics_proxy_->OnDecodedFrame(frame_sd, absl::nullopt, content_type_);
Sergey Silkin278f8252019-01-09 14:37:40 +01001377 statistics_proxy_->OnRenderedFrame(frame_sd);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001378 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1379 }
1380 // Extra last frame.
Sergey Silkin278f8252019-01-09 14:37:40 +01001381 statistics_proxy_->OnRenderedFrame(frame_sd);
1382
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001383 statistics_proxy_.reset();
1384 const int kExpectedTimeInHdPercents = 33;
Sergey Silkin02371062019-01-31 16:45:42 +01001385 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001386 EXPECT_EQ(
1387 kExpectedTimeInHdPercents,
1388 metrics::MinSample("WebRTC.Video.Screenshare.TimeInHdPercentage"));
1389 } else {
1390 EXPECT_EQ(kExpectedTimeInHdPercents,
1391 metrics::MinSample("WebRTC.Video.TimeInHdPercentage"));
1392 }
1393}
1394
Sergey Silkin02371062019-01-31 16:45:42 +01001395TEST_P(ReceiveStatisticsProxyTestWithContent, TimeInBlockyVideoReported) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001396 const int kInterFrameDelayMs = 20;
1397 const int kHighQp = 80;
1398 const int kLowQp = 30;
Sergey Silkin278f8252019-01-09 14:37:40 +01001399 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1400
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001401 // High quality frames.
1402 for (int i = 0; i < kMinRequiredSamples; ++i) {
Sergey Silkin02371062019-01-31 16:45:42 +01001403 statistics_proxy_->OnDecodedFrame(frame, kLowQp, content_type_);
Sergey Silkin278f8252019-01-09 14:37:40 +01001404 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001405 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1406 }
1407 // Blocky frames.
1408 for (int i = 0; i < 2 * kMinRequiredSamples; ++i) {
Sergey Silkin02371062019-01-31 16:45:42 +01001409 statistics_proxy_->OnDecodedFrame(frame, kHighQp, content_type_);
Sergey Silkin278f8252019-01-09 14:37:40 +01001410 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001411 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1412 }
1413 // Extra last frame.
Sergey Silkin02371062019-01-31 16:45:42 +01001414 statistics_proxy_->OnDecodedFrame(frame, kHighQp, content_type_);
Sergey Silkin278f8252019-01-09 14:37:40 +01001415 statistics_proxy_->OnRenderedFrame(frame);
1416
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001417 statistics_proxy_.reset();
1418 const int kExpectedTimeInHdPercents = 66;
Sergey Silkin02371062019-01-31 16:45:42 +01001419 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001420 EXPECT_EQ(kExpectedTimeInHdPercents,
1421 metrics::MinSample(
1422 "WebRTC.Video.Screenshare.TimeInBlockyVideoPercentage"));
1423 } else {
1424 EXPECT_EQ(kExpectedTimeInHdPercents,
1425 metrics::MinSample("WebRTC.Video.TimeInBlockyVideoPercentage"));
1426 }
1427}
1428
Sergey Silkin02371062019-01-31 16:45:42 +01001429TEST_P(ReceiveStatisticsProxyTestWithContent, DownscalesReported) {
Sergey Silkin278f8252019-01-09 14:37:40 +01001430 const int kInterFrameDelayMs = 2000; // To ensure long enough call duration.
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001431
Sergey Silkin278f8252019-01-09 14:37:40 +01001432 webrtc::VideoFrame frame_hd = CreateFrame(1280, 720);
1433 webrtc::VideoFrame frame_sd = CreateFrame(640, 360);
1434 webrtc::VideoFrame frame_ld = CreateFrame(320, 180);
1435
1436 // Call once to pass content type.
Sergey Silkin02371062019-01-31 16:45:42 +01001437 statistics_proxy_->OnDecodedFrame(frame_hd, absl::nullopt, content_type_);
Sergey Silkin278f8252019-01-09 14:37:40 +01001438
1439 statistics_proxy_->OnRenderedFrame(frame_hd);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001440 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1441
1442 // Downscale.
Sergey Silkin278f8252019-01-09 14:37:40 +01001443 statistics_proxy_->OnRenderedFrame(frame_sd);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001444 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1445
1446 // Downscale.
Sergey Silkin278f8252019-01-09 14:37:40 +01001447 statistics_proxy_->OnRenderedFrame(frame_ld);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001448 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1449
1450 statistics_proxy_.reset();
Sergey Silkin278f8252019-01-09 14:37:40 +01001451 const int kExpectedDownscales = 30; // 2 per 4 seconds = 30 per minute.
Sergey Silkin02371062019-01-31 16:45:42 +01001452 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001453 EXPECT_EQ(
1454 kExpectedDownscales,
1455 metrics::MinSample(
1456 "WebRTC.Video.Screenshare.NumberResolutionDownswitchesPerMinute"));
1457 } else {
1458 EXPECT_EQ(kExpectedDownscales,
1459 metrics::MinSample(
1460 "WebRTC.Video.NumberResolutionDownswitchesPerMinute"));
1461 }
1462}
1463
Sergey Silkin02371062019-01-31 16:45:42 +01001464TEST_P(ReceiveStatisticsProxyTestWithContent,
1465 StatsAreSlicedOnSimulcastAndExperiment) {
ilnik6d5b4d62017-08-30 03:32:14 -07001466 const uint8_t experiment_id = 1;
Sergey Silkin02371062019-01-31 16:45:42 +01001467 webrtc::VideoContentType content_type = content_type_;
ilnik6d5b4d62017-08-30 03:32:14 -07001468 videocontenttypehelpers::SetExperimentId(&content_type, experiment_id);
1469 const int kInterFrameDelayMs1 = 30;
1470 const int kInterFrameDelayMs2 = 50;
Sergey Silkin278f8252019-01-09 14:37:40 +01001471 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
ilnik6d5b4d62017-08-30 03:32:14 -07001472
1473 videocontenttypehelpers::SetSimulcastId(&content_type, 1);
1474 for (int i = 0; i <= kMinRequiredSamples; ++i) {
1475 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs1);
Sergey Silkin278f8252019-01-09 14:37:40 +01001476 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type);
ilnik6d5b4d62017-08-30 03:32:14 -07001477 }
1478
1479 videocontenttypehelpers::SetSimulcastId(&content_type, 2);
1480 for (int i = 0; i <= kMinRequiredSamples; ++i) {
1481 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs2);
Sergey Silkin278f8252019-01-09 14:37:40 +01001482 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type);
ilnik6d5b4d62017-08-30 03:32:14 -07001483 }
1484 statistics_proxy_.reset();
1485
1486 if (videocontenttypehelpers::IsScreenshare(content_type)) {
1487 EXPECT_EQ(
1488 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1489 EXPECT_EQ(1, metrics::NumSamples(
1490 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1491 EXPECT_EQ(1, metrics::NumSamples(
1492 "WebRTC.Video.Screenshare.InterframeDelayInMs.S0"));
1493 EXPECT_EQ(1, metrics::NumSamples(
1494 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs.S0"));
1495 EXPECT_EQ(1, metrics::NumSamples(
1496 "WebRTC.Video.Screenshare.InterframeDelayInMs.S1"));
1497 EXPECT_EQ(1, metrics::NumSamples(
1498 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs.S1"));
1499 EXPECT_EQ(1,
1500 metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"
1501 ".ExperimentGroup0"));
1502 EXPECT_EQ(
1503 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"
1504 ".ExperimentGroup0"));
1505 EXPECT_EQ(
1506 kInterFrameDelayMs1,
1507 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs.S0"));
1508 EXPECT_EQ(
1509 kInterFrameDelayMs2,
1510 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs.S1"));
1511 EXPECT_EQ(
1512 (kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1513 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1514 EXPECT_EQ(
1515 kInterFrameDelayMs2,
1516 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1517 EXPECT_EQ(
1518 (kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1519 metrics::MinSample(
1520 "WebRTC.Video.Screenshare.InterframeDelayInMs.ExperimentGroup0"));
1521 } else {
1522 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
1523 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
1524 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs.S0"));
1525 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs.S0"));
1526 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs.S1"));
1527 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs.S1"));
1528 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"
1529 ".ExperimentGroup0"));
1530 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"
1531 ".ExperimentGroup0"));
1532 EXPECT_EQ(kInterFrameDelayMs1,
1533 metrics::MinSample("WebRTC.Video.InterframeDelayInMs.S0"));
1534 EXPECT_EQ(kInterFrameDelayMs2,
1535 metrics::MinSample("WebRTC.Video.InterframeDelayInMs.S1"));
1536 EXPECT_EQ((kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1537 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
1538 EXPECT_EQ(kInterFrameDelayMs2,
1539 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
1540 EXPECT_EQ((kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1541 metrics::MinSample(
1542 "WebRTC.Video.InterframeDelayInMs.ExperimentGroup0"));
1543 }
1544}
sakale5ba44e2016-10-26 07:09:24 -07001545} // namespace webrtc