1 /*
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
11 #include "video/receive_statistics_proxy.h"
12
13 #include <limits>
14 #include <memory>
15 #include <string>
16 #include <tuple>
17 #include <utility>
18
19 #include "absl/types/optional.h"
20 #include "api/scoped_refptr.h"
21 #include "api/video/i420_buffer.h"
22 #include "api/video/video_frame.h"
23 #include "api/video/video_frame_buffer.h"
24 #include "api/video/video_rotation.h"
25 #include "system_wrappers/include/metrics.h"
26 #include "test/field_trial.h"
27 #include "test/gtest.h"
28
29 namespace webrtc {
30 namespace {
31 const int64_t kFreqOffsetProcessIntervalInMs = 40000;
32 const uint32_t kLocalSsrc = 123;
33 const uint32_t kRemoteSsrc = 456;
34 const int kMinRequiredSamples = 200;
35 const int kWidth = 1280;
36 const int kHeight = 720;
37 } // namespace
38
39 // TODO(sakal): ReceiveStatisticsProxy is lacking unittesting.
40 class ReceiveStatisticsProxyTest : public ::testing::Test {
41 public:
ReceiveStatisticsProxyTest()42 ReceiveStatisticsProxyTest() : fake_clock_(1234), config_(GetTestConfig()) {}
~ReceiveStatisticsProxyTest()43 virtual ~ReceiveStatisticsProxyTest() {}
44
45 protected:
SetUp()46 virtual void SetUp() {
47 metrics::Reset();
48 statistics_proxy_.reset(new ReceiveStatisticsProxy(&config_, &fake_clock_));
49 }
50
GetTestConfig()51 VideoReceiveStream::Config GetTestConfig() {
52 VideoReceiveStream::Config config(nullptr);
53 config.rtp.local_ssrc = kLocalSsrc;
54 config.rtp.remote_ssrc = kRemoteSsrc;
55 return config;
56 }
57
CreateFrame(int width,int height)58 VideoFrame CreateFrame(int width, int height) {
59 return CreateVideoFrame(width, height, 0);
60 }
61
CreateFrameWithRenderTimeMs(int64_t render_time_ms)62 VideoFrame CreateFrameWithRenderTimeMs(int64_t render_time_ms) {
63 return CreateVideoFrame(kWidth, kHeight, render_time_ms);
64 }
65
CreateVideoFrame(int width,int height,int64_t render_time_ms)66 VideoFrame CreateVideoFrame(int width, int height, int64_t render_time_ms) {
67 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();
74 frame.set_ntp_time_ms(fake_clock_.CurrentNtpInMilliseconds());
75 return frame;
76 }
77
78 SimulatedClock fake_clock_;
79 const VideoReceiveStream::Config config_;
80 std::unique_ptr<ReceiveStatisticsProxy> statistics_proxy_;
81 };
82
TEST_F(ReceiveStatisticsProxyTest,OnDecodedFrameIncreasesFramesDecoded)83 TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameIncreasesFramesDecoded) {
84 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_decoded);
85 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
86 for (uint32_t i = 1; i <= 3; ++i) {
87 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
88 VideoContentType::UNSPECIFIED);
89 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_decoded);
90 }
91 }
92
TEST_F(ReceiveStatisticsProxyTest,DecodedFpsIsReported)93 TEST_F(ReceiveStatisticsProxyTest, DecodedFpsIsReported) {
94 const int kFps = 20;
95 const int kRequiredSamples = metrics::kMinRunTimeInSeconds * kFps;
96 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
97 for (int i = 0; i < kRequiredSamples; ++i) {
98 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
99 VideoContentType::UNSPECIFIED);
100 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
101 }
102 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
103 nullptr);
104 EXPECT_METRIC_EQ(1,
105 metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
106 EXPECT_METRIC_EQ(
107 1, metrics::NumEvents("WebRTC.Video.DecodedFramesPerSecond", kFps));
108 }
109
TEST_F(ReceiveStatisticsProxyTest,DecodedFpsIsNotReportedForTooFewSamples)110 TEST_F(ReceiveStatisticsProxyTest, DecodedFpsIsNotReportedForTooFewSamples) {
111 const int kFps = 20;
112 const int kRequiredSamples = metrics::kMinRunTimeInSeconds * kFps;
113 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
114 for (int i = 0; i < kRequiredSamples - 1; ++i) {
115 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
116 VideoContentType::UNSPECIFIED);
117 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
118 }
119 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
120 nullptr);
121 EXPECT_METRIC_EQ(0,
122 metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
123 }
124
TEST_F(ReceiveStatisticsProxyTest,OnDecodedFrameWithQpDoesNotResetFramesDecodedOrTotalDecodeTime)125 TEST_F(ReceiveStatisticsProxyTest,
126 OnDecodedFrameWithQpDoesNotResetFramesDecodedOrTotalDecodeTime) {
127 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_decoded);
128 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
129 unsigned int expected_total_decode_time_ms = 0;
130 unsigned int expected_frames_decoded = 0;
131 for (uint32_t i = 1; i <= 3; ++i) {
132 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 1,
133 VideoContentType::UNSPECIFIED);
134 expected_total_decode_time_ms += 1;
135 ++expected_frames_decoded;
136 EXPECT_EQ(expected_frames_decoded,
137 statistics_proxy_->GetStats().frames_decoded);
138 EXPECT_EQ(expected_total_decode_time_ms,
139 statistics_proxy_->GetStats().total_decode_time_ms);
140 }
141 statistics_proxy_->OnDecodedFrame(frame, 1u, 3,
142 VideoContentType::UNSPECIFIED);
143 ++expected_frames_decoded;
144 expected_total_decode_time_ms += 3;
145 EXPECT_EQ(expected_frames_decoded,
146 statistics_proxy_->GetStats().frames_decoded);
147 EXPECT_EQ(expected_total_decode_time_ms,
148 statistics_proxy_->GetStats().total_decode_time_ms);
149 }
150
TEST_F(ReceiveStatisticsProxyTest,OnDecodedFrameIncreasesQpSum)151 TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameIncreasesQpSum) {
152 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
153 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
154 statistics_proxy_->OnDecodedFrame(frame, 3u, 0,
155 VideoContentType::UNSPECIFIED);
156 EXPECT_EQ(3u, statistics_proxy_->GetStats().qp_sum);
157 statistics_proxy_->OnDecodedFrame(frame, 127u, 0,
158 VideoContentType::UNSPECIFIED);
159 EXPECT_EQ(130u, statistics_proxy_->GetStats().qp_sum);
160 }
161
TEST_F(ReceiveStatisticsProxyTest,OnDecodedFrameIncreasesTotalDecodeTime)162 TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameIncreasesTotalDecodeTime) {
163 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
164 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
165 statistics_proxy_->OnDecodedFrame(frame, 3u, 4,
166 VideoContentType::UNSPECIFIED);
167 EXPECT_EQ(4u, statistics_proxy_->GetStats().total_decode_time_ms);
168 statistics_proxy_->OnDecodedFrame(frame, 127u, 7,
169 VideoContentType::UNSPECIFIED);
170 EXPECT_EQ(11u, statistics_proxy_->GetStats().total_decode_time_ms);
171 }
172
TEST_F(ReceiveStatisticsProxyTest,ReportsContentType)173 TEST_F(ReceiveStatisticsProxyTest, ReportsContentType) {
174 const std::string kRealtimeString("realtime");
175 const std::string kScreenshareString("screen");
176 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
177 EXPECT_EQ(kRealtimeString, videocontenttypehelpers::ToString(
178 statistics_proxy_->GetStats().content_type));
179 statistics_proxy_->OnDecodedFrame(frame, 3u, 0,
180 VideoContentType::SCREENSHARE);
181 EXPECT_EQ(kScreenshareString,
182 videocontenttypehelpers::ToString(
183 statistics_proxy_->GetStats().content_type));
184 statistics_proxy_->OnDecodedFrame(frame, 3u, 0,
185 VideoContentType::UNSPECIFIED);
186 EXPECT_EQ(kRealtimeString, videocontenttypehelpers::ToString(
187 statistics_proxy_->GetStats().content_type));
188 }
189
TEST_F(ReceiveStatisticsProxyTest,ReportsMaxTotalInterFrameDelay)190 TEST_F(ReceiveStatisticsProxyTest, ReportsMaxTotalInterFrameDelay) {
191 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
192 const TimeDelta kInterFrameDelay1 = TimeDelta::Millis(100);
193 const TimeDelta kInterFrameDelay2 = TimeDelta::Millis(200);
194 const TimeDelta kInterFrameDelay3 = TimeDelta::Millis(300);
195 double expected_total_inter_frame_delay = 0;
196 double expected_total_squared_inter_frame_delay = 0;
197 EXPECT_EQ(expected_total_inter_frame_delay,
198 statistics_proxy_->GetStats().total_inter_frame_delay);
199 EXPECT_EQ(expected_total_squared_inter_frame_delay,
200 statistics_proxy_->GetStats().total_squared_inter_frame_delay);
201
202 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
203 VideoContentType::UNSPECIFIED);
204 EXPECT_DOUBLE_EQ(expected_total_inter_frame_delay,
205 statistics_proxy_->GetStats().total_inter_frame_delay);
206 EXPECT_DOUBLE_EQ(
207 expected_total_squared_inter_frame_delay,
208 statistics_proxy_->GetStats().total_squared_inter_frame_delay);
209
210 fake_clock_.AdvanceTime(kInterFrameDelay1);
211 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
212 VideoContentType::UNSPECIFIED);
213 expected_total_inter_frame_delay += kInterFrameDelay1.seconds<double>();
214 expected_total_squared_inter_frame_delay +=
215 pow(kInterFrameDelay1.seconds<double>(), 2.0);
216 EXPECT_DOUBLE_EQ(expected_total_inter_frame_delay,
217 statistics_proxy_->GetStats().total_inter_frame_delay);
218 EXPECT_DOUBLE_EQ(
219 expected_total_squared_inter_frame_delay,
220 statistics_proxy_->GetStats().total_squared_inter_frame_delay);
221
222 fake_clock_.AdvanceTime(kInterFrameDelay2);
223 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
224 VideoContentType::UNSPECIFIED);
225 expected_total_inter_frame_delay += kInterFrameDelay2.seconds<double>();
226 expected_total_squared_inter_frame_delay +=
227 pow(kInterFrameDelay2.seconds<double>(), 2.0);
228 EXPECT_DOUBLE_EQ(expected_total_inter_frame_delay,
229 statistics_proxy_->GetStats().total_inter_frame_delay);
230 EXPECT_DOUBLE_EQ(
231 expected_total_squared_inter_frame_delay,
232 statistics_proxy_->GetStats().total_squared_inter_frame_delay);
233
234 fake_clock_.AdvanceTime(kInterFrameDelay3);
235 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
236 VideoContentType::UNSPECIFIED);
237 expected_total_inter_frame_delay += kInterFrameDelay3.seconds<double>();
238 expected_total_squared_inter_frame_delay +=
239 pow(kInterFrameDelay3.seconds<double>(), 2.0);
240 EXPECT_DOUBLE_EQ(expected_total_inter_frame_delay,
241 statistics_proxy_->GetStats().total_inter_frame_delay);
242 EXPECT_DOUBLE_EQ(
243 expected_total_squared_inter_frame_delay,
244 statistics_proxy_->GetStats().total_squared_inter_frame_delay);
245 }
246
TEST_F(ReceiveStatisticsProxyTest,ReportsMaxInterframeDelay)247 TEST_F(ReceiveStatisticsProxyTest, ReportsMaxInterframeDelay) {
248 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
249 const int64_t kInterframeDelayMs1 = 100;
250 const int64_t kInterframeDelayMs2 = 200;
251 const int64_t kInterframeDelayMs3 = 100;
252 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
253 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
254 VideoContentType::UNSPECIFIED);
255 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
256
257 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs1);
258 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
259 VideoContentType::UNSPECIFIED);
260 EXPECT_EQ(kInterframeDelayMs1,
261 statistics_proxy_->GetStats().interframe_delay_max_ms);
262
263 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs2);
264 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
265 VideoContentType::UNSPECIFIED);
266 EXPECT_EQ(kInterframeDelayMs2,
267 statistics_proxy_->GetStats().interframe_delay_max_ms);
268
269 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs3);
270 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
271 VideoContentType::UNSPECIFIED);
272 // kInterframeDelayMs3 is smaller than kInterframeDelayMs2.
273 EXPECT_EQ(kInterframeDelayMs2,
274 statistics_proxy_->GetStats().interframe_delay_max_ms);
275 }
276
TEST_F(ReceiveStatisticsProxyTest,ReportInterframeDelayInWindow)277 TEST_F(ReceiveStatisticsProxyTest, ReportInterframeDelayInWindow) {
278 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
279 const int64_t kInterframeDelayMs1 = 900;
280 const int64_t kInterframeDelayMs2 = 750;
281 const int64_t kInterframeDelayMs3 = 700;
282 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
283 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
284 VideoContentType::UNSPECIFIED);
285 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
286
287 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs1);
288 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
289 VideoContentType::UNSPECIFIED);
290 EXPECT_EQ(kInterframeDelayMs1,
291 statistics_proxy_->GetStats().interframe_delay_max_ms);
292
293 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs2);
294 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
295 VideoContentType::UNSPECIFIED);
296 // Still first delay is the maximum
297 EXPECT_EQ(kInterframeDelayMs1,
298 statistics_proxy_->GetStats().interframe_delay_max_ms);
299
300 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs3);
301 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
302 VideoContentType::UNSPECIFIED);
303 // Now the first sample is out of the window, so the second is the maximum.
304 EXPECT_EQ(kInterframeDelayMs2,
305 statistics_proxy_->GetStats().interframe_delay_max_ms);
306 }
307
TEST_F(ReceiveStatisticsProxyTest,ReportsFreezeMetrics)308 TEST_F(ReceiveStatisticsProxyTest, ReportsFreezeMetrics) {
309 const int64_t kFreezeDurationMs = 1000;
310
311 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
312 EXPECT_EQ(0u, stats.freeze_count);
313 EXPECT_FALSE(stats.total_freezes_duration_ms);
314
315 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
316 for (size_t i = 0; i < VideoQualityObserver::kMinFrameSamplesToDetectFreeze;
317 ++i) {
318 fake_clock_.AdvanceTimeMilliseconds(30);
319 statistics_proxy_->OnRenderedFrame(frame);
320 }
321
322 // Freeze.
323 fake_clock_.AdvanceTimeMilliseconds(kFreezeDurationMs);
324 statistics_proxy_->OnRenderedFrame(frame);
325
326 stats = statistics_proxy_->GetStats();
327 EXPECT_EQ(1u, stats.freeze_count);
328 EXPECT_EQ(kFreezeDurationMs, stats.total_freezes_duration_ms);
329 }
330
TEST_F(ReceiveStatisticsProxyTest,ReportsPauseMetrics)331 TEST_F(ReceiveStatisticsProxyTest, ReportsPauseMetrics) {
332 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
333 ASSERT_EQ(0u, stats.pause_count);
334 ASSERT_EQ(0u, stats.total_pauses_duration_ms);
335
336 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
337 statistics_proxy_->OnRenderedFrame(frame);
338
339 // Pause.
340 fake_clock_.AdvanceTimeMilliseconds(5432);
341 statistics_proxy_->OnStreamInactive();
342 statistics_proxy_->OnRenderedFrame(frame);
343
344 stats = statistics_proxy_->GetStats();
345 EXPECT_EQ(1u, stats.pause_count);
346 EXPECT_EQ(5432u, stats.total_pauses_duration_ms);
347 }
348
TEST_F(ReceiveStatisticsProxyTest,PauseBeforeFirstAndAfterLastFrameIgnored)349 TEST_F(ReceiveStatisticsProxyTest, PauseBeforeFirstAndAfterLastFrameIgnored) {
350 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
351 ASSERT_EQ(0u, stats.pause_count);
352 ASSERT_EQ(0u, stats.total_pauses_duration_ms);
353
354 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
355
356 // Pause -> Frame -> Pause
357 fake_clock_.AdvanceTimeMilliseconds(5000);
358 statistics_proxy_->OnStreamInactive();
359 statistics_proxy_->OnRenderedFrame(frame);
360
361 fake_clock_.AdvanceTimeMilliseconds(30);
362 statistics_proxy_->OnRenderedFrame(frame);
363
364 fake_clock_.AdvanceTimeMilliseconds(5000);
365 statistics_proxy_->OnStreamInactive();
366
367 stats = statistics_proxy_->GetStats();
368 EXPECT_EQ(0u, stats.pause_count);
369 EXPECT_EQ(0u, stats.total_pauses_duration_ms);
370 }
371
TEST_F(ReceiveStatisticsProxyTest,ReportsFramesDuration)372 TEST_F(ReceiveStatisticsProxyTest, ReportsFramesDuration) {
373 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
374 ASSERT_EQ(0u, stats.total_frames_duration_ms);
375
376 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
377
378 // Emulate delay before first frame is rendered. This is needed to ensure
379 // that frame duration only covers time since first frame is rendered and
380 // not the total time.
381 fake_clock_.AdvanceTimeMilliseconds(5432);
382
383 for (int i = 0; i <= 10; ++i) {
384 fake_clock_.AdvanceTimeMilliseconds(30);
385 statistics_proxy_->OnRenderedFrame(frame);
386 }
387
388 stats = statistics_proxy_->GetStats();
389 EXPECT_EQ(10 * 30u, stats.total_frames_duration_ms);
390 }
391
TEST_F(ReceiveStatisticsProxyTest,ReportsSumSquaredFrameDurations)392 TEST_F(ReceiveStatisticsProxyTest, ReportsSumSquaredFrameDurations) {
393 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
394 ASSERT_EQ(0u, stats.sum_squared_frame_durations);
395
396 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
397 for (int i = 0; i <= 10; ++i) {
398 fake_clock_.AdvanceTimeMilliseconds(30);
399 statistics_proxy_->OnRenderedFrame(frame);
400 }
401
402 stats = statistics_proxy_->GetStats();
403 const double kExpectedSumSquaredFrameDurationsSecs =
404 10 * (30 / 1000.0 * 30 / 1000.0);
405 EXPECT_EQ(kExpectedSumSquaredFrameDurationsSecs,
406 stats.sum_squared_frame_durations);
407 }
408
TEST_F(ReceiveStatisticsProxyTest,OnDecodedFrameWithoutQpQpSumWontExist)409 TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameWithoutQpQpSumWontExist) {
410 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
411 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
412 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
413 VideoContentType::UNSPECIFIED);
414 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
415 }
416
TEST_F(ReceiveStatisticsProxyTest,OnDecodedFrameWithoutQpResetsQpSum)417 TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameWithoutQpResetsQpSum) {
418 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
419 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
420 statistics_proxy_->OnDecodedFrame(frame, 3u, 0,
421 VideoContentType::UNSPECIFIED);
422 EXPECT_EQ(3u, statistics_proxy_->GetStats().qp_sum);
423 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
424 VideoContentType::UNSPECIFIED);
425 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
426 }
427
TEST_F(ReceiveStatisticsProxyTest,OnRenderedFrameIncreasesFramesRendered)428 TEST_F(ReceiveStatisticsProxyTest, OnRenderedFrameIncreasesFramesRendered) {
429 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_rendered);
430 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
431 for (uint32_t i = 1; i <= 3; ++i) {
432 statistics_proxy_->OnRenderedFrame(frame);
433 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_rendered);
434 }
435 }
436
TEST_F(ReceiveStatisticsProxyTest,GetStatsReportsSsrc)437 TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsSsrc) {
438 EXPECT_EQ(kRemoteSsrc, statistics_proxy_->GetStats().ssrc);
439 }
440
TEST_F(ReceiveStatisticsProxyTest,GetStatsReportsIncomingPayloadType)441 TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsIncomingPayloadType) {
442 const int kPayloadType = 111;
443 statistics_proxy_->OnIncomingPayloadType(kPayloadType);
444 EXPECT_EQ(kPayloadType, statistics_proxy_->GetStats().current_payload_type);
445 }
446
TEST_F(ReceiveStatisticsProxyTest,GetStatsReportsDecoderImplementationName)447 TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsDecoderImplementationName) {
448 const char* kName = "decoderName";
449 statistics_proxy_->OnDecoderImplementationName(kName);
450 EXPECT_STREQ(
451 kName, statistics_proxy_->GetStats().decoder_implementation_name.c_str());
452 }
453
TEST_F(ReceiveStatisticsProxyTest,GetStatsReportsOnCompleteFrame)454 TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsOnCompleteFrame) {
455 const int kFrameSizeBytes = 1000;
456 statistics_proxy_->OnCompleteFrame(true, kFrameSizeBytes,
457 VideoContentType::UNSPECIFIED);
458 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
459 EXPECT_EQ(1, stats.network_frame_rate);
460 EXPECT_EQ(1, stats.frame_counts.key_frames);
461 EXPECT_EQ(0, stats.frame_counts.delta_frames);
462 }
463
TEST_F(ReceiveStatisticsProxyTest,GetStatsReportsOnDroppedFrame)464 TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsOnDroppedFrame) {
465 unsigned int dropped_frames = 0;
466 for (int i = 0; i < 10; ++i) {
467 statistics_proxy_->OnDroppedFrames(i);
468 dropped_frames += i;
469 }
470 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
471 EXPECT_EQ(dropped_frames, stats.frames_dropped);
472 }
473
TEST_F(ReceiveStatisticsProxyTest,GetStatsReportsDecodeTimingStats)474 TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsDecodeTimingStats) {
475 const int kMaxDecodeMs = 2;
476 const int kCurrentDelayMs = 3;
477 const int kTargetDelayMs = 4;
478 const int kJitterBufferMs = 5;
479 const int kMinPlayoutDelayMs = 6;
480 const int kRenderDelayMs = 7;
481 const int64_t kRttMs = 8;
482 statistics_proxy_->OnRttUpdate(kRttMs, 0);
483 statistics_proxy_->OnFrameBufferTimingsUpdated(
484 kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs, kJitterBufferMs,
485 kMinPlayoutDelayMs, kRenderDelayMs);
486 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
487 EXPECT_EQ(kMaxDecodeMs, stats.max_decode_ms);
488 EXPECT_EQ(kCurrentDelayMs, stats.current_delay_ms);
489 EXPECT_EQ(kTargetDelayMs, stats.target_delay_ms);
490 EXPECT_EQ(kJitterBufferMs, stats.jitter_buffer_ms);
491 EXPECT_EQ(kMinPlayoutDelayMs, stats.min_playout_delay_ms);
492 EXPECT_EQ(kRenderDelayMs, stats.render_delay_ms);
493 }
494
TEST_F(ReceiveStatisticsProxyTest,GetStatsReportsRtcpPacketTypeCounts)495 TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsRtcpPacketTypeCounts) {
496 const uint32_t kFirPackets = 33;
497 const uint32_t kPliPackets = 44;
498 const uint32_t kNackPackets = 55;
499 RtcpPacketTypeCounter counter;
500 counter.fir_packets = kFirPackets;
501 counter.pli_packets = kPliPackets;
502 counter.nack_packets = kNackPackets;
503 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
504 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
505 EXPECT_EQ(kFirPackets, stats.rtcp_packet_type_counts.fir_packets);
506 EXPECT_EQ(kPliPackets, stats.rtcp_packet_type_counts.pli_packets);
507 EXPECT_EQ(kNackPackets, stats.rtcp_packet_type_counts.nack_packets);
508 }
509
TEST_F(ReceiveStatisticsProxyTest,GetStatsReportsNoRtcpPacketTypeCountsForUnknownSsrc)510 TEST_F(ReceiveStatisticsProxyTest,
511 GetStatsReportsNoRtcpPacketTypeCountsForUnknownSsrc) {
512 RtcpPacketTypeCounter counter;
513 counter.fir_packets = 33;
514 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc + 1, counter);
515 EXPECT_EQ(0u,
516 statistics_proxy_->GetStats().rtcp_packet_type_counts.fir_packets);
517 }
518
TEST_F(ReceiveStatisticsProxyTest,GetStatsReportsFrameCounts)519 TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsFrameCounts) {
520 const int kKeyFrames = 3;
521 const int kDeltaFrames = 22;
522 for (int i = 0; i < kKeyFrames; i++) {
523 statistics_proxy_->OnCompleteFrame(true, 0, VideoContentType::UNSPECIFIED);
524 }
525 for (int i = 0; i < kDeltaFrames; i++) {
526 statistics_proxy_->OnCompleteFrame(false, 0, VideoContentType::UNSPECIFIED);
527 }
528
529 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
530 EXPECT_EQ(kKeyFrames, stats.frame_counts.key_frames);
531 EXPECT_EQ(kDeltaFrames, stats.frame_counts.delta_frames);
532 }
533
TEST_F(ReceiveStatisticsProxyTest,GetStatsReportsCName)534 TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsCName) {
535 const char* kName = "cName";
536 statistics_proxy_->OnCname(kRemoteSsrc, kName);
537 EXPECT_STREQ(kName, statistics_proxy_->GetStats().c_name.c_str());
538 }
539
TEST_F(ReceiveStatisticsProxyTest,GetStatsReportsNoCNameForUnknownSsrc)540 TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsNoCNameForUnknownSsrc) {
541 const char* kName = "cName";
542 statistics_proxy_->OnCname(kRemoteSsrc + 1, kName);
543 EXPECT_STREQ("", statistics_proxy_->GetStats().c_name.c_str());
544 }
545
TEST_F(ReceiveStatisticsProxyTest,ReportsLongestTimingFrameInfo)546 TEST_F(ReceiveStatisticsProxyTest, ReportsLongestTimingFrameInfo) {
547 const int64_t kShortEndToEndDelay = 10;
548 const int64_t kMedEndToEndDelay = 20;
549 const int64_t kLongEndToEndDelay = 100;
550 const uint32_t kExpectedRtpTimestamp = 2;
551 TimingFrameInfo info;
552 absl::optional<TimingFrameInfo> result;
553 info.rtp_timestamp = kExpectedRtpTimestamp - 1;
554 info.capture_time_ms = 0;
555 info.decode_finish_ms = kShortEndToEndDelay;
556 statistics_proxy_->OnTimingFrameInfoUpdated(info);
557 info.rtp_timestamp =
558 kExpectedRtpTimestamp; // this frame should be reported in the end.
559 info.capture_time_ms = 0;
560 info.decode_finish_ms = kLongEndToEndDelay;
561 statistics_proxy_->OnTimingFrameInfoUpdated(info);
562 info.rtp_timestamp = kExpectedRtpTimestamp + 1;
563 info.capture_time_ms = 0;
564 info.decode_finish_ms = kMedEndToEndDelay;
565 statistics_proxy_->OnTimingFrameInfoUpdated(info);
566 result = statistics_proxy_->GetStats().timing_frame_info;
567 EXPECT_TRUE(result);
568 EXPECT_EQ(kExpectedRtpTimestamp, result->rtp_timestamp);
569 }
570
TEST_F(ReceiveStatisticsProxyTest,RespectsReportingIntervalForTimingFrames)571 TEST_F(ReceiveStatisticsProxyTest, RespectsReportingIntervalForTimingFrames) {
572 TimingFrameInfo info;
573 const int64_t kShortEndToEndDelay = 10;
574 const uint32_t kExpectedRtpTimestamp = 2;
575 const int64_t kShortDelayMs = 1000;
576 const int64_t kLongDelayMs = 10000;
577 absl::optional<TimingFrameInfo> result;
578 info.rtp_timestamp = kExpectedRtpTimestamp;
579 info.capture_time_ms = 0;
580 info.decode_finish_ms = kShortEndToEndDelay;
581 statistics_proxy_->OnTimingFrameInfoUpdated(info);
582 fake_clock_.AdvanceTimeMilliseconds(kShortDelayMs);
583 result = statistics_proxy_->GetStats().timing_frame_info;
584 EXPECT_TRUE(result);
585 EXPECT_EQ(kExpectedRtpTimestamp, result->rtp_timestamp);
586 fake_clock_.AdvanceTimeMilliseconds(kLongDelayMs);
587 result = statistics_proxy_->GetStats().timing_frame_info;
588 EXPECT_FALSE(result);
589 }
590
TEST_F(ReceiveStatisticsProxyTest,LifetimeHistogramIsUpdated)591 TEST_F(ReceiveStatisticsProxyTest, LifetimeHistogramIsUpdated) {
592 const int64_t kTimeSec = 3;
593 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
594 // Need at least one frame to report stream lifetime.
595 statistics_proxy_->OnCompleteFrame(true, 1000, VideoContentType::UNSPECIFIED);
596 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
597 nullptr);
598 EXPECT_METRIC_EQ(
599 1, metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
600 EXPECT_METRIC_EQ(
601 1, metrics::NumEvents("WebRTC.Video.ReceiveStreamLifetimeInSeconds",
602 kTimeSec));
603 }
604
TEST_F(ReceiveStatisticsProxyTest,LifetimeHistogramNotReportedForEmptyStreams)605 TEST_F(ReceiveStatisticsProxyTest,
606 LifetimeHistogramNotReportedForEmptyStreams) {
607 const int64_t kTimeSec = 3;
608 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
609 // No frames received.
610 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
611 nullptr);
612 EXPECT_METRIC_EQ(
613 0, metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
614 }
615
TEST_F(ReceiveStatisticsProxyTest,BadCallHistogramsAreUpdated)616 TEST_F(ReceiveStatisticsProxyTest, BadCallHistogramsAreUpdated) {
617 // Based on the tuning parameters this will produce 7 uncertain states,
618 // then 10 certainly bad states. There has to be 10 certain states before
619 // any histograms are recorded.
620 const int kNumBadSamples = 17;
621 // We only count one sample per second.
622 const int kBadFameIntervalMs = 1100;
623
624 StreamDataCounters counters;
625 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
626
627 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
628
629 for (int i = 0; i < kNumBadSamples; ++i) {
630 fake_clock_.AdvanceTimeMilliseconds(kBadFameIntervalMs);
631 statistics_proxy_->OnRenderedFrame(frame);
632 }
633 statistics_proxy_->UpdateHistograms(absl::nullopt, counters, nullptr);
634 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.BadCall.Any"));
635 EXPECT_METRIC_EQ(1, metrics::NumEvents("WebRTC.Video.BadCall.Any", 100));
636
637 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.BadCall.FrameRate"));
638 EXPECT_METRIC_EQ(1,
639 metrics::NumEvents("WebRTC.Video.BadCall.FrameRate", 100));
640
641 EXPECT_METRIC_EQ(
642 0, metrics::NumSamples("WebRTC.Video.BadCall.FrameRateVariance"));
643
644 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.BadCall.Qp"));
645 }
646
TEST_F(ReceiveStatisticsProxyTest,PacketLossHistogramIsUpdated)647 TEST_F(ReceiveStatisticsProxyTest, PacketLossHistogramIsUpdated) {
648 statistics_proxy_->UpdateHistograms(10, StreamDataCounters(), nullptr);
649 EXPECT_METRIC_EQ(
650 0, metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
651
652 // Restart
653 SetUp();
654
655 // Min run time has passed.
656 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
657 statistics_proxy_->UpdateHistograms(10, StreamDataCounters(), nullptr);
658 EXPECT_METRIC_EQ(
659 1, metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
660 EXPECT_METRIC_EQ(
661 1, metrics::NumEvents("WebRTC.Video.ReceivedPacketsLostInPercent", 10));
662 }
663
TEST_F(ReceiveStatisticsProxyTest,GetStatsReportsPlayoutTimestamp)664 TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsPlayoutTimestamp) {
665 const int64_t kVideoNtpMs = 21;
666 const int64_t kSyncOffsetMs = 22;
667 const double kFreqKhz = 90.0;
668 EXPECT_EQ(absl::nullopt,
669 statistics_proxy_->GetStats().estimated_playout_ntp_timestamp_ms);
670 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs, kFreqKhz);
671 EXPECT_EQ(kVideoNtpMs,
672 statistics_proxy_->GetStats().estimated_playout_ntp_timestamp_ms);
673 fake_clock_.AdvanceTimeMilliseconds(13);
674 EXPECT_EQ(kVideoNtpMs + 13,
675 statistics_proxy_->GetStats().estimated_playout_ntp_timestamp_ms);
676 fake_clock_.AdvanceTimeMilliseconds(5);
677 EXPECT_EQ(kVideoNtpMs + 13 + 5,
678 statistics_proxy_->GetStats().estimated_playout_ntp_timestamp_ms);
679 }
680
TEST_F(ReceiveStatisticsProxyTest,GetStatsReportsAvSyncOffset)681 TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsAvSyncOffset) {
682 const int64_t kVideoNtpMs = 21;
683 const int64_t kSyncOffsetMs = 22;
684 const double kFreqKhz = 90.0;
685 EXPECT_EQ(std::numeric_limits<int>::max(),
686 statistics_proxy_->GetStats().sync_offset_ms);
687 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs, kFreqKhz);
688 EXPECT_EQ(kSyncOffsetMs, statistics_proxy_->GetStats().sync_offset_ms);
689 }
690
TEST_F(ReceiveStatisticsProxyTest,AvSyncOffsetHistogramIsUpdated)691 TEST_F(ReceiveStatisticsProxyTest, AvSyncOffsetHistogramIsUpdated) {
692 const int64_t kVideoNtpMs = 21;
693 const int64_t kSyncOffsetMs = 22;
694 const double kFreqKhz = 90.0;
695 for (int i = 0; i < kMinRequiredSamples; ++i)
696 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs,
697 kFreqKhz);
698 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
699 nullptr);
700 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.AVSyncOffsetInMs"));
701 EXPECT_METRIC_EQ(
702 1, metrics::NumEvents("WebRTC.Video.AVSyncOffsetInMs", kSyncOffsetMs));
703 }
704
TEST_F(ReceiveStatisticsProxyTest,RtpToNtpFrequencyOffsetHistogramIsUpdated)705 TEST_F(ReceiveStatisticsProxyTest, RtpToNtpFrequencyOffsetHistogramIsUpdated) {
706 const int64_t kVideoNtpMs = 21;
707 const int64_t kSyncOffsetMs = 22;
708 const double kFreqKhz = 90.0;
709 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs, kFreqKhz);
710 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs,
711 kFreqKhz + 2.2);
712 fake_clock_.AdvanceTimeMilliseconds(kFreqOffsetProcessIntervalInMs);
713 // Process interval passed, max diff: 2.
714 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs,
715 kFreqKhz + 1.1);
716 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs,
717 kFreqKhz - 4.2);
718 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs,
719 kFreqKhz - 0.9);
720 fake_clock_.AdvanceTimeMilliseconds(kFreqOffsetProcessIntervalInMs);
721 // Process interval passed, max diff: 4.
722 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs, kFreqKhz);
723 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
724 nullptr);
725 // Average reported: (2 + 4) / 2 = 3.
726 EXPECT_METRIC_EQ(1,
727 metrics::NumSamples("WebRTC.Video.RtpToNtpFreqOffsetInKhz"));
728 EXPECT_METRIC_EQ(
729 1, metrics::NumEvents("WebRTC.Video.RtpToNtpFreqOffsetInKhz", 3));
730 }
731
TEST_F(ReceiveStatisticsProxyTest,Vp8QpHistogramIsUpdated)732 TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsUpdated) {
733 const int kQp = 22;
734
735 for (int i = 0; i < kMinRequiredSamples; ++i)
736 statistics_proxy_->OnPreDecode(kVideoCodecVP8, kQp);
737
738 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
739 nullptr);
740 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
741 EXPECT_METRIC_EQ(1, metrics::NumEvents("WebRTC.Video.Decoded.Vp8.Qp", kQp));
742 }
743
TEST_F(ReceiveStatisticsProxyTest,Vp8QpHistogramIsNotUpdatedForTooFewSamples)744 TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsNotUpdatedForTooFewSamples) {
745 const int kQp = 22;
746
747 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
748 statistics_proxy_->OnPreDecode(kVideoCodecVP8, kQp);
749
750 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
751 nullptr);
752 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
753 }
754
TEST_F(ReceiveStatisticsProxyTest,Vp8QpHistogramIsNotUpdatedIfNoQpValue)755 TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsNotUpdatedIfNoQpValue) {
756 for (int i = 0; i < kMinRequiredSamples; ++i)
757 statistics_proxy_->OnPreDecode(kVideoCodecVP8, -1);
758
759 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
760 nullptr);
761 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
762 }
763
TEST_F(ReceiveStatisticsProxyTest,KeyFrameHistogramNotUpdatedForTooFewSamples)764 TEST_F(ReceiveStatisticsProxyTest,
765 KeyFrameHistogramNotUpdatedForTooFewSamples) {
766 const bool kIsKeyFrame = false;
767 const int kFrameSizeBytes = 1000;
768
769 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
770 statistics_proxy_->OnCompleteFrame(kIsKeyFrame, kFrameSizeBytes,
771 VideoContentType::UNSPECIFIED);
772
773 EXPECT_EQ(0, statistics_proxy_->GetStats().frame_counts.key_frames);
774 EXPECT_EQ(kMinRequiredSamples - 1,
775 statistics_proxy_->GetStats().frame_counts.delta_frames);
776
777 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
778 nullptr);
779 EXPECT_METRIC_EQ(
780 0, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
781 }
782
TEST_F(ReceiveStatisticsProxyTest,KeyFrameHistogramUpdatedForMinRequiredSamples)783 TEST_F(ReceiveStatisticsProxyTest,
784 KeyFrameHistogramUpdatedForMinRequiredSamples) {
785 const bool kIsKeyFrame = false;
786 const int kFrameSizeBytes = 1000;
787
788 for (int i = 0; i < kMinRequiredSamples; ++i)
789 statistics_proxy_->OnCompleteFrame(kIsKeyFrame, kFrameSizeBytes,
790 VideoContentType::UNSPECIFIED);
791
792 EXPECT_EQ(0, statistics_proxy_->GetStats().frame_counts.key_frames);
793 EXPECT_EQ(kMinRequiredSamples,
794 statistics_proxy_->GetStats().frame_counts.delta_frames);
795
796 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
797 nullptr);
798 EXPECT_METRIC_EQ(
799 1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
800 EXPECT_METRIC_EQ(
801 1, metrics::NumEvents("WebRTC.Video.KeyFramesReceivedInPermille", 0));
802 }
803
TEST_F(ReceiveStatisticsProxyTest,KeyFrameHistogramIsUpdated)804 TEST_F(ReceiveStatisticsProxyTest, KeyFrameHistogramIsUpdated) {
805 const int kFrameSizeBytes = 1000;
806
807 for (int i = 0; i < kMinRequiredSamples; ++i)
808 statistics_proxy_->OnCompleteFrame(true, kFrameSizeBytes,
809 VideoContentType::UNSPECIFIED);
810
811 for (int i = 0; i < kMinRequiredSamples; ++i)
812 statistics_proxy_->OnCompleteFrame(false, kFrameSizeBytes,
813 VideoContentType::UNSPECIFIED);
814
815 EXPECT_EQ(kMinRequiredSamples,
816 statistics_proxy_->GetStats().frame_counts.key_frames);
817 EXPECT_EQ(kMinRequiredSamples,
818 statistics_proxy_->GetStats().frame_counts.delta_frames);
819
820 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
821 nullptr);
822 EXPECT_METRIC_EQ(
823 1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
824 EXPECT_METRIC_EQ(
825 1, metrics::NumEvents("WebRTC.Video.KeyFramesReceivedInPermille", 500));
826 }
827
TEST_F(ReceiveStatisticsProxyTest,TimingHistogramsNotUpdatedForTooFewSamples)828 TEST_F(ReceiveStatisticsProxyTest, TimingHistogramsNotUpdatedForTooFewSamples) {
829 const int kMaxDecodeMs = 2;
830 const int kCurrentDelayMs = 3;
831 const int kTargetDelayMs = 4;
832 const int kJitterBufferMs = 5;
833 const int kMinPlayoutDelayMs = 6;
834 const int kRenderDelayMs = 7;
835
836 for (int i = 0; i < kMinRequiredSamples - 1; ++i) {
837 statistics_proxy_->OnFrameBufferTimingsUpdated(
838 kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs, kJitterBufferMs,
839 kMinPlayoutDelayMs, kRenderDelayMs);
840 }
841
842 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
843 nullptr);
844 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
845 EXPECT_METRIC_EQ(0,
846 metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
847 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
848 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
849 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
850 }
851
TEST_F(ReceiveStatisticsProxyTest,TimingHistogramsAreUpdated)852 TEST_F(ReceiveStatisticsProxyTest, TimingHistogramsAreUpdated) {
853 const int kMaxDecodeMs = 2;
854 const int kCurrentDelayMs = 3;
855 const int kTargetDelayMs = 4;
856 const int kJitterBufferMs = 5;
857 const int kMinPlayoutDelayMs = 6;
858 const int kRenderDelayMs = 7;
859
860 for (int i = 0; i < kMinRequiredSamples; ++i) {
861 statistics_proxy_->OnFrameBufferTimingsUpdated(
862 kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs, kJitterBufferMs,
863 kMinPlayoutDelayMs, kRenderDelayMs);
864 }
865
866 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
867 nullptr);
868 EXPECT_METRIC_EQ(1,
869 metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
870 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
871 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
872 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
873
874 EXPECT_METRIC_EQ(1, metrics::NumEvents("WebRTC.Video.JitterBufferDelayInMs",
875 kJitterBufferMs));
876 EXPECT_METRIC_EQ(
877 1, metrics::NumEvents("WebRTC.Video.TargetDelayInMs", kTargetDelayMs));
878 EXPECT_METRIC_EQ(
879 1, metrics::NumEvents("WebRTC.Video.CurrentDelayInMs", kCurrentDelayMs));
880 EXPECT_METRIC_EQ(
881 1, metrics::NumEvents("WebRTC.Video.OnewayDelayInMs", kTargetDelayMs));
882 }
883
TEST_F(ReceiveStatisticsProxyTest,DoesNotReportStaleFramerates)884 TEST_F(ReceiveStatisticsProxyTest, DoesNotReportStaleFramerates) {
885 const int kDefaultFps = 30;
886 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
887
888 for (int i = 0; i < kDefaultFps; ++i) {
889 // Since OnRenderedFrame is never called the fps in each sample will be 0,
890 // i.e. bad
891 frame.set_ntp_time_ms(fake_clock_.CurrentNtpInMilliseconds());
892 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
893 VideoContentType::UNSPECIFIED);
894 statistics_proxy_->OnRenderedFrame(frame);
895 fake_clock_.AdvanceTimeMilliseconds(1000 / kDefaultFps);
896 }
897
898 EXPECT_EQ(kDefaultFps, statistics_proxy_->GetStats().decode_frame_rate);
899 EXPECT_EQ(kDefaultFps, statistics_proxy_->GetStats().render_frame_rate);
900
901 // FPS trackers in stats proxy have a 1000ms sliding window.
902 fake_clock_.AdvanceTimeMilliseconds(1000);
903 EXPECT_EQ(0, statistics_proxy_->GetStats().decode_frame_rate);
904 EXPECT_EQ(0, statistics_proxy_->GetStats().render_frame_rate);
905 }
906
TEST_F(ReceiveStatisticsProxyTest,GetStatsReportsReceivedFrameStats)907 TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsReceivedFrameStats) {
908 EXPECT_EQ(0, statistics_proxy_->GetStats().width);
909 EXPECT_EQ(0, statistics_proxy_->GetStats().height);
910 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_rendered);
911
912 statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight));
913
914 EXPECT_EQ(kWidth, statistics_proxy_->GetStats().width);
915 EXPECT_EQ(kHeight, statistics_proxy_->GetStats().height);
916 EXPECT_EQ(1u, statistics_proxy_->GetStats().frames_rendered);
917 }
918
TEST_F(ReceiveStatisticsProxyTest,ReceivedFrameHistogramsAreNotUpdatedForTooFewSamples)919 TEST_F(ReceiveStatisticsProxyTest,
920 ReceivedFrameHistogramsAreNotUpdatedForTooFewSamples) {
921 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
922 statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight));
923
924 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
925 nullptr);
926 EXPECT_METRIC_EQ(0,
927 metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
928 EXPECT_METRIC_EQ(0,
929 metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
930 EXPECT_METRIC_EQ(0,
931 metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
932 EXPECT_METRIC_EQ(
933 0, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
934 }
935
TEST_F(ReceiveStatisticsProxyTest,ReceivedFrameHistogramsAreUpdated)936 TEST_F(ReceiveStatisticsProxyTest, ReceivedFrameHistogramsAreUpdated) {
937 for (int i = 0; i < kMinRequiredSamples; ++i)
938 statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight));
939
940 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
941 nullptr);
942 EXPECT_METRIC_EQ(1,
943 metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
944 EXPECT_METRIC_EQ(1,
945 metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
946 EXPECT_METRIC_EQ(1,
947 metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
948 EXPECT_METRIC_EQ(
949 1, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
950 EXPECT_METRIC_EQ(
951 1, metrics::NumEvents("WebRTC.Video.ReceivedWidthInPixels", kWidth));
952 EXPECT_METRIC_EQ(
953 1, metrics::NumEvents("WebRTC.Video.ReceivedHeightInPixels", kHeight));
954 }
955
TEST_F(ReceiveStatisticsProxyTest,ZeroDelayReportedIfFrameNotDelayed)956 TEST_F(ReceiveStatisticsProxyTest, ZeroDelayReportedIfFrameNotDelayed) {
957 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
958 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
959 VideoContentType::UNSPECIFIED);
960
961 // Frame not delayed, delayed frames to render: 0%.
962 const int64_t kNowMs = fake_clock_.TimeInMilliseconds();
963 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs));
964
965 // Min run time has passed.
966 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
967 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
968 nullptr);
969 EXPECT_METRIC_EQ(1,
970 metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
971 EXPECT_METRIC_EQ(
972 1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 0));
973 EXPECT_METRIC_EQ(0, metrics::NumSamples(
974 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
975 }
976
TEST_F(ReceiveStatisticsProxyTest,DelayedFrameHistogramsAreNotUpdatedIfMinRuntimeHasNotPassed)977 TEST_F(ReceiveStatisticsProxyTest,
978 DelayedFrameHistogramsAreNotUpdatedIfMinRuntimeHasNotPassed) {
979 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
980 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
981 VideoContentType::UNSPECIFIED);
982
983 // Frame not delayed, delayed frames to render: 0%.
984 const int64_t kNowMs = fake_clock_.TimeInMilliseconds();
985 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs));
986
987 // Min run time has not passed.
988 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000) -
989 1);
990 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
991 nullptr);
992 EXPECT_METRIC_EQ(0,
993 metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
994 EXPECT_METRIC_EQ(0, metrics::NumSamples(
995 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
996 }
997
TEST_F(ReceiveStatisticsProxyTest,DelayedFramesHistogramsAreNotUpdatedIfNoRenderedFrames)998 TEST_F(ReceiveStatisticsProxyTest,
999 DelayedFramesHistogramsAreNotUpdatedIfNoRenderedFrames) {
1000 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1001 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
1002 VideoContentType::UNSPECIFIED);
1003
1004 // Min run time has passed. No rendered frames.
1005 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
1006 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1007 nullptr);
1008 EXPECT_METRIC_EQ(0,
1009 metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
1010 EXPECT_METRIC_EQ(0, metrics::NumSamples(
1011 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
1012 }
1013
TEST_F(ReceiveStatisticsProxyTest,DelayReportedIfFrameIsDelayed)1014 TEST_F(ReceiveStatisticsProxyTest, DelayReportedIfFrameIsDelayed) {
1015 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1016 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
1017 VideoContentType::UNSPECIFIED);
1018
1019 // Frame delayed 1 ms, delayed frames to render: 100%.
1020 const int64_t kNowMs = fake_clock_.TimeInMilliseconds();
1021 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs - 1));
1022
1023 // Min run time has passed.
1024 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
1025 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1026 nullptr);
1027 EXPECT_METRIC_EQ(1,
1028 metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
1029 EXPECT_METRIC_EQ(
1030 1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 100));
1031 EXPECT_METRIC_EQ(1, metrics::NumSamples(
1032 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
1033 EXPECT_METRIC_EQ(
1034 1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs",
1035 1));
1036 }
1037
TEST_F(ReceiveStatisticsProxyTest,AverageDelayOfDelayedFramesIsReported)1038 TEST_F(ReceiveStatisticsProxyTest, AverageDelayOfDelayedFramesIsReported) {
1039 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1040 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
1041 VideoContentType::UNSPECIFIED);
1042
1043 // Two frames delayed (6 ms, 10 ms), delayed frames to render: 50%.
1044 const int64_t kNowMs = fake_clock_.TimeInMilliseconds();
1045 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs - 10));
1046 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs - 6));
1047 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs));
1048 statistics_proxy_->OnRenderedFrame(CreateFrameWithRenderTimeMs(kNowMs + 1));
1049
1050 // Min run time has passed.
1051 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
1052 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1053 nullptr);
1054 EXPECT_METRIC_EQ(1,
1055 metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
1056 EXPECT_METRIC_EQ(
1057 1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 50));
1058 EXPECT_METRIC_EQ(1, metrics::NumSamples(
1059 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
1060 EXPECT_METRIC_EQ(
1061 1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs",
1062 8));
1063 }
1064
TEST_F(ReceiveStatisticsProxyTest,RtcpHistogramsNotUpdatedIfMinRuntimeHasNotPassed)1065 TEST_F(ReceiveStatisticsProxyTest,
1066 RtcpHistogramsNotUpdatedIfMinRuntimeHasNotPassed) {
1067 StreamDataCounters data_counters;
1068 data_counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
1069
1070 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000) -
1071 1);
1072
1073 RtcpPacketTypeCounter counter;
1074 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
1075
1076 statistics_proxy_->UpdateHistograms(absl::nullopt, data_counters, nullptr);
1077 EXPECT_METRIC_EQ(0,
1078 metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
1079 EXPECT_METRIC_EQ(0,
1080 metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
1081 EXPECT_METRIC_EQ(
1082 0, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
1083 }
1084
TEST_F(ReceiveStatisticsProxyTest,RtcpHistogramsAreUpdated)1085 TEST_F(ReceiveStatisticsProxyTest, RtcpHistogramsAreUpdated) {
1086 StreamDataCounters data_counters;
1087 data_counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
1088 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1089
1090 const uint32_t kFirPackets = 100;
1091 const uint32_t kPliPackets = 200;
1092 const uint32_t kNackPackets = 300;
1093
1094 RtcpPacketTypeCounter counter;
1095 counter.fir_packets = kFirPackets;
1096 counter.pli_packets = kPliPackets;
1097 counter.nack_packets = kNackPackets;
1098 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
1099
1100 statistics_proxy_->UpdateHistograms(absl::nullopt, data_counters, nullptr);
1101 EXPECT_METRIC_EQ(1,
1102 metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
1103 EXPECT_METRIC_EQ(1,
1104 metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
1105 EXPECT_METRIC_EQ(
1106 1, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
1107 EXPECT_METRIC_EQ(
1108 1, metrics::NumEvents("WebRTC.Video.FirPacketsSentPerMinute",
1109 kFirPackets * 60 / metrics::kMinRunTimeInSeconds));
1110 EXPECT_METRIC_EQ(
1111 1, metrics::NumEvents("WebRTC.Video.PliPacketsSentPerMinute",
1112 kPliPackets * 60 / metrics::kMinRunTimeInSeconds));
1113 EXPECT_METRIC_EQ(
1114 1, metrics::NumEvents("WebRTC.Video.NackPacketsSentPerMinute",
1115 kNackPackets * 60 / metrics::kMinRunTimeInSeconds));
1116 }
1117
1118 class ReceiveStatisticsProxyTestWithFreezeDuration
1119 : public ReceiveStatisticsProxyTest,
1120 public ::testing::WithParamInterface<
1121 std::tuple<uint32_t, uint32_t, uint32_t>> {
1122 protected:
1123 const uint32_t frame_duration_ms_ = {std::get<0>(GetParam())};
1124 const uint32_t freeze_duration_ms_ = {std::get<1>(GetParam())};
1125 const uint32_t expected_freeze_count_ = {std::get<2>(GetParam())};
1126 };
1127
1128 // It is a freeze if:
1129 // frame_duration_ms >= max(3 * avg_frame_duration, avg_frame_duration + 150)
1130 // where avg_frame_duration is average duration of last 30 frames including
1131 // the current one.
1132 //
1133 // Condition 1: 3 * avg_frame_duration > avg_frame_duration + 150
1134 const auto kFreezeDetectionCond1Freeze = std::make_tuple(150, 483, 1);
1135 const auto kFreezeDetectionCond1NotFreeze = std::make_tuple(150, 482, 0);
1136 // Condition 2: 3 * avg_frame_duration < avg_frame_duration + 150
1137 const auto kFreezeDetectionCond2Freeze = std::make_tuple(30, 185, 1);
1138 const auto kFreezeDetectionCond2NotFreeze = std::make_tuple(30, 184, 0);
1139
1140 INSTANTIATE_TEST_SUITE_P(_,
1141 ReceiveStatisticsProxyTestWithFreezeDuration,
1142 ::testing::Values(kFreezeDetectionCond1Freeze,
1143 kFreezeDetectionCond1NotFreeze,
1144 kFreezeDetectionCond2Freeze,
1145 kFreezeDetectionCond2NotFreeze));
1146
TEST_P(ReceiveStatisticsProxyTestWithFreezeDuration,FreezeDetection)1147 TEST_P(ReceiveStatisticsProxyTestWithFreezeDuration, FreezeDetection) {
1148 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
1149 EXPECT_EQ(0u, stats.freeze_count);
1150 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1151
1152 // Add a very long frame. This is need to verify that average frame
1153 // duration, which is supposed to be calculated as mean of durations of
1154 // last 30 frames, is calculated correctly.
1155 statistics_proxy_->OnRenderedFrame(frame);
1156 fake_clock_.AdvanceTimeMilliseconds(2000);
1157
1158 for (size_t i = 0;
1159 i <= VideoQualityObserver::kAvgInterframeDelaysWindowSizeFrames; ++i) {
1160 fake_clock_.AdvanceTimeMilliseconds(frame_duration_ms_);
1161 statistics_proxy_->OnRenderedFrame(frame);
1162 }
1163
1164 fake_clock_.AdvanceTimeMilliseconds(freeze_duration_ms_);
1165 statistics_proxy_->OnRenderedFrame(frame);
1166
1167 stats = statistics_proxy_->GetStats();
1168 EXPECT_EQ(stats.freeze_count, expected_freeze_count_);
1169 }
1170
1171 class ReceiveStatisticsProxyTestWithContent
1172 : public ReceiveStatisticsProxyTest,
1173 public ::testing::WithParamInterface<webrtc::VideoContentType> {
1174 protected:
1175 const webrtc::VideoContentType content_type_{GetParam()};
1176 };
1177
1178 INSTANTIATE_TEST_SUITE_P(ContentTypes,
1179 ReceiveStatisticsProxyTestWithContent,
1180 ::testing::Values(VideoContentType::UNSPECIFIED,
1181 VideoContentType::SCREENSHARE));
1182
TEST_P(ReceiveStatisticsProxyTestWithContent,InterFrameDelaysAreReported)1183 TEST_P(ReceiveStatisticsProxyTestWithContent, InterFrameDelaysAreReported) {
1184 const int kInterFrameDelayMs = 33;
1185 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1186
1187 for (int i = 0; i < kMinRequiredSamples; ++i) {
1188 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
1189 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1190 }
1191 // One extra with double the interval.
1192 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1193 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
1194
1195 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1196 nullptr);
1197 const int kExpectedInterFrame =
1198 (kInterFrameDelayMs * (kMinRequiredSamples - 1) +
1199 kInterFrameDelayMs * 2) /
1200 kMinRequiredSamples;
1201 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
1202 EXPECT_METRIC_EQ(
1203 kExpectedInterFrame,
1204 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1205 EXPECT_METRIC_EQ(
1206 kInterFrameDelayMs * 2,
1207 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1208 } else {
1209 EXPECT_METRIC_EQ(kExpectedInterFrame,
1210 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
1211 EXPECT_METRIC_EQ(kInterFrameDelayMs * 2,
1212 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
1213 }
1214 }
1215
TEST_P(ReceiveStatisticsProxyTestWithContent,InterFrameDelaysPercentilesAreReported)1216 TEST_P(ReceiveStatisticsProxyTestWithContent,
1217 InterFrameDelaysPercentilesAreReported) {
1218 const int kInterFrameDelayMs = 33;
1219 const int kLastFivePercentsSamples = kMinRequiredSamples * 5 / 100;
1220 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1221
1222 for (int i = 0; i <= kMinRequiredSamples - kLastFivePercentsSamples; ++i) {
1223 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1224 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
1225 }
1226 // Last 5% of intervals are double in size.
1227 for (int i = 0; i < kLastFivePercentsSamples; ++i) {
1228 fake_clock_.AdvanceTimeMilliseconds(2 * kInterFrameDelayMs);
1229 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
1230 }
1231 // Final sample is outlier and 10 times as big.
1232 fake_clock_.AdvanceTimeMilliseconds(10 * kInterFrameDelayMs);
1233 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
1234
1235 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1236 nullptr);
1237 const int kExpectedInterFrame = kInterFrameDelayMs * 2;
1238 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
1239 EXPECT_METRIC_EQ(
1240 kExpectedInterFrame,
1241 metrics::MinSample(
1242 "WebRTC.Video.Screenshare.InterframeDelay95PercentileInMs"));
1243 } else {
1244 EXPECT_METRIC_EQ(
1245 kExpectedInterFrame,
1246 metrics::MinSample("WebRTC.Video.InterframeDelay95PercentileInMs"));
1247 }
1248 }
1249
TEST_P(ReceiveStatisticsProxyTestWithContent,MaxInterFrameDelayOnlyWithValidAverage)1250 TEST_P(ReceiveStatisticsProxyTestWithContent,
1251 MaxInterFrameDelayOnlyWithValidAverage) {
1252 const int kInterFrameDelayMs = 33;
1253 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1254
1255 for (int i = 0; i < kMinRequiredSamples; ++i) {
1256 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
1257 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1258 }
1259
1260 // |kMinRequiredSamples| samples, and thereby intervals, is required. That
1261 // means we're one frame short of having a valid data set.
1262 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1263 nullptr);
1264 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
1265 EXPECT_METRIC_EQ(0,
1266 metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
1267 EXPECT_METRIC_EQ(
1268 0, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1269 EXPECT_METRIC_EQ(0, metrics::NumSamples(
1270 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1271 }
1272
TEST_P(ReceiveStatisticsProxyTestWithContent,MaxInterFrameDelayOnlyWithPause)1273 TEST_P(ReceiveStatisticsProxyTestWithContent, MaxInterFrameDelayOnlyWithPause) {
1274 const int kInterFrameDelayMs = 33;
1275 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1276
1277 for (int i = 0; i <= kMinRequiredSamples; ++i) {
1278 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
1279 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1280 }
1281
1282 // At this state, we should have a valid inter-frame delay.
1283 // Indicate stream paused and make a large jump in time.
1284 statistics_proxy_->OnStreamInactive();
1285 fake_clock_.AdvanceTimeMilliseconds(5000);
1286
1287 // Insert two more frames. The interval during the pause should be disregarded
1288 // in the stats.
1289 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
1290 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1291 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
1292
1293 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1294 nullptr);
1295 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
1296 EXPECT_METRIC_EQ(
1297 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1298 EXPECT_METRIC_EQ(1, metrics::NumSamples(
1299 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1300 EXPECT_METRIC_EQ(
1301 kInterFrameDelayMs,
1302 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1303 EXPECT_METRIC_EQ(
1304 kInterFrameDelayMs,
1305 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1306 } else {
1307 EXPECT_METRIC_EQ(1,
1308 metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
1309 EXPECT_METRIC_EQ(
1310 1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
1311 EXPECT_METRIC_EQ(kInterFrameDelayMs,
1312 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
1313 EXPECT_METRIC_EQ(kInterFrameDelayMs,
1314 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
1315 }
1316 }
1317
TEST_P(ReceiveStatisticsProxyTestWithContent,FreezesAreReported)1318 TEST_P(ReceiveStatisticsProxyTestWithContent, FreezesAreReported) {
1319 const int kInterFrameDelayMs = 33;
1320 const int kFreezeDelayMs = 200;
1321 const int kCallDurationMs =
1322 kMinRequiredSamples * kInterFrameDelayMs + kFreezeDelayMs;
1323 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1324
1325 for (int i = 0; i < kMinRequiredSamples; ++i) {
1326 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
1327 statistics_proxy_->OnRenderedFrame(frame);
1328 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1329 }
1330 // Add extra freeze.
1331 fake_clock_.AdvanceTimeMilliseconds(kFreezeDelayMs);
1332 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
1333 statistics_proxy_->OnRenderedFrame(frame);
1334
1335 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1336 nullptr);
1337 const int kExpectedTimeBetweenFreezes =
1338 kInterFrameDelayMs * (kMinRequiredSamples - 1);
1339 const int kExpectedNumberFreezesPerMinute = 60 * 1000 / kCallDurationMs;
1340 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
1341 EXPECT_METRIC_EQ(
1342 kFreezeDelayMs + kInterFrameDelayMs,
1343 metrics::MinSample("WebRTC.Video.Screenshare.MeanFreezeDurationMs"));
1344 EXPECT_METRIC_EQ(kExpectedTimeBetweenFreezes,
1345 metrics::MinSample(
1346 "WebRTC.Video.Screenshare.MeanTimeBetweenFreezesMs"));
1347 EXPECT_METRIC_EQ(
1348 kExpectedNumberFreezesPerMinute,
1349 metrics::MinSample("WebRTC.Video.Screenshare.NumberFreezesPerMinute"));
1350 } else {
1351 EXPECT_METRIC_EQ(kFreezeDelayMs + kInterFrameDelayMs,
1352 metrics::MinSample("WebRTC.Video.MeanFreezeDurationMs"));
1353 EXPECT_METRIC_EQ(
1354 kExpectedTimeBetweenFreezes,
1355 metrics::MinSample("WebRTC.Video.MeanTimeBetweenFreezesMs"));
1356 EXPECT_METRIC_EQ(kExpectedNumberFreezesPerMinute,
1357 metrics::MinSample("WebRTC.Video.NumberFreezesPerMinute"));
1358 }
1359 }
1360
TEST_P(ReceiveStatisticsProxyTestWithContent,HarmonicFrameRateIsReported)1361 TEST_P(ReceiveStatisticsProxyTestWithContent, HarmonicFrameRateIsReported) {
1362 const int kFrameDurationMs = 33;
1363 const int kFreezeDurationMs = 200;
1364 const int kPauseDurationMs = 10000;
1365 const int kCallDurationMs = kMinRequiredSamples * kFrameDurationMs +
1366 kFreezeDurationMs + kPauseDurationMs;
1367 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1368
1369 for (int i = 0; i < kMinRequiredSamples; ++i) {
1370 fake_clock_.AdvanceTimeMilliseconds(kFrameDurationMs);
1371 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
1372 statistics_proxy_->OnRenderedFrame(frame);
1373 }
1374
1375 // Freezes and pauses should be included into harmonic frame rate.
1376 // Add freeze.
1377 fake_clock_.AdvanceTimeMilliseconds(kFreezeDurationMs);
1378 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
1379 statistics_proxy_->OnRenderedFrame(frame);
1380
1381 // Add pause.
1382 fake_clock_.AdvanceTimeMilliseconds(kPauseDurationMs);
1383 statistics_proxy_->OnStreamInactive();
1384 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
1385 statistics_proxy_->OnRenderedFrame(frame);
1386
1387 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1388 nullptr);
1389 double kSumSquaredFrameDurationSecs =
1390 (kMinRequiredSamples - 1) *
1391 (kFrameDurationMs / 1000.0 * kFrameDurationMs / 1000.0);
1392 kSumSquaredFrameDurationSecs +=
1393 kFreezeDurationMs / 1000.0 * kFreezeDurationMs / 1000.0;
1394 kSumSquaredFrameDurationSecs +=
1395 kPauseDurationMs / 1000.0 * kPauseDurationMs / 1000.0;
1396 const int kExpectedHarmonicFrameRateFps =
1397 std::round(kCallDurationMs / (1000 * kSumSquaredFrameDurationSecs));
1398 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
1399 EXPECT_METRIC_EQ(
1400 kExpectedHarmonicFrameRateFps,
1401 metrics::MinSample("WebRTC.Video.Screenshare.HarmonicFrameRate"));
1402 } else {
1403 EXPECT_METRIC_EQ(kExpectedHarmonicFrameRateFps,
1404 metrics::MinSample("WebRTC.Video.HarmonicFrameRate"));
1405 }
1406 }
1407
TEST_P(ReceiveStatisticsProxyTestWithContent,PausesAreIgnored)1408 TEST_P(ReceiveStatisticsProxyTestWithContent, PausesAreIgnored) {
1409 const int kInterFrameDelayMs = 33;
1410 const int kPauseDurationMs = 10000;
1411 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1412
1413 for (int i = 0; i <= kMinRequiredSamples; ++i) {
1414 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
1415 statistics_proxy_->OnRenderedFrame(frame);
1416 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1417 }
1418 // Add a pause.
1419 fake_clock_.AdvanceTimeMilliseconds(kPauseDurationMs);
1420 statistics_proxy_->OnStreamInactive();
1421
1422 // Second playback interval with triple the length.
1423 for (int i = 0; i <= kMinRequiredSamples * 3; ++i) {
1424 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
1425 statistics_proxy_->OnRenderedFrame(frame);
1426 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1427 }
1428
1429 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1430 nullptr);
1431 // Average of two playback intervals.
1432 const int kExpectedTimeBetweenFreezes =
1433 kInterFrameDelayMs * kMinRequiredSamples * 2;
1434 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
1435 EXPECT_METRIC_EQ(-1, metrics::MinSample(
1436 "WebRTC.Video.Screenshare.MeanFreezeDurationMs"));
1437 EXPECT_METRIC_EQ(kExpectedTimeBetweenFreezes,
1438 metrics::MinSample(
1439 "WebRTC.Video.Screenshare.MeanTimeBetweenFreezesMs"));
1440 } else {
1441 EXPECT_METRIC_EQ(-1,
1442 metrics::MinSample("WebRTC.Video.MeanFreezeDurationMs"));
1443 EXPECT_METRIC_EQ(
1444 kExpectedTimeBetweenFreezes,
1445 metrics::MinSample("WebRTC.Video.MeanTimeBetweenFreezesMs"));
1446 }
1447 }
1448
TEST_P(ReceiveStatisticsProxyTestWithContent,ManyPausesAtTheBeginning)1449 TEST_P(ReceiveStatisticsProxyTestWithContent, ManyPausesAtTheBeginning) {
1450 const int kInterFrameDelayMs = 33;
1451 const int kPauseDurationMs = 10000;
1452 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1453
1454 for (int i = 0; i <= kMinRequiredSamples; ++i) {
1455 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
1456 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1457
1458 statistics_proxy_->OnStreamInactive();
1459 fake_clock_.AdvanceTimeMilliseconds(kPauseDurationMs);
1460
1461 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
1462 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1463 }
1464
1465 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1466 nullptr);
1467 // No freezes should be detected, as all long inter-frame delays were pauses.
1468 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
1469 EXPECT_METRIC_EQ(-1, metrics::MinSample(
1470 "WebRTC.Video.Screenshare.MeanFreezeDurationMs"));
1471 } else {
1472 EXPECT_METRIC_EQ(-1,
1473 metrics::MinSample("WebRTC.Video.MeanFreezeDurationMs"));
1474 }
1475 }
1476
TEST_P(ReceiveStatisticsProxyTestWithContent,TimeInHdReported)1477 TEST_P(ReceiveStatisticsProxyTestWithContent, TimeInHdReported) {
1478 const int kInterFrameDelayMs = 20;
1479 webrtc::VideoFrame frame_hd = CreateFrame(1280, 720);
1480 webrtc::VideoFrame frame_sd = CreateFrame(640, 360);
1481
1482 // HD frames.
1483 for (int i = 0; i < kMinRequiredSamples; ++i) {
1484 statistics_proxy_->OnDecodedFrame(frame_hd, absl::nullopt, 0,
1485 content_type_);
1486 statistics_proxy_->OnRenderedFrame(frame_hd);
1487 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1488 }
1489 // SD frames.
1490 for (int i = 0; i < 2 * kMinRequiredSamples; ++i) {
1491 statistics_proxy_->OnDecodedFrame(frame_sd, absl::nullopt, 0,
1492 content_type_);
1493 statistics_proxy_->OnRenderedFrame(frame_sd);
1494 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1495 }
1496 // Extra last frame.
1497 statistics_proxy_->OnRenderedFrame(frame_sd);
1498
1499 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1500 nullptr);
1501 const int kExpectedTimeInHdPercents = 33;
1502 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
1503 EXPECT_METRIC_EQ(
1504 kExpectedTimeInHdPercents,
1505 metrics::MinSample("WebRTC.Video.Screenshare.TimeInHdPercentage"));
1506 } else {
1507 EXPECT_METRIC_EQ(kExpectedTimeInHdPercents,
1508 metrics::MinSample("WebRTC.Video.TimeInHdPercentage"));
1509 }
1510 }
1511
TEST_P(ReceiveStatisticsProxyTestWithContent,TimeInBlockyVideoReported)1512 TEST_P(ReceiveStatisticsProxyTestWithContent, TimeInBlockyVideoReported) {
1513 const int kInterFrameDelayMs = 20;
1514 const int kHighQp = 80;
1515 const int kLowQp = 30;
1516 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1517
1518 // High quality frames.
1519 for (int i = 0; i < kMinRequiredSamples; ++i) {
1520 statistics_proxy_->OnDecodedFrame(frame, kLowQp, 0, content_type_);
1521 statistics_proxy_->OnRenderedFrame(frame);
1522 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1523 }
1524 // Blocky frames.
1525 for (int i = 0; i < 2 * kMinRequiredSamples; ++i) {
1526 statistics_proxy_->OnDecodedFrame(frame, kHighQp, 0, content_type_);
1527 statistics_proxy_->OnRenderedFrame(frame);
1528 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1529 }
1530 // Extra last frame.
1531 statistics_proxy_->OnDecodedFrame(frame, kHighQp, 0, content_type_);
1532 statistics_proxy_->OnRenderedFrame(frame);
1533
1534 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1535 nullptr);
1536 const int kExpectedTimeInHdPercents = 66;
1537 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
1538 EXPECT_METRIC_EQ(
1539 kExpectedTimeInHdPercents,
1540 metrics::MinSample(
1541 "WebRTC.Video.Screenshare.TimeInBlockyVideoPercentage"));
1542 } else {
1543 EXPECT_METRIC_EQ(
1544 kExpectedTimeInHdPercents,
1545 metrics::MinSample("WebRTC.Video.TimeInBlockyVideoPercentage"));
1546 }
1547 }
1548
TEST_P(ReceiveStatisticsProxyTestWithContent,DownscalesReported)1549 TEST_P(ReceiveStatisticsProxyTestWithContent, DownscalesReported) {
1550 const int kInterFrameDelayMs = 2000; // To ensure long enough call duration.
1551
1552 webrtc::VideoFrame frame_hd = CreateFrame(1280, 720);
1553 webrtc::VideoFrame frame_sd = CreateFrame(640, 360);
1554 webrtc::VideoFrame frame_ld = CreateFrame(320, 180);
1555
1556 // Call once to pass content type.
1557 statistics_proxy_->OnDecodedFrame(frame_hd, absl::nullopt, 0, content_type_);
1558
1559 statistics_proxy_->OnRenderedFrame(frame_hd);
1560 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1561
1562 // Downscale.
1563 statistics_proxy_->OnRenderedFrame(frame_sd);
1564 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1565
1566 // Downscale.
1567 statistics_proxy_->OnRenderedFrame(frame_ld);
1568 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1569
1570 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1571 nullptr);
1572 const int kExpectedDownscales = 30; // 2 per 4 seconds = 30 per minute.
1573 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
1574 EXPECT_METRIC_EQ(
1575 kExpectedDownscales,
1576 metrics::MinSample(
1577 "WebRTC.Video.Screenshare.NumberResolutionDownswitchesPerMinute"));
1578 } else {
1579 EXPECT_METRIC_EQ(kExpectedDownscales,
1580 metrics::MinSample(
1581 "WebRTC.Video.NumberResolutionDownswitchesPerMinute"));
1582 }
1583 }
1584
TEST_P(ReceiveStatisticsProxyTestWithContent,DecodeTimeReported)1585 TEST_P(ReceiveStatisticsProxyTestWithContent, DecodeTimeReported) {
1586 const int kInterFrameDelayMs = 20;
1587 const int kLowQp = 30;
1588 const int kDecodeMs = 7;
1589
1590 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1591
1592 for (int i = 0; i < kMinRequiredSamples; ++i) {
1593 statistics_proxy_->OnDecodedFrame(frame, kLowQp, kDecodeMs, content_type_);
1594 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1595 }
1596 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1597 nullptr);
1598 EXPECT_METRIC_EQ(
1599 1, metrics::NumEvents("WebRTC.Video.DecodeTimeInMs", kDecodeMs));
1600 }
1601
TEST_P(ReceiveStatisticsProxyTestWithContent,StatsAreSlicedOnSimulcastAndExperiment)1602 TEST_P(ReceiveStatisticsProxyTestWithContent,
1603 StatsAreSlicedOnSimulcastAndExperiment) {
1604 const uint8_t experiment_id = 1;
1605 webrtc::VideoContentType content_type = content_type_;
1606 videocontenttypehelpers::SetExperimentId(&content_type, experiment_id);
1607 const int kInterFrameDelayMs1 = 30;
1608 const int kInterFrameDelayMs2 = 50;
1609 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1610
1611 videocontenttypehelpers::SetSimulcastId(&content_type, 1);
1612 for (int i = 0; i <= kMinRequiredSamples; ++i) {
1613 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs1);
1614 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type);
1615 }
1616
1617 videocontenttypehelpers::SetSimulcastId(&content_type, 2);
1618 for (int i = 0; i <= kMinRequiredSamples; ++i) {
1619 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs2);
1620 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type);
1621 }
1622 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1623 nullptr);
1624
1625 if (videocontenttypehelpers::IsScreenshare(content_type)) {
1626 EXPECT_METRIC_EQ(
1627 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1628 EXPECT_METRIC_EQ(1, metrics::NumSamples(
1629 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1630 EXPECT_METRIC_EQ(1, metrics::NumSamples(
1631 "WebRTC.Video.Screenshare.InterframeDelayInMs.S0"));
1632 EXPECT_METRIC_EQ(1,
1633 metrics::NumSamples(
1634 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs.S0"));
1635 EXPECT_METRIC_EQ(1, metrics::NumSamples(
1636 "WebRTC.Video.Screenshare.InterframeDelayInMs.S1"));
1637 EXPECT_METRIC_EQ(1,
1638 metrics::NumSamples(
1639 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs.S1"));
1640 EXPECT_METRIC_EQ(
1641 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"
1642 ".ExperimentGroup0"));
1643 EXPECT_METRIC_EQ(
1644 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"
1645 ".ExperimentGroup0"));
1646 EXPECT_METRIC_EQ(
1647 kInterFrameDelayMs1,
1648 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs.S0"));
1649 EXPECT_METRIC_EQ(
1650 kInterFrameDelayMs2,
1651 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs.S1"));
1652 EXPECT_METRIC_EQ(
1653 (kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1654 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1655 EXPECT_METRIC_EQ(
1656 kInterFrameDelayMs2,
1657 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1658 EXPECT_METRIC_EQ(
1659 (kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1660 metrics::MinSample(
1661 "WebRTC.Video.Screenshare.InterframeDelayInMs.ExperimentGroup0"));
1662 } else {
1663 EXPECT_METRIC_EQ(1,
1664 metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
1665 EXPECT_METRIC_EQ(
1666 1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
1667 EXPECT_METRIC_EQ(
1668 1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs.S0"));
1669 EXPECT_METRIC_EQ(
1670 1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs.S0"));
1671 EXPECT_METRIC_EQ(
1672 1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs.S1"));
1673 EXPECT_METRIC_EQ(
1674 1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs.S1"));
1675 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"
1676 ".ExperimentGroup0"));
1677 EXPECT_METRIC_EQ(1,
1678 metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"
1679 ".ExperimentGroup0"));
1680 EXPECT_METRIC_EQ(kInterFrameDelayMs1,
1681 metrics::MinSample("WebRTC.Video.InterframeDelayInMs.S0"));
1682 EXPECT_METRIC_EQ(kInterFrameDelayMs2,
1683 metrics::MinSample("WebRTC.Video.InterframeDelayInMs.S1"));
1684 EXPECT_METRIC_EQ((kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1685 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
1686 EXPECT_METRIC_EQ(kInterFrameDelayMs2,
1687 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
1688 EXPECT_METRIC_EQ((kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1689 metrics::MinSample(
1690 "WebRTC.Video.InterframeDelayInMs.ExperimentGroup0"));
1691 }
1692 }
1693
1694 class DecodeTimeHistogramsKillswitch {
1695 public:
DecodeTimeHistogramsKillswitch(bool disable_histograms)1696 explicit DecodeTimeHistogramsKillswitch(bool disable_histograms)
1697 : field_trial_(disable_histograms
1698 ? "WebRTC-DecodeTimeHistogramsKillSwitch/Enabled/"
1699 : "") {}
1700
1701 private:
1702 webrtc::test::ScopedFieldTrials field_trial_;
1703 };
1704
1705 class ReceiveStatisticsProxyTestWithDecodeTimeHistograms
1706 : public DecodeTimeHistogramsKillswitch,
1707 public ::testing::WithParamInterface<
1708 std::tuple<bool, int, int, int, VideoCodecType, std::string>>,
1709 public ReceiveStatisticsProxyTest {
1710 public:
ReceiveStatisticsProxyTestWithDecodeTimeHistograms()1711 ReceiveStatisticsProxyTestWithDecodeTimeHistograms()
1712 : DecodeTimeHistogramsKillswitch(std::get<0>(GetParam())) {}
1713
1714 protected:
1715 const std::string kUmaPrefix = "WebRTC.Video.DecodeTimePerFrameInMs.";
1716 const int expected_number_of_samples_ = {std::get<1>(GetParam())};
1717 const int width_ = {std::get<2>(GetParam())};
1718 const int height_ = {std::get<3>(GetParam())};
1719 const VideoCodecType codec_type_ = {std::get<4>(GetParam())};
1720 const std::string implementation_name_ = {std::get<5>(GetParam())};
1721 const std::string uma_histogram_name_ =
1722 kUmaPrefix + (codec_type_ == kVideoCodecVP9 ? "Vp9." : "H264.") +
1723 (height_ == 2160 ? "4k." : "Hd.") +
1724 (implementation_name_.compare("ExternalDecoder") == 0 ? "Hw" : "Sw");
1725 };
1726
TEST_P(ReceiveStatisticsProxyTestWithDecodeTimeHistograms,DecodeTimeHistogramsUpdated)1727 TEST_P(ReceiveStatisticsProxyTestWithDecodeTimeHistograms,
1728 DecodeTimeHistogramsUpdated) {
1729 constexpr int kNumberOfFrames = 10;
1730 constexpr int kDecodeTimeMs = 7;
1731 constexpr int kFrameDurationMs = 1000 / 60;
1732
1733 webrtc::VideoFrame frame = CreateFrame(width_, height_);
1734
1735 statistics_proxy_->OnDecoderImplementationName(implementation_name_.c_str());
1736 statistics_proxy_->OnPreDecode(codec_type_, /*qp=*/0);
1737
1738 for (int i = 0; i < kNumberOfFrames; ++i) {
1739 statistics_proxy_->OnDecodedFrame(frame, /*qp=*/absl::nullopt,
1740 kDecodeTimeMs,
1741 VideoContentType::UNSPECIFIED);
1742 fake_clock_.AdvanceTimeMilliseconds(kFrameDurationMs);
1743 }
1744
1745 EXPECT_METRIC_EQ(expected_number_of_samples_,
1746 metrics::NumSamples(uma_histogram_name_));
1747 EXPECT_METRIC_EQ(expected_number_of_samples_,
1748 metrics::NumEvents(uma_histogram_name_, kDecodeTimeMs));
1749 }
1750
1751 const auto kVp94kHw = std::make_tuple(/*killswitch=*/false,
1752 /*expected_number_of_samples=*/10,
1753 /*width=*/3840,
1754 /*height=*/2160,
1755 kVideoCodecVP9,
1756 /*implementation=*/"ExternalDecoder");
1757 const auto kVp94kSw = std::make_tuple(/*killswitch=*/false,
1758 /*expected_number_of_samples=*/10,
1759 /*width=*/3840,
1760 /*height=*/2160,
1761 kVideoCodecVP9,
1762 /*implementation=*/"libvpx");
1763 const auto kVp9HdHw = std::make_tuple(/*killswitch=*/false,
1764 /*expected_number_of_samples=*/10,
1765 /*width=*/1920,
1766 /*height=*/1080,
1767 kVideoCodecVP9,
1768 /*implementation=*/"ExternalDecoder");
1769 const auto kVp9HdSw = std::make_tuple(/*killswitch=*/false,
1770 /*expected_number_of_samples=*/10,
1771 /*width=*/1920,
1772 /*height=*/1080,
1773 kVideoCodecVP9,
1774 /*implementation=*/"libvpx");
1775 const auto kH2644kHw = std::make_tuple(/*killswitch=*/false,
1776 /*expected_number_of_samples=*/10,
1777 /*width=*/3840,
1778 /*height=*/2160,
1779 kVideoCodecH264,
1780 /*implementation=*/"ExternalDecoder");
1781 const auto kH2644kSw = std::make_tuple(/*killswitch=*/false,
1782 /*expected_number_of_samples=*/10,
1783 /*width=*/3840,
1784 /*height=*/2160,
1785 kVideoCodecH264,
1786 /*implementation=*/"FFmpeg");
1787 const auto kH264HdHw = std::make_tuple(/*killswitch=*/false,
1788 /*expected_number_of_samples=*/10,
1789 /*width=*/1920,
1790 /*height=*/1080,
1791 kVideoCodecH264,
1792 /*implementation=*/"ExternalDecoder");
1793 const auto kH264HdSw = std::make_tuple(/*killswitch=*/false,
1794 /*expected_number_of_samples=*/10,
1795 /*width=*/1920,
1796 /*height=*/1080,
1797 kVideoCodecH264,
1798 /*implementation=*/"FFmpeg");
1799
1800 INSTANTIATE_TEST_SUITE_P(AllHistogramsPopulated,
1801 ReceiveStatisticsProxyTestWithDecodeTimeHistograms,
1802 ::testing::Values(kVp94kHw,
1803 kVp94kSw,
1804 kVp9HdHw,
1805 kVp9HdSw,
1806 kH2644kHw,
1807 kH2644kSw,
1808 kH264HdHw,
1809 kH264HdSw));
1810
1811 const auto kKillswitchDisabled =
1812 std::make_tuple(/*killswitch=*/false,
1813 /*expected_number_of_samples=*/10,
1814 /*width=*/1920,
1815 /*height=*/1080,
1816 kVideoCodecVP9,
1817 /*implementation=*/"libvpx");
1818 const auto kKillswitchEnabled =
1819 std::make_tuple(/*killswitch=*/true,
1820 /*expected_number_of_samples=*/0,
1821 /*width=*/1920,
1822 /*height=*/1080,
1823 kVideoCodecVP9,
1824 /*implementation=*/"libvpx");
1825
1826 INSTANTIATE_TEST_SUITE_P(KillswitchEffective,
1827 ReceiveStatisticsProxyTestWithDecodeTimeHistograms,
1828 ::testing::Values(kKillswitchDisabled,
1829 kKillswitchEnabled));
1830
1831 } // namespace webrtc
1832