blob: 3d870b4376f997e1e2d6036ee018af504b68c0f4 [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;
568
569 StreamDataCounters counters;
570 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
571 statistics_proxy_->DataCountersUpdated(counters, config_.rtp.remote_ssrc);
572
573 for (int i = 0; i < kNumBadSamples; ++i) {
574 // Since OnRenderedFrame is never called the fps in each sample will be 0,
575 // i.e. bad
576 fake_clock_.AdvanceTimeMilliseconds(1000);
577 statistics_proxy_->OnIncomingRate(0, 0);
578 }
579 // Histograms are updated when the statistics_proxy_ is deleted.
580 statistics_proxy_.reset();
581 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BadCall.Any"));
582 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BadCall.Any", 100));
583
584 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BadCall.FrameRate"));
585 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BadCall.FrameRate", 100));
586
587 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.BadCall.FrameRateVariance"));
588
589 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.BadCall.Qp"));
590}
591
asapersson0c43f772016-11-30 01:42:26 -0800592TEST_F(ReceiveStatisticsProxyTest, PacketLossHistogramIsUpdated) {
593 const uint32_t kCumLost1 = 1;
594 const uint32_t kExtSeqNum1 = 10;
595 const uint32_t kCumLost2 = 2;
596 const uint32_t kExtSeqNum2 = 20;
597
598 // One report block received.
599 RtcpStatistics rtcp_stats1;
srte186d9c32017-08-04 05:03:53 -0700600 rtcp_stats1.packets_lost = kCumLost1;
601 rtcp_stats1.extended_highest_sequence_number = kExtSeqNum1;
asapersson0c43f772016-11-30 01:42:26 -0800602 statistics_proxy_->StatisticsUpdated(rtcp_stats1, kRemoteSsrc);
603
604 // Two report blocks received.
605 RtcpStatistics rtcp_stats2;
srte186d9c32017-08-04 05:03:53 -0700606 rtcp_stats2.packets_lost = kCumLost2;
607 rtcp_stats2.extended_highest_sequence_number = kExtSeqNum2;
asapersson0c43f772016-11-30 01:42:26 -0800608 statistics_proxy_->StatisticsUpdated(rtcp_stats2, kRemoteSsrc);
609
610 // Two received report blocks but min run time has not passed.
611 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
612 SetUp(); // Reset stat proxy causes histograms to be updated.
613 EXPECT_EQ(0,
614 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
615
616 // Two report blocks received.
617 statistics_proxy_->StatisticsUpdated(rtcp_stats1, kRemoteSsrc);
618 statistics_proxy_->StatisticsUpdated(rtcp_stats2, kRemoteSsrc);
619
620 // Two received report blocks and min run time has passed.
621 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
622 SetUp();
623 EXPECT_EQ(1,
624 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
625 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceivedPacketsLostInPercent",
626 (kCumLost2 - kCumLost1) * 100 /
627 (kExtSeqNum2 - kExtSeqNum1)));
628}
629
630TEST_F(ReceiveStatisticsProxyTest,
631 PacketLossHistogramIsNotUpdatedIfLessThanTwoReportBlocksAreReceived) {
632 RtcpStatistics rtcp_stats1;
srte186d9c32017-08-04 05:03:53 -0700633 rtcp_stats1.packets_lost = 1;
634 rtcp_stats1.extended_highest_sequence_number = 10;
asapersson0c43f772016-11-30 01:42:26 -0800635
636 // Min run time has passed but no received report block.
637 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
638 SetUp(); // Reset stat proxy causes histograms to be updated.
639 EXPECT_EQ(0,
640 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
641
642 // Min run time has passed but only one received report block.
643 statistics_proxy_->StatisticsUpdated(rtcp_stats1, kRemoteSsrc);
644 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
645 SetUp();
646 EXPECT_EQ(0,
647 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
648}
649
asapersson2077f2f2017-05-11 05:37:35 -0700650TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsAvSyncOffset) {
651 const int64_t kSyncOffsetMs = 22;
652 const double kFreqKhz = 90.0;
653 EXPECT_EQ(std::numeric_limits<int>::max(),
654 statistics_proxy_->GetStats().sync_offset_ms);
655 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
656 EXPECT_EQ(kSyncOffsetMs, statistics_proxy_->GetStats().sync_offset_ms);
657}
658
asapersson46c4e3c2016-11-03 06:48:19 -0700659TEST_F(ReceiveStatisticsProxyTest, AvSyncOffsetHistogramIsUpdated) {
660 const int64_t kSyncOffsetMs = 22;
661 const double kFreqKhz = 90.0;
662 for (int i = 0; i < kMinRequiredSamples; ++i)
663 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
664 // Histograms are updated when the statistics_proxy_ is deleted.
665 statistics_proxy_.reset();
666 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AVSyncOffsetInMs"));
667 EXPECT_EQ(1,
668 metrics::NumEvents("WebRTC.Video.AVSyncOffsetInMs", kSyncOffsetMs));
669}
670
asaperssonde9e5ff2016-11-02 07:14:03 -0700671TEST_F(ReceiveStatisticsProxyTest, RtpToNtpFrequencyOffsetHistogramIsUpdated) {
672 const int64_t kSyncOffsetMs = 22;
673 const double kFreqKhz = 90.0;
674 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
675 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz + 2.2);
676 fake_clock_.AdvanceTimeMilliseconds(kFreqOffsetProcessIntervalInMs);
677 // Process interval passed, max diff: 2.
678 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz + 1.1);
679 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz - 4.2);
680 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz - 0.9);
681 fake_clock_.AdvanceTimeMilliseconds(kFreqOffsetProcessIntervalInMs);
682 // Process interval passed, max diff: 4.
683 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
684 statistics_proxy_.reset();
685 // Average reported: (2 + 4) / 2 = 3.
686 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtpToNtpFreqOffsetInKhz"));
687 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtpToNtpFreqOffsetInKhz", 3));
688}
689
asapersson6966bd52017-01-03 00:44:06 -0800690TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsUpdated) {
691 const int kQp = 22;
asapersson6966bd52017-01-03 00:44:06 -0800692
693 for (int i = 0; i < kMinRequiredSamples; ++i)
Niels Möller147013a2018-10-01 15:56:33 +0200694 statistics_proxy_->OnPreDecode(kVideoCodecVP8, kQp);
asapersson6966bd52017-01-03 00:44:06 -0800695
696 statistics_proxy_.reset();
697 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
698 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Decoded.Vp8.Qp", kQp));
699}
700
701TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsNotUpdatedForTooFewSamples) {
Niels Möller147013a2018-10-01 15:56:33 +0200702 const int kQp = 22;
asapersson6966bd52017-01-03 00:44:06 -0800703
704 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
Niels Möller147013a2018-10-01 15:56:33 +0200705 statistics_proxy_->OnPreDecode(kVideoCodecVP8, kQp);
asapersson6966bd52017-01-03 00:44:06 -0800706
707 statistics_proxy_.reset();
708 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
709}
710
711TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsNotUpdatedIfNoQpValue) {
asapersson6966bd52017-01-03 00:44:06 -0800712 for (int i = 0; i < kMinRequiredSamples; ++i)
Niels Möller147013a2018-10-01 15:56:33 +0200713 statistics_proxy_->OnPreDecode(kVideoCodecVP8, -1);
asapersson6966bd52017-01-03 00:44:06 -0800714
715 statistics_proxy_.reset();
716 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
717}
718
asaperssonb99baf82017-04-20 04:05:43 -0700719TEST_F(ReceiveStatisticsProxyTest,
720 KeyFrameHistogramNotUpdatedForTooFewSamples) {
721 const bool kIsKeyFrame = false;
722 const int kFrameSizeBytes = 1000;
723
724 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
ilnik6d5b4d62017-08-30 03:32:14 -0700725 statistics_proxy_->OnCompleteFrame(kIsKeyFrame, kFrameSizeBytes,
726 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 04:05:43 -0700727
728 EXPECT_EQ(0, statistics_proxy_->GetStats().frame_counts.key_frames);
729 EXPECT_EQ(kMinRequiredSamples - 1,
730 statistics_proxy_->GetStats().frame_counts.delta_frames);
731
732 statistics_proxy_.reset();
733 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
734}
735
736TEST_F(ReceiveStatisticsProxyTest,
737 KeyFrameHistogramUpdatedForMinRequiredSamples) {
738 const bool kIsKeyFrame = false;
739 const int kFrameSizeBytes = 1000;
740
741 for (int i = 0; i < kMinRequiredSamples; ++i)
ilnik6d5b4d62017-08-30 03:32:14 -0700742 statistics_proxy_->OnCompleteFrame(kIsKeyFrame, kFrameSizeBytes,
743 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 04:05:43 -0700744
745 EXPECT_EQ(0, statistics_proxy_->GetStats().frame_counts.key_frames);
746 EXPECT_EQ(kMinRequiredSamples,
747 statistics_proxy_->GetStats().frame_counts.delta_frames);
748
749 statistics_proxy_.reset();
750 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
751 EXPECT_EQ(1,
752 metrics::NumEvents("WebRTC.Video.KeyFramesReceivedInPermille", 0));
753}
754
755TEST_F(ReceiveStatisticsProxyTest, KeyFrameHistogramIsUpdated) {
756 const int kFrameSizeBytes = 1000;
757
758 for (int i = 0; i < kMinRequiredSamples; ++i)
ilnik6d5b4d62017-08-30 03:32:14 -0700759 statistics_proxy_->OnCompleteFrame(true, kFrameSizeBytes,
760 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 04:05:43 -0700761
762 for (int i = 0; i < kMinRequiredSamples; ++i)
ilnik6d5b4d62017-08-30 03:32:14 -0700763 statistics_proxy_->OnCompleteFrame(false, kFrameSizeBytes,
764 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 04:05:43 -0700765
766 EXPECT_EQ(kMinRequiredSamples,
767 statistics_proxy_->GetStats().frame_counts.key_frames);
768 EXPECT_EQ(kMinRequiredSamples,
769 statistics_proxy_->GetStats().frame_counts.delta_frames);
770
771 statistics_proxy_.reset();
772 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
773 EXPECT_EQ(
774 1, metrics::NumEvents("WebRTC.Video.KeyFramesReceivedInPermille", 500));
775}
776
777TEST_F(ReceiveStatisticsProxyTest, TimingHistogramsNotUpdatedForTooFewSamples) {
778 const int kDecodeMs = 1;
779 const int kMaxDecodeMs = 2;
780 const int kCurrentDelayMs = 3;
781 const int kTargetDelayMs = 4;
782 const int kJitterBufferMs = 5;
783 const int kMinPlayoutDelayMs = 6;
784 const int kRenderDelayMs = 7;
785
786 for (int i = 0; i < kMinRequiredSamples - 1; ++i) {
787 statistics_proxy_->OnFrameBufferTimingsUpdated(
788 kDecodeMs, kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs,
789 kJitterBufferMs, kMinPlayoutDelayMs, kRenderDelayMs);
790 }
791
792 statistics_proxy_.reset();
793 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
794 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
795 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
796 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
797 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
798}
799
800TEST_F(ReceiveStatisticsProxyTest, TimingHistogramsAreUpdated) {
801 const int kDecodeMs = 1;
802 const int kMaxDecodeMs = 2;
803 const int kCurrentDelayMs = 3;
804 const int kTargetDelayMs = 4;
805 const int kJitterBufferMs = 5;
806 const int kMinPlayoutDelayMs = 6;
807 const int kRenderDelayMs = 7;
808
809 for (int i = 0; i < kMinRequiredSamples; ++i) {
810 statistics_proxy_->OnFrameBufferTimingsUpdated(
811 kDecodeMs, kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs,
812 kJitterBufferMs, kMinPlayoutDelayMs, kRenderDelayMs);
813 }
814
815 statistics_proxy_.reset();
816 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
817 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
818 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
819 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
820 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
821
822 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DecodeTimeInMs", kDecodeMs));
823 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.JitterBufferDelayInMs",
824 kJitterBufferMs));
825 EXPECT_EQ(1,
826 metrics::NumEvents("WebRTC.Video.TargetDelayInMs", kTargetDelayMs));
827 EXPECT_EQ(
828 1, metrics::NumEvents("WebRTC.Video.CurrentDelayInMs", kCurrentDelayMs));
829 EXPECT_EQ(1,
830 metrics::NumEvents("WebRTC.Video.OnewayDelayInMs", kTargetDelayMs));
831}
832
sprang948b2752017-05-04 02:47:13 -0700833TEST_F(ReceiveStatisticsProxyTest, DoesNotReportStaleFramerates) {
834 const int kDefaultFps = 30;
Sergey Silkin278f8252019-01-09 14:37:40 +0100835 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
sprang948b2752017-05-04 02:47:13 -0700836
837 for (int i = 0; i < kDefaultFps; ++i) {
838 // Since OnRenderedFrame is never called the fps in each sample will be 0,
839 // i.e. bad
840 frame.set_ntp_time_ms(fake_clock_.CurrentNtpInMilliseconds());
Sergey Silkin278f8252019-01-09 14:37:40 +0100841 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
sprang948b2752017-05-04 02:47:13 -0700842 VideoContentType::UNSPECIFIED);
843 statistics_proxy_->OnRenderedFrame(frame);
844 fake_clock_.AdvanceTimeMilliseconds(1000 / kDefaultFps);
845 }
846
847 EXPECT_EQ(kDefaultFps, statistics_proxy_->GetStats().decode_frame_rate);
848 EXPECT_EQ(kDefaultFps, statistics_proxy_->GetStats().render_frame_rate);
849
850 // FPS trackers in stats proxy have a 1000ms sliding window.
851 fake_clock_.AdvanceTimeMilliseconds(1000);
852 EXPECT_EQ(0, statistics_proxy_->GetStats().decode_frame_rate);
853 EXPECT_EQ(0, statistics_proxy_->GetStats().render_frame_rate);
854}
855
asapersson2077f2f2017-05-11 05:37:35 -0700856TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsReceivedFrameStats) {
asapersson2077f2f2017-05-11 05:37:35 -0700857 EXPECT_EQ(0, statistics_proxy_->GetStats().width);
858 EXPECT_EQ(0, statistics_proxy_->GetStats().height);
859 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_rendered);
860
861 statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight));
862
863 EXPECT_EQ(kWidth, statistics_proxy_->GetStats().width);
864 EXPECT_EQ(kHeight, statistics_proxy_->GetStats().height);
865 EXPECT_EQ(1u, statistics_proxy_->GetStats().frames_rendered);
866}
867
868TEST_F(ReceiveStatisticsProxyTest,
869 ReceivedFrameHistogramsAreNotUpdatedForTooFewSamples) {
asapersson2077f2f2017-05-11 05:37:35 -0700870 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
871 statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight));
872
873 statistics_proxy_.reset();
874 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
875 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
876 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
877 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
878}
879
880TEST_F(ReceiveStatisticsProxyTest, ReceivedFrameHistogramsAreUpdated) {
asapersson2077f2f2017-05-11 05:37:35 -0700881 for (int i = 0; i < kMinRequiredSamples; ++i)
882 statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight));
883
884 statistics_proxy_.reset();
885 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
886 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
887 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
888 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
889 EXPECT_EQ(1,
890 metrics::NumEvents("WebRTC.Video.ReceivedWidthInPixels", kWidth));
891 EXPECT_EQ(1,
892 metrics::NumEvents("WebRTC.Video.ReceivedHeightInPixels", kHeight));
893}
894
Åsa Persson81327d52018-06-05 13:34:33 +0200895TEST_F(ReceiveStatisticsProxyTest, ZeroDelayReportedIfFrameNotDelayed) {
Sergey Silkin278f8252019-01-09 14:37:40 +0100896 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
897 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
Åsa Persson81327d52018-06-05 13:34:33 +0200898 VideoContentType::UNSPECIFIED);
899
900 // Frame not delayed, delayed frames to render: 0%.
901 const int64_t kNowMs = fake_clock_.TimeInMilliseconds();
902 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs));
903
904 // Min run time has passed.
905 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
906 statistics_proxy_.reset();
907 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
908 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 0));
909 EXPECT_EQ(0, metrics::NumSamples(
910 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
911}
912
913TEST_F(ReceiveStatisticsProxyTest,
914 DelayedFrameHistogramsAreNotUpdatedIfMinRuntimeHasNotPassed) {
Sergey Silkin278f8252019-01-09 14:37:40 +0100915 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
916 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
Åsa Persson81327d52018-06-05 13:34:33 +0200917 VideoContentType::UNSPECIFIED);
918
919 // Frame not delayed, delayed frames to render: 0%.
920 const int64_t kNowMs = fake_clock_.TimeInMilliseconds();
921 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs));
922
923 // Min run time has not passed.
924 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000) -
925 1);
926 statistics_proxy_.reset();
927 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
928 EXPECT_EQ(0, metrics::NumSamples(
929 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
930}
931
932TEST_F(ReceiveStatisticsProxyTest,
933 DelayedFramesHistogramsAreNotUpdatedIfNoRenderedFrames) {
Sergey Silkin278f8252019-01-09 14:37:40 +0100934 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
935 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
Åsa Persson81327d52018-06-05 13:34:33 +0200936 VideoContentType::UNSPECIFIED);
937
938 // Min run time has passed. No rendered frames.
939 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
940 statistics_proxy_.reset();
941 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
942 EXPECT_EQ(0, metrics::NumSamples(
943 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
944}
945
946TEST_F(ReceiveStatisticsProxyTest, DelayReportedIfFrameIsDelayed) {
Sergey Silkin278f8252019-01-09 14:37:40 +0100947 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
948 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
Åsa Persson81327d52018-06-05 13:34:33 +0200949 VideoContentType::UNSPECIFIED);
950
951 // Frame delayed 1 ms, delayed frames to render: 100%.
952 const int64_t kNowMs = fake_clock_.TimeInMilliseconds();
953 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs - 1));
954
955 // Min run time has passed.
956 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
957 statistics_proxy_.reset();
958 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
959 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 100));
960 EXPECT_EQ(1, metrics::NumSamples(
961 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
962 EXPECT_EQ(1, metrics::NumEvents(
963 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs", 1));
964}
965
966TEST_F(ReceiveStatisticsProxyTest, AverageDelayOfDelayedFramesIsReported) {
Sergey Silkin278f8252019-01-09 14:37:40 +0100967 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
968 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
Åsa Persson81327d52018-06-05 13:34:33 +0200969 VideoContentType::UNSPECIFIED);
970
971 // Two frames delayed (6 ms, 10 ms), delayed frames to render: 50%.
972 const int64_t kNowMs = fake_clock_.TimeInMilliseconds();
973 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs - 10));
974 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs - 6));
975 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs));
976 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs + 1));
977
978 // Min run time has passed.
979 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
980 statistics_proxy_.reset();
981 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
982 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 50));
983 EXPECT_EQ(1, metrics::NumSamples(
984 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
985 EXPECT_EQ(1, metrics::NumEvents(
986 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs", 8));
987}
988
asapersson2077f2f2017-05-11 05:37:35 -0700989TEST_F(ReceiveStatisticsProxyTest,
990 RtcpHistogramsNotUpdatedIfMinRuntimeHasNotPassed) {
991 InsertFirstRtpPacket(kRemoteSsrc);
992 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000) -
993 1);
994
995 RtcpPacketTypeCounter counter;
996 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
997
998 statistics_proxy_.reset();
999 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
1000 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
1001 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
1002}
1003
1004TEST_F(ReceiveStatisticsProxyTest, RtcpHistogramsAreUpdated) {
1005 InsertFirstRtpPacket(kRemoteSsrc);
1006 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1007
1008 const uint32_t kFirPackets = 100;
1009 const uint32_t kPliPackets = 200;
1010 const uint32_t kNackPackets = 300;
1011
1012 RtcpPacketTypeCounter counter;
1013 counter.fir_packets = kFirPackets;
1014 counter.pli_packets = kPliPackets;
1015 counter.nack_packets = kNackPackets;
1016 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
1017
1018 statistics_proxy_.reset();
1019 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
1020 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
1021 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
1022 EXPECT_EQ(
1023 1, metrics::NumEvents("WebRTC.Video.FirPacketsSentPerMinute",
1024 kFirPackets * 60 / metrics::kMinRunTimeInSeconds));
1025 EXPECT_EQ(
1026 1, metrics::NumEvents("WebRTC.Video.PliPacketsSentPerMinute",
1027 kPliPackets * 60 / metrics::kMinRunTimeInSeconds));
1028 EXPECT_EQ(
1029 1, metrics::NumEvents("WebRTC.Video.NackPacketsSentPerMinute",
1030 kNackPackets * 60 / metrics::kMinRunTimeInSeconds));
1031}
1032
Sergey Silkin02371062019-01-31 16:45:42 +01001033class ReceiveStatisticsProxyTestWithFreezeDuration
1034 : public ReceiveStatisticsProxyTest,
1035 public testing::WithParamInterface<
1036 std::tuple<uint32_t, uint32_t, uint32_t>> {
1037 protected:
1038 const uint32_t frame_duration_ms_ = {std::get<0>(GetParam())};
1039 const uint32_t freeze_duration_ms_ = {std::get<1>(GetParam())};
1040 const uint32_t expected_freeze_count_ = {std::get<2>(GetParam())};
1041};
sprang892dab52017-08-15 05:00:33 -07001042
Sergey Silkin02371062019-01-31 16:45:42 +01001043// It is a freeze if:
1044// frame_duration_ms >= max(3 * avg_frame_duration, avg_frame_duration + 150)
1045// where avg_frame_duration is average duration of last 30 frames including
1046// the current one.
1047//
1048// Condition 1: 3 * avg_frame_duration > avg_frame_duration + 150
1049const auto kFreezeDetectionCond1Freeze = std::make_tuple(150, 483, 1);
1050const auto kFreezeDetectionCond1NotFreeze = std::make_tuple(150, 482, 0);
1051// Condition 2: 3 * avg_frame_duration < avg_frame_duration + 150
1052const auto kFreezeDetectionCond2Freeze = std::make_tuple(30, 185, 1);
1053const auto kFreezeDetectionCond2NotFreeze = std::make_tuple(30, 184, 0);
1054
1055INSTANTIATE_TEST_CASE_P(_,
1056 ReceiveStatisticsProxyTestWithFreezeDuration,
1057 ::testing::Values(kFreezeDetectionCond1Freeze,
1058 kFreezeDetectionCond1NotFreeze,
1059 kFreezeDetectionCond2Freeze,
1060 kFreezeDetectionCond2NotFreeze));
1061
1062TEST_P(ReceiveStatisticsProxyTestWithFreezeDuration, FreezeDetection) {
1063 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
1064 EXPECT_EQ(0u, stats.freeze_count);
1065 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1066
1067 // Add a very long frame. This is need to verify that average frame
1068 // duration, which is supposed to be calculated as mean of durations of
1069 // last 30 frames, is calculated correctly.
1070 statistics_proxy_->OnRenderedFrame(frame);
1071 fake_clock_.AdvanceTimeMilliseconds(2000);
1072
1073 for (size_t i = 0;
1074 i <= VideoQualityObserver::kAvgInterframeDelaysWindowSizeFrames; ++i) {
1075 fake_clock_.AdvanceTimeMilliseconds(frame_duration_ms_);
1076 statistics_proxy_->OnRenderedFrame(frame);
1077 }
1078
1079 fake_clock_.AdvanceTimeMilliseconds(freeze_duration_ms_);
1080 statistics_proxy_->OnRenderedFrame(frame);
1081
1082 stats = statistics_proxy_->GetStats();
1083 EXPECT_EQ(stats.freeze_count, expected_freeze_count_);
1084}
1085
1086class ReceiveStatisticsProxyTestWithContent
1087 : public ReceiveStatisticsProxyTest,
1088 public ::testing::WithParamInterface<webrtc::VideoContentType> {
1089 protected:
1090 const webrtc::VideoContentType content_type_{GetParam()};
1091};
1092
1093INSTANTIATE_TEST_CASE_P(ContentTypes,
1094 ReceiveStatisticsProxyTestWithContent,
1095 ::testing::Values(VideoContentType::UNSPECIFIED,
1096 VideoContentType::SCREENSHARE));
1097
1098TEST_P(ReceiveStatisticsProxyTestWithContent, InterFrameDelaysAreReported) {
sprang892dab52017-08-15 05:00:33 -07001099 const int kInterFrameDelayMs = 33;
Sergey Silkin278f8252019-01-09 14:37:40 +01001100 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1101
sprang892dab52017-08-15 05:00:33 -07001102 for (int i = 0; i < kMinRequiredSamples; ++i) {
Sergey Silkin02371062019-01-31 16:45:42 +01001103 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
sprang892dab52017-08-15 05:00:33 -07001104 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1105 }
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001106 // One extra with double the interval.
sprang892dab52017-08-15 05:00:33 -07001107 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
Sergey Silkin02371062019-01-31 16:45:42 +01001108 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
sprang892dab52017-08-15 05:00:33 -07001109
1110 statistics_proxy_.reset();
1111 const int kExpectedInterFrame =
1112 (kInterFrameDelayMs * (kMinRequiredSamples - 1) +
1113 kInterFrameDelayMs * 2) /
1114 kMinRequiredSamples;
Sergey Silkin02371062019-01-31 16:45:42 +01001115 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
ilnik6d5b4d62017-08-30 03:32:14 -07001116 EXPECT_EQ(
1117 kExpectedInterFrame,
1118 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1119 EXPECT_EQ(
1120 kInterFrameDelayMs * 2,
1121 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1122 } else {
1123 EXPECT_EQ(kExpectedInterFrame,
1124 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
1125 EXPECT_EQ(kInterFrameDelayMs * 2,
1126 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
sprang892dab52017-08-15 05:00:33 -07001127 }
1128}
1129
Sergey Silkin02371062019-01-31 16:45:42 +01001130TEST_P(ReceiveStatisticsProxyTestWithContent,
1131 InterFrameDelaysPercentilesAreReported) {
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001132 const int kInterFrameDelayMs = 33;
1133 const int kLastFivePercentsSamples = kMinRequiredSamples * 5 / 100;
Sergey Silkin278f8252019-01-09 14:37:40 +01001134 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1135
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001136 for (int i = 0; i <= kMinRequiredSamples - kLastFivePercentsSamples; ++i) {
1137 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
Sergey Silkin02371062019-01-31 16:45:42 +01001138 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001139 }
1140 // Last 5% of intervals are double in size.
1141 for (int i = 0; i < kLastFivePercentsSamples; ++i) {
1142 fake_clock_.AdvanceTimeMilliseconds(2 * kInterFrameDelayMs);
Sergey Silkin02371062019-01-31 16:45:42 +01001143 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001144 }
1145 // Final sample is outlier and 10 times as big.
1146 fake_clock_.AdvanceTimeMilliseconds(10 * kInterFrameDelayMs);
Sergey Silkin02371062019-01-31 16:45:42 +01001147 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001148
1149 statistics_proxy_.reset();
1150 const int kExpectedInterFrame = kInterFrameDelayMs * 2;
Sergey Silkin02371062019-01-31 16:45:42 +01001151 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001152 EXPECT_EQ(kExpectedInterFrame,
1153 metrics::MinSample(
1154 "WebRTC.Video.Screenshare.InterframeDelay95PercentileInMs"));
1155 } else {
1156 EXPECT_EQ(
1157 kExpectedInterFrame,
1158 metrics::MinSample("WebRTC.Video.InterframeDelay95PercentileInMs"));
1159 }
1160}
1161
Sergey Silkin02371062019-01-31 16:45:42 +01001162TEST_P(ReceiveStatisticsProxyTestWithContent,
1163 MaxInterFrameDelayOnlyWithValidAverage) {
sprang892dab52017-08-15 05:00:33 -07001164 const int kInterFrameDelayMs = 33;
Sergey Silkin278f8252019-01-09 14:37:40 +01001165 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1166
sprang892dab52017-08-15 05:00:33 -07001167 for (int i = 0; i < kMinRequiredSamples; ++i) {
Sergey Silkin02371062019-01-31 16:45:42 +01001168 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
sprang892dab52017-08-15 05:00:33 -07001169 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1170 }
1171
1172 // |kMinRequiredSamples| samples, and thereby intervals, is required. That
1173 // means we're one frame short of having a valid data set.
1174 statistics_proxy_.reset();
1175 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
1176 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
1177 EXPECT_EQ(
1178 0, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1179 EXPECT_EQ(0, metrics::NumSamples(
1180 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1181}
1182
Sergey Silkin02371062019-01-31 16:45:42 +01001183TEST_P(ReceiveStatisticsProxyTestWithContent, MaxInterFrameDelayOnlyWithPause) {
sprang3e86e7e2017-08-22 09:23:28 -07001184 const int kInterFrameDelayMs = 33;
Sergey Silkin278f8252019-01-09 14:37:40 +01001185 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1186
sprang3e86e7e2017-08-22 09:23:28 -07001187 for (int i = 0; i <= kMinRequiredSamples; ++i) {
Sergey Silkin02371062019-01-31 16:45:42 +01001188 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
sprang3e86e7e2017-08-22 09:23:28 -07001189 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1190 }
1191
1192 // At this state, we should have a valid inter-frame delay.
1193 // Indicate stream paused and make a large jump in time.
1194 statistics_proxy_->OnStreamInactive();
1195 fake_clock_.AdvanceTimeMilliseconds(5000);
1196
1197 // Insert two more frames. The interval during the pause should be disregarded
1198 // in the stats.
Sergey Silkin02371062019-01-31 16:45:42 +01001199 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
sprang3e86e7e2017-08-22 09:23:28 -07001200 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
Sergey Silkin02371062019-01-31 16:45:42 +01001201 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
sprang3e86e7e2017-08-22 09:23:28 -07001202
1203 statistics_proxy_.reset();
Sergey Silkin02371062019-01-31 16:45:42 +01001204 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
sprang3e86e7e2017-08-22 09:23:28 -07001205 EXPECT_EQ(
1206 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1207 EXPECT_EQ(1, metrics::NumSamples(
1208 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1209 EXPECT_EQ(
1210 kInterFrameDelayMs,
1211 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1212 EXPECT_EQ(
1213 kInterFrameDelayMs,
1214 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1215 } else {
1216 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
1217 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
1218 EXPECT_EQ(kInterFrameDelayMs,
1219 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
1220 EXPECT_EQ(kInterFrameDelayMs,
1221 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
1222 }
1223}
1224
Sergey Silkin02371062019-01-31 16:45:42 +01001225TEST_P(ReceiveStatisticsProxyTestWithContent, FreezesAreReported) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001226 const int kInterFrameDelayMs = 33;
1227 const int kFreezeDelayMs = 200;
Sergey Silkinbea18ca2018-10-02 16:22:46 +02001228 const int kCallDurationMs =
1229 kMinRequiredSamples * kInterFrameDelayMs + kFreezeDelayMs;
Sergey Silkin278f8252019-01-09 14:37:40 +01001230 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1231
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001232 for (int i = 0; i < kMinRequiredSamples; ++i) {
Sergey Silkin02371062019-01-31 16:45:42 +01001233 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
Ilya Nikolaevskiycdc959f2018-10-10 13:15:09 +02001234 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001235 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1236 }
1237 // Add extra freeze.
1238 fake_clock_.AdvanceTimeMilliseconds(kFreezeDelayMs);
Sergey Silkin02371062019-01-31 16:45:42 +01001239 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
Ilya Nikolaevskiycdc959f2018-10-10 13:15:09 +02001240 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001241
1242 statistics_proxy_.reset();
1243 const int kExpectedTimeBetweenFreezes =
1244 kInterFrameDelayMs * (kMinRequiredSamples - 1);
Sergey Silkinbea18ca2018-10-02 16:22:46 +02001245 const int kExpectedNumberFreezesPerMinute = 60 * 1000 / kCallDurationMs;
Sergey Silkin02371062019-01-31 16:45:42 +01001246 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001247 EXPECT_EQ(
1248 kFreezeDelayMs + kInterFrameDelayMs,
1249 metrics::MinSample("WebRTC.Video.Screenshare.MeanFreezeDurationMs"));
1250 EXPECT_EQ(kExpectedTimeBetweenFreezes,
1251 metrics::MinSample(
1252 "WebRTC.Video.Screenshare.MeanTimeBetweenFreezesMs"));
Sergey Silkinbea18ca2018-10-02 16:22:46 +02001253 EXPECT_EQ(
1254 kExpectedNumberFreezesPerMinute,
1255 metrics::MinSample("WebRTC.Video.Screenshare.NumberFreezesPerMinute"));
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001256 } else {
1257 EXPECT_EQ(kFreezeDelayMs + kInterFrameDelayMs,
1258 metrics::MinSample("WebRTC.Video.MeanFreezeDurationMs"));
1259 EXPECT_EQ(kExpectedTimeBetweenFreezes,
1260 metrics::MinSample("WebRTC.Video.MeanTimeBetweenFreezesMs"));
Sergey Silkinbea18ca2018-10-02 16:22:46 +02001261 EXPECT_EQ(kExpectedNumberFreezesPerMinute,
1262 metrics::MinSample("WebRTC.Video.NumberFreezesPerMinute"));
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001263 }
1264}
1265
Sergey Silkin02371062019-01-31 16:45:42 +01001266TEST_P(ReceiveStatisticsProxyTestWithContent, HarmonicFrameRateIsReported) {
Sergey Silkin50e77452019-01-16 13:41:46 +01001267 const int kInterFrameDelayMs = 33;
1268 const int kFreezeDelayMs = 200;
1269 const int kCallDurationMs =
1270 kMinRequiredSamples * kInterFrameDelayMs + kFreezeDelayMs;
1271 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1272
1273 for (int i = 0; i < kMinRequiredSamples; ++i) {
1274 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
Sergey Silkin02371062019-01-31 16:45:42 +01001275 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
Sergey Silkin50e77452019-01-16 13:41:46 +01001276 statistics_proxy_->OnRenderedFrame(frame);
1277 }
1278 // Add extra freeze.
1279 fake_clock_.AdvanceTimeMilliseconds(kFreezeDelayMs);
Sergey Silkin02371062019-01-31 16:45:42 +01001280 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
Sergey Silkin50e77452019-01-16 13:41:46 +01001281 statistics_proxy_->OnRenderedFrame(frame);
1282
1283 statistics_proxy_.reset();
1284 double kSumSquaredInterframeDelaysSecs =
1285 (kMinRequiredSamples - 1) *
1286 (kInterFrameDelayMs / 1000.0 * kInterFrameDelayMs / 1000.0);
1287 kSumSquaredInterframeDelaysSecs +=
1288 kFreezeDelayMs / 1000.0 * kFreezeDelayMs / 1000.0;
1289 const int kExpectedHarmonicFrameRateFps =
1290 std::round(kCallDurationMs / (1000 * kSumSquaredInterframeDelaysSecs));
Sergey Silkin02371062019-01-31 16:45:42 +01001291 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Sergey Silkin50e77452019-01-16 13:41:46 +01001292 EXPECT_EQ(kExpectedHarmonicFrameRateFps,
1293 metrics::MinSample("WebRTC.Video.Screenshare.HarmonicFrameRate"));
1294 } else {
1295 EXPECT_EQ(kExpectedHarmonicFrameRateFps,
1296 metrics::MinSample("WebRTC.Video.HarmonicFrameRate"));
1297 }
1298}
1299
Sergey Silkin02371062019-01-31 16:45:42 +01001300TEST_P(ReceiveStatisticsProxyTestWithContent, PausesAreIgnored) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001301 const int kInterFrameDelayMs = 33;
1302 const int kPauseDurationMs = 10000;
Sergey Silkin278f8252019-01-09 14:37:40 +01001303 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1304
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001305 for (int i = 0; i <= kMinRequiredSamples; ++i) {
Sergey Silkin02371062019-01-31 16:45:42 +01001306 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
Ilya Nikolaevskiycdc959f2018-10-10 13:15:09 +02001307 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001308 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1309 }
1310 // Add a pause.
1311 fake_clock_.AdvanceTimeMilliseconds(kPauseDurationMs);
1312 statistics_proxy_->OnStreamInactive();
1313
1314 // Second playback interval with triple the length.
1315 for (int i = 0; i <= kMinRequiredSamples * 3; ++i) {
Sergey Silkin02371062019-01-31 16:45:42 +01001316 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
Ilya Nikolaevskiycdc959f2018-10-10 13:15:09 +02001317 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001318 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1319 }
1320
1321 statistics_proxy_.reset();
1322 // Average of two playback intervals.
1323 const int kExpectedTimeBetweenFreezes =
1324 kInterFrameDelayMs * kMinRequiredSamples * 2;
Sergey Silkin02371062019-01-31 16:45:42 +01001325 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001326 EXPECT_EQ(-1, metrics::MinSample(
1327 "WebRTC.Video.Screenshare.MeanFreezeDurationMs"));
1328 EXPECT_EQ(kExpectedTimeBetweenFreezes,
1329 metrics::MinSample(
1330 "WebRTC.Video.Screenshare.MeanTimeBetweenFreezesMs"));
1331 } else {
1332 EXPECT_EQ(-1, metrics::MinSample("WebRTC.Video.MeanFreezeDurationMs"));
1333 EXPECT_EQ(kExpectedTimeBetweenFreezes,
1334 metrics::MinSample("WebRTC.Video.MeanTimeBetweenFreezesMs"));
1335 }
1336}
1337
Sergey Silkin02371062019-01-31 16:45:42 +01001338TEST_P(ReceiveStatisticsProxyTestWithContent, ManyPausesAtTheBeginning) {
Ilya Nikolaevskiy879f5a32018-05-31 09:47:17 +02001339 const int kInterFrameDelayMs = 33;
1340 const int kPauseDurationMs = 10000;
Sergey Silkin278f8252019-01-09 14:37:40 +01001341 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1342
Ilya Nikolaevskiy879f5a32018-05-31 09:47:17 +02001343 for (int i = 0; i <= kMinRequiredSamples; ++i) {
Sergey Silkin02371062019-01-31 16:45:42 +01001344 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
Ilya Nikolaevskiy879f5a32018-05-31 09:47:17 +02001345 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1346
1347 statistics_proxy_->OnStreamInactive();
1348 fake_clock_.AdvanceTimeMilliseconds(kPauseDurationMs);
1349
Sergey Silkin02371062019-01-31 16:45:42 +01001350 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type_);
Ilya Nikolaevskiy879f5a32018-05-31 09:47:17 +02001351 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1352 }
1353
1354 statistics_proxy_.reset();
1355 // No freezes should be detected, as all long inter-frame delays were pauses.
Sergey Silkin02371062019-01-31 16:45:42 +01001356 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiy879f5a32018-05-31 09:47:17 +02001357 EXPECT_EQ(-1, metrics::MinSample(
1358 "WebRTC.Video.Screenshare.MeanFreezeDurationMs"));
1359 } else {
1360 EXPECT_EQ(-1, metrics::MinSample("WebRTC.Video.MeanFreezeDurationMs"));
1361 }
1362}
1363
Sergey Silkin02371062019-01-31 16:45:42 +01001364TEST_P(ReceiveStatisticsProxyTestWithContent, TimeInHdReported) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001365 const int kInterFrameDelayMs = 20;
Sergey Silkin278f8252019-01-09 14:37:40 +01001366 webrtc::VideoFrame frame_hd = CreateFrame(1280, 720);
1367 webrtc::VideoFrame frame_sd = CreateFrame(640, 360);
1368
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001369 // HD frames.
1370 for (int i = 0; i < kMinRequiredSamples; ++i) {
Sergey Silkin02371062019-01-31 16:45:42 +01001371 statistics_proxy_->OnDecodedFrame(frame_hd, absl::nullopt, content_type_);
Sergey Silkin278f8252019-01-09 14:37:40 +01001372 statistics_proxy_->OnRenderedFrame(frame_hd);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001373 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1374 }
1375 // SD frames.
1376 for (int i = 0; i < 2 * kMinRequiredSamples; ++i) {
Sergey Silkin02371062019-01-31 16:45:42 +01001377 statistics_proxy_->OnDecodedFrame(frame_sd, absl::nullopt, content_type_);
Sergey Silkin278f8252019-01-09 14:37:40 +01001378 statistics_proxy_->OnRenderedFrame(frame_sd);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001379 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1380 }
1381 // Extra last frame.
Sergey Silkin278f8252019-01-09 14:37:40 +01001382 statistics_proxy_->OnRenderedFrame(frame_sd);
1383
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001384 statistics_proxy_.reset();
1385 const int kExpectedTimeInHdPercents = 33;
Sergey Silkin02371062019-01-31 16:45:42 +01001386 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001387 EXPECT_EQ(
1388 kExpectedTimeInHdPercents,
1389 metrics::MinSample("WebRTC.Video.Screenshare.TimeInHdPercentage"));
1390 } else {
1391 EXPECT_EQ(kExpectedTimeInHdPercents,
1392 metrics::MinSample("WebRTC.Video.TimeInHdPercentage"));
1393 }
1394}
1395
Sergey Silkin02371062019-01-31 16:45:42 +01001396TEST_P(ReceiveStatisticsProxyTestWithContent, TimeInBlockyVideoReported) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001397 const int kInterFrameDelayMs = 20;
1398 const int kHighQp = 80;
1399 const int kLowQp = 30;
Sergey Silkin278f8252019-01-09 14:37:40 +01001400 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1401
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001402 // High quality frames.
1403 for (int i = 0; i < kMinRequiredSamples; ++i) {
Sergey Silkin02371062019-01-31 16:45:42 +01001404 statistics_proxy_->OnDecodedFrame(frame, kLowQp, content_type_);
Sergey Silkin278f8252019-01-09 14:37:40 +01001405 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001406 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1407 }
1408 // Blocky frames.
1409 for (int i = 0; i < 2 * kMinRequiredSamples; ++i) {
Sergey Silkin02371062019-01-31 16:45:42 +01001410 statistics_proxy_->OnDecodedFrame(frame, kHighQp, content_type_);
Sergey Silkin278f8252019-01-09 14:37:40 +01001411 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001412 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1413 }
1414 // Extra last frame.
Sergey Silkin02371062019-01-31 16:45:42 +01001415 statistics_proxy_->OnDecodedFrame(frame, kHighQp, content_type_);
Sergey Silkin278f8252019-01-09 14:37:40 +01001416 statistics_proxy_->OnRenderedFrame(frame);
1417
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001418 statistics_proxy_.reset();
1419 const int kExpectedTimeInHdPercents = 66;
Sergey Silkin02371062019-01-31 16:45:42 +01001420 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001421 EXPECT_EQ(kExpectedTimeInHdPercents,
1422 metrics::MinSample(
1423 "WebRTC.Video.Screenshare.TimeInBlockyVideoPercentage"));
1424 } else {
1425 EXPECT_EQ(kExpectedTimeInHdPercents,
1426 metrics::MinSample("WebRTC.Video.TimeInBlockyVideoPercentage"));
1427 }
1428}
1429
Sergey Silkin02371062019-01-31 16:45:42 +01001430TEST_P(ReceiveStatisticsProxyTestWithContent, DownscalesReported) {
Sergey Silkin278f8252019-01-09 14:37:40 +01001431 const int kInterFrameDelayMs = 2000; // To ensure long enough call duration.
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001432
Sergey Silkin278f8252019-01-09 14:37:40 +01001433 webrtc::VideoFrame frame_hd = CreateFrame(1280, 720);
1434 webrtc::VideoFrame frame_sd = CreateFrame(640, 360);
1435 webrtc::VideoFrame frame_ld = CreateFrame(320, 180);
1436
1437 // Call once to pass content type.
Sergey Silkin02371062019-01-31 16:45:42 +01001438 statistics_proxy_->OnDecodedFrame(frame_hd, absl::nullopt, content_type_);
Sergey Silkin278f8252019-01-09 14:37:40 +01001439
1440 statistics_proxy_->OnRenderedFrame(frame_hd);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001441 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1442
1443 // Downscale.
Sergey Silkin278f8252019-01-09 14:37:40 +01001444 statistics_proxy_->OnRenderedFrame(frame_sd);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001445 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1446
1447 // Downscale.
Sergey Silkin278f8252019-01-09 14:37:40 +01001448 statistics_proxy_->OnRenderedFrame(frame_ld);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001449 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1450
1451 statistics_proxy_.reset();
Sergey Silkin278f8252019-01-09 14:37:40 +01001452 const int kExpectedDownscales = 30; // 2 per 4 seconds = 30 per minute.
Sergey Silkin02371062019-01-31 16:45:42 +01001453 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001454 EXPECT_EQ(
1455 kExpectedDownscales,
1456 metrics::MinSample(
1457 "WebRTC.Video.Screenshare.NumberResolutionDownswitchesPerMinute"));
1458 } else {
1459 EXPECT_EQ(kExpectedDownscales,
1460 metrics::MinSample(
1461 "WebRTC.Video.NumberResolutionDownswitchesPerMinute"));
1462 }
1463}
1464
Sergey Silkin02371062019-01-31 16:45:42 +01001465TEST_P(ReceiveStatisticsProxyTestWithContent,
1466 StatsAreSlicedOnSimulcastAndExperiment) {
ilnik6d5b4d62017-08-30 03:32:14 -07001467 const uint8_t experiment_id = 1;
Sergey Silkin02371062019-01-31 16:45:42 +01001468 webrtc::VideoContentType content_type = content_type_;
ilnik6d5b4d62017-08-30 03:32:14 -07001469 videocontenttypehelpers::SetExperimentId(&content_type, experiment_id);
1470 const int kInterFrameDelayMs1 = 30;
1471 const int kInterFrameDelayMs2 = 50;
Sergey Silkin278f8252019-01-09 14:37:40 +01001472 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
ilnik6d5b4d62017-08-30 03:32:14 -07001473
1474 videocontenttypehelpers::SetSimulcastId(&content_type, 1);
1475 for (int i = 0; i <= kMinRequiredSamples; ++i) {
1476 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs1);
Sergey Silkin278f8252019-01-09 14:37:40 +01001477 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type);
ilnik6d5b4d62017-08-30 03:32:14 -07001478 }
1479
1480 videocontenttypehelpers::SetSimulcastId(&content_type, 2);
1481 for (int i = 0; i <= kMinRequiredSamples; ++i) {
1482 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs2);
Sergey Silkin278f8252019-01-09 14:37:40 +01001483 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, content_type);
ilnik6d5b4d62017-08-30 03:32:14 -07001484 }
1485 statistics_proxy_.reset();
1486
1487 if (videocontenttypehelpers::IsScreenshare(content_type)) {
1488 EXPECT_EQ(
1489 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1490 EXPECT_EQ(1, metrics::NumSamples(
1491 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1492 EXPECT_EQ(1, metrics::NumSamples(
1493 "WebRTC.Video.Screenshare.InterframeDelayInMs.S0"));
1494 EXPECT_EQ(1, metrics::NumSamples(
1495 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs.S0"));
1496 EXPECT_EQ(1, metrics::NumSamples(
1497 "WebRTC.Video.Screenshare.InterframeDelayInMs.S1"));
1498 EXPECT_EQ(1, metrics::NumSamples(
1499 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs.S1"));
1500 EXPECT_EQ(1,
1501 metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"
1502 ".ExperimentGroup0"));
1503 EXPECT_EQ(
1504 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"
1505 ".ExperimentGroup0"));
1506 EXPECT_EQ(
1507 kInterFrameDelayMs1,
1508 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs.S0"));
1509 EXPECT_EQ(
1510 kInterFrameDelayMs2,
1511 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs.S1"));
1512 EXPECT_EQ(
1513 (kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1514 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1515 EXPECT_EQ(
1516 kInterFrameDelayMs2,
1517 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1518 EXPECT_EQ(
1519 (kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1520 metrics::MinSample(
1521 "WebRTC.Video.Screenshare.InterframeDelayInMs.ExperimentGroup0"));
1522 } else {
1523 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
1524 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
1525 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs.S0"));
1526 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs.S0"));
1527 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs.S1"));
1528 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs.S1"));
1529 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"
1530 ".ExperimentGroup0"));
1531 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"
1532 ".ExperimentGroup0"));
1533 EXPECT_EQ(kInterFrameDelayMs1,
1534 metrics::MinSample("WebRTC.Video.InterframeDelayInMs.S0"));
1535 EXPECT_EQ(kInterFrameDelayMs2,
1536 metrics::MinSample("WebRTC.Video.InterframeDelayInMs.S1"));
1537 EXPECT_EQ((kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1538 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
1539 EXPECT_EQ(kInterFrameDelayMs2,
1540 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
1541 EXPECT_EQ((kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1542 metrics::MinSample(
1543 "WebRTC.Video.InterframeDelayInMs.ExperimentGroup0"));
1544 }
1545}
sakale5ba44e2016-10-26 07:09:24 -07001546} // namespace webrtc