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