blob: eb7c8655ab52919d7dcbf682084e2397898d3086 [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
Åsa Perssonfcf79cc2019-10-22 15:23:44 +0200601TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsPlayoutTimestamp) {
602 const int64_t kVideoNtpMs = 21;
603 const int64_t kSyncOffsetMs = 22;
604 const double kFreqKhz = 90.0;
605 EXPECT_EQ(absl::nullopt,
606 statistics_proxy_->GetStats().estimated_playout_ntp_timestamp_ms);
607 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs, kFreqKhz);
608 EXPECT_EQ(kVideoNtpMs,
609 statistics_proxy_->GetStats().estimated_playout_ntp_timestamp_ms);
610 fake_clock_.AdvanceTimeMilliseconds(13);
611 EXPECT_EQ(kVideoNtpMs + 13,
612 statistics_proxy_->GetStats().estimated_playout_ntp_timestamp_ms);
613 fake_clock_.AdvanceTimeMilliseconds(5);
614 EXPECT_EQ(kVideoNtpMs + 13 + 5,
615 statistics_proxy_->GetStats().estimated_playout_ntp_timestamp_ms);
616}
617
asapersson2077f2f2017-05-11 05:37:35 -0700618TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsAvSyncOffset) {
Åsa Perssonfcf79cc2019-10-22 15:23:44 +0200619 const int64_t kVideoNtpMs = 21;
asapersson2077f2f2017-05-11 05:37:35 -0700620 const int64_t kSyncOffsetMs = 22;
621 const double kFreqKhz = 90.0;
622 EXPECT_EQ(std::numeric_limits<int>::max(),
623 statistics_proxy_->GetStats().sync_offset_ms);
Åsa Perssonfcf79cc2019-10-22 15:23:44 +0200624 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs, kFreqKhz);
asapersson2077f2f2017-05-11 05:37:35 -0700625 EXPECT_EQ(kSyncOffsetMs, statistics_proxy_->GetStats().sync_offset_ms);
626}
627
asapersson46c4e3c2016-11-03 06:48:19 -0700628TEST_F(ReceiveStatisticsProxyTest, AvSyncOffsetHistogramIsUpdated) {
Åsa Perssonfcf79cc2019-10-22 15:23:44 +0200629 const int64_t kVideoNtpMs = 21;
asapersson46c4e3c2016-11-03 06:48:19 -0700630 const int64_t kSyncOffsetMs = 22;
631 const double kFreqKhz = 90.0;
632 for (int i = 0; i < kMinRequiredSamples; ++i)
Åsa Perssonfcf79cc2019-10-22 15:23:44 +0200633 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs,
634 kFreqKhz);
Niels Möllerd7819652019-08-13 14:43:02 +0200635 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
636 nullptr);
asapersson46c4e3c2016-11-03 06:48:19 -0700637 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AVSyncOffsetInMs"));
638 EXPECT_EQ(1,
639 metrics::NumEvents("WebRTC.Video.AVSyncOffsetInMs", kSyncOffsetMs));
640}
641
asaperssonde9e5ff2016-11-02 07:14:03 -0700642TEST_F(ReceiveStatisticsProxyTest, RtpToNtpFrequencyOffsetHistogramIsUpdated) {
Åsa Perssonfcf79cc2019-10-22 15:23:44 +0200643 const int64_t kVideoNtpMs = 21;
asaperssonde9e5ff2016-11-02 07:14:03 -0700644 const int64_t kSyncOffsetMs = 22;
645 const double kFreqKhz = 90.0;
Åsa Perssonfcf79cc2019-10-22 15:23:44 +0200646 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs, kFreqKhz);
647 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs,
648 kFreqKhz + 2.2);
asaperssonde9e5ff2016-11-02 07:14:03 -0700649 fake_clock_.AdvanceTimeMilliseconds(kFreqOffsetProcessIntervalInMs);
650 // Process interval passed, max diff: 2.
Åsa Perssonfcf79cc2019-10-22 15:23:44 +0200651 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs,
652 kFreqKhz + 1.1);
653 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs,
654 kFreqKhz - 4.2);
655 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs,
656 kFreqKhz - 0.9);
asaperssonde9e5ff2016-11-02 07:14:03 -0700657 fake_clock_.AdvanceTimeMilliseconds(kFreqOffsetProcessIntervalInMs);
658 // Process interval passed, max diff: 4.
Åsa Perssonfcf79cc2019-10-22 15:23:44 +0200659 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs, kFreqKhz);
Niels Möllerd7819652019-08-13 14:43:02 +0200660 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
661 nullptr);
asaperssonde9e5ff2016-11-02 07:14:03 -0700662 // Average reported: (2 + 4) / 2 = 3.
663 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtpToNtpFreqOffsetInKhz"));
664 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtpToNtpFreqOffsetInKhz", 3));
665}
666
asapersson6966bd52017-01-03 00:44:06 -0800667TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsUpdated) {
668 const int kQp = 22;
asapersson6966bd52017-01-03 00:44:06 -0800669
670 for (int i = 0; i < kMinRequiredSamples; ++i)
Niels Möller147013a2018-10-01 15:56:33 +0200671 statistics_proxy_->OnPreDecode(kVideoCodecVP8, kQp);
asapersson6966bd52017-01-03 00:44:06 -0800672
Niels Möllerd7819652019-08-13 14:43:02 +0200673 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
674 nullptr);
asapersson6966bd52017-01-03 00:44:06 -0800675 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
676 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Decoded.Vp8.Qp", kQp));
677}
678
679TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsNotUpdatedForTooFewSamples) {
Niels Möller147013a2018-10-01 15:56:33 +0200680 const int kQp = 22;
asapersson6966bd52017-01-03 00:44:06 -0800681
682 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
Niels Möller147013a2018-10-01 15:56:33 +0200683 statistics_proxy_->OnPreDecode(kVideoCodecVP8, kQp);
asapersson6966bd52017-01-03 00:44:06 -0800684
Niels Möllerd7819652019-08-13 14:43:02 +0200685 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
686 nullptr);
asapersson6966bd52017-01-03 00:44:06 -0800687 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
688}
689
690TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsNotUpdatedIfNoQpValue) {
asapersson6966bd52017-01-03 00:44:06 -0800691 for (int i = 0; i < kMinRequiredSamples; ++i)
Niels Möller147013a2018-10-01 15:56:33 +0200692 statistics_proxy_->OnPreDecode(kVideoCodecVP8, -1);
asapersson6966bd52017-01-03 00:44:06 -0800693
Niels Möllerd7819652019-08-13 14:43:02 +0200694 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
695 nullptr);
asapersson6966bd52017-01-03 00:44:06 -0800696 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
697}
698
asaperssonb99baf82017-04-20 04:05:43 -0700699TEST_F(ReceiveStatisticsProxyTest,
700 KeyFrameHistogramNotUpdatedForTooFewSamples) {
701 const bool kIsKeyFrame = false;
702 const int kFrameSizeBytes = 1000;
703
704 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
ilnik6d5b4d62017-08-30 03:32:14 -0700705 statistics_proxy_->OnCompleteFrame(kIsKeyFrame, kFrameSizeBytes,
706 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 04:05:43 -0700707
708 EXPECT_EQ(0, statistics_proxy_->GetStats().frame_counts.key_frames);
709 EXPECT_EQ(kMinRequiredSamples - 1,
710 statistics_proxy_->GetStats().frame_counts.delta_frames);
711
Niels Möllerd7819652019-08-13 14:43:02 +0200712 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
713 nullptr);
asaperssonb99baf82017-04-20 04:05:43 -0700714 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
715}
716
717TEST_F(ReceiveStatisticsProxyTest,
718 KeyFrameHistogramUpdatedForMinRequiredSamples) {
719 const bool kIsKeyFrame = false;
720 const int kFrameSizeBytes = 1000;
721
722 for (int i = 0; i < kMinRequiredSamples; ++i)
ilnik6d5b4d62017-08-30 03:32:14 -0700723 statistics_proxy_->OnCompleteFrame(kIsKeyFrame, kFrameSizeBytes,
724 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 04:05:43 -0700725
726 EXPECT_EQ(0, statistics_proxy_->GetStats().frame_counts.key_frames);
727 EXPECT_EQ(kMinRequiredSamples,
728 statistics_proxy_->GetStats().frame_counts.delta_frames);
729
Niels Möllerd7819652019-08-13 14:43:02 +0200730 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
731 nullptr);
asaperssonb99baf82017-04-20 04:05:43 -0700732 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
733 EXPECT_EQ(1,
734 metrics::NumEvents("WebRTC.Video.KeyFramesReceivedInPermille", 0));
735}
736
737TEST_F(ReceiveStatisticsProxyTest, KeyFrameHistogramIsUpdated) {
738 const int kFrameSizeBytes = 1000;
739
740 for (int i = 0; i < kMinRequiredSamples; ++i)
ilnik6d5b4d62017-08-30 03:32:14 -0700741 statistics_proxy_->OnCompleteFrame(true, kFrameSizeBytes,
742 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 04:05:43 -0700743
744 for (int i = 0; i < kMinRequiredSamples; ++i)
ilnik6d5b4d62017-08-30 03:32:14 -0700745 statistics_proxy_->OnCompleteFrame(false, kFrameSizeBytes,
746 VideoContentType::UNSPECIFIED);
asaperssonb99baf82017-04-20 04:05:43 -0700747
748 EXPECT_EQ(kMinRequiredSamples,
749 statistics_proxy_->GetStats().frame_counts.key_frames);
750 EXPECT_EQ(kMinRequiredSamples,
751 statistics_proxy_->GetStats().frame_counts.delta_frames);
752
Niels Möllerd7819652019-08-13 14:43:02 +0200753 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
754 nullptr);
asaperssonb99baf82017-04-20 04:05:43 -0700755 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
756 EXPECT_EQ(
757 1, metrics::NumEvents("WebRTC.Video.KeyFramesReceivedInPermille", 500));
758}
759
760TEST_F(ReceiveStatisticsProxyTest, TimingHistogramsNotUpdatedForTooFewSamples) {
asaperssonb99baf82017-04-20 04:05:43 -0700761 const int kMaxDecodeMs = 2;
762 const int kCurrentDelayMs = 3;
763 const int kTargetDelayMs = 4;
764 const int kJitterBufferMs = 5;
765 const int kMinPlayoutDelayMs = 6;
766 const int kRenderDelayMs = 7;
767
768 for (int i = 0; i < kMinRequiredSamples - 1; ++i) {
769 statistics_proxy_->OnFrameBufferTimingsUpdated(
Johannes Kronbfd343b2019-07-01 10:07:50 +0200770 kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs, kJitterBufferMs,
771 kMinPlayoutDelayMs, kRenderDelayMs);
asaperssonb99baf82017-04-20 04:05:43 -0700772 }
773
Niels Möllerd7819652019-08-13 14:43:02 +0200774 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
775 nullptr);
asaperssonb99baf82017-04-20 04:05:43 -0700776 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
777 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
778 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
779 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
780 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
781}
782
783TEST_F(ReceiveStatisticsProxyTest, TimingHistogramsAreUpdated) {
asaperssonb99baf82017-04-20 04:05:43 -0700784 const int kMaxDecodeMs = 2;
785 const int kCurrentDelayMs = 3;
786 const int kTargetDelayMs = 4;
787 const int kJitterBufferMs = 5;
788 const int kMinPlayoutDelayMs = 6;
789 const int kRenderDelayMs = 7;
790
791 for (int i = 0; i < kMinRequiredSamples; ++i) {
792 statistics_proxy_->OnFrameBufferTimingsUpdated(
Johannes Kronbfd343b2019-07-01 10:07:50 +0200793 kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs, kJitterBufferMs,
794 kMinPlayoutDelayMs, kRenderDelayMs);
asaperssonb99baf82017-04-20 04:05:43 -0700795 }
796
Niels Möllerd7819652019-08-13 14:43:02 +0200797 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
798 nullptr);
asaperssonb99baf82017-04-20 04:05:43 -0700799 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
800 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
801 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
802 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
803
asaperssonb99baf82017-04-20 04:05:43 -0700804 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.JitterBufferDelayInMs",
805 kJitterBufferMs));
806 EXPECT_EQ(1,
807 metrics::NumEvents("WebRTC.Video.TargetDelayInMs", kTargetDelayMs));
808 EXPECT_EQ(
809 1, metrics::NumEvents("WebRTC.Video.CurrentDelayInMs", kCurrentDelayMs));
810 EXPECT_EQ(1,
811 metrics::NumEvents("WebRTC.Video.OnewayDelayInMs", kTargetDelayMs));
812}
813
sprang948b2752017-05-04 02:47:13 -0700814TEST_F(ReceiveStatisticsProxyTest, DoesNotReportStaleFramerates) {
815 const int kDefaultFps = 30;
Sergey Silkin278f8252019-01-09 14:37:40 +0100816 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
sprang948b2752017-05-04 02:47:13 -0700817
818 for (int i = 0; i < kDefaultFps; ++i) {
819 // Since OnRenderedFrame is never called the fps in each sample will be 0,
820 // i.e. bad
821 frame.set_ntp_time_ms(fake_clock_.CurrentNtpInMilliseconds());
Johannes Kronbfd343b2019-07-01 10:07:50 +0200822 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
sprang948b2752017-05-04 02:47:13 -0700823 VideoContentType::UNSPECIFIED);
824 statistics_proxy_->OnRenderedFrame(frame);
825 fake_clock_.AdvanceTimeMilliseconds(1000 / kDefaultFps);
826 }
827
828 EXPECT_EQ(kDefaultFps, statistics_proxy_->GetStats().decode_frame_rate);
829 EXPECT_EQ(kDefaultFps, statistics_proxy_->GetStats().render_frame_rate);
830
831 // FPS trackers in stats proxy have a 1000ms sliding window.
832 fake_clock_.AdvanceTimeMilliseconds(1000);
833 EXPECT_EQ(0, statistics_proxy_->GetStats().decode_frame_rate);
834 EXPECT_EQ(0, statistics_proxy_->GetStats().render_frame_rate);
835}
836
asapersson2077f2f2017-05-11 05:37:35 -0700837TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsReceivedFrameStats) {
asapersson2077f2f2017-05-11 05:37:35 -0700838 EXPECT_EQ(0, statistics_proxy_->GetStats().width);
839 EXPECT_EQ(0, statistics_proxy_->GetStats().height);
840 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_rendered);
841
842 statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight));
843
844 EXPECT_EQ(kWidth, statistics_proxy_->GetStats().width);
845 EXPECT_EQ(kHeight, statistics_proxy_->GetStats().height);
846 EXPECT_EQ(1u, statistics_proxy_->GetStats().frames_rendered);
847}
848
849TEST_F(ReceiveStatisticsProxyTest,
850 ReceivedFrameHistogramsAreNotUpdatedForTooFewSamples) {
asapersson2077f2f2017-05-11 05:37:35 -0700851 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
852 statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight));
853
Niels Möllerd7819652019-08-13 14:43:02 +0200854 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
855 nullptr);
asapersson2077f2f2017-05-11 05:37:35 -0700856 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
857 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
858 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
859 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
860}
861
862TEST_F(ReceiveStatisticsProxyTest, ReceivedFrameHistogramsAreUpdated) {
asapersson2077f2f2017-05-11 05:37:35 -0700863 for (int i = 0; i < kMinRequiredSamples; ++i)
864 statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight));
865
Niels Möllerd7819652019-08-13 14:43:02 +0200866 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
867 nullptr);
asapersson2077f2f2017-05-11 05:37:35 -0700868 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
869 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
870 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
871 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
872 EXPECT_EQ(1,
873 metrics::NumEvents("WebRTC.Video.ReceivedWidthInPixels", kWidth));
874 EXPECT_EQ(1,
875 metrics::NumEvents("WebRTC.Video.ReceivedHeightInPixels", kHeight));
876}
877
Åsa Persson81327d52018-06-05 13:34:33 +0200878TEST_F(ReceiveStatisticsProxyTest, ZeroDelayReportedIfFrameNotDelayed) {
Sergey Silkin278f8252019-01-09 14:37:40 +0100879 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200880 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Åsa Persson81327d52018-06-05 13:34:33 +0200881 VideoContentType::UNSPECIFIED);
882
883 // Frame not delayed, delayed frames to render: 0%.
884 const int64_t kNowMs = fake_clock_.TimeInMilliseconds();
885 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs));
886
887 // Min run time has passed.
888 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
Niels Möllerd7819652019-08-13 14:43:02 +0200889 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
890 nullptr);
Åsa Persson81327d52018-06-05 13:34:33 +0200891 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
892 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 0));
893 EXPECT_EQ(0, metrics::NumSamples(
894 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
895}
896
897TEST_F(ReceiveStatisticsProxyTest,
898 DelayedFrameHistogramsAreNotUpdatedIfMinRuntimeHasNotPassed) {
Sergey Silkin278f8252019-01-09 14:37:40 +0100899 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200900 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Åsa Persson81327d52018-06-05 13:34:33 +0200901 VideoContentType::UNSPECIFIED);
902
903 // Frame not delayed, delayed frames to render: 0%.
904 const int64_t kNowMs = fake_clock_.TimeInMilliseconds();
905 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs));
906
907 // Min run time has not passed.
908 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000) -
909 1);
Niels Möllerd7819652019-08-13 14:43:02 +0200910 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
911 nullptr);
Åsa Persson81327d52018-06-05 13:34:33 +0200912 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
913 EXPECT_EQ(0, metrics::NumSamples(
914 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
915}
916
917TEST_F(ReceiveStatisticsProxyTest,
918 DelayedFramesHistogramsAreNotUpdatedIfNoRenderedFrames) {
Sergey Silkin278f8252019-01-09 14:37:40 +0100919 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200920 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Åsa Persson81327d52018-06-05 13:34:33 +0200921 VideoContentType::UNSPECIFIED);
922
923 // Min run time has passed. No rendered frames.
924 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
Niels Möllerd7819652019-08-13 14:43:02 +0200925 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
926 nullptr);
Åsa Persson81327d52018-06-05 13:34:33 +0200927 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
928 EXPECT_EQ(0, metrics::NumSamples(
929 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
930}
931
932TEST_F(ReceiveStatisticsProxyTest, DelayReportedIfFrameIsDelayed) {
Sergey Silkin278f8252019-01-09 14:37:40 +0100933 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200934 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Åsa Persson81327d52018-06-05 13:34:33 +0200935 VideoContentType::UNSPECIFIED);
936
937 // Frame delayed 1 ms, delayed frames to render: 100%.
938 const int64_t kNowMs = fake_clock_.TimeInMilliseconds();
939 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs - 1));
940
941 // Min run time has passed.
942 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
Niels Möllerd7819652019-08-13 14:43:02 +0200943 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
944 nullptr);
Åsa Persson81327d52018-06-05 13:34:33 +0200945 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
946 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 100));
947 EXPECT_EQ(1, metrics::NumSamples(
948 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
949 EXPECT_EQ(1, metrics::NumEvents(
950 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs", 1));
951}
952
953TEST_F(ReceiveStatisticsProxyTest, AverageDelayOfDelayedFramesIsReported) {
Sergey Silkin278f8252019-01-09 14:37:40 +0100954 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Johannes Kronbfd343b2019-07-01 10:07:50 +0200955 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
Åsa Persson81327d52018-06-05 13:34:33 +0200956 VideoContentType::UNSPECIFIED);
957
958 // Two frames delayed (6 ms, 10 ms), delayed frames to render: 50%.
959 const int64_t kNowMs = fake_clock_.TimeInMilliseconds();
960 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs - 10));
961 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs - 6));
962 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs));
963 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs + 1));
964
965 // Min run time has passed.
966 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
Niels Möllerd7819652019-08-13 14:43:02 +0200967 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
968 nullptr);
Åsa Persson81327d52018-06-05 13:34:33 +0200969 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
970 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 50));
971 EXPECT_EQ(1, metrics::NumSamples(
972 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
973 EXPECT_EQ(1, metrics::NumEvents(
974 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs", 8));
975}
976
asapersson2077f2f2017-05-11 05:37:35 -0700977TEST_F(ReceiveStatisticsProxyTest,
978 RtcpHistogramsNotUpdatedIfMinRuntimeHasNotPassed) {
Niels Möllerd7819652019-08-13 14:43:02 +0200979 StreamDataCounters data_counters;
980 data_counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
981
asapersson2077f2f2017-05-11 05:37:35 -0700982 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000) -
983 1);
984
985 RtcpPacketTypeCounter counter;
986 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
987
Niels Möllerd7819652019-08-13 14:43:02 +0200988 statistics_proxy_->UpdateHistograms(absl::nullopt, data_counters, nullptr);
asapersson2077f2f2017-05-11 05:37:35 -0700989 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
990 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
991 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
992}
993
994TEST_F(ReceiveStatisticsProxyTest, RtcpHistogramsAreUpdated) {
Niels Möllerd7819652019-08-13 14:43:02 +0200995 StreamDataCounters data_counters;
996 data_counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
asapersson2077f2f2017-05-11 05:37:35 -0700997 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
998
999 const uint32_t kFirPackets = 100;
1000 const uint32_t kPliPackets = 200;
1001 const uint32_t kNackPackets = 300;
1002
1003 RtcpPacketTypeCounter counter;
1004 counter.fir_packets = kFirPackets;
1005 counter.pli_packets = kPliPackets;
1006 counter.nack_packets = kNackPackets;
1007 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
1008
Niels Möllerd7819652019-08-13 14:43:02 +02001009 statistics_proxy_->UpdateHistograms(absl::nullopt, data_counters, nullptr);
asapersson2077f2f2017-05-11 05:37:35 -07001010 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
1011 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
1012 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
1013 EXPECT_EQ(
1014 1, metrics::NumEvents("WebRTC.Video.FirPacketsSentPerMinute",
1015 kFirPackets * 60 / metrics::kMinRunTimeInSeconds));
1016 EXPECT_EQ(
1017 1, metrics::NumEvents("WebRTC.Video.PliPacketsSentPerMinute",
1018 kPliPackets * 60 / metrics::kMinRunTimeInSeconds));
1019 EXPECT_EQ(
1020 1, metrics::NumEvents("WebRTC.Video.NackPacketsSentPerMinute",
1021 kNackPackets * 60 / metrics::kMinRunTimeInSeconds));
1022}
1023
Sergey Silkin02371062019-01-31 16:45:42 +01001024class ReceiveStatisticsProxyTestWithFreezeDuration
1025 : public ReceiveStatisticsProxyTest,
Mirko Bonadei6a489f22019-04-09 15:11:12 +02001026 public ::testing::WithParamInterface<
Sergey Silkin02371062019-01-31 16:45:42 +01001027 std::tuple<uint32_t, uint32_t, uint32_t>> {
1028 protected:
1029 const uint32_t frame_duration_ms_ = {std::get<0>(GetParam())};
1030 const uint32_t freeze_duration_ms_ = {std::get<1>(GetParam())};
1031 const uint32_t expected_freeze_count_ = {std::get<2>(GetParam())};
1032};
sprang892dab52017-08-15 05:00:33 -07001033
Sergey Silkin02371062019-01-31 16:45:42 +01001034// It is a freeze if:
1035// frame_duration_ms >= max(3 * avg_frame_duration, avg_frame_duration + 150)
1036// where avg_frame_duration is average duration of last 30 frames including
1037// the current one.
1038//
1039// Condition 1: 3 * avg_frame_duration > avg_frame_duration + 150
1040const auto kFreezeDetectionCond1Freeze = std::make_tuple(150, 483, 1);
1041const auto kFreezeDetectionCond1NotFreeze = std::make_tuple(150, 482, 0);
1042// Condition 2: 3 * avg_frame_duration < avg_frame_duration + 150
1043const auto kFreezeDetectionCond2Freeze = std::make_tuple(30, 185, 1);
1044const auto kFreezeDetectionCond2NotFreeze = std::make_tuple(30, 184, 0);
1045
Mirko Bonadei12d12852019-02-05 17:04:04 +01001046INSTANTIATE_TEST_SUITE_P(_,
1047 ReceiveStatisticsProxyTestWithFreezeDuration,
1048 ::testing::Values(kFreezeDetectionCond1Freeze,
1049 kFreezeDetectionCond1NotFreeze,
1050 kFreezeDetectionCond2Freeze,
1051 kFreezeDetectionCond2NotFreeze));
Sergey Silkin02371062019-01-31 16:45:42 +01001052
1053TEST_P(ReceiveStatisticsProxyTestWithFreezeDuration, FreezeDetection) {
1054 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
1055 EXPECT_EQ(0u, stats.freeze_count);
1056 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1057
1058 // Add a very long frame. This is need to verify that average frame
1059 // duration, which is supposed to be calculated as mean of durations of
1060 // last 30 frames, is calculated correctly.
1061 statistics_proxy_->OnRenderedFrame(frame);
1062 fake_clock_.AdvanceTimeMilliseconds(2000);
1063
1064 for (size_t i = 0;
1065 i <= VideoQualityObserver::kAvgInterframeDelaysWindowSizeFrames; ++i) {
1066 fake_clock_.AdvanceTimeMilliseconds(frame_duration_ms_);
1067 statistics_proxy_->OnRenderedFrame(frame);
1068 }
1069
1070 fake_clock_.AdvanceTimeMilliseconds(freeze_duration_ms_);
1071 statistics_proxy_->OnRenderedFrame(frame);
1072
1073 stats = statistics_proxy_->GetStats();
1074 EXPECT_EQ(stats.freeze_count, expected_freeze_count_);
1075}
1076
1077class ReceiveStatisticsProxyTestWithContent
1078 : public ReceiveStatisticsProxyTest,
1079 public ::testing::WithParamInterface<webrtc::VideoContentType> {
1080 protected:
1081 const webrtc::VideoContentType content_type_{GetParam()};
1082};
1083
Mirko Bonadei12d12852019-02-05 17:04:04 +01001084INSTANTIATE_TEST_SUITE_P(ContentTypes,
1085 ReceiveStatisticsProxyTestWithContent,
1086 ::testing::Values(VideoContentType::UNSPECIFIED,
1087 VideoContentType::SCREENSHARE));
Sergey Silkin02371062019-01-31 16:45:42 +01001088
1089TEST_P(ReceiveStatisticsProxyTestWithContent, InterFrameDelaysAreReported) {
sprang892dab52017-08-15 05:00:33 -07001090 const int kInterFrameDelayMs = 33;
Sergey Silkin278f8252019-01-09 14:37:40 +01001091 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1092
sprang892dab52017-08-15 05:00:33 -07001093 for (int i = 0; i < kMinRequiredSamples; ++i) {
Johannes Kronbfd343b2019-07-01 10:07:50 +02001094 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
sprang892dab52017-08-15 05:00:33 -07001095 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1096 }
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001097 // One extra with double the interval.
sprang892dab52017-08-15 05:00:33 -07001098 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
Johannes Kronbfd343b2019-07-01 10:07:50 +02001099 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
sprang892dab52017-08-15 05:00:33 -07001100
Niels Möllerd7819652019-08-13 14:43:02 +02001101 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1102 nullptr);
sprang892dab52017-08-15 05:00:33 -07001103 const int kExpectedInterFrame =
1104 (kInterFrameDelayMs * (kMinRequiredSamples - 1) +
1105 kInterFrameDelayMs * 2) /
1106 kMinRequiredSamples;
Sergey Silkin02371062019-01-31 16:45:42 +01001107 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
ilnik6d5b4d62017-08-30 03:32:14 -07001108 EXPECT_EQ(
1109 kExpectedInterFrame,
1110 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1111 EXPECT_EQ(
1112 kInterFrameDelayMs * 2,
1113 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1114 } else {
1115 EXPECT_EQ(kExpectedInterFrame,
1116 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
1117 EXPECT_EQ(kInterFrameDelayMs * 2,
1118 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
sprang892dab52017-08-15 05:00:33 -07001119 }
1120}
1121
Sergey Silkin02371062019-01-31 16:45:42 +01001122TEST_P(ReceiveStatisticsProxyTestWithContent,
1123 InterFrameDelaysPercentilesAreReported) {
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001124 const int kInterFrameDelayMs = 33;
1125 const int kLastFivePercentsSamples = kMinRequiredSamples * 5 / 100;
Sergey Silkin278f8252019-01-09 14:37:40 +01001126 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1127
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001128 for (int i = 0; i <= kMinRequiredSamples - kLastFivePercentsSamples; ++i) {
1129 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
Johannes Kronbfd343b2019-07-01 10:07:50 +02001130 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001131 }
1132 // Last 5% of intervals are double in size.
1133 for (int i = 0; i < kLastFivePercentsSamples; ++i) {
1134 fake_clock_.AdvanceTimeMilliseconds(2 * kInterFrameDelayMs);
Johannes Kronbfd343b2019-07-01 10:07:50 +02001135 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001136 }
1137 // Final sample is outlier and 10 times as big.
1138 fake_clock_.AdvanceTimeMilliseconds(10 * kInterFrameDelayMs);
Johannes Kronbfd343b2019-07-01 10:07:50 +02001139 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001140
Niels Möllerd7819652019-08-13 14:43:02 +02001141 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1142 nullptr);
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001143 const int kExpectedInterFrame = kInterFrameDelayMs * 2;
Sergey Silkin02371062019-01-31 16:45:42 +01001144 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiydaa4f7a2017-10-06 12:29:47 +02001145 EXPECT_EQ(kExpectedInterFrame,
1146 metrics::MinSample(
1147 "WebRTC.Video.Screenshare.InterframeDelay95PercentileInMs"));
1148 } else {
1149 EXPECT_EQ(
1150 kExpectedInterFrame,
1151 metrics::MinSample("WebRTC.Video.InterframeDelay95PercentileInMs"));
1152 }
1153}
1154
Sergey Silkin02371062019-01-31 16:45:42 +01001155TEST_P(ReceiveStatisticsProxyTestWithContent,
1156 MaxInterFrameDelayOnlyWithValidAverage) {
sprang892dab52017-08-15 05:00:33 -07001157 const int kInterFrameDelayMs = 33;
Sergey Silkin278f8252019-01-09 14:37:40 +01001158 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1159
sprang892dab52017-08-15 05:00:33 -07001160 for (int i = 0; i < kMinRequiredSamples; ++i) {
Johannes Kronbfd343b2019-07-01 10:07:50 +02001161 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
sprang892dab52017-08-15 05:00:33 -07001162 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1163 }
1164
1165 // |kMinRequiredSamples| samples, and thereby intervals, is required. That
1166 // means we're one frame short of having a valid data set.
Niels Möllerd7819652019-08-13 14:43:02 +02001167 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1168 nullptr);
sprang892dab52017-08-15 05:00:33 -07001169 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
1170 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
1171 EXPECT_EQ(
1172 0, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1173 EXPECT_EQ(0, metrics::NumSamples(
1174 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1175}
1176
Sergey Silkin02371062019-01-31 16:45:42 +01001177TEST_P(ReceiveStatisticsProxyTestWithContent, MaxInterFrameDelayOnlyWithPause) {
sprang3e86e7e2017-08-22 09:23:28 -07001178 const int kInterFrameDelayMs = 33;
Sergey Silkin278f8252019-01-09 14:37:40 +01001179 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1180
sprang3e86e7e2017-08-22 09:23:28 -07001181 for (int i = 0; i <= kMinRequiredSamples; ++i) {
Johannes Kronbfd343b2019-07-01 10:07:50 +02001182 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
sprang3e86e7e2017-08-22 09:23:28 -07001183 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1184 }
1185
1186 // At this state, we should have a valid inter-frame delay.
1187 // Indicate stream paused and make a large jump in time.
1188 statistics_proxy_->OnStreamInactive();
1189 fake_clock_.AdvanceTimeMilliseconds(5000);
1190
1191 // Insert two more frames. The interval during the pause should be disregarded
1192 // in the stats.
Johannes Kronbfd343b2019-07-01 10:07:50 +02001193 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
sprang3e86e7e2017-08-22 09:23:28 -07001194 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
Johannes Kronbfd343b2019-07-01 10:07:50 +02001195 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
sprang3e86e7e2017-08-22 09:23:28 -07001196
Niels Möllerd7819652019-08-13 14:43:02 +02001197 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1198 nullptr);
Sergey Silkin02371062019-01-31 16:45:42 +01001199 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
sprang3e86e7e2017-08-22 09:23:28 -07001200 EXPECT_EQ(
1201 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1202 EXPECT_EQ(1, metrics::NumSamples(
1203 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1204 EXPECT_EQ(
1205 kInterFrameDelayMs,
1206 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1207 EXPECT_EQ(
1208 kInterFrameDelayMs,
1209 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1210 } else {
1211 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
1212 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
1213 EXPECT_EQ(kInterFrameDelayMs,
1214 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
1215 EXPECT_EQ(kInterFrameDelayMs,
1216 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
1217 }
1218}
1219
Sergey Silkin02371062019-01-31 16:45:42 +01001220TEST_P(ReceiveStatisticsProxyTestWithContent, FreezesAreReported) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001221 const int kInterFrameDelayMs = 33;
1222 const int kFreezeDelayMs = 200;
Sergey Silkinbea18ca2018-10-02 16:22:46 +02001223 const int kCallDurationMs =
1224 kMinRequiredSamples * kInterFrameDelayMs + kFreezeDelayMs;
Sergey Silkin278f8252019-01-09 14:37:40 +01001225 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1226
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001227 for (int i = 0; i < kMinRequiredSamples; ++i) {
Johannes Kronbfd343b2019-07-01 10:07:50 +02001228 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Ilya Nikolaevskiycdc959f2018-10-10 13:15:09 +02001229 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001230 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1231 }
1232 // Add extra freeze.
1233 fake_clock_.AdvanceTimeMilliseconds(kFreezeDelayMs);
Johannes Kronbfd343b2019-07-01 10:07:50 +02001234 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Ilya Nikolaevskiycdc959f2018-10-10 13:15:09 +02001235 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001236
Niels Möllerd7819652019-08-13 14:43:02 +02001237 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1238 nullptr);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001239 const int kExpectedTimeBetweenFreezes =
1240 kInterFrameDelayMs * (kMinRequiredSamples - 1);
Sergey Silkinbea18ca2018-10-02 16:22:46 +02001241 const int kExpectedNumberFreezesPerMinute = 60 * 1000 / kCallDurationMs;
Sergey Silkin02371062019-01-31 16:45:42 +01001242 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001243 EXPECT_EQ(
1244 kFreezeDelayMs + kInterFrameDelayMs,
1245 metrics::MinSample("WebRTC.Video.Screenshare.MeanFreezeDurationMs"));
1246 EXPECT_EQ(kExpectedTimeBetweenFreezes,
1247 metrics::MinSample(
1248 "WebRTC.Video.Screenshare.MeanTimeBetweenFreezesMs"));
Sergey Silkinbea18ca2018-10-02 16:22:46 +02001249 EXPECT_EQ(
1250 kExpectedNumberFreezesPerMinute,
1251 metrics::MinSample("WebRTC.Video.Screenshare.NumberFreezesPerMinute"));
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001252 } else {
1253 EXPECT_EQ(kFreezeDelayMs + kInterFrameDelayMs,
1254 metrics::MinSample("WebRTC.Video.MeanFreezeDurationMs"));
1255 EXPECT_EQ(kExpectedTimeBetweenFreezes,
1256 metrics::MinSample("WebRTC.Video.MeanTimeBetweenFreezesMs"));
Sergey Silkinbea18ca2018-10-02 16:22:46 +02001257 EXPECT_EQ(kExpectedNumberFreezesPerMinute,
1258 metrics::MinSample("WebRTC.Video.NumberFreezesPerMinute"));
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001259 }
1260}
1261
Sergey Silkin02371062019-01-31 16:45:42 +01001262TEST_P(ReceiveStatisticsProxyTestWithContent, HarmonicFrameRateIsReported) {
Sergey Silkinfc6f3e52019-04-03 10:57:26 +02001263 const int kFrameDurationMs = 33;
1264 const int kFreezeDurationMs = 200;
1265 const int kPauseDurationMs = 10000;
1266 const int kCallDurationMs = kMinRequiredSamples * kFrameDurationMs +
1267 kFreezeDurationMs + kPauseDurationMs;
Sergey Silkin50e77452019-01-16 13:41:46 +01001268 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1269
1270 for (int i = 0; i < kMinRequiredSamples; ++i) {
Sergey Silkinfc6f3e52019-04-03 10:57:26 +02001271 fake_clock_.AdvanceTimeMilliseconds(kFrameDurationMs);
Johannes Kronbfd343b2019-07-01 10:07:50 +02001272 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Sergey Silkin50e77452019-01-16 13:41:46 +01001273 statistics_proxy_->OnRenderedFrame(frame);
1274 }
Sergey Silkinfc6f3e52019-04-03 10:57:26 +02001275
1276 // Freezes and pauses should be included into harmonic frame rate.
1277 // Add freeze.
1278 fake_clock_.AdvanceTimeMilliseconds(kFreezeDurationMs);
Johannes Kronbfd343b2019-07-01 10:07:50 +02001279 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Sergey Silkinfc6f3e52019-04-03 10:57:26 +02001280 statistics_proxy_->OnRenderedFrame(frame);
1281
1282 // Add pause.
1283 fake_clock_.AdvanceTimeMilliseconds(kPauseDurationMs);
1284 statistics_proxy_->OnStreamInactive();
Johannes Kronbfd343b2019-07-01 10:07:50 +02001285 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Sergey Silkin50e77452019-01-16 13:41:46 +01001286 statistics_proxy_->OnRenderedFrame(frame);
1287
Niels Möllerd7819652019-08-13 14:43:02 +02001288 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1289 nullptr);
Sergey Silkinfc6f3e52019-04-03 10:57:26 +02001290 double kSumSquaredFrameDurationSecs =
Sergey Silkin50e77452019-01-16 13:41:46 +01001291 (kMinRequiredSamples - 1) *
Sergey Silkinfc6f3e52019-04-03 10:57:26 +02001292 (kFrameDurationMs / 1000.0 * kFrameDurationMs / 1000.0);
1293 kSumSquaredFrameDurationSecs +=
1294 kFreezeDurationMs / 1000.0 * kFreezeDurationMs / 1000.0;
1295 kSumSquaredFrameDurationSecs +=
1296 kPauseDurationMs / 1000.0 * kPauseDurationMs / 1000.0;
Sergey Silkin50e77452019-01-16 13:41:46 +01001297 const int kExpectedHarmonicFrameRateFps =
Sergey Silkinfc6f3e52019-04-03 10:57:26 +02001298 std::round(kCallDurationMs / (1000 * kSumSquaredFrameDurationSecs));
Sergey Silkin02371062019-01-31 16:45:42 +01001299 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Sergey Silkin50e77452019-01-16 13:41:46 +01001300 EXPECT_EQ(kExpectedHarmonicFrameRateFps,
1301 metrics::MinSample("WebRTC.Video.Screenshare.HarmonicFrameRate"));
1302 } else {
1303 EXPECT_EQ(kExpectedHarmonicFrameRateFps,
1304 metrics::MinSample("WebRTC.Video.HarmonicFrameRate"));
1305 }
1306}
1307
Sergey Silkin02371062019-01-31 16:45:42 +01001308TEST_P(ReceiveStatisticsProxyTestWithContent, PausesAreIgnored) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001309 const int kInterFrameDelayMs = 33;
1310 const int kPauseDurationMs = 10000;
Sergey Silkin278f8252019-01-09 14:37:40 +01001311 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1312
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001313 for (int i = 0; i <= kMinRequiredSamples; ++i) {
Johannes Kronbfd343b2019-07-01 10:07:50 +02001314 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Ilya Nikolaevskiycdc959f2018-10-10 13:15:09 +02001315 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001316 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1317 }
1318 // Add a pause.
1319 fake_clock_.AdvanceTimeMilliseconds(kPauseDurationMs);
1320 statistics_proxy_->OnStreamInactive();
1321
1322 // Second playback interval with triple the length.
1323 for (int i = 0; i <= kMinRequiredSamples * 3; ++i) {
Johannes Kronbfd343b2019-07-01 10:07:50 +02001324 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Ilya Nikolaevskiycdc959f2018-10-10 13:15:09 +02001325 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001326 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1327 }
1328
Niels Möllerd7819652019-08-13 14:43:02 +02001329 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1330 nullptr);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001331 // Average of two playback intervals.
1332 const int kExpectedTimeBetweenFreezes =
1333 kInterFrameDelayMs * kMinRequiredSamples * 2;
Sergey Silkin02371062019-01-31 16:45:42 +01001334 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001335 EXPECT_EQ(-1, metrics::MinSample(
1336 "WebRTC.Video.Screenshare.MeanFreezeDurationMs"));
1337 EXPECT_EQ(kExpectedTimeBetweenFreezes,
1338 metrics::MinSample(
1339 "WebRTC.Video.Screenshare.MeanTimeBetweenFreezesMs"));
1340 } else {
1341 EXPECT_EQ(-1, metrics::MinSample("WebRTC.Video.MeanFreezeDurationMs"));
1342 EXPECT_EQ(kExpectedTimeBetweenFreezes,
1343 metrics::MinSample("WebRTC.Video.MeanTimeBetweenFreezesMs"));
1344 }
1345}
1346
Sergey Silkin02371062019-01-31 16:45:42 +01001347TEST_P(ReceiveStatisticsProxyTestWithContent, ManyPausesAtTheBeginning) {
Ilya Nikolaevskiy879f5a32018-05-31 09:47:17 +02001348 const int kInterFrameDelayMs = 33;
1349 const int kPauseDurationMs = 10000;
Sergey Silkin278f8252019-01-09 14:37:40 +01001350 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1351
Ilya Nikolaevskiy879f5a32018-05-31 09:47:17 +02001352 for (int i = 0; i <= kMinRequiredSamples; ++i) {
Johannes Kronbfd343b2019-07-01 10:07:50 +02001353 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Ilya Nikolaevskiy879f5a32018-05-31 09:47:17 +02001354 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1355
1356 statistics_proxy_->OnStreamInactive();
1357 fake_clock_.AdvanceTimeMilliseconds(kPauseDurationMs);
1358
Johannes Kronbfd343b2019-07-01 10:07:50 +02001359 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Ilya Nikolaevskiy879f5a32018-05-31 09:47:17 +02001360 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1361 }
1362
Niels Möllerd7819652019-08-13 14:43:02 +02001363 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1364 nullptr);
Ilya Nikolaevskiy879f5a32018-05-31 09:47:17 +02001365 // No freezes should be detected, as all long inter-frame delays were pauses.
Sergey Silkin02371062019-01-31 16:45:42 +01001366 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiy879f5a32018-05-31 09:47:17 +02001367 EXPECT_EQ(-1, metrics::MinSample(
1368 "WebRTC.Video.Screenshare.MeanFreezeDurationMs"));
1369 } else {
1370 EXPECT_EQ(-1, metrics::MinSample("WebRTC.Video.MeanFreezeDurationMs"));
1371 }
1372}
1373
Sergey Silkin02371062019-01-31 16:45:42 +01001374TEST_P(ReceiveStatisticsProxyTestWithContent, TimeInHdReported) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001375 const int kInterFrameDelayMs = 20;
Sergey Silkin278f8252019-01-09 14:37:40 +01001376 webrtc::VideoFrame frame_hd = CreateFrame(1280, 720);
1377 webrtc::VideoFrame frame_sd = CreateFrame(640, 360);
1378
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001379 // HD frames.
1380 for (int i = 0; i < kMinRequiredSamples; ++i) {
Johannes Kronbfd343b2019-07-01 10:07:50 +02001381 statistics_proxy_->OnDecodedFrame(frame_hd, absl::nullopt, 0,
1382 content_type_);
Sergey Silkin278f8252019-01-09 14:37:40 +01001383 statistics_proxy_->OnRenderedFrame(frame_hd);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001384 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1385 }
1386 // SD frames.
1387 for (int i = 0; i < 2 * kMinRequiredSamples; ++i) {
Johannes Kronbfd343b2019-07-01 10:07:50 +02001388 statistics_proxy_->OnDecodedFrame(frame_sd, absl::nullopt, 0,
1389 content_type_);
Sergey Silkin278f8252019-01-09 14:37:40 +01001390 statistics_proxy_->OnRenderedFrame(frame_sd);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001391 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1392 }
1393 // Extra last frame.
Sergey Silkin278f8252019-01-09 14:37:40 +01001394 statistics_proxy_->OnRenderedFrame(frame_sd);
1395
Niels Möllerd7819652019-08-13 14:43:02 +02001396 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1397 nullptr);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001398 const int kExpectedTimeInHdPercents = 33;
Sergey Silkin02371062019-01-31 16:45:42 +01001399 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001400 EXPECT_EQ(
1401 kExpectedTimeInHdPercents,
1402 metrics::MinSample("WebRTC.Video.Screenshare.TimeInHdPercentage"));
1403 } else {
1404 EXPECT_EQ(kExpectedTimeInHdPercents,
1405 metrics::MinSample("WebRTC.Video.TimeInHdPercentage"));
1406 }
1407}
1408
Sergey Silkin02371062019-01-31 16:45:42 +01001409TEST_P(ReceiveStatisticsProxyTestWithContent, TimeInBlockyVideoReported) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001410 const int kInterFrameDelayMs = 20;
1411 const int kHighQp = 80;
1412 const int kLowQp = 30;
Sergey Silkin278f8252019-01-09 14:37:40 +01001413 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1414
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001415 // High quality frames.
1416 for (int i = 0; i < kMinRequiredSamples; ++i) {
Johannes Kronbfd343b2019-07-01 10:07:50 +02001417 statistics_proxy_->OnDecodedFrame(frame, kLowQp, 0, content_type_);
Sergey Silkin278f8252019-01-09 14:37:40 +01001418 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001419 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1420 }
1421 // Blocky frames.
1422 for (int i = 0; i < 2 * kMinRequiredSamples; ++i) {
Johannes Kronbfd343b2019-07-01 10:07:50 +02001423 statistics_proxy_->OnDecodedFrame(frame, kHighQp, 0, content_type_);
Sergey Silkin278f8252019-01-09 14:37:40 +01001424 statistics_proxy_->OnRenderedFrame(frame);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001425 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1426 }
1427 // Extra last frame.
Johannes Kronbfd343b2019-07-01 10:07:50 +02001428 statistics_proxy_->OnDecodedFrame(frame, kHighQp, 0, content_type_);
Sergey Silkin278f8252019-01-09 14:37:40 +01001429 statistics_proxy_->OnRenderedFrame(frame);
1430
Niels Möllerd7819652019-08-13 14:43:02 +02001431 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1432 nullptr);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001433 const int kExpectedTimeInHdPercents = 66;
Sergey Silkin02371062019-01-31 16:45:42 +01001434 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001435 EXPECT_EQ(kExpectedTimeInHdPercents,
1436 metrics::MinSample(
1437 "WebRTC.Video.Screenshare.TimeInBlockyVideoPercentage"));
1438 } else {
1439 EXPECT_EQ(kExpectedTimeInHdPercents,
1440 metrics::MinSample("WebRTC.Video.TimeInBlockyVideoPercentage"));
1441 }
1442}
1443
Sergey Silkin02371062019-01-31 16:45:42 +01001444TEST_P(ReceiveStatisticsProxyTestWithContent, DownscalesReported) {
Sergey Silkin278f8252019-01-09 14:37:40 +01001445 const int kInterFrameDelayMs = 2000; // To ensure long enough call duration.
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001446
Sergey Silkin278f8252019-01-09 14:37:40 +01001447 webrtc::VideoFrame frame_hd = CreateFrame(1280, 720);
1448 webrtc::VideoFrame frame_sd = CreateFrame(640, 360);
1449 webrtc::VideoFrame frame_ld = CreateFrame(320, 180);
1450
1451 // Call once to pass content type.
Johannes Kronbfd343b2019-07-01 10:07:50 +02001452 statistics_proxy_->OnDecodedFrame(frame_hd, absl::nullopt, 0, content_type_);
Sergey Silkin278f8252019-01-09 14:37:40 +01001453
1454 statistics_proxy_->OnRenderedFrame(frame_hd);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001455 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1456
1457 // Downscale.
Sergey Silkin278f8252019-01-09 14:37:40 +01001458 statistics_proxy_->OnRenderedFrame(frame_sd);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001459 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1460
1461 // Downscale.
Sergey Silkin278f8252019-01-09 14:37:40 +01001462 statistics_proxy_->OnRenderedFrame(frame_ld);
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001463 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1464
Niels Möllerd7819652019-08-13 14:43:02 +02001465 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1466 nullptr);
Sergey Silkin278f8252019-01-09 14:37:40 +01001467 const int kExpectedDownscales = 30; // 2 per 4 seconds = 30 per minute.
Sergey Silkin02371062019-01-31 16:45:42 +01001468 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
Ilya Nikolaevskiy94150ee2018-05-23 11:53:19 +02001469 EXPECT_EQ(
1470 kExpectedDownscales,
1471 metrics::MinSample(
1472 "WebRTC.Video.Screenshare.NumberResolutionDownswitchesPerMinute"));
1473 } else {
1474 EXPECT_EQ(kExpectedDownscales,
1475 metrics::MinSample(
1476 "WebRTC.Video.NumberResolutionDownswitchesPerMinute"));
1477 }
1478}
1479
Johannes Kronbfd343b2019-07-01 10:07:50 +02001480TEST_P(ReceiveStatisticsProxyTestWithContent, DecodeTimeReported) {
1481 const int kInterFrameDelayMs = 20;
1482 const int kLowQp = 30;
1483 const int kDecodeMs = 7;
1484
1485 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1486
1487 for (int i = 0; i < kMinRequiredSamples; ++i) {
1488 statistics_proxy_->OnDecodedFrame(frame, kLowQp, kDecodeMs, content_type_);
1489 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1490 }
Niels Möllerd7819652019-08-13 14:43:02 +02001491 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1492 nullptr);
Johannes Kronbfd343b2019-07-01 10:07:50 +02001493 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DecodeTimeInMs", kDecodeMs));
1494}
1495
Sergey Silkin02371062019-01-31 16:45:42 +01001496TEST_P(ReceiveStatisticsProxyTestWithContent,
1497 StatsAreSlicedOnSimulcastAndExperiment) {
ilnik6d5b4d62017-08-30 03:32:14 -07001498 const uint8_t experiment_id = 1;
Sergey Silkin02371062019-01-31 16:45:42 +01001499 webrtc::VideoContentType content_type = content_type_;
ilnik6d5b4d62017-08-30 03:32:14 -07001500 videocontenttypehelpers::SetExperimentId(&content_type, experiment_id);
1501 const int kInterFrameDelayMs1 = 30;
1502 const int kInterFrameDelayMs2 = 50;
Sergey Silkin278f8252019-01-09 14:37:40 +01001503 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
ilnik6d5b4d62017-08-30 03:32:14 -07001504
1505 videocontenttypehelpers::SetSimulcastId(&content_type, 1);
1506 for (int i = 0; i <= kMinRequiredSamples; ++i) {
1507 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs1);
Johannes Kronbfd343b2019-07-01 10:07:50 +02001508 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type);
ilnik6d5b4d62017-08-30 03:32:14 -07001509 }
1510
1511 videocontenttypehelpers::SetSimulcastId(&content_type, 2);
1512 for (int i = 0; i <= kMinRequiredSamples; ++i) {
1513 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs2);
Johannes Kronbfd343b2019-07-01 10:07:50 +02001514 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type);
ilnik6d5b4d62017-08-30 03:32:14 -07001515 }
Niels Möllerd7819652019-08-13 14:43:02 +02001516 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1517 nullptr);
ilnik6d5b4d62017-08-30 03:32:14 -07001518
1519 if (videocontenttypehelpers::IsScreenshare(content_type)) {
1520 EXPECT_EQ(
1521 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1522 EXPECT_EQ(1, metrics::NumSamples(
1523 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1524 EXPECT_EQ(1, metrics::NumSamples(
1525 "WebRTC.Video.Screenshare.InterframeDelayInMs.S0"));
1526 EXPECT_EQ(1, metrics::NumSamples(
1527 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs.S0"));
1528 EXPECT_EQ(1, metrics::NumSamples(
1529 "WebRTC.Video.Screenshare.InterframeDelayInMs.S1"));
1530 EXPECT_EQ(1, metrics::NumSamples(
1531 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs.S1"));
1532 EXPECT_EQ(1,
1533 metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"
1534 ".ExperimentGroup0"));
1535 EXPECT_EQ(
1536 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"
1537 ".ExperimentGroup0"));
1538 EXPECT_EQ(
1539 kInterFrameDelayMs1,
1540 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs.S0"));
1541 EXPECT_EQ(
1542 kInterFrameDelayMs2,
1543 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs.S1"));
1544 EXPECT_EQ(
1545 (kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1546 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1547 EXPECT_EQ(
1548 kInterFrameDelayMs2,
1549 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1550 EXPECT_EQ(
1551 (kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1552 metrics::MinSample(
1553 "WebRTC.Video.Screenshare.InterframeDelayInMs.ExperimentGroup0"));
1554 } else {
1555 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
1556 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
1557 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs.S0"));
1558 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs.S0"));
1559 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs.S1"));
1560 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs.S1"));
1561 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"
1562 ".ExperimentGroup0"));
1563 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"
1564 ".ExperimentGroup0"));
1565 EXPECT_EQ(kInterFrameDelayMs1,
1566 metrics::MinSample("WebRTC.Video.InterframeDelayInMs.S0"));
1567 EXPECT_EQ(kInterFrameDelayMs2,
1568 metrics::MinSample("WebRTC.Video.InterframeDelayInMs.S1"));
1569 EXPECT_EQ((kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1570 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
1571 EXPECT_EQ(kInterFrameDelayMs2,
1572 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
1573 EXPECT_EQ((kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1574 metrics::MinSample(
1575 "WebRTC.Video.InterframeDelayInMs.ExperimentGroup0"));
1576 }
1577}
Johannes Krone76b3ab2019-10-22 13:22:26 +02001578
1579class DecodeTimeHistogramsKillswitch {
1580 public:
1581 explicit DecodeTimeHistogramsKillswitch(bool disable_histograms)
1582 : field_trial_(disable_histograms
1583 ? "WebRTC-DecodeTimeHistogramsKillSwitch/Enabled/"
1584 : "") {}
1585
1586 private:
1587 webrtc::test::ScopedFieldTrials field_trial_;
1588};
1589
1590class ReceiveStatisticsProxyTestWithDecodeTimeHistograms
1591 : public DecodeTimeHistogramsKillswitch,
1592 public ::testing::WithParamInterface<
1593 std::tuple<bool, int, int, int, VideoCodecType, std::string>>,
1594 public ReceiveStatisticsProxyTest {
1595 public:
1596 ReceiveStatisticsProxyTestWithDecodeTimeHistograms()
1597 : DecodeTimeHistogramsKillswitch(std::get<0>(GetParam())) {}
1598
1599 protected:
1600 const std::string kUmaPrefix = "WebRTC.Video.DecodeTimePerFrameInMs.";
1601 const int expected_number_of_samples_ = {std::get<1>(GetParam())};
1602 const int width_ = {std::get<2>(GetParam())};
1603 const int height_ = {std::get<3>(GetParam())};
1604 const VideoCodecType codec_type_ = {std::get<4>(GetParam())};
1605 const std::string implementation_name_ = {std::get<5>(GetParam())};
1606 const std::string uma_histogram_name_ =
1607 kUmaPrefix + (codec_type_ == kVideoCodecVP9 ? "Vp9." : "H264.") +
1608 (height_ == 2160 ? "4k." : "Hd.") +
1609 (implementation_name_.compare("ExternalDecoder") == 0 ? "Hw" : "Sw");
1610};
1611
1612TEST_P(ReceiveStatisticsProxyTestWithDecodeTimeHistograms,
1613 DecodeTimeHistogramsUpdated) {
1614 constexpr int kNumberOfFrames = 10;
1615 constexpr int kDecodeTimeMs = 7;
1616 constexpr int kFrameDurationMs = 1000 / 60;
1617
1618 webrtc::VideoFrame frame = CreateFrame(width_, height_);
1619
1620 statistics_proxy_->OnDecoderImplementationName(implementation_name_.c_str());
1621 statistics_proxy_->OnPreDecode(codec_type_, /*qp=*/0);
1622
1623 for (int i = 0; i < kNumberOfFrames; ++i) {
1624 statistics_proxy_->OnDecodedFrame(frame, /*qp=*/absl::nullopt,
1625 kDecodeTimeMs,
1626 VideoContentType::UNSPECIFIED);
1627 fake_clock_.AdvanceTimeMilliseconds(kFrameDurationMs);
1628 }
1629
1630 EXPECT_EQ(expected_number_of_samples_,
1631 metrics::NumSamples(uma_histogram_name_));
1632 EXPECT_EQ(expected_number_of_samples_,
1633 metrics::NumEvents(uma_histogram_name_, kDecodeTimeMs));
1634}
1635
1636const auto kVp94kHw = std::make_tuple(/*killswitch=*/false,
1637 /*expected_number_of_samples=*/10,
1638 /*width=*/3840,
1639 /*height=*/2160,
1640 kVideoCodecVP9,
1641 /*implementation=*/"ExternalDecoder");
1642const auto kVp94kSw = std::make_tuple(/*killswitch=*/false,
1643 /*expected_number_of_samples=*/10,
1644 /*width=*/3840,
1645 /*height=*/2160,
1646 kVideoCodecVP9,
1647 /*implementation=*/"libvpx");
1648const auto kVp9HdHw = std::make_tuple(/*killswitch=*/false,
1649 /*expected_number_of_samples=*/10,
1650 /*width=*/1920,
1651 /*height=*/1080,
1652 kVideoCodecVP9,
1653 /*implementation=*/"ExternalDecoder");
1654const auto kVp9HdSw = std::make_tuple(/*killswitch=*/false,
1655 /*expected_number_of_samples=*/10,
1656 /*width=*/1920,
1657 /*height=*/1080,
1658 kVideoCodecVP9,
1659 /*implementation=*/"libvpx");
1660const auto kH2644kHw = std::make_tuple(/*killswitch=*/false,
1661 /*expected_number_of_samples=*/10,
1662 /*width=*/3840,
1663 /*height=*/2160,
1664 kVideoCodecH264,
1665 /*implementation=*/"ExternalDecoder");
1666const auto kH2644kSw = std::make_tuple(/*killswitch=*/false,
1667 /*expected_number_of_samples=*/10,
1668 /*width=*/3840,
1669 /*height=*/2160,
1670 kVideoCodecH264,
1671 /*implementation=*/"FFmpeg");
1672const auto kH264HdHw = std::make_tuple(/*killswitch=*/false,
1673 /*expected_number_of_samples=*/10,
1674 /*width=*/1920,
1675 /*height=*/1080,
1676 kVideoCodecH264,
1677 /*implementation=*/"ExternalDecoder");
1678const auto kH264HdSw = std::make_tuple(/*killswitch=*/false,
1679 /*expected_number_of_samples=*/10,
1680 /*width=*/1920,
1681 /*height=*/1080,
1682 kVideoCodecH264,
1683 /*implementation=*/"FFmpeg");
1684
1685INSTANTIATE_TEST_SUITE_P(AllHistogramsPopulated,
1686 ReceiveStatisticsProxyTestWithDecodeTimeHistograms,
1687 ::testing::Values(kVp94kHw,
1688 kVp94kSw,
1689 kVp9HdHw,
1690 kVp9HdSw,
1691 kH2644kHw,
1692 kH2644kSw,
1693 kH264HdHw,
1694 kH264HdSw));
1695
1696const auto kKillswitchDisabled =
1697 std::make_tuple(/*killswitch=*/false,
1698 /*expected_number_of_samples=*/10,
1699 /*width=*/1920,
1700 /*height=*/1080,
1701 kVideoCodecVP9,
1702 /*implementation=*/"libvpx");
1703const auto kKillswitchEnabled =
1704 std::make_tuple(/*killswitch=*/true,
1705 /*expected_number_of_samples=*/0,
1706 /*width=*/1920,
1707 /*height=*/1080,
1708 kVideoCodecVP9,
1709 /*implementation=*/"libvpx");
1710
1711INSTANTIATE_TEST_SUITE_P(KillswitchEffective,
1712 ReceiveStatisticsProxyTestWithDecodeTimeHistograms,
1713 ::testing::Values(kKillswitchDisabled,
1714 kKillswitchEnabled));
1715
sakale5ba44e2016-10-26 07:09:24 -07001716} // namespace webrtc