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