blob: 66adb83aeaeec0ca74ff8d014c4af586b26a50a5 [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
Johannes Krone76b3ab2019-10-22 13:22:26 +020019#include "absl/types/optional.h"
Mirko Bonadeid9708072019-01-25 20:26:48 +010020#include "api/scoped_refptr.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020021#include "api/video/i420_buffer.h"
22#include "api/video/video_frame.h"
Yves Gerey3e707812018-11-28 16:47:49 +010023#include "api/video/video_frame_buffer.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020024#include "api/video/video_rotation.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020025#include "system_wrappers/include/metrics.h"
Johannes Krone76b3ab2019-10-22 13:22:26 +020026#include "test/field_trial.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020027#include "test/gtest.h"
sakale5ba44e2016-10-26 07:09:24 -070028
29namespace webrtc {
asaperssonde9e5ff2016-11-02 07:14:03 -070030namespace {
31const int64_t kFreqOffsetProcessIntervalInMs = 40000;
asapersson46c4e3c2016-11-03 06:48:19 -070032const uint32_t kLocalSsrc = 123;
33const uint32_t kRemoteSsrc = 456;
34const int kMinRequiredSamples = 200;
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +020035const int kWidth = 1280;
36const int kHeight = 720;
asaperssonde9e5ff2016-11-02 07:14:03 -070037} // namespace
sakale5ba44e2016-10-26 07:09:24 -070038
39// TODO(sakal): ReceiveStatisticsProxy is lacking unittesting.
Sergey Silkin02371062019-01-31 16:45:42 +010040class ReceiveStatisticsProxyTest : public ::testing::Test {
sakale5ba44e2016-10-26 07:09:24 -070041 public:
42 ReceiveStatisticsProxyTest() : fake_clock_(1234), config_(GetTestConfig()) {}
43 virtual ~ReceiveStatisticsProxyTest() {}
44
45 protected:
46 virtual void SetUp() {
asaperssonde9e5ff2016-11-02 07:14:03 -070047 metrics::Reset();
sakale5ba44e2016-10-26 07:09:24 -070048 statistics_proxy_.reset(new ReceiveStatisticsProxy(&config_, &fake_clock_));
49 }
50
51 VideoReceiveStream::Config GetTestConfig() {
52 VideoReceiveStream::Config config(nullptr);
asapersson46c4e3c2016-11-03 06:48:19 -070053 config.rtp.local_ssrc = kLocalSsrc;
54 config.rtp.remote_ssrc = kRemoteSsrc;
sakale5ba44e2016-10-26 07:09:24 -070055 return config;
56 }
57
asapersson2077f2f2017-05-11 05:37:35 -070058 VideoFrame CreateFrame(int width, int height) {
Åsa Persson81327d52018-06-05 13:34:33 +020059 return CreateVideoFrame(width, height, 0);
60 }
61
62 VideoFrame CreateFrameWithRenderTimeMs(int64_t render_time_ms) {
63 return CreateVideoFrame(kWidth, kHeight, render_time_ms);
64 }
65
66 VideoFrame CreateVideoFrame(int width, int height, int64_t render_time_ms) {
Artem Titov1ebfb6a2019-01-03 23:49:37 +010067 VideoFrame frame =
68 VideoFrame::Builder()
69 .set_video_frame_buffer(I420Buffer::Create(width, height))
70 .set_timestamp_rtp(0)
71 .set_timestamp_ms(render_time_ms)
72 .set_rotation(kVideoRotation_0)
73 .build();
asapersson2077f2f2017-05-11 05:37:35 -070074 frame.set_ntp_time_ms(fake_clock_.CurrentNtpInMilliseconds());
75 return frame;
76 }
77
sakale5ba44e2016-10-26 07:09:24 -070078 SimulatedClock fake_clock_;
asaperssonde9e5ff2016-11-02 07:14:03 -070079 const VideoReceiveStream::Config config_;
sakale5ba44e2016-10-26 07:09:24 -070080 std::unique_ptr<ReceiveStatisticsProxy> statistics_proxy_;
sakale5ba44e2016-10-26 07:09:24 -070081};
82
83TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameIncreasesFramesDecoded) {
84 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_decoded);
Sergey Silkin278f8252019-01-09 14:37:40 +010085 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
sakale5ba44e2016-10-26 07:09:24 -070086 for (uint32_t i = 1; i <= 3; ++i) {
Johannes Kronbfd343b2019-07-01 10:07:50 +020087 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
ilnik00d802b2017-04-11 10:34:31 -070088 VideoContentType::UNSPECIFIED);
sakale5ba44e2016-10-26 07:09:24 -070089 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_decoded);
90 }
91}
92
Åsa Perssonb9b07ea2018-01-24 17:04:07 +010093TEST_F(ReceiveStatisticsProxyTest, DecodedFpsIsReported) {
94 const int kFps = 20;
95 const int kRequiredSamples = metrics::kMinRunTimeInSeconds * kFps;
Sergey Silkin278f8252019-01-09 14:37:40 +010096 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Åsa Perssonb9b07ea2018-01-24 17:04:07 +010097 for (int i = 0; i < kRequiredSamples; ++i) {
Johannes Kronbfd343b2019-07-01 10:07:50 +020098 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Sergey Silkin278f8252019-01-09 14:37:40 +010099 VideoContentType::UNSPECIFIED);
Åsa Perssonb9b07ea2018-01-24 17:04:07 +0100100 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
101 }
Niels Möllerd7819652019-08-13 14:43:02 +0200102 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
103 nullptr);
Åsa Perssonb9b07ea2018-01-24 17:04:07 +0100104 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
105 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DecodedFramesPerSecond", kFps));
106}
107
108TEST_F(ReceiveStatisticsProxyTest, DecodedFpsIsNotReportedForTooFewSamples) {
109 const int kFps = 20;
110 const int kRequiredSamples = metrics::kMinRunTimeInSeconds * kFps;
Sergey Silkin278f8252019-01-09 14:37:40 +0100111 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Åsa Perssonb9b07ea2018-01-24 17:04:07 +0100112 for (int i = 0; i < kRequiredSamples - 1; ++i) {
Johannes Kronbfd343b2019-07-01 10:07:50 +0200113 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Sergey Silkin278f8252019-01-09 14:37:40 +0100114 VideoContentType::UNSPECIFIED);
Åsa Perssonb9b07ea2018-01-24 17:04:07 +0100115 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
116 }
Niels Möllerd7819652019-08-13 14:43:02 +0200117 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
118 nullptr);
Åsa Perssonb9b07ea2018-01-24 17:04:07 +0100119 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
120}
121
Johannes Kronbfd343b2019-07-01 10:07:50 +0200122TEST_F(ReceiveStatisticsProxyTest,
123 OnDecodedFrameWithQpDoesNotResetFramesDecodedOrTotalDecodeTime) {
sakalcc452e12017-02-09 04:53:45 -0800124 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_decoded);
Sergey Silkin278f8252019-01-09 14:37:40 +0100125 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200126 unsigned int expected_total_decode_time_ms = 0;
127 unsigned int expected_frames_decoded = 0;
sakalcc452e12017-02-09 04:53:45 -0800128 for (uint32_t i = 1; i <= 3; ++i) {
Johannes Kronbfd343b2019-07-01 10:07:50 +0200129 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 1,
ilnik00d802b2017-04-11 10:34:31 -0700130 VideoContentType::UNSPECIFIED);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200131 expected_total_decode_time_ms += 1;
132 ++expected_frames_decoded;
133 EXPECT_EQ(expected_frames_decoded,
134 statistics_proxy_->GetStats().frames_decoded);
135 EXPECT_EQ(expected_total_decode_time_ms,
136 statistics_proxy_->GetStats().total_decode_time_ms);
sakalcc452e12017-02-09 04:53:45 -0800137 }
Johannes Kronbfd343b2019-07-01 10:07:50 +0200138 statistics_proxy_->OnDecodedFrame(frame, 1u, 3,
139 VideoContentType::UNSPECIFIED);
140 ++expected_frames_decoded;
141 expected_total_decode_time_ms += 3;
142 EXPECT_EQ(expected_frames_decoded,
143 statistics_proxy_->GetStats().frames_decoded);
144 EXPECT_EQ(expected_total_decode_time_ms,
145 statistics_proxy_->GetStats().total_decode_time_ms);
sakalcc452e12017-02-09 04:53:45 -0800146}
147
148TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameIncreasesQpSum) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200149 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
Sergey Silkin278f8252019-01-09 14:37:40 +0100150 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200151 statistics_proxy_->OnDecodedFrame(frame, 3u, 0,
152 VideoContentType::UNSPECIFIED);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100153 EXPECT_EQ(3u, statistics_proxy_->GetStats().qp_sum);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200154 statistics_proxy_->OnDecodedFrame(frame, 127u, 0,
155 VideoContentType::UNSPECIFIED);
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100156 EXPECT_EQ(130u, statistics_proxy_->GetStats().qp_sum);
sakalcc452e12017-02-09 04:53:45 -0800157}
158
Johannes Kronbfd343b2019-07-01 10:07:50 +0200159TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameIncreasesTotalDecodeTime) {
160 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
161 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
162 statistics_proxy_->OnDecodedFrame(frame, 3u, 4,
163 VideoContentType::UNSPECIFIED);
164 EXPECT_EQ(4u, statistics_proxy_->GetStats().total_decode_time_ms);
165 statistics_proxy_->OnDecodedFrame(frame, 127u, 7,
166 VideoContentType::UNSPECIFIED);
167 EXPECT_EQ(11u, statistics_proxy_->GetStats().total_decode_time_ms);
168}
169
ilnik2e1b40b2017-09-04 07:57:17 -0700170TEST_F(ReceiveStatisticsProxyTest, ReportsContentType) {
171 const std::string kRealtimeString("realtime");
172 const std::string kScreenshareString("screen");
Sergey Silkin278f8252019-01-09 14:37:40 +0100173 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
ilnik2e1b40b2017-09-04 07:57:17 -0700174 EXPECT_EQ(kRealtimeString, videocontenttypehelpers::ToString(
Sergey Silkin02371062019-01-31 16:45:42 +0100175 statistics_proxy_->GetStats().content_type));
Johannes Kronbfd343b2019-07-01 10:07:50 +0200176 statistics_proxy_->OnDecodedFrame(frame, 3u, 0,
177 VideoContentType::SCREENSHARE);
Sergey Silkin02371062019-01-31 16:45:42 +0100178 EXPECT_EQ(kScreenshareString,
179 videocontenttypehelpers::ToString(
180 statistics_proxy_->GetStats().content_type));
Johannes Kronbfd343b2019-07-01 10:07:50 +0200181 statistics_proxy_->OnDecodedFrame(frame, 3u, 0,
182 VideoContentType::UNSPECIFIED);
ilnik2e1b40b2017-09-04 07:57:17 -0700183 EXPECT_EQ(kRealtimeString, videocontenttypehelpers::ToString(
Sergey Silkin02371062019-01-31 16:45:42 +0100184 statistics_proxy_->GetStats().content_type));
ilnik2e1b40b2017-09-04 07:57:17 -0700185}
186
ilnika79cc282017-08-23 05:24:10 -0700187TEST_F(ReceiveStatisticsProxyTest, ReportsMaxInterframeDelay) {
Sergey Silkin278f8252019-01-09 14:37:40 +0100188 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
ilnika79cc282017-08-23 05:24:10 -0700189 const int64_t kInterframeDelayMs1 = 100;
190 const int64_t kInterframeDelayMs2 = 200;
191 const int64_t kInterframeDelayMs3 = 100;
192 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200193 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200194 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700195 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
ilnikf04afde2017-07-07 01:26:24 -0700196
197 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs1);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200198 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200199 VideoContentType::UNSPECIFIED);
ilnikf04afde2017-07-07 01:26:24 -0700200 EXPECT_EQ(kInterframeDelayMs1,
ilnika79cc282017-08-23 05:24:10 -0700201 statistics_proxy_->GetStats().interframe_delay_max_ms);
ilnikf04afde2017-07-07 01:26:24 -0700202
203 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs2);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200204 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200205 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700206 EXPECT_EQ(kInterframeDelayMs2,
207 statistics_proxy_->GetStats().interframe_delay_max_ms);
208
209 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs3);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200210 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200211 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700212 // kInterframeDelayMs3 is smaller than kInterframeDelayMs2.
213 EXPECT_EQ(kInterframeDelayMs2,
214 statistics_proxy_->GetStats().interframe_delay_max_ms);
215}
216
217TEST_F(ReceiveStatisticsProxyTest, ReportInterframeDelayInWindow) {
Sergey Silkin278f8252019-01-09 14:37:40 +0100218 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Ilya Nikolaevskiyb06b3582017-10-16 17:59:12 +0200219 const int64_t kInterframeDelayMs1 = 900;
220 const int64_t kInterframeDelayMs2 = 750;
221 const int64_t kInterframeDelayMs3 = 700;
ilnika79cc282017-08-23 05:24:10 -0700222 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200223 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200224 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700225 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
226
227 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs1);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200228 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200229 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700230 EXPECT_EQ(kInterframeDelayMs1,
231 statistics_proxy_->GetStats().interframe_delay_max_ms);
232
233 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs2);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200234 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200235 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700236 // Still first delay is the maximum
237 EXPECT_EQ(kInterframeDelayMs1,
238 statistics_proxy_->GetStats().interframe_delay_max_ms);
239
240 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs3);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200241 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +0200242 VideoContentType::UNSPECIFIED);
ilnika79cc282017-08-23 05:24:10 -0700243 // Now the first sample is out of the window, so the second is the maximum.
244 EXPECT_EQ(kInterframeDelayMs2,
245 statistics_proxy_->GetStats().interframe_delay_max_ms);
ilnikf04afde2017-07-07 01:26:24 -0700246}
247
Sergey Silkin02371062019-01-31 16:45:42 +0100248TEST_F(ReceiveStatisticsProxyTest, ReportsFreezeMetrics) {
249 const int64_t kFreezeDurationMs = 1000;
250
251 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
252 EXPECT_EQ(0u, stats.freeze_count);
253 EXPECT_FALSE(stats.total_freezes_duration_ms);
254
255 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
256 for (size_t i = 0; i < VideoQualityObserver::kMinFrameSamplesToDetectFreeze;
257 ++i) {
258 fake_clock_.AdvanceTimeMilliseconds(30);
259 statistics_proxy_->OnRenderedFrame(frame);
260 }
261
262 // Freeze.
263 fake_clock_.AdvanceTimeMilliseconds(kFreezeDurationMs);
264 statistics_proxy_->OnRenderedFrame(frame);
265
266 stats = statistics_proxy_->GetStats();
267 EXPECT_EQ(1u, stats.freeze_count);
268 EXPECT_EQ(kFreezeDurationMs, stats.total_freezes_duration_ms);
269}
270
271TEST_F(ReceiveStatisticsProxyTest, ReportsPauseMetrics) {
272 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
273 ASSERT_EQ(0u, stats.pause_count);
274 ASSERT_EQ(0u, stats.total_pauses_duration_ms);
275
276 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
277 statistics_proxy_->OnRenderedFrame(frame);
278
279 // Pause.
280 fake_clock_.AdvanceTimeMilliseconds(5432);
281 statistics_proxy_->OnStreamInactive();
282 statistics_proxy_->OnRenderedFrame(frame);
283
284 stats = statistics_proxy_->GetStats();
285 EXPECT_EQ(1u, stats.pause_count);
286 EXPECT_EQ(5432u, stats.total_pauses_duration_ms);
287}
288
289TEST_F(ReceiveStatisticsProxyTest, PauseBeforeFirstAndAfterLastFrameIgnored) {
290 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
291 ASSERT_EQ(0u, stats.pause_count);
292 ASSERT_EQ(0u, stats.total_pauses_duration_ms);
293
294 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
295
296 // Pause -> Frame -> Pause
297 fake_clock_.AdvanceTimeMilliseconds(5000);
298 statistics_proxy_->OnStreamInactive();
299 statistics_proxy_->OnRenderedFrame(frame);
300
301 fake_clock_.AdvanceTimeMilliseconds(30);
302 statistics_proxy_->OnRenderedFrame(frame);
303
304 fake_clock_.AdvanceTimeMilliseconds(5000);
305 statistics_proxy_->OnStreamInactive();
306
307 stats = statistics_proxy_->GetStats();
308 EXPECT_EQ(0u, stats.pause_count);
309 EXPECT_EQ(0u, stats.total_pauses_duration_ms);
310}
311
312TEST_F(ReceiveStatisticsProxyTest, ReportsFramesDuration) {
313 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
314 ASSERT_EQ(0u, stats.total_frames_duration_ms);
315
316 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
317
318 // Emulate delay before first frame is rendered. This is needed to ensure
319 // that frame duration only covers time since first frame is rendered and
320 // not the total time.
321 fake_clock_.AdvanceTimeMilliseconds(5432);
322
323 for (int i = 0; i <= 10; ++i) {
324 fake_clock_.AdvanceTimeMilliseconds(30);
325 statistics_proxy_->OnRenderedFrame(frame);
326 }
327
328 stats = statistics_proxy_->GetStats();
329 EXPECT_EQ(10 * 30u, stats.total_frames_duration_ms);
330}
331
332TEST_F(ReceiveStatisticsProxyTest, ReportsSumSquaredFrameDurations) {
333 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
334 ASSERT_EQ(0u, stats.sum_squared_frame_durations);
335
336 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
337 for (int i = 0; i <= 10; ++i) {
338 fake_clock_.AdvanceTimeMilliseconds(30);
339 statistics_proxy_->OnRenderedFrame(frame);
340 }
341
342 stats = statistics_proxy_->GetStats();
343 const double kExpectedSumSquaredFrameDurationsSecs =
344 10 * (30 / 1000.0 * 30 / 1000.0);
345 EXPECT_EQ(kExpectedSumSquaredFrameDurationsSecs,
346 stats.sum_squared_frame_durations);
347}
348
sakalcc452e12017-02-09 04:53:45 -0800349TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameWithoutQpQpSumWontExist) {
Sergey Silkin278f8252019-01-09 14:37:40 +0100350 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200351 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200352 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
ilnik00d802b2017-04-11 10:34:31 -0700353 VideoContentType::UNSPECIFIED);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200354 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakalcc452e12017-02-09 04:53:45 -0800355}
356
Mirta Dvornicic608083b2019-10-03 15:52:36 +0200357TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameWithoutQpResetsQpSum) {
Sergey Silkin278f8252019-01-09 14:37:40 +0100358 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200359 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200360 statistics_proxy_->OnDecodedFrame(frame, 3u, 0,
ilnik00d802b2017-04-11 10:34:31 -0700361 VideoContentType::UNSPECIFIED);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200362 EXPECT_EQ(3u, statistics_proxy_->GetStats().qp_sum);
363 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
364 VideoContentType::UNSPECIFIED);
Mirta Dvornicic608083b2019-10-03 15:52:36 +0200365 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
sakalcc452e12017-02-09 04:53:45 -0800366}
367
hbos50cfe1f2017-01-23 07:21:55 -0800368TEST_F(ReceiveStatisticsProxyTest, OnRenderedFrameIncreasesFramesRendered) {
369 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_rendered);
Sergey Silkin278f8252019-01-09 14:37:40 +0100370 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
hbos50cfe1f2017-01-23 07:21:55 -0800371 for (uint32_t i = 1; i <= 3; ++i) {
372 statistics_proxy_->OnRenderedFrame(frame);
373 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_rendered);
374 }
375}
376
asapersson46c4e3c2016-11-03 06:48:19 -0700377TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsSsrc) {
378 EXPECT_EQ(kRemoteSsrc, statistics_proxy_->GetStats().ssrc);
379}
380
381TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsIncomingPayloadType) {
382 const int kPayloadType = 111;
383 statistics_proxy_->OnIncomingPayloadType(kPayloadType);
384 EXPECT_EQ(kPayloadType, statistics_proxy_->GetStats().current_payload_type);
385}
386
asapersson6966bd52017-01-03 00:44:06 -0800387TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsDecoderImplementationName) {
388 const char* kName = "decoderName";
389 statistics_proxy_->OnDecoderImplementationName(kName);
390 EXPECT_STREQ(
391 kName, statistics_proxy_->GetStats().decoder_implementation_name.c_str());
392}
393
philipela45102f2017-02-22 05:30:39 -0800394TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsOnCompleteFrame) {
395 const int kFrameSizeBytes = 1000;
ilnik6d5b4d62017-08-30 03:32:14 -0700396 statistics_proxy_->OnCompleteFrame(true, kFrameSizeBytes,
397 VideoContentType::UNSPECIFIED);
philipela45102f2017-02-22 05:30:39 -0800398 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
399 EXPECT_EQ(1, stats.network_frame_rate);
philipela45102f2017-02-22 05:30:39 -0800400 EXPECT_EQ(1, stats.frame_counts.key_frames);
401 EXPECT_EQ(0, stats.frame_counts.delta_frames);
asapersson46c4e3c2016-11-03 06:48:19 -0700402}
403
Johannes Kron0c141c52019-08-26 15:04:43 +0200404TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsOnDroppedFrame) {
405 unsigned int dropped_frames = 0;
406 for (int i = 0; i < 10; ++i) {
407 statistics_proxy_->OnDroppedFrames(i);
408 dropped_frames += i;
409 }
410 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
411 EXPECT_EQ(dropped_frames, stats.frames_dropped);
412}
413
asapersson46c4e3c2016-11-03 06:48:19 -0700414TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsDecodeTimingStats) {
asapersson46c4e3c2016-11-03 06:48:19 -0700415 const int kMaxDecodeMs = 2;
416 const int kCurrentDelayMs = 3;
417 const int kTargetDelayMs = 4;
418 const int kJitterBufferMs = 5;
419 const int kMinPlayoutDelayMs = 6;
420 const int kRenderDelayMs = 7;
421 const int64_t kRttMs = 8;
philipela45102f2017-02-22 05:30:39 -0800422 statistics_proxy_->OnRttUpdate(kRttMs, 0);
423 statistics_proxy_->OnFrameBufferTimingsUpdated(
Johannes Kronbfd343b2019-07-01 10:07:50 +0200424 kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs, kJitterBufferMs,
philipela45102f2017-02-22 05:30:39 -0800425 kMinPlayoutDelayMs, kRenderDelayMs);
asapersson46c4e3c2016-11-03 06:48:19 -0700426 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
asapersson46c4e3c2016-11-03 06:48:19 -0700427 EXPECT_EQ(kMaxDecodeMs, stats.max_decode_ms);
428 EXPECT_EQ(kCurrentDelayMs, stats.current_delay_ms);
429 EXPECT_EQ(kTargetDelayMs, stats.target_delay_ms);
430 EXPECT_EQ(kJitterBufferMs, stats.jitter_buffer_ms);
431 EXPECT_EQ(kMinPlayoutDelayMs, stats.min_playout_delay_ms);
432 EXPECT_EQ(kRenderDelayMs, stats.render_delay_ms);
433}
434
asapersson6966bd52017-01-03 00:44:06 -0800435TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsRtcpPacketTypeCounts) {
436 const uint32_t kFirPackets = 33;
437 const uint32_t kPliPackets = 44;
438 const uint32_t kNackPackets = 55;
439 RtcpPacketTypeCounter counter;
440 counter.fir_packets = kFirPackets;
441 counter.pli_packets = kPliPackets;
442 counter.nack_packets = kNackPackets;
443 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
444 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
445 EXPECT_EQ(kFirPackets, stats.rtcp_packet_type_counts.fir_packets);
446 EXPECT_EQ(kPliPackets, stats.rtcp_packet_type_counts.pli_packets);
447 EXPECT_EQ(kNackPackets, stats.rtcp_packet_type_counts.nack_packets);
448}
449
450TEST_F(ReceiveStatisticsProxyTest,
451 GetStatsReportsNoRtcpPacketTypeCountsForUnknownSsrc) {
452 RtcpPacketTypeCounter counter;
453 counter.fir_packets = 33;
454 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc + 1, counter);
455 EXPECT_EQ(0u,
456 statistics_proxy_->GetStats().rtcp_packet_type_counts.fir_packets);
457}
458
459TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsFrameCounts) {
460 const int kKeyFrames = 3;
461 const int kDeltaFrames = 22;
Niels Möllerdd41da62019-03-28 08:59:07 +0100462 for (int i = 0; i < kKeyFrames; i++) {
463 statistics_proxy_->OnCompleteFrame(true, 0, VideoContentType::UNSPECIFIED);
464 }
465 for (int i = 0; i < kDeltaFrames; i++) {
466 statistics_proxy_->OnCompleteFrame(false, 0, VideoContentType::UNSPECIFIED);
467 }
468
asapersson6966bd52017-01-03 00:44:06 -0800469 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
470 EXPECT_EQ(kKeyFrames, stats.frame_counts.key_frames);
471 EXPECT_EQ(kDeltaFrames, stats.frame_counts.delta_frames);
472}
473
asapersson6966bd52017-01-03 00:44:06 -0800474TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsCName) {
475 const char* kName = "cName";
Niels Möller4d7c4052019-08-05 12:45:19 +0200476 statistics_proxy_->OnCname(kRemoteSsrc, kName);
asapersson6966bd52017-01-03 00:44:06 -0800477 EXPECT_STREQ(kName, statistics_proxy_->GetStats().c_name.c_str());
478}
479
480TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsNoCNameForUnknownSsrc) {
481 const char* kName = "cName";
Niels Möller4d7c4052019-08-05 12:45:19 +0200482 statistics_proxy_->OnCname(kRemoteSsrc + 1, kName);
asapersson6966bd52017-01-03 00:44:06 -0800483 EXPECT_STREQ("", statistics_proxy_->GetStats().c_name.c_str());
484}
485
Jonas Olssona4d87372019-07-05 19:08:33 +0200486TEST_F(ReceiveStatisticsProxyTest, ReportsLongestTimingFrameInfo) {
ilnik2edc6842017-07-06 03:06:50 -0700487 const int64_t kShortEndToEndDelay = 10;
488 const int64_t kMedEndToEndDelay = 20;
489 const int64_t kLongEndToEndDelay = 100;
490 const uint32_t kExpectedRtpTimestamp = 2;
491 TimingFrameInfo info;
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200492 absl::optional<TimingFrameInfo> result;
ilnik2edc6842017-07-06 03:06:50 -0700493 info.rtp_timestamp = kExpectedRtpTimestamp - 1;
494 info.capture_time_ms = 0;
495 info.decode_finish_ms = kShortEndToEndDelay;
496 statistics_proxy_->OnTimingFrameInfoUpdated(info);
497 info.rtp_timestamp =
498 kExpectedRtpTimestamp; // this frame should be reported in the end.
499 info.capture_time_ms = 0;
500 info.decode_finish_ms = kLongEndToEndDelay;
501 statistics_proxy_->OnTimingFrameInfoUpdated(info);
502 info.rtp_timestamp = kExpectedRtpTimestamp + 1;
503 info.capture_time_ms = 0;
504 info.decode_finish_ms = kMedEndToEndDelay;
505 statistics_proxy_->OnTimingFrameInfoUpdated(info);
ilnik75204c52017-09-04 03:35:40 -0700506 result = statistics_proxy_->GetStats().timing_frame_info;
ilnik2edc6842017-07-06 03:06:50 -0700507 EXPECT_TRUE(result);
508 EXPECT_EQ(kExpectedRtpTimestamp, result->rtp_timestamp);
509}
510
ilnik75204c52017-09-04 03:35:40 -0700511TEST_F(ReceiveStatisticsProxyTest, RespectsReportingIntervalForTimingFrames) {
512 TimingFrameInfo info;
ilnik2edc6842017-07-06 03:06:50 -0700513 const int64_t kShortEndToEndDelay = 10;
514 const uint32_t kExpectedRtpTimestamp = 2;
ilnik75204c52017-09-04 03:35:40 -0700515 const int64_t kShortDelayMs = 1000;
516 const int64_t kLongDelayMs = 10000;
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200517 absl::optional<TimingFrameInfo> result;
ilnik2edc6842017-07-06 03:06:50 -0700518 info.rtp_timestamp = kExpectedRtpTimestamp;
519 info.capture_time_ms = 0;
520 info.decode_finish_ms = kShortEndToEndDelay;
521 statistics_proxy_->OnTimingFrameInfoUpdated(info);
ilnik75204c52017-09-04 03:35:40 -0700522 fake_clock_.AdvanceTimeMilliseconds(kShortDelayMs);
523 result = statistics_proxy_->GetStats().timing_frame_info;
ilnik2edc6842017-07-06 03:06:50 -0700524 EXPECT_TRUE(result);
525 EXPECT_EQ(kExpectedRtpTimestamp, result->rtp_timestamp);
ilnik75204c52017-09-04 03:35:40 -0700526 fake_clock_.AdvanceTimeMilliseconds(kLongDelayMs);
527 result = statistics_proxy_->GetStats().timing_frame_info;
ilnik2edc6842017-07-06 03:06:50 -0700528 EXPECT_FALSE(result);
529}
530
asapersson46c4e3c2016-11-03 06:48:19 -0700531TEST_F(ReceiveStatisticsProxyTest, LifetimeHistogramIsUpdated) {
532 const int64_t kTimeSec = 3;
533 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
ilnik6d5b4d62017-08-30 03:32:14 -0700534 // Need at least one frame to report stream lifetime.
535 statistics_proxy_->OnCompleteFrame(true, 1000, VideoContentType::UNSPECIFIED);
Niels Möllerd7819652019-08-13 14:43:02 +0200536 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
537 nullptr);
asapersson46c4e3c2016-11-03 06:48:19 -0700538 EXPECT_EQ(1,
539 metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
540 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceiveStreamLifetimeInSeconds",
541 kTimeSec));
542}
543
ilnik6d5b4d62017-08-30 03:32:14 -0700544TEST_F(ReceiveStatisticsProxyTest,
545 LifetimeHistogramNotReportedForEmptyStreams) {
546 const int64_t kTimeSec = 3;
547 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
548 // No frames received.
Niels Möllerd7819652019-08-13 14:43:02 +0200549 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
550 nullptr);
ilnik6d5b4d62017-08-30 03:32:14 -0700551 EXPECT_EQ(0,
552 metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
553}
554
palmkvista40672a2017-01-13 05:58:34 -0800555TEST_F(ReceiveStatisticsProxyTest, BadCallHistogramsAreUpdated) {
556 // Based on the tuning parameters this will produce 7 uncertain states,
557 // then 10 certainly bad states. There has to be 10 certain states before
558 // any histograms are recorded.
559 const int kNumBadSamples = 17;
Niels Möller9b0b1e02019-03-22 13:56:46 +0100560 // We only count one sample per second.
561 const int kBadFameIntervalMs = 1100;
palmkvista40672a2017-01-13 05:58:34 -0800562
563 StreamDataCounters counters;
564 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
palmkvista40672a2017-01-13 05:58:34 -0800565
Niels Möller9b0b1e02019-03-22 13:56:46 +0100566 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
567
palmkvista40672a2017-01-13 05:58:34 -0800568 for (int i = 0; i < kNumBadSamples; ++i) {
Niels Möller9b0b1e02019-03-22 13:56:46 +0100569 fake_clock_.AdvanceTimeMilliseconds(kBadFameIntervalMs);
570 statistics_proxy_->OnRenderedFrame(frame);
palmkvista40672a2017-01-13 05:58:34 -0800571 }
Niels Möllerd7819652019-08-13 14:43:02 +0200572 statistics_proxy_->UpdateHistograms(absl::nullopt, counters, nullptr);
palmkvista40672a2017-01-13 05:58:34 -0800573 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BadCall.Any"));
574 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BadCall.Any", 100));
575
576 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BadCall.FrameRate"));
577 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BadCall.FrameRate", 100));
578
579 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.BadCall.FrameRateVariance"));
580
581 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.BadCall.Qp"));
582}
583
asapersson0c43f772016-11-30 01:42:26 -0800584TEST_F(ReceiveStatisticsProxyTest, PacketLossHistogramIsUpdated) {
Niels Möllerd7819652019-08-13 14:43:02 +0200585 statistics_proxy_->UpdateHistograms(10, StreamDataCounters(), nullptr);
asapersson0c43f772016-11-30 01:42:26 -0800586 EXPECT_EQ(0,
587 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
588
Niels Möller9a9f18a2019-08-02 13:52:37 +0200589 // Restart
asapersson0c43f772016-11-30 01:42:26 -0800590 SetUp();
Niels Möller9a9f18a2019-08-02 13:52:37 +0200591
592 // Min run time has passed.
593 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
Niels Möllerd7819652019-08-13 14:43:02 +0200594 statistics_proxy_->UpdateHistograms(10, StreamDataCounters(), nullptr);
asapersson0c43f772016-11-30 01:42:26 -0800595 EXPECT_EQ(1,
596 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
Niels Möller9a9f18a2019-08-02 13:52:37 +0200597 EXPECT_EQ(
598 1, metrics::NumEvents("WebRTC.Video.ReceivedPacketsLostInPercent", 10));
asapersson0c43f772016-11-30 01:42:26 -0800599}
600
asapersson2077f2f2017-05-11 05:37:35 -0700601TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsAvSyncOffset) {
602 const int64_t kSyncOffsetMs = 22;
603 const double kFreqKhz = 90.0;
604 EXPECT_EQ(std::numeric_limits<int>::max(),
605 statistics_proxy_->GetStats().sync_offset_ms);
606 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
607 EXPECT_EQ(kSyncOffsetMs, statistics_proxy_->GetStats().sync_offset_ms);
608}
609
asapersson46c4e3c2016-11-03 06:48:19 -0700610TEST_F(ReceiveStatisticsProxyTest, AvSyncOffsetHistogramIsUpdated) {
611 const int64_t kSyncOffsetMs = 22;
612 const double kFreqKhz = 90.0;
613 for (int i = 0; i < kMinRequiredSamples; ++i)
614 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
Niels Möllerd7819652019-08-13 14:43:02 +0200615 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
616 nullptr);
asapersson46c4e3c2016-11-03 06:48:19 -0700617 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AVSyncOffsetInMs"));
618 EXPECT_EQ(1,
619 metrics::NumEvents("WebRTC.Video.AVSyncOffsetInMs", kSyncOffsetMs));
620}
621
asaperssonde9e5ff2016-11-02 07:14:03 -0700622TEST_F(ReceiveStatisticsProxyTest, RtpToNtpFrequencyOffsetHistogramIsUpdated) {
623 const int64_t kSyncOffsetMs = 22;
624 const double kFreqKhz = 90.0;
625 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
626 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz + 2.2);
627 fake_clock_.AdvanceTimeMilliseconds(kFreqOffsetProcessIntervalInMs);
628 // Process interval passed, max diff: 2.
629 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz + 1.1);
630 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz - 4.2);
631 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz - 0.9);
632 fake_clock_.AdvanceTimeMilliseconds(kFreqOffsetProcessIntervalInMs);
633 // Process interval passed, max diff: 4.
634 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
Niels Möllerd7819652019-08-13 14:43:02 +0200635 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
636 nullptr);
asaperssonde9e5ff2016-11-02 07:14:03 -0700637 // Average reported: (2 + 4) / 2 = 3.
638 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtpToNtpFreqOffsetInKhz"));
639 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtpToNtpFreqOffsetInKhz", 3));
640}
641
asapersson6966bd52017-01-03 00:44:06 -0800642TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsUpdated) {
643 const int kQp = 22;
asapersson6966bd52017-01-03 00:44:06 -0800644
645 for (int i = 0; i < kMinRequiredSamples; ++i)
Niels Möller147013a2018-10-01 15:56:33 +0200646 statistics_proxy_->OnPreDecode(kVideoCodecVP8, kQp);
asapersson6966bd52017-01-03 00:44:06 -0800647
Niels Möllerd7819652019-08-13 14:43:02 +0200648 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
649 nullptr);
asapersson6966bd52017-01-03 00:44:06 -0800650 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
651 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Decoded.Vp8.Qp", kQp));
652}
653
654TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsNotUpdatedForTooFewSamples) {
Niels Möller147013a2018-10-01 15:56:33 +0200655 const int kQp = 22;
asapersson6966bd52017-01-03 00:44:06 -0800656
657 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
Niels Möller147013a2018-10-01 15:56:33 +0200658 statistics_proxy_->OnPreDecode(kVideoCodecVP8, kQp);
asapersson6966bd52017-01-03 00:44:06 -0800659
Niels Möllerd7819652019-08-13 14:43:02 +0200660 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
661 nullptr);
asapersson6966bd52017-01-03 00:44:06 -0800662 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
663}
664
665TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsNotUpdatedIfNoQpValue) {
asapersson6966bd52017-01-03 00:44:06 -0800666 for (int i = 0; i < kMinRequiredSamples; ++i)
Niels Möller147013a2018-10-01 15:56:33 +0200667 statistics_proxy_->OnPreDecode(kVideoCodecVP8, -1);
asapersson6966bd52017-01-03 00:44:06 -0800668
Niels Möllerd7819652019-08-13 14:43:02 +0200669 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
670 nullptr);
asapersson6966bd52017-01-03 00:44:06 -0800671 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
672}
673
asaperssonb99baf82017-04-20 04:05:43 -0700674TEST_F(ReceiveStatisticsProxyTest,
675 KeyFrameHistogramNotUpdatedForTooFewSamples) {
676 const bool kIsKeyFrame = false;
677 const int kFrameSizeBytes = 1000;
678
679 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
ilnik6d5b4d62017-08-30 03:32:14 -0700680 statistics_proxy_->OnCompleteFrame(kIsKeyFrame, kFrameSizeBytes,
681 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 04:05:43 -0700682
683 EXPECT_EQ(0, statistics_proxy_->GetStats().frame_counts.key_frames);
684 EXPECT_EQ(kMinRequiredSamples - 1,
685 statistics_proxy_->GetStats().frame_counts.delta_frames);
686
Niels Möllerd7819652019-08-13 14:43:02 +0200687 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
688 nullptr);
asaperssonb99baf82017-04-20 04:05:43 -0700689 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
690}
691
692TEST_F(ReceiveStatisticsProxyTest,
693 KeyFrameHistogramUpdatedForMinRequiredSamples) {
694 const bool kIsKeyFrame = false;
695 const int kFrameSizeBytes = 1000;
696
697 for (int i = 0; i < kMinRequiredSamples; ++i)
ilnik6d5b4d62017-08-30 03:32:14 -0700698 statistics_proxy_->OnCompleteFrame(kIsKeyFrame, kFrameSizeBytes,
699 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 04:05:43 -0700700
701 EXPECT_EQ(0, statistics_proxy_->GetStats().frame_counts.key_frames);
702 EXPECT_EQ(kMinRequiredSamples,
703 statistics_proxy_->GetStats().frame_counts.delta_frames);
704
Niels Möllerd7819652019-08-13 14:43:02 +0200705 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
706 nullptr);
asaperssonb99baf82017-04-20 04:05:43 -0700707 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
708 EXPECT_EQ(1,
709 metrics::NumEvents("WebRTC.Video.KeyFramesReceivedInPermille", 0));
710}
711
712TEST_F(ReceiveStatisticsProxyTest, KeyFrameHistogramIsUpdated) {
713 const int kFrameSizeBytes = 1000;
714
715 for (int i = 0; i < kMinRequiredSamples; ++i)
ilnik6d5b4d62017-08-30 03:32:14 -0700716 statistics_proxy_->OnCompleteFrame(true, kFrameSizeBytes,
717 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 04:05:43 -0700718
719 for (int i = 0; i < kMinRequiredSamples; ++i)
ilnik6d5b4d62017-08-30 03:32:14 -0700720 statistics_proxy_->OnCompleteFrame(false, kFrameSizeBytes,
721 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 04:05:43 -0700722
723 EXPECT_EQ(kMinRequiredSamples,
724 statistics_proxy_->GetStats().frame_counts.key_frames);
725 EXPECT_EQ(kMinRequiredSamples,
726 statistics_proxy_->GetStats().frame_counts.delta_frames);
727
Niels Möllerd7819652019-08-13 14:43:02 +0200728 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
729 nullptr);
asaperssonb99baf82017-04-20 04:05:43 -0700730 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
731 EXPECT_EQ(
732 1, metrics::NumEvents("WebRTC.Video.KeyFramesReceivedInPermille", 500));
733}
734
735TEST_F(ReceiveStatisticsProxyTest, TimingHistogramsNotUpdatedForTooFewSamples) {
asaperssonb99baf82017-04-20 04:05:43 -0700736 const int kMaxDecodeMs = 2;
737 const int kCurrentDelayMs = 3;
738 const int kTargetDelayMs = 4;
739 const int kJitterBufferMs = 5;
740 const int kMinPlayoutDelayMs = 6;
741 const int kRenderDelayMs = 7;
742
743 for (int i = 0; i < kMinRequiredSamples - 1; ++i) {
744 statistics_proxy_->OnFrameBufferTimingsUpdated(
Johannes Kronbfd343b2019-07-01 10:07:50 +0200745 kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs, kJitterBufferMs,
746 kMinPlayoutDelayMs, kRenderDelayMs);
asaperssonb99baf82017-04-20 04:05:43 -0700747 }
748
Niels Möllerd7819652019-08-13 14:43:02 +0200749 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
750 nullptr);
asaperssonb99baf82017-04-20 04:05:43 -0700751 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
752 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
753 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
754 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
755 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
756}
757
758TEST_F(ReceiveStatisticsProxyTest, TimingHistogramsAreUpdated) {
asaperssonb99baf82017-04-20 04:05:43 -0700759 const int kMaxDecodeMs = 2;
760 const int kCurrentDelayMs = 3;
761 const int kTargetDelayMs = 4;
762 const int kJitterBufferMs = 5;
763 const int kMinPlayoutDelayMs = 6;
764 const int kRenderDelayMs = 7;
765
766 for (int i = 0; i < kMinRequiredSamples; ++i) {
767 statistics_proxy_->OnFrameBufferTimingsUpdated(
Johannes Kronbfd343b2019-07-01 10:07:50 +0200768 kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs, kJitterBufferMs,
769 kMinPlayoutDelayMs, kRenderDelayMs);
asaperssonb99baf82017-04-20 04:05:43 -0700770 }
771
Niels Möllerd7819652019-08-13 14:43:02 +0200772 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
773 nullptr);
asaperssonb99baf82017-04-20 04:05:43 -0700774 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
775 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
776 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
777 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
778
asaperssonb99baf82017-04-20 04:05:43 -0700779 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.JitterBufferDelayInMs",
780 kJitterBufferMs));
781 EXPECT_EQ(1,
782 metrics::NumEvents("WebRTC.Video.TargetDelayInMs", kTargetDelayMs));
783 EXPECT_EQ(
784 1, metrics::NumEvents("WebRTC.Video.CurrentDelayInMs", kCurrentDelayMs));
785 EXPECT_EQ(1,
786 metrics::NumEvents("WebRTC.Video.OnewayDelayInMs", kTargetDelayMs));
787}
788
sprang948b2752017-05-04 02:47:13 -0700789TEST_F(ReceiveStatisticsProxyTest, DoesNotReportStaleFramerates) {
790 const int kDefaultFps = 30;
Sergey Silkin278f8252019-01-09 14:37:40 +0100791 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
sprang948b2752017-05-04 02:47:13 -0700792
793 for (int i = 0; i < kDefaultFps; ++i) {
794 // Since OnRenderedFrame is never called the fps in each sample will be 0,
795 // i.e. bad
796 frame.set_ntp_time_ms(fake_clock_.CurrentNtpInMilliseconds());
Johannes Kronbfd343b2019-07-01 10:07:50 +0200797 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
sprang948b2752017-05-04 02:47:13 -0700798 VideoContentType::UNSPECIFIED);
799 statistics_proxy_->OnRenderedFrame(frame);
800 fake_clock_.AdvanceTimeMilliseconds(1000 / kDefaultFps);
801 }
802
803 EXPECT_EQ(kDefaultFps, statistics_proxy_->GetStats().decode_frame_rate);
804 EXPECT_EQ(kDefaultFps, statistics_proxy_->GetStats().render_frame_rate);
805
806 // FPS trackers in stats proxy have a 1000ms sliding window.
807 fake_clock_.AdvanceTimeMilliseconds(1000);
808 EXPECT_EQ(0, statistics_proxy_->GetStats().decode_frame_rate);
809 EXPECT_EQ(0, statistics_proxy_->GetStats().render_frame_rate);
810}
811
asapersson2077f2f2017-05-11 05:37:35 -0700812TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsReceivedFrameStats) {
asapersson2077f2f2017-05-11 05:37:35 -0700813 EXPECT_EQ(0, statistics_proxy_->GetStats().width);
814 EXPECT_EQ(0, statistics_proxy_->GetStats().height);
815 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_rendered);
816
817 statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight));
818
819 EXPECT_EQ(kWidth, statistics_proxy_->GetStats().width);
820 EXPECT_EQ(kHeight, statistics_proxy_->GetStats().height);
821 EXPECT_EQ(1u, statistics_proxy_->GetStats().frames_rendered);
822}
823
824TEST_F(ReceiveStatisticsProxyTest,
825 ReceivedFrameHistogramsAreNotUpdatedForTooFewSamples) {
asapersson2077f2f2017-05-11 05:37:35 -0700826 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
827 statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight));
828
Niels Möllerd7819652019-08-13 14:43:02 +0200829 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
830 nullptr);
asapersson2077f2f2017-05-11 05:37:35 -0700831 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
832 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
833 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
834 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
835}
836
837TEST_F(ReceiveStatisticsProxyTest, ReceivedFrameHistogramsAreUpdated) {
asapersson2077f2f2017-05-11 05:37:35 -0700838 for (int i = 0; i < kMinRequiredSamples; ++i)
839 statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight));
840
Niels Möllerd7819652019-08-13 14:43:02 +0200841 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
842 nullptr);
asapersson2077f2f2017-05-11 05:37:35 -0700843 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
844 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
845 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
846 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
847 EXPECT_EQ(1,
848 metrics::NumEvents("WebRTC.Video.ReceivedWidthInPixels", kWidth));
849 EXPECT_EQ(1,
850 metrics::NumEvents("WebRTC.Video.ReceivedHeightInPixels", kHeight));
851}
852
Åsa Persson81327d52018-06-05 13:34:33 +0200853TEST_F(ReceiveStatisticsProxyTest, ZeroDelayReportedIfFrameNotDelayed) {
Sergey Silkin278f8252019-01-09 14:37:40 +0100854 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200855 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Åsa Persson81327d52018-06-05 13:34:33 +0200856 VideoContentType::UNSPECIFIED);
857
858 // Frame not delayed, delayed frames to render: 0%.
859 const int64_t kNowMs = fake_clock_.TimeInMilliseconds();
860 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs));
861
862 // Min run time has passed.
863 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
Niels Möllerd7819652019-08-13 14:43:02 +0200864 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
865 nullptr);
Åsa Persson81327d52018-06-05 13:34:33 +0200866 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
867 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 0));
868 EXPECT_EQ(0, metrics::NumSamples(
869 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
870}
871
872TEST_F(ReceiveStatisticsProxyTest,
873 DelayedFrameHistogramsAreNotUpdatedIfMinRuntimeHasNotPassed) {
Sergey Silkin278f8252019-01-09 14:37:40 +0100874 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200875 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Åsa Persson81327d52018-06-05 13:34:33 +0200876 VideoContentType::UNSPECIFIED);
877
878 // Frame not delayed, delayed frames to render: 0%.
879 const int64_t kNowMs = fake_clock_.TimeInMilliseconds();
880 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs));
881
882 // Min run time has not passed.
883 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000) -
884 1);
Niels Möllerd7819652019-08-13 14:43:02 +0200885 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
886 nullptr);
Åsa Persson81327d52018-06-05 13:34:33 +0200887 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
888 EXPECT_EQ(0, metrics::NumSamples(
889 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
890}
891
892TEST_F(ReceiveStatisticsProxyTest,
893 DelayedFramesHistogramsAreNotUpdatedIfNoRenderedFrames) {
Sergey Silkin278f8252019-01-09 14:37:40 +0100894 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200895 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Åsa Persson81327d52018-06-05 13:34:33 +0200896 VideoContentType::UNSPECIFIED);
897
898 // Min run time has passed. No rendered frames.
899 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
Niels Möllerd7819652019-08-13 14:43:02 +0200900 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
901 nullptr);
Åsa Persson81327d52018-06-05 13:34:33 +0200902 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
903 EXPECT_EQ(0, metrics::NumSamples(
904 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
905}
906
907TEST_F(ReceiveStatisticsProxyTest, DelayReportedIfFrameIsDelayed) {
Sergey Silkin278f8252019-01-09 14:37:40 +0100908 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200909 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Åsa Persson81327d52018-06-05 13:34:33 +0200910 VideoContentType::UNSPECIFIED);
911
912 // Frame delayed 1 ms, delayed frames to render: 100%.
913 const int64_t kNowMs = fake_clock_.TimeInMilliseconds();
914 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs - 1));
915
916 // Min run time has passed.
917 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
Niels Möllerd7819652019-08-13 14:43:02 +0200918 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
919 nullptr);
Åsa Persson81327d52018-06-05 13:34:33 +0200920 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
921 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 100));
922 EXPECT_EQ(1, metrics::NumSamples(
923 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
924 EXPECT_EQ(1, metrics::NumEvents(
925 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs", 1));
926}
927
928TEST_F(ReceiveStatisticsProxyTest, AverageDelayOfDelayedFramesIsReported) {
Sergey Silkin278f8252019-01-09 14:37:40 +0100929 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200930 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Åsa Persson81327d52018-06-05 13:34:33 +0200931 VideoContentType::UNSPECIFIED);
932
933 // Two frames delayed (6 ms, 10 ms), delayed frames to render: 50%.
934 const int64_t kNowMs = fake_clock_.TimeInMilliseconds();
935 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs - 10));
936 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs - 6));
937 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs));
938 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs + 1));
939
940 // Min run time has passed.
941 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
Niels Möllerd7819652019-08-13 14:43:02 +0200942 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
943 nullptr);
Åsa Persson81327d52018-06-05 13:34:33 +0200944 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
945 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 50));
946 EXPECT_EQ(1, metrics::NumSamples(
947 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
948 EXPECT_EQ(1, metrics::NumEvents(
949 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs", 8));
950}
951
asapersson2077f2f2017-05-11 05:37:35 -0700952TEST_F(ReceiveStatisticsProxyTest,
953 RtcpHistogramsNotUpdatedIfMinRuntimeHasNotPassed) {
Niels Möllerd7819652019-08-13 14:43:02 +0200954 StreamDataCounters data_counters;
955 data_counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
956
asapersson2077f2f2017-05-11 05:37:35 -0700957 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000) -
958 1);
959
960 RtcpPacketTypeCounter counter;
961 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
962
Niels Möllerd7819652019-08-13 14:43:02 +0200963 statistics_proxy_->UpdateHistograms(absl::nullopt, data_counters, nullptr);
asapersson2077f2f2017-05-11 05:37:35 -0700964 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
965 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
966 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
967}
968
969TEST_F(ReceiveStatisticsProxyTest, RtcpHistogramsAreUpdated) {
Niels Möllerd7819652019-08-13 14:43:02 +0200970 StreamDataCounters data_counters;
971 data_counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
asapersson2077f2f2017-05-11 05:37:35 -0700972 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
973
974 const uint32_t kFirPackets = 100;
975 const uint32_t kPliPackets = 200;
976 const uint32_t kNackPackets = 300;
977
978 RtcpPacketTypeCounter counter;
979 counter.fir_packets = kFirPackets;
980 counter.pli_packets = kPliPackets;
981 counter.nack_packets = kNackPackets;
982 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
983
Niels Möllerd7819652019-08-13 14:43:02 +0200984 statistics_proxy_->UpdateHistograms(absl::nullopt, data_counters, nullptr);
asapersson2077f2f2017-05-11 05:37:35 -0700985 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
986 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
987 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
988 EXPECT_EQ(
989 1, metrics::NumEvents("WebRTC.Video.FirPacketsSentPerMinute",
990 kFirPackets * 60 / metrics::kMinRunTimeInSeconds));
991 EXPECT_EQ(
992 1, metrics::NumEvents("WebRTC.Video.PliPacketsSentPerMinute",
993 kPliPackets * 60 / metrics::kMinRunTimeInSeconds));
994 EXPECT_EQ(
995 1, metrics::NumEvents("WebRTC.Video.NackPacketsSentPerMinute",
996 kNackPackets * 60 / metrics::kMinRunTimeInSeconds));
997}
998
Sergey Silkin02371062019-01-31 16:45:42 +0100999class ReceiveStatisticsProxyTestWithFreezeDuration
1000 : public ReceiveStatisticsProxyTest,
Mirko Bonadei6a489f22019-04-09 15:11:12 +02001001 public ::testing::WithParamInterface<
Sergey Silkin02371062019-01-31 16:45:42 +01001002 std::tuple<uint32_t, uint32_t, uint32_t>> {
1003 protected:
1004 const uint32_t frame_duration_ms_ = {std::get<0>(GetParam())};
1005 const uint32_t freeze_duration_ms_ = {std::get<1>(GetParam())};
1006 const uint32_t expected_freeze_count_ = {std::get<2>(GetParam())};
1007};
sprang892dab52017-08-15 05:00:33 -07001008
Sergey Silkin02371062019-01-31 16:45:42 +01001009// It is a freeze if:
1010// frame_duration_ms >= max(3 * avg_frame_duration, avg_frame_duration + 150)
1011// where avg_frame_duration is average duration of last 30 frames including
1012// the current one.
1013//
1014// Condition 1: 3 * avg_frame_duration > avg_frame_duration + 150
1015const auto kFreezeDetectionCond1Freeze = std::make_tuple(150, 483, 1);
1016const auto kFreezeDetectionCond1NotFreeze = std::make_tuple(150, 482, 0);
1017// Condition 2: 3 * avg_frame_duration < avg_frame_duration + 150
1018const auto kFreezeDetectionCond2Freeze = std::make_tuple(30, 185, 1);
1019const auto kFreezeDetectionCond2NotFreeze = std::make_tuple(30, 184, 0);
1020
Mirko Bonadei12d12852019-02-05 17:04:04 +01001021INSTANTIATE_TEST_SUITE_P(_,
1022 ReceiveStatisticsProxyTestWithFreezeDuration,
1023 ::testing::Values(kFreezeDetectionCond1Freeze,
1024 kFreezeDetectionCond1NotFreeze,
1025 kFreezeDetectionCond2Freeze,
1026 kFreezeDetectionCond2NotFreeze));
Sergey Silkin02371062019-01-31 16:45:42 +01001027
1028TEST_P(ReceiveStatisticsProxyTestWithFreezeDuration, FreezeDetection) {
1029 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
1030 EXPECT_EQ(0u, stats.freeze_count);
1031 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1032
1033 // Add a very long frame. This is need to verify that average frame
1034 // duration, which is supposed to be calculated as mean of durations of
1035 // last 30 frames, is calculated correctly.
1036 statistics_proxy_->OnRenderedFrame(frame);
1037 fake_clock_.AdvanceTimeMilliseconds(2000);
1038
1039 for (size_t i = 0;
1040 i <= VideoQualityObserver::kAvgInterframeDelaysWindowSizeFrames; ++i) {
1041 fake_clock_.AdvanceTimeMilliseconds(frame_duration_ms_);
1042 statistics_proxy_->OnRenderedFrame(frame);
1043 }
1044
1045 fake_clock_.AdvanceTimeMilliseconds(freeze_duration_ms_);
1046 statistics_proxy_->OnRenderedFrame(frame);
1047
1048 stats = statistics_proxy_->GetStats();
1049 EXPECT_EQ(stats.freeze_count, expected_freeze_count_);
1050}
1051
1052class ReceiveStatisticsProxyTestWithContent
1053 : public ReceiveStatisticsProxyTest,
1054 public ::testing::WithParamInterface<webrtc::VideoContentType> {
1055 protected:
1056 const webrtc::VideoContentType content_type_{GetParam()};
1057};
1058
Mirko Bonadei12d12852019-02-05 17:04:04 +01001059INSTANTIATE_TEST_SUITE_P(ContentTypes,
1060 ReceiveStatisticsProxyTestWithContent,
1061 ::testing::Values(VideoContentType::UNSPECIFIED,
1062 VideoContentType::SCREENSHARE));
Sergey Silkin02371062019-01-31 16:45:42 +01001063
1064TEST_P(ReceiveStatisticsProxyTestWithContent, InterFrameDelaysAreReported) {
sprang892dab52017-08-15 05:00:33 -07001065 const int kInterFrameDelayMs = 33;
Sergey Silkin278f8252019-01-09 14:37:40 +01001066 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1067
sprang892dab52017-08-15 05:00:33 -07001068 for (int i = 0; i < kMinRequiredSamples; ++i) {
Johannes Kronbfd343b2019-07-01 10:07:50 +02001069 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
sprang892dab52017-08-15 05:00:33 -07001070 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1071 }
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001072 // One extra with double the interval.
sprang892dab52017-08-15 05:00:33 -07001073 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
Johannes Kronbfd343b2019-07-01 10:07:50 +02001074 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
sprang892dab52017-08-15 05:00:33 -07001075
Niels Möllerd7819652019-08-13 14:43:02 +02001076 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1077 nullptr);
sprang892dab52017-08-15 05:00:33 -07001078 const int kExpectedInterFrame =
1079 (kInterFrameDelayMs * (kMinRequiredSamples - 1) +
1080 kInterFrameDelayMs * 2) /
1081 kMinRequiredSamples;
Sergey Silkin02371062019-01-31 16:45:42 +01001082 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
ilnik6d5b4d62017-08-30 03:32:14 -07001083 EXPECT_EQ(
1084 kExpectedInterFrame,
1085 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1086 EXPECT_EQ(
1087 kInterFrameDelayMs * 2,
1088 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1089 } else {
1090 EXPECT_EQ(kExpectedInterFrame,
1091 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
1092 EXPECT_EQ(kInterFrameDelayMs * 2,
1093 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
sprang892dab52017-08-15 05:00:33 -07001094 }
1095}
1096
Sergey Silkin02371062019-01-31 16:45:42 +01001097TEST_P(ReceiveStatisticsProxyTestWithContent,
1098 InterFrameDelaysPercentilesAreReported) {
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001099 const int kInterFrameDelayMs = 33;
1100 const int kLastFivePercentsSamples = kMinRequiredSamples * 5 / 100;
Sergey Silkin278f8252019-01-09 14:37:40 +01001101 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1102
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001103 for (int i = 0; i <= kMinRequiredSamples - kLastFivePercentsSamples; ++i) {
1104 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
Johannes Kronbfd343b2019-07-01 10:07:50 +02001105 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001106 }
1107 // Last 5% of intervals are double in size.
1108 for (int i = 0; i < kLastFivePercentsSamples; ++i) {
1109 fake_clock_.AdvanceTimeMilliseconds(2 * kInterFrameDelayMs);
Johannes Kronbfd343b2019-07-01 10:07:50 +02001110 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001111 }
1112 // Final sample is outlier and 10 times as big.
1113 fake_clock_.AdvanceTimeMilliseconds(10 * kInterFrameDelayMs);
Johannes Kronbfd343b2019-07-01 10:07:50 +02001114 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001115
Niels Möllerd7819652019-08-13 14:43:02 +02001116 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1117 nullptr);
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001118 const int kExpectedInterFrame = kInterFrameDelayMs * 2;
Sergey Silkin02371062019-01-31 16:45:42 +01001119 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001120 EXPECT_EQ(kExpectedInterFrame,
1121 metrics::MinSample(
1122 "WebRTC.Video.Screenshare.InterframeDelay95PercentileInMs"));
1123 } else {
1124 EXPECT_EQ(
1125 kExpectedInterFrame,
1126 metrics::MinSample("WebRTC.Video.InterframeDelay95PercentileInMs"));
1127 }
1128}
1129
Sergey Silkin02371062019-01-31 16:45:42 +01001130TEST_P(ReceiveStatisticsProxyTestWithContent,
1131 MaxInterFrameDelayOnlyWithValidAverage) {
sprang892dab52017-08-15 05:00:33 -07001132 const int kInterFrameDelayMs = 33;
Sergey Silkin278f8252019-01-09 14:37:40 +01001133 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1134
sprang892dab52017-08-15 05:00:33 -07001135 for (int i = 0; i < kMinRequiredSamples; ++i) {
Johannes Kronbfd343b2019-07-01 10:07:50 +02001136 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
sprang892dab52017-08-15 05:00:33 -07001137 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1138 }
1139
1140 // |kMinRequiredSamples| samples, and thereby intervals, is required. That
1141 // means we're one frame short of having a valid data set.
Niels Möllerd7819652019-08-13 14:43:02 +02001142 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1143 nullptr);
sprang892dab52017-08-15 05:00:33 -07001144 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
1145 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
1146 EXPECT_EQ(
1147 0, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1148 EXPECT_EQ(0, metrics::NumSamples(
1149 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1150}
1151
Sergey Silkin02371062019-01-31 16:45:42 +01001152TEST_P(ReceiveStatisticsProxyTestWithContent, MaxInterFrameDelayOnlyWithPause) {
sprang3e86e7e2017-08-22 09:23:28 -07001153 const int kInterFrameDelayMs = 33;
Sergey Silkin278f8252019-01-09 14:37:40 +01001154 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1155
sprang3e86e7e2017-08-22 09:23:28 -07001156 for (int i = 0; i <= kMinRequiredSamples; ++i) {
Johannes Kronbfd343b2019-07-01 10:07:50 +02001157 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
sprang3e86e7e2017-08-22 09:23:28 -07001158 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1159 }
1160
1161 // At this state, we should have a valid inter-frame delay.
1162 // Indicate stream paused and make a large jump in time.
1163 statistics_proxy_->OnStreamInactive();
1164 fake_clock_.AdvanceTimeMilliseconds(5000);
1165
1166 // Insert two more frames. The interval during the pause should be disregarded
1167 // in the stats.
Johannes Kronbfd343b2019-07-01 10:07:50 +02001168 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
sprang3e86e7e2017-08-22 09:23:28 -07001169 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
Johannes Kronbfd343b2019-07-01 10:07:50 +02001170 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
sprang3e86e7e2017-08-22 09:23:28 -07001171
Niels Möllerd7819652019-08-13 14:43:02 +02001172 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1173 nullptr);
Sergey Silkin02371062019-01-31 16:45:42 +01001174 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
sprang3e86e7e2017-08-22 09:23:28 -07001175 EXPECT_EQ(
1176 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1177 EXPECT_EQ(1, metrics::NumSamples(
1178 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1179 EXPECT_EQ(
1180 kInterFrameDelayMs,
1181 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1182 EXPECT_EQ(
1183 kInterFrameDelayMs,
1184 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1185 } else {
1186 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
1187 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
1188 EXPECT_EQ(kInterFrameDelayMs,
1189 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
1190 EXPECT_EQ(kInterFrameDelayMs,
1191 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
1192 }
1193}
1194
Sergey Silkin02371062019-01-31 16:45:42 +01001195TEST_P(ReceiveStatisticsProxyTestWithContent, FreezesAreReported) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001196 const int kInterFrameDelayMs = 33;
1197 const int kFreezeDelayMs = 200;
Sergey Silkinbea18ca2018-10-02 16:22:46 +02001198 const int kCallDurationMs =
1199 kMinRequiredSamples * kInterFrameDelayMs + kFreezeDelayMs;
Sergey Silkin278f8252019-01-09 14:37:40 +01001200 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1201
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001202 for (int i = 0; i < kMinRequiredSamples; ++i) {
Johannes Kronbfd343b2019-07-01 10:07:50 +02001203 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Ilya Nikolaevskiycdc959f2018-10-10 13:15:09 +02001204 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001205 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1206 }
1207 // Add extra freeze.
1208 fake_clock_.AdvanceTimeMilliseconds(kFreezeDelayMs);
Johannes Kronbfd343b2019-07-01 10:07:50 +02001209 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Ilya Nikolaevskiycdc959f2018-10-10 13:15:09 +02001210 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001211
Niels Möllerd7819652019-08-13 14:43:02 +02001212 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1213 nullptr);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001214 const int kExpectedTimeBetweenFreezes =
1215 kInterFrameDelayMs * (kMinRequiredSamples - 1);
Sergey Silkinbea18ca2018-10-02 16:22:46 +02001216 const int kExpectedNumberFreezesPerMinute = 60 * 1000 / kCallDurationMs;
Sergey Silkin02371062019-01-31 16:45:42 +01001217 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001218 EXPECT_EQ(
1219 kFreezeDelayMs + kInterFrameDelayMs,
1220 metrics::MinSample("WebRTC.Video.Screenshare.MeanFreezeDurationMs"));
1221 EXPECT_EQ(kExpectedTimeBetweenFreezes,
1222 metrics::MinSample(
1223 "WebRTC.Video.Screenshare.MeanTimeBetweenFreezesMs"));
Sergey Silkinbea18ca2018-10-02 16:22:46 +02001224 EXPECT_EQ(
1225 kExpectedNumberFreezesPerMinute,
1226 metrics::MinSample("WebRTC.Video.Screenshare.NumberFreezesPerMinute"));
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001227 } else {
1228 EXPECT_EQ(kFreezeDelayMs + kInterFrameDelayMs,
1229 metrics::MinSample("WebRTC.Video.MeanFreezeDurationMs"));
1230 EXPECT_EQ(kExpectedTimeBetweenFreezes,
1231 metrics::MinSample("WebRTC.Video.MeanTimeBetweenFreezesMs"));
Sergey Silkinbea18ca2018-10-02 16:22:46 +02001232 EXPECT_EQ(kExpectedNumberFreezesPerMinute,
1233 metrics::MinSample("WebRTC.Video.NumberFreezesPerMinute"));
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001234 }
1235}
1236
Sergey Silkin02371062019-01-31 16:45:42 +01001237TEST_P(ReceiveStatisticsProxyTestWithContent, HarmonicFrameRateIsReported) {
Sergey Silkinfc6f3e52019-04-03 10:57:26 +02001238 const int kFrameDurationMs = 33;
1239 const int kFreezeDurationMs = 200;
1240 const int kPauseDurationMs = 10000;
1241 const int kCallDurationMs = kMinRequiredSamples * kFrameDurationMs +
1242 kFreezeDurationMs + kPauseDurationMs;
Sergey Silkin50e77452019-01-16 13:41:46 +01001243 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1244
1245 for (int i = 0; i < kMinRequiredSamples; ++i) {
Sergey Silkinfc6f3e52019-04-03 10:57:26 +02001246 fake_clock_.AdvanceTimeMilliseconds(kFrameDurationMs);
Johannes Kronbfd343b2019-07-01 10:07:50 +02001247 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Sergey Silkin50e77452019-01-16 13:41:46 +01001248 statistics_proxy_->OnRenderedFrame(frame);
1249 }
Sergey Silkinfc6f3e52019-04-03 10:57:26 +02001250
1251 // Freezes and pauses should be included into harmonic frame rate.
1252 // Add freeze.
1253 fake_clock_.AdvanceTimeMilliseconds(kFreezeDurationMs);
Johannes Kronbfd343b2019-07-01 10:07:50 +02001254 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Sergey Silkinfc6f3e52019-04-03 10:57:26 +02001255 statistics_proxy_->OnRenderedFrame(frame);
1256
1257 // Add pause.
1258 fake_clock_.AdvanceTimeMilliseconds(kPauseDurationMs);
1259 statistics_proxy_->OnStreamInactive();
Johannes Kronbfd343b2019-07-01 10:07:50 +02001260 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Sergey Silkin50e77452019-01-16 13:41:46 +01001261 statistics_proxy_->OnRenderedFrame(frame);
1262
Niels Möllerd7819652019-08-13 14:43:02 +02001263 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1264 nullptr);
Sergey Silkinfc6f3e52019-04-03 10:57:26 +02001265 double kSumSquaredFrameDurationSecs =
Sergey Silkin50e77452019-01-16 13:41:46 +01001266 (kMinRequiredSamples - 1) *
Sergey Silkinfc6f3e52019-04-03 10:57:26 +02001267 (kFrameDurationMs / 1000.0 * kFrameDurationMs / 1000.0);
1268 kSumSquaredFrameDurationSecs +=
1269 kFreezeDurationMs / 1000.0 * kFreezeDurationMs / 1000.0;
1270 kSumSquaredFrameDurationSecs +=
1271 kPauseDurationMs / 1000.0 * kPauseDurationMs / 1000.0;
Sergey Silkin50e77452019-01-16 13:41:46 +01001272 const int kExpectedHarmonicFrameRateFps =
Sergey Silkinfc6f3e52019-04-03 10:57:26 +02001273 std::round(kCallDurationMs / (1000 * kSumSquaredFrameDurationSecs));
Sergey Silkin02371062019-01-31 16:45:42 +01001274 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Sergey Silkin50e77452019-01-16 13:41:46 +01001275 EXPECT_EQ(kExpectedHarmonicFrameRateFps,
1276 metrics::MinSample("WebRTC.Video.Screenshare.HarmonicFrameRate"));
1277 } else {
1278 EXPECT_EQ(kExpectedHarmonicFrameRateFps,
1279 metrics::MinSample("WebRTC.Video.HarmonicFrameRate"));
1280 }
1281}
1282
Sergey Silkin02371062019-01-31 16:45:42 +01001283TEST_P(ReceiveStatisticsProxyTestWithContent, PausesAreIgnored) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001284 const int kInterFrameDelayMs = 33;
1285 const int kPauseDurationMs = 10000;
Sergey Silkin278f8252019-01-09 14:37:40 +01001286 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1287
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001288 for (int i = 0; i <= kMinRequiredSamples; ++i) {
Johannes Kronbfd343b2019-07-01 10:07:50 +02001289 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Ilya Nikolaevskiycdc959f2018-10-10 13:15:09 +02001290 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001291 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1292 }
1293 // Add a pause.
1294 fake_clock_.AdvanceTimeMilliseconds(kPauseDurationMs);
1295 statistics_proxy_->OnStreamInactive();
1296
1297 // Second playback interval with triple the length.
1298 for (int i = 0; i <= kMinRequiredSamples * 3; ++i) {
Johannes Kronbfd343b2019-07-01 10:07:50 +02001299 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Ilya Nikolaevskiycdc959f2018-10-10 13:15:09 +02001300 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001301 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1302 }
1303
Niels Möllerd7819652019-08-13 14:43:02 +02001304 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1305 nullptr);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001306 // Average of two playback intervals.
1307 const int kExpectedTimeBetweenFreezes =
1308 kInterFrameDelayMs * kMinRequiredSamples * 2;
Sergey Silkin02371062019-01-31 16:45:42 +01001309 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001310 EXPECT_EQ(-1, metrics::MinSample(
1311 "WebRTC.Video.Screenshare.MeanFreezeDurationMs"));
1312 EXPECT_EQ(kExpectedTimeBetweenFreezes,
1313 metrics::MinSample(
1314 "WebRTC.Video.Screenshare.MeanTimeBetweenFreezesMs"));
1315 } else {
1316 EXPECT_EQ(-1, metrics::MinSample("WebRTC.Video.MeanFreezeDurationMs"));
1317 EXPECT_EQ(kExpectedTimeBetweenFreezes,
1318 metrics::MinSample("WebRTC.Video.MeanTimeBetweenFreezesMs"));
1319 }
1320}
1321
Sergey Silkin02371062019-01-31 16:45:42 +01001322TEST_P(ReceiveStatisticsProxyTestWithContent, ManyPausesAtTheBeginning) {
Ilya Nikolaevskiy879f5a32018-05-31 09:47:17 +02001323 const int kInterFrameDelayMs = 33;
1324 const int kPauseDurationMs = 10000;
Sergey Silkin278f8252019-01-09 14:37:40 +01001325 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1326
Ilya Nikolaevskiy879f5a32018-05-31 09:47:17 +02001327 for (int i = 0; i <= kMinRequiredSamples; ++i) {
Johannes Kronbfd343b2019-07-01 10:07:50 +02001328 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Ilya Nikolaevskiy879f5a32018-05-31 09:47:17 +02001329 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1330
1331 statistics_proxy_->OnStreamInactive();
1332 fake_clock_.AdvanceTimeMilliseconds(kPauseDurationMs);
1333
Johannes Kronbfd343b2019-07-01 10:07:50 +02001334 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Ilya Nikolaevskiy879f5a32018-05-31 09:47:17 +02001335 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1336 }
1337
Niels Möllerd7819652019-08-13 14:43:02 +02001338 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1339 nullptr);
Ilya Nikolaevskiy879f5a32018-05-31 09:47:17 +02001340 // No freezes should be detected, as all long inter-frame delays were pauses.
Sergey Silkin02371062019-01-31 16:45:42 +01001341 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiy879f5a32018-05-31 09:47:17 +02001342 EXPECT_EQ(-1, metrics::MinSample(
1343 "WebRTC.Video.Screenshare.MeanFreezeDurationMs"));
1344 } else {
1345 EXPECT_EQ(-1, metrics::MinSample("WebRTC.Video.MeanFreezeDurationMs"));
1346 }
1347}
1348
Sergey Silkin02371062019-01-31 16:45:42 +01001349TEST_P(ReceiveStatisticsProxyTestWithContent, TimeInHdReported) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001350 const int kInterFrameDelayMs = 20;
Sergey Silkin278f8252019-01-09 14:37:40 +01001351 webrtc::VideoFrame frame_hd = CreateFrame(1280, 720);
1352 webrtc::VideoFrame frame_sd = CreateFrame(640, 360);
1353
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001354 // HD frames.
1355 for (int i = 0; i < kMinRequiredSamples; ++i) {
Johannes Kronbfd343b2019-07-01 10:07:50 +02001356 statistics_proxy_->OnDecodedFrame(frame_hd, absl::nullopt, 0,
1357 content_type_);
Sergey Silkin278f8252019-01-09 14:37:40 +01001358 statistics_proxy_->OnRenderedFrame(frame_hd);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001359 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1360 }
1361 // SD frames.
1362 for (int i = 0; i < 2 * kMinRequiredSamples; ++i) {
Johannes Kronbfd343b2019-07-01 10:07:50 +02001363 statistics_proxy_->OnDecodedFrame(frame_sd, absl::nullopt, 0,
1364 content_type_);
Sergey Silkin278f8252019-01-09 14:37:40 +01001365 statistics_proxy_->OnRenderedFrame(frame_sd);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001366 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1367 }
1368 // Extra last frame.
Sergey Silkin278f8252019-01-09 14:37:40 +01001369 statistics_proxy_->OnRenderedFrame(frame_sd);
1370
Niels Möllerd7819652019-08-13 14:43:02 +02001371 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1372 nullptr);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001373 const int kExpectedTimeInHdPercents = 33;
Sergey Silkin02371062019-01-31 16:45:42 +01001374 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001375 EXPECT_EQ(
1376 kExpectedTimeInHdPercents,
1377 metrics::MinSample("WebRTC.Video.Screenshare.TimeInHdPercentage"));
1378 } else {
1379 EXPECT_EQ(kExpectedTimeInHdPercents,
1380 metrics::MinSample("WebRTC.Video.TimeInHdPercentage"));
1381 }
1382}
1383
Sergey Silkin02371062019-01-31 16:45:42 +01001384TEST_P(ReceiveStatisticsProxyTestWithContent, TimeInBlockyVideoReported) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001385 const int kInterFrameDelayMs = 20;
1386 const int kHighQp = 80;
1387 const int kLowQp = 30;
Sergey Silkin278f8252019-01-09 14:37:40 +01001388 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1389
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001390 // High quality frames.
1391 for (int i = 0; i < kMinRequiredSamples; ++i) {
Johannes Kronbfd343b2019-07-01 10:07:50 +02001392 statistics_proxy_->OnDecodedFrame(frame, kLowQp, 0, content_type_);
Sergey Silkin278f8252019-01-09 14:37:40 +01001393 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001394 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1395 }
1396 // Blocky frames.
1397 for (int i = 0; i < 2 * kMinRequiredSamples; ++i) {
Johannes Kronbfd343b2019-07-01 10:07:50 +02001398 statistics_proxy_->OnDecodedFrame(frame, kHighQp, 0, content_type_);
Sergey Silkin278f8252019-01-09 14:37:40 +01001399 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001400 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1401 }
1402 // Extra last frame.
Johannes Kronbfd343b2019-07-01 10:07:50 +02001403 statistics_proxy_->OnDecodedFrame(frame, kHighQp, 0, content_type_);
Sergey Silkin278f8252019-01-09 14:37:40 +01001404 statistics_proxy_->OnRenderedFrame(frame);
1405
Niels Möllerd7819652019-08-13 14:43:02 +02001406 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1407 nullptr);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001408 const int kExpectedTimeInHdPercents = 66;
Sergey Silkin02371062019-01-31 16:45:42 +01001409 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001410 EXPECT_EQ(kExpectedTimeInHdPercents,
1411 metrics::MinSample(
1412 "WebRTC.Video.Screenshare.TimeInBlockyVideoPercentage"));
1413 } else {
1414 EXPECT_EQ(kExpectedTimeInHdPercents,
1415 metrics::MinSample("WebRTC.Video.TimeInBlockyVideoPercentage"));
1416 }
1417}
1418
Sergey Silkin02371062019-01-31 16:45:42 +01001419TEST_P(ReceiveStatisticsProxyTestWithContent, DownscalesReported) {
Sergey Silkin278f8252019-01-09 14:37:40 +01001420 const int kInterFrameDelayMs = 2000; // To ensure long enough call duration.
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001421
Sergey Silkin278f8252019-01-09 14:37:40 +01001422 webrtc::VideoFrame frame_hd = CreateFrame(1280, 720);
1423 webrtc::VideoFrame frame_sd = CreateFrame(640, 360);
1424 webrtc::VideoFrame frame_ld = CreateFrame(320, 180);
1425
1426 // Call once to pass content type.
Johannes Kronbfd343b2019-07-01 10:07:50 +02001427 statistics_proxy_->OnDecodedFrame(frame_hd, absl::nullopt, 0, content_type_);
Sergey Silkin278f8252019-01-09 14:37:40 +01001428
1429 statistics_proxy_->OnRenderedFrame(frame_hd);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001430 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1431
1432 // Downscale.
Sergey Silkin278f8252019-01-09 14:37:40 +01001433 statistics_proxy_->OnRenderedFrame(frame_sd);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001434 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1435
1436 // Downscale.
Sergey Silkin278f8252019-01-09 14:37:40 +01001437 statistics_proxy_->OnRenderedFrame(frame_ld);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001438 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1439
Niels Möllerd7819652019-08-13 14:43:02 +02001440 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1441 nullptr);
Sergey Silkin278f8252019-01-09 14:37:40 +01001442 const int kExpectedDownscales = 30; // 2 per 4 seconds = 30 per minute.
Sergey Silkin02371062019-01-31 16:45:42 +01001443 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001444 EXPECT_EQ(
1445 kExpectedDownscales,
1446 metrics::MinSample(
1447 "WebRTC.Video.Screenshare.NumberResolutionDownswitchesPerMinute"));
1448 } else {
1449 EXPECT_EQ(kExpectedDownscales,
1450 metrics::MinSample(
1451 "WebRTC.Video.NumberResolutionDownswitchesPerMinute"));
1452 }
1453}
1454
Johannes Kronbfd343b2019-07-01 10:07:50 +02001455TEST_P(ReceiveStatisticsProxyTestWithContent, DecodeTimeReported) {
1456 const int kInterFrameDelayMs = 20;
1457 const int kLowQp = 30;
1458 const int kDecodeMs = 7;
1459
1460 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1461
1462 for (int i = 0; i < kMinRequiredSamples; ++i) {
1463 statistics_proxy_->OnDecodedFrame(frame, kLowQp, kDecodeMs, content_type_);
1464 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1465 }
Niels Möllerd7819652019-08-13 14:43:02 +02001466 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1467 nullptr);
Johannes Kronbfd343b2019-07-01 10:07:50 +02001468 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DecodeTimeInMs", kDecodeMs));
1469}
1470
Sergey Silkin02371062019-01-31 16:45:42 +01001471TEST_P(ReceiveStatisticsProxyTestWithContent,
1472 StatsAreSlicedOnSimulcastAndExperiment) {
ilnik6d5b4d62017-08-30 03:32:14 -07001473 const uint8_t experiment_id = 1;
Sergey Silkin02371062019-01-31 16:45:42 +01001474 webrtc::VideoContentType content_type = content_type_;
ilnik6d5b4d62017-08-30 03:32:14 -07001475 videocontenttypehelpers::SetExperimentId(&content_type, experiment_id);
1476 const int kInterFrameDelayMs1 = 30;
1477 const int kInterFrameDelayMs2 = 50;
Sergey Silkin278f8252019-01-09 14:37:40 +01001478 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
ilnik6d5b4d62017-08-30 03:32:14 -07001479
1480 videocontenttypehelpers::SetSimulcastId(&content_type, 1);
1481 for (int i = 0; i <= kMinRequiredSamples; ++i) {
1482 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs1);
Johannes Kronbfd343b2019-07-01 10:07:50 +02001483 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type);
ilnik6d5b4d62017-08-30 03:32:14 -07001484 }
1485
1486 videocontenttypehelpers::SetSimulcastId(&content_type, 2);
1487 for (int i = 0; i <= kMinRequiredSamples; ++i) {
1488 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs2);
Johannes Kronbfd343b2019-07-01 10:07:50 +02001489 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type);
ilnik6d5b4d62017-08-30 03:32:14 -07001490 }
Niels Möllerd7819652019-08-13 14:43:02 +02001491 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1492 nullptr);
ilnik6d5b4d62017-08-30 03:32:14 -07001493
1494 if (videocontenttypehelpers::IsScreenshare(content_type)) {
1495 EXPECT_EQ(
1496 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1497 EXPECT_EQ(1, metrics::NumSamples(
1498 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1499 EXPECT_EQ(1, metrics::NumSamples(
1500 "WebRTC.Video.Screenshare.InterframeDelayInMs.S0"));
1501 EXPECT_EQ(1, metrics::NumSamples(
1502 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs.S0"));
1503 EXPECT_EQ(1, metrics::NumSamples(
1504 "WebRTC.Video.Screenshare.InterframeDelayInMs.S1"));
1505 EXPECT_EQ(1, metrics::NumSamples(
1506 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs.S1"));
1507 EXPECT_EQ(1,
1508 metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"
1509 ".ExperimentGroup0"));
1510 EXPECT_EQ(
1511 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"
1512 ".ExperimentGroup0"));
1513 EXPECT_EQ(
1514 kInterFrameDelayMs1,
1515 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs.S0"));
1516 EXPECT_EQ(
1517 kInterFrameDelayMs2,
1518 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs.S1"));
1519 EXPECT_EQ(
1520 (kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1521 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1522 EXPECT_EQ(
1523 kInterFrameDelayMs2,
1524 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1525 EXPECT_EQ(
1526 (kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1527 metrics::MinSample(
1528 "WebRTC.Video.Screenshare.InterframeDelayInMs.ExperimentGroup0"));
1529 } else {
1530 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
1531 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
1532 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs.S0"));
1533 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs.S0"));
1534 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs.S1"));
1535 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs.S1"));
1536 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"
1537 ".ExperimentGroup0"));
1538 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"
1539 ".ExperimentGroup0"));
1540 EXPECT_EQ(kInterFrameDelayMs1,
1541 metrics::MinSample("WebRTC.Video.InterframeDelayInMs.S0"));
1542 EXPECT_EQ(kInterFrameDelayMs2,
1543 metrics::MinSample("WebRTC.Video.InterframeDelayInMs.S1"));
1544 EXPECT_EQ((kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1545 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
1546 EXPECT_EQ(kInterFrameDelayMs2,
1547 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
1548 EXPECT_EQ((kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1549 metrics::MinSample(
1550 "WebRTC.Video.InterframeDelayInMs.ExperimentGroup0"));
1551 }
1552}
Johannes Krone76b3ab2019-10-22 13:22:26 +02001553
1554class DecodeTimeHistogramsKillswitch {
1555 public:
1556 explicit DecodeTimeHistogramsKillswitch(bool disable_histograms)
1557 : field_trial_(disable_histograms
1558 ? "WebRTC-DecodeTimeHistogramsKillSwitch/Enabled/"
1559 : "") {}
1560
1561 private:
1562 webrtc::test::ScopedFieldTrials field_trial_;
1563};
1564
1565class ReceiveStatisticsProxyTestWithDecodeTimeHistograms
1566 : public DecodeTimeHistogramsKillswitch,
1567 public ::testing::WithParamInterface<
1568 std::tuple<bool, int, int, int, VideoCodecType, std::string>>,
1569 public ReceiveStatisticsProxyTest {
1570 public:
1571 ReceiveStatisticsProxyTestWithDecodeTimeHistograms()
1572 : DecodeTimeHistogramsKillswitch(std::get<0>(GetParam())) {}
1573
1574 protected:
1575 const std::string kUmaPrefix = "WebRTC.Video.DecodeTimePerFrameInMs.";
1576 const int expected_number_of_samples_ = {std::get<1>(GetParam())};
1577 const int width_ = {std::get<2>(GetParam())};
1578 const int height_ = {std::get<3>(GetParam())};
1579 const VideoCodecType codec_type_ = {std::get<4>(GetParam())};
1580 const std::string implementation_name_ = {std::get<5>(GetParam())};
1581 const std::string uma_histogram_name_ =
1582 kUmaPrefix + (codec_type_ == kVideoCodecVP9 ? "Vp9." : "H264.") +
1583 (height_ == 2160 ? "4k." : "Hd.") +
1584 (implementation_name_.compare("ExternalDecoder") == 0 ? "Hw" : "Sw");
1585};
1586
1587TEST_P(ReceiveStatisticsProxyTestWithDecodeTimeHistograms,
1588 DecodeTimeHistogramsUpdated) {
1589 constexpr int kNumberOfFrames = 10;
1590 constexpr int kDecodeTimeMs = 7;
1591 constexpr int kFrameDurationMs = 1000 / 60;
1592
1593 webrtc::VideoFrame frame = CreateFrame(width_, height_);
1594
1595 statistics_proxy_->OnDecoderImplementationName(implementation_name_.c_str());
1596 statistics_proxy_->OnPreDecode(codec_type_, /*qp=*/0);
1597
1598 for (int i = 0; i < kNumberOfFrames; ++i) {
1599 statistics_proxy_->OnDecodedFrame(frame, /*qp=*/absl::nullopt,
1600 kDecodeTimeMs,
1601 VideoContentType::UNSPECIFIED);
1602 fake_clock_.AdvanceTimeMilliseconds(kFrameDurationMs);
1603 }
1604
1605 EXPECT_EQ(expected_number_of_samples_,
1606 metrics::NumSamples(uma_histogram_name_));
1607 EXPECT_EQ(expected_number_of_samples_,
1608 metrics::NumEvents(uma_histogram_name_, kDecodeTimeMs));
1609}
1610
1611const auto kVp94kHw = std::make_tuple(/*killswitch=*/false,
1612 /*expected_number_of_samples=*/10,
1613 /*width=*/3840,
1614 /*height=*/2160,
1615 kVideoCodecVP9,
1616 /*implementation=*/"ExternalDecoder");
1617const auto kVp94kSw = std::make_tuple(/*killswitch=*/false,
1618 /*expected_number_of_samples=*/10,
1619 /*width=*/3840,
1620 /*height=*/2160,
1621 kVideoCodecVP9,
1622 /*implementation=*/"libvpx");
1623const auto kVp9HdHw = std::make_tuple(/*killswitch=*/false,
1624 /*expected_number_of_samples=*/10,
1625 /*width=*/1920,
1626 /*height=*/1080,
1627 kVideoCodecVP9,
1628 /*implementation=*/"ExternalDecoder");
1629const auto kVp9HdSw = std::make_tuple(/*killswitch=*/false,
1630 /*expected_number_of_samples=*/10,
1631 /*width=*/1920,
1632 /*height=*/1080,
1633 kVideoCodecVP9,
1634 /*implementation=*/"libvpx");
1635const auto kH2644kHw = std::make_tuple(/*killswitch=*/false,
1636 /*expected_number_of_samples=*/10,
1637 /*width=*/3840,
1638 /*height=*/2160,
1639 kVideoCodecH264,
1640 /*implementation=*/"ExternalDecoder");
1641const auto kH2644kSw = std::make_tuple(/*killswitch=*/false,
1642 /*expected_number_of_samples=*/10,
1643 /*width=*/3840,
1644 /*height=*/2160,
1645 kVideoCodecH264,
1646 /*implementation=*/"FFmpeg");
1647const auto kH264HdHw = std::make_tuple(/*killswitch=*/false,
1648 /*expected_number_of_samples=*/10,
1649 /*width=*/1920,
1650 /*height=*/1080,
1651 kVideoCodecH264,
1652 /*implementation=*/"ExternalDecoder");
1653const auto kH264HdSw = std::make_tuple(/*killswitch=*/false,
1654 /*expected_number_of_samples=*/10,
1655 /*width=*/1920,
1656 /*height=*/1080,
1657 kVideoCodecH264,
1658 /*implementation=*/"FFmpeg");
1659
1660INSTANTIATE_TEST_SUITE_P(AllHistogramsPopulated,
1661 ReceiveStatisticsProxyTestWithDecodeTimeHistograms,
1662 ::testing::Values(kVp94kHw,
1663 kVp94kSw,
1664 kVp9HdHw,
1665 kVp9HdSw,
1666 kH2644kHw,
1667 kH2644kSw,
1668 kH264HdHw,
1669 kH264HdSw));
1670
1671const auto kKillswitchDisabled =
1672 std::make_tuple(/*killswitch=*/false,
1673 /*expected_number_of_samples=*/10,
1674 /*width=*/1920,
1675 /*height=*/1080,
1676 kVideoCodecVP9,
1677 /*implementation=*/"libvpx");
1678const auto kKillswitchEnabled =
1679 std::make_tuple(/*killswitch=*/true,
1680 /*expected_number_of_samples=*/0,
1681 /*width=*/1920,
1682 /*height=*/1080,
1683 kVideoCodecVP9,
1684 /*implementation=*/"libvpx");
1685
1686INSTANTIATE_TEST_SUITE_P(KillswitchEffective,
1687 ReceiveStatisticsProxyTestWithDecodeTimeHistograms,
1688 ::testing::Values(kKillswitchDisabled,
1689 kKillswitchEnabled));
1690
sakale5ba44e2016-10-26 07:09:24 -07001691} // namespace webrtc