blob: ca135dfce52765f53af278650e66b46e85d79be3 [file] [log] [blame]
Tommi74fc5742020-04-27 10:43:06 +02001/*
Tommi553c8692020-05-05 15:35:45 +02002 * Copyright 2020 The WebRTC project authors. All Rights Reserved.
Tommi74fc5742020-04-27 10:43:06 +02003 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "video/receive_statistics_proxy2.h"
12
13#include <limits>
14#include <memory>
15#include <string>
16#include <tuple>
17#include <utility>
18
19#include "absl/types/optional.h"
20#include "api/scoped_refptr.h"
21#include "api/video/i420_buffer.h"
22#include "api/video/video_frame.h"
23#include "api/video/video_frame_buffer.h"
24#include "api/video/video_rotation.h"
Tommi553c8692020-05-05 15:35:45 +020025#include "rtc_base/task_utils/to_queued_task.h"
26#include "rtc_base/thread.h"
Tommi74fc5742020-04-27 10:43:06 +020027#include "system_wrappers/include/metrics.h"
Tommi74fc5742020-04-27 10:43:06 +020028#include "test/gtest.h"
Tommi553c8692020-05-05 15:35:45 +020029#include "test/run_loop.h"
Jonas Oreland8ca06132022-03-14 12:52:48 +010030#include "test/scoped_key_value_config.h"
Tommid7e08c82020-05-10 11:24:43 +020031#include "video/video_receive_stream2.h"
Tommi74fc5742020-04-27 10:43:06 +020032
33namespace webrtc {
34namespace internal {
35namespace {
36const int64_t kFreqOffsetProcessIntervalInMs = 40000;
Tommi74fc5742020-04-27 10:43:06 +020037const uint32_t kRemoteSsrc = 456;
38const int kMinRequiredSamples = 200;
39const int kWidth = 1280;
40const int kHeight = 720;
41} // namespace
42
43// TODO(sakal): ReceiveStatisticsProxy is lacking unittesting.
44class ReceiveStatisticsProxy2Test : public ::testing::Test {
45 public:
Jonas Oreland8ca06132022-03-14 12:52:48 +010046 explicit ReceiveStatisticsProxy2Test(std::string field_trials = "")
47 : field_trials_(field_trials), fake_clock_(1234) {
Tommi74fc5742020-04-27 10:43:06 +020048 metrics::Reset();
Tommib2db9892021-08-23 22:44:49 +020049 statistics_proxy_.reset(new ReceiveStatisticsProxy(
Jonas Oreland8ca06132022-03-14 12:52:48 +010050 kRemoteSsrc, &fake_clock_, loop_.task_queue(), field_trials_));
Tommi74fc5742020-04-27 10:43:06 +020051 }
52
Tommi553c8692020-05-05 15:35:45 +020053 ~ReceiveStatisticsProxy2Test() override { statistics_proxy_.reset(); }
54
55 protected:
Tommid93bf122020-05-10 20:24:59 +020056 // Convenience method to avoid too many explict flushes.
Tommif6f45432022-05-20 15:21:20 +020057 VideoReceiveStreamInterface::Stats FlushAndGetStats() {
Tommid93bf122020-05-10 20:24:59 +020058 loop_.Flush();
59 return statistics_proxy_->GetStats();
60 }
61
62 void FlushAndUpdateHistograms(absl::optional<int> fraction_lost,
63 const StreamDataCounters& rtp_stats,
64 const StreamDataCounters* rtx_stats) {
65 loop_.Flush();
66 statistics_proxy_->UpdateHistograms(fraction_lost, rtp_stats, rtx_stats);
67 }
68
Tommi74fc5742020-04-27 10:43:06 +020069 VideoFrame CreateFrame(int width, int height) {
70 return CreateVideoFrame(width, height, 0);
71 }
72
Tommid7e08c82020-05-10 11:24:43 +020073 VideoFrame CreateFrameWithRenderTime(Timestamp render_time) {
74 return CreateFrameWithRenderTimeMs(render_time.ms());
75 }
76
Tommi74fc5742020-04-27 10:43:06 +020077 VideoFrame CreateFrameWithRenderTimeMs(int64_t render_time_ms) {
78 return CreateVideoFrame(kWidth, kHeight, render_time_ms);
79 }
80
81 VideoFrame CreateVideoFrame(int width, int height, int64_t render_time_ms) {
82 VideoFrame frame =
83 VideoFrame::Builder()
84 .set_video_frame_buffer(I420Buffer::Create(width, height))
85 .set_timestamp_rtp(0)
86 .set_timestamp_ms(render_time_ms)
87 .set_rotation(kVideoRotation_0)
88 .build();
89 frame.set_ntp_time_ms(fake_clock_.CurrentNtpInMilliseconds());
90 return frame;
91 }
92
Tommid7e08c82020-05-10 11:24:43 +020093 // Return the current fake time as a Timestamp.
94 Timestamp Now() { return fake_clock_.CurrentTime(); }
95
96 // Creates a VideoFrameMetaData instance with a timestamp.
97 VideoFrameMetaData MetaData(const VideoFrame& frame, Timestamp ts) {
98 return VideoFrameMetaData(frame, ts);
99 }
100
101 // Creates a VideoFrameMetaData instance with the current fake time.
102 VideoFrameMetaData MetaData(const VideoFrame& frame) {
103 return VideoFrameMetaData(frame, Now());
104 }
105
Jonas Oreland8ca06132022-03-14 12:52:48 +0100106 test::ScopedKeyValueConfig field_trials_;
Tommi74fc5742020-04-27 10:43:06 +0200107 SimulatedClock fake_clock_;
Tommi74fc5742020-04-27 10:43:06 +0200108 std::unique_ptr<ReceiveStatisticsProxy> statistics_proxy_;
Tommi553c8692020-05-05 15:35:45 +0200109 test::RunLoop loop_;
Tommi74fc5742020-04-27 10:43:06 +0200110};
111
112TEST_F(ReceiveStatisticsProxy2Test, OnDecodedFrameIncreasesFramesDecoded) {
113 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_decoded);
114 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
115 for (uint32_t i = 1; i <= 3; ++i) {
116 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
117 VideoContentType::UNSPECIFIED);
Tommid93bf122020-05-10 20:24:59 +0200118 EXPECT_EQ(i, FlushAndGetStats().frames_decoded);
Tommi74fc5742020-04-27 10:43:06 +0200119 }
120}
121
122TEST_F(ReceiveStatisticsProxy2Test, DecodedFpsIsReported) {
123 const int kFps = 20;
124 const int kRequiredSamples = metrics::kMinRunTimeInSeconds * kFps;
125 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
126 for (int i = 0; i < kRequiredSamples; ++i) {
127 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
128 VideoContentType::UNSPECIFIED);
129 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
130 }
Tommid93bf122020-05-10 20:24:59 +0200131 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 10:43:06 +0200132 EXPECT_METRIC_EQ(1,
133 metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
134 EXPECT_METRIC_EQ(
135 1, metrics::NumEvents("WebRTC.Video.DecodedFramesPerSecond", kFps));
136}
137
138TEST_F(ReceiveStatisticsProxy2Test, DecodedFpsIsNotReportedForTooFewSamples) {
139 const int kFps = 20;
140 const int kRequiredSamples = metrics::kMinRunTimeInSeconds * kFps;
141 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
142 for (int i = 0; i < kRequiredSamples - 1; ++i) {
143 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
144 VideoContentType::UNSPECIFIED);
145 fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
146 }
Tommid93bf122020-05-10 20:24:59 +0200147 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 10:43:06 +0200148 EXPECT_METRIC_EQ(0,
149 metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
150}
151
152TEST_F(ReceiveStatisticsProxy2Test,
153 OnDecodedFrameWithQpDoesNotResetFramesDecodedOrTotalDecodeTime) {
154 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_decoded);
155 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
156 unsigned int expected_total_decode_time_ms = 0;
157 unsigned int expected_frames_decoded = 0;
158 for (uint32_t i = 1; i <= 3; ++i) {
159 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 1,
160 VideoContentType::UNSPECIFIED);
161 expected_total_decode_time_ms += 1;
162 ++expected_frames_decoded;
Tommid93bf122020-05-10 20:24:59 +0200163 loop_.Flush();
Tommi74fc5742020-04-27 10:43:06 +0200164 EXPECT_EQ(expected_frames_decoded,
165 statistics_proxy_->GetStats().frames_decoded);
166 EXPECT_EQ(expected_total_decode_time_ms,
167 statistics_proxy_->GetStats().total_decode_time_ms);
168 }
169 statistics_proxy_->OnDecodedFrame(frame, 1u, 3,
170 VideoContentType::UNSPECIFIED);
171 ++expected_frames_decoded;
172 expected_total_decode_time_ms += 3;
Tommid93bf122020-05-10 20:24:59 +0200173 loop_.Flush();
Tommi74fc5742020-04-27 10:43:06 +0200174 EXPECT_EQ(expected_frames_decoded,
175 statistics_proxy_->GetStats().frames_decoded);
176 EXPECT_EQ(expected_total_decode_time_ms,
177 statistics_proxy_->GetStats().total_decode_time_ms);
178}
179
Philipp Hanckea16a6a62022-04-25 12:21:30 +0200180TEST_F(ReceiveStatisticsProxy2Test, OnDecodedFrameIncreasesProcessingDelay) {
181 const TimeDelta kProcessingDelay = TimeDelta::Millis(10);
182 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_decoded);
183 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
184 TimeDelta expected_total_processing_delay = TimeDelta::Millis(0);
185 unsigned int expected_frames_decoded = 0;
186 // We set receive time fixed and increase the clock by 10ms
187 // in the loop which will increase the processing delay by
188 // 10/20/30ms respectively.
189 RtpPacketInfos::vector_type packet_infos = {
190 RtpPacketInfo({}, {}, {}, {}, {}, Now())};
191 frame.set_packet_infos(RtpPacketInfos(packet_infos));
192 for (int i = 1; i <= 3; ++i) {
193 fake_clock_.AdvanceTime(kProcessingDelay);
194 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 1,
195 VideoContentType::UNSPECIFIED);
196 expected_total_processing_delay += i * kProcessingDelay;
197 ++expected_frames_decoded;
198 loop_.Flush();
199 EXPECT_EQ(expected_frames_decoded,
200 statistics_proxy_->GetStats().frames_decoded);
201 EXPECT_EQ(expected_total_processing_delay,
202 statistics_proxy_->GetStats().total_processing_delay);
203 }
204 fake_clock_.AdvanceTime(kProcessingDelay);
205 statistics_proxy_->OnDecodedFrame(frame, 1u, 3,
206 VideoContentType::UNSPECIFIED);
207 ++expected_frames_decoded;
208 expected_total_processing_delay += 4 * kProcessingDelay;
209 loop_.Flush();
210 EXPECT_EQ(expected_frames_decoded,
211 statistics_proxy_->GetStats().frames_decoded);
212 EXPECT_EQ(expected_total_processing_delay,
213 statistics_proxy_->GetStats().total_processing_delay);
214}
215
Philipp Hancke0359ba22022-05-05 15:55:36 +0200216TEST_F(ReceiveStatisticsProxy2Test, OnDecodedFrameIncreasesAssemblyTime) {
217 const TimeDelta kAssemblyTime = TimeDelta::Millis(7);
218 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_decoded);
219 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
220 TimeDelta expected_total_assembly_time = TimeDelta::Millis(0);
221 unsigned int expected_frames_decoded = 0;
222 unsigned int expected_frames_assembled_from_multiple_packets = 0;
223
224 // A single-packet frame will not increase total assembly time
225 // and frames assembled.
226 RtpPacketInfos::vector_type single_packet_frame = {
227 RtpPacketInfo({}, {}, {}, {}, {}, Now())};
228 frame.set_packet_infos(RtpPacketInfos(single_packet_frame));
229 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 1,
230 VideoContentType::UNSPECIFIED);
231 ++expected_frames_decoded;
232 loop_.Flush();
233 EXPECT_EQ(expected_total_assembly_time,
234 statistics_proxy_->GetStats().total_assembly_time);
235 EXPECT_EQ(
236 expected_frames_assembled_from_multiple_packets,
237 statistics_proxy_->GetStats().frames_assembled_from_multiple_packets);
238
239 // In an ordered frame the first and last packet matter.
240 RtpPacketInfos::vector_type ordered_frame = {
241 RtpPacketInfo({}, {}, {}, {}, {}, Now()),
242 RtpPacketInfo({}, {}, {}, {}, {}, Now() + kAssemblyTime),
243 RtpPacketInfo({}, {}, {}, {}, {}, Now() + 2 * kAssemblyTime),
244 };
245 frame.set_packet_infos(RtpPacketInfos(ordered_frame));
246 statistics_proxy_->OnDecodedFrame(frame, 1u, 3,
247 VideoContentType::UNSPECIFIED);
248 ++expected_frames_decoded;
249 ++expected_frames_assembled_from_multiple_packets;
250 expected_total_assembly_time += 2 * kAssemblyTime;
251 loop_.Flush();
252 EXPECT_EQ(expected_frames_decoded,
253 statistics_proxy_->GetStats().frames_decoded);
254 EXPECT_EQ(expected_total_assembly_time,
255 statistics_proxy_->GetStats().total_assembly_time);
256 EXPECT_EQ(
257 expected_frames_assembled_from_multiple_packets,
258 statistics_proxy_->GetStats().frames_assembled_from_multiple_packets);
259
260 // "First" and "last" are in receive time, not sequence number.
261 RtpPacketInfos::vector_type unordered_frame = {
262 RtpPacketInfo({}, {}, {}, {}, {}, Now() + 2 * kAssemblyTime),
263 RtpPacketInfo({}, {}, {}, {}, {}, Now()),
264 RtpPacketInfo({}, {}, {}, {}, {}, Now() + kAssemblyTime),
265 };
266 frame.set_packet_infos(RtpPacketInfos(unordered_frame));
267 statistics_proxy_->OnDecodedFrame(frame, 1u, 3,
268 VideoContentType::UNSPECIFIED);
269 ++expected_frames_decoded;
270 ++expected_frames_assembled_from_multiple_packets;
271 expected_total_assembly_time += 2 * kAssemblyTime;
272 loop_.Flush();
273 EXPECT_EQ(expected_frames_decoded,
274 statistics_proxy_->GetStats().frames_decoded);
275 EXPECT_EQ(expected_total_assembly_time,
276 statistics_proxy_->GetStats().total_assembly_time);
277 EXPECT_EQ(
278 expected_frames_assembled_from_multiple_packets,
279 statistics_proxy_->GetStats().frames_assembled_from_multiple_packets);
280}
281
Tommi74fc5742020-04-27 10:43:06 +0200282TEST_F(ReceiveStatisticsProxy2Test, OnDecodedFrameIncreasesQpSum) {
283 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
284 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
285 statistics_proxy_->OnDecodedFrame(frame, 3u, 0,
286 VideoContentType::UNSPECIFIED);
Tommid93bf122020-05-10 20:24:59 +0200287 EXPECT_EQ(3u, FlushAndGetStats().qp_sum);
Tommi74fc5742020-04-27 10:43:06 +0200288 statistics_proxy_->OnDecodedFrame(frame, 127u, 0,
289 VideoContentType::UNSPECIFIED);
Tommid93bf122020-05-10 20:24:59 +0200290 EXPECT_EQ(130u, FlushAndGetStats().qp_sum);
Tommi74fc5742020-04-27 10:43:06 +0200291}
292
293TEST_F(ReceiveStatisticsProxy2Test, OnDecodedFrameIncreasesTotalDecodeTime) {
294 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
295 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
296 statistics_proxy_->OnDecodedFrame(frame, 3u, 4,
297 VideoContentType::UNSPECIFIED);
Tommid93bf122020-05-10 20:24:59 +0200298 EXPECT_EQ(4u, FlushAndGetStats().total_decode_time_ms);
Tommi74fc5742020-04-27 10:43:06 +0200299 statistics_proxy_->OnDecodedFrame(frame, 127u, 7,
300 VideoContentType::UNSPECIFIED);
Tommid93bf122020-05-10 20:24:59 +0200301 EXPECT_EQ(11u, FlushAndGetStats().total_decode_time_ms);
Tommi74fc5742020-04-27 10:43:06 +0200302}
303
304TEST_F(ReceiveStatisticsProxy2Test, ReportsContentType) {
305 const std::string kRealtimeString("realtime");
306 const std::string kScreenshareString("screen");
307 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
308 EXPECT_EQ(kRealtimeString, videocontenttypehelpers::ToString(
309 statistics_proxy_->GetStats().content_type));
310 statistics_proxy_->OnDecodedFrame(frame, 3u, 0,
311 VideoContentType::SCREENSHARE);
312 EXPECT_EQ(kScreenshareString,
Tommid93bf122020-05-10 20:24:59 +0200313 videocontenttypehelpers::ToString(FlushAndGetStats().content_type));
Tommi74fc5742020-04-27 10:43:06 +0200314 statistics_proxy_->OnDecodedFrame(frame, 3u, 0,
315 VideoContentType::UNSPECIFIED);
Tommid93bf122020-05-10 20:24:59 +0200316 EXPECT_EQ(kRealtimeString,
317 videocontenttypehelpers::ToString(FlushAndGetStats().content_type));
Tommi74fc5742020-04-27 10:43:06 +0200318}
319
320TEST_F(ReceiveStatisticsProxy2Test, ReportsMaxTotalInterFrameDelay) {
321 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
322 const TimeDelta kInterFrameDelay1 = TimeDelta::Millis(100);
323 const TimeDelta kInterFrameDelay2 = TimeDelta::Millis(200);
324 const TimeDelta kInterFrameDelay3 = TimeDelta::Millis(300);
325 double expected_total_inter_frame_delay = 0;
326 double expected_total_squared_inter_frame_delay = 0;
327 EXPECT_EQ(expected_total_inter_frame_delay,
328 statistics_proxy_->GetStats().total_inter_frame_delay);
329 EXPECT_EQ(expected_total_squared_inter_frame_delay,
330 statistics_proxy_->GetStats().total_squared_inter_frame_delay);
331
332 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
333 VideoContentType::UNSPECIFIED);
334 EXPECT_DOUBLE_EQ(expected_total_inter_frame_delay,
Tommid93bf122020-05-10 20:24:59 +0200335 FlushAndGetStats().total_inter_frame_delay);
336 EXPECT_DOUBLE_EQ(expected_total_squared_inter_frame_delay,
337 FlushAndGetStats().total_squared_inter_frame_delay);
Tommi74fc5742020-04-27 10:43:06 +0200338
339 fake_clock_.AdvanceTime(kInterFrameDelay1);
340 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
341 VideoContentType::UNSPECIFIED);
342 expected_total_inter_frame_delay += kInterFrameDelay1.seconds<double>();
343 expected_total_squared_inter_frame_delay +=
344 pow(kInterFrameDelay1.seconds<double>(), 2.0);
345 EXPECT_DOUBLE_EQ(expected_total_inter_frame_delay,
Tommid93bf122020-05-10 20:24:59 +0200346 FlushAndGetStats().total_inter_frame_delay);
Tommi74fc5742020-04-27 10:43:06 +0200347 EXPECT_DOUBLE_EQ(
348 expected_total_squared_inter_frame_delay,
349 statistics_proxy_->GetStats().total_squared_inter_frame_delay);
350
351 fake_clock_.AdvanceTime(kInterFrameDelay2);
352 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
353 VideoContentType::UNSPECIFIED);
354 expected_total_inter_frame_delay += kInterFrameDelay2.seconds<double>();
355 expected_total_squared_inter_frame_delay +=
356 pow(kInterFrameDelay2.seconds<double>(), 2.0);
357 EXPECT_DOUBLE_EQ(expected_total_inter_frame_delay,
Tommid93bf122020-05-10 20:24:59 +0200358 FlushAndGetStats().total_inter_frame_delay);
Tommi74fc5742020-04-27 10:43:06 +0200359 EXPECT_DOUBLE_EQ(
360 expected_total_squared_inter_frame_delay,
361 statistics_proxy_->GetStats().total_squared_inter_frame_delay);
362
363 fake_clock_.AdvanceTime(kInterFrameDelay3);
364 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
365 VideoContentType::UNSPECIFIED);
366 expected_total_inter_frame_delay += kInterFrameDelay3.seconds<double>();
367 expected_total_squared_inter_frame_delay +=
368 pow(kInterFrameDelay3.seconds<double>(), 2.0);
369 EXPECT_DOUBLE_EQ(expected_total_inter_frame_delay,
Tommid93bf122020-05-10 20:24:59 +0200370 FlushAndGetStats().total_inter_frame_delay);
Tommi74fc5742020-04-27 10:43:06 +0200371 EXPECT_DOUBLE_EQ(
372 expected_total_squared_inter_frame_delay,
373 statistics_proxy_->GetStats().total_squared_inter_frame_delay);
374}
375
376TEST_F(ReceiveStatisticsProxy2Test, ReportsMaxInterframeDelay) {
377 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
378 const int64_t kInterframeDelayMs1 = 100;
379 const int64_t kInterframeDelayMs2 = 200;
380 const int64_t kInterframeDelayMs3 = 100;
381 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
382 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
383 VideoContentType::UNSPECIFIED);
Tommid93bf122020-05-10 20:24:59 +0200384 EXPECT_EQ(-1, FlushAndGetStats().interframe_delay_max_ms);
Tommi74fc5742020-04-27 10:43:06 +0200385
386 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs1);
387 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
388 VideoContentType::UNSPECIFIED);
Tommid93bf122020-05-10 20:24:59 +0200389 EXPECT_EQ(kInterframeDelayMs1, FlushAndGetStats().interframe_delay_max_ms);
Tommi74fc5742020-04-27 10:43:06 +0200390
391 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs2);
392 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
393 VideoContentType::UNSPECIFIED);
Tommid93bf122020-05-10 20:24:59 +0200394 EXPECT_EQ(kInterframeDelayMs2, FlushAndGetStats().interframe_delay_max_ms);
Tommi74fc5742020-04-27 10:43:06 +0200395
396 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs3);
397 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
398 VideoContentType::UNSPECIFIED);
399 // kInterframeDelayMs3 is smaller than kInterframeDelayMs2.
Tommid93bf122020-05-10 20:24:59 +0200400 EXPECT_EQ(kInterframeDelayMs2, FlushAndGetStats().interframe_delay_max_ms);
Tommi74fc5742020-04-27 10:43:06 +0200401}
402
403TEST_F(ReceiveStatisticsProxy2Test, ReportInterframeDelayInWindow) {
404 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
405 const int64_t kInterframeDelayMs1 = 900;
406 const int64_t kInterframeDelayMs2 = 750;
407 const int64_t kInterframeDelayMs3 = 700;
408 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
409 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
410 VideoContentType::UNSPECIFIED);
Tommid93bf122020-05-10 20:24:59 +0200411 EXPECT_EQ(-1, FlushAndGetStats().interframe_delay_max_ms);
Tommi74fc5742020-04-27 10:43:06 +0200412
413 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs1);
414 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
415 VideoContentType::UNSPECIFIED);
Tommid93bf122020-05-10 20:24:59 +0200416 EXPECT_EQ(kInterframeDelayMs1, FlushAndGetStats().interframe_delay_max_ms);
Tommi74fc5742020-04-27 10:43:06 +0200417
418 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs2);
419 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
420 VideoContentType::UNSPECIFIED);
421 // Still first delay is the maximum
Tommid93bf122020-05-10 20:24:59 +0200422 EXPECT_EQ(kInterframeDelayMs1, FlushAndGetStats().interframe_delay_max_ms);
Tommi74fc5742020-04-27 10:43:06 +0200423
424 fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs3);
425 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
426 VideoContentType::UNSPECIFIED);
427 // Now the first sample is out of the window, so the second is the maximum.
Tommid93bf122020-05-10 20:24:59 +0200428 EXPECT_EQ(kInterframeDelayMs2, FlushAndGetStats().interframe_delay_max_ms);
Tommi74fc5742020-04-27 10:43:06 +0200429}
430
431TEST_F(ReceiveStatisticsProxy2Test, ReportsFreezeMetrics) {
432 const int64_t kFreezeDurationMs = 1000;
433
Tommif6f45432022-05-20 15:21:20 +0200434 VideoReceiveStreamInterface::Stats stats = statistics_proxy_->GetStats();
Tommi74fc5742020-04-27 10:43:06 +0200435 EXPECT_EQ(0u, stats.freeze_count);
436 EXPECT_FALSE(stats.total_freezes_duration_ms);
437
438 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
439 for (size_t i = 0; i < VideoQualityObserver::kMinFrameSamplesToDetectFreeze;
440 ++i) {
441 fake_clock_.AdvanceTimeMilliseconds(30);
Tommid7e08c82020-05-10 11:24:43 +0200442 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 10:43:06 +0200443 }
444
445 // Freeze.
446 fake_clock_.AdvanceTimeMilliseconds(kFreezeDurationMs);
Tommid7e08c82020-05-10 11:24:43 +0200447 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 10:43:06 +0200448
449 stats = statistics_proxy_->GetStats();
450 EXPECT_EQ(1u, stats.freeze_count);
451 EXPECT_EQ(kFreezeDurationMs, stats.total_freezes_duration_ms);
452}
453
454TEST_F(ReceiveStatisticsProxy2Test, ReportsPauseMetrics) {
Tommif6f45432022-05-20 15:21:20 +0200455 VideoReceiveStreamInterface::Stats stats = statistics_proxy_->GetStats();
Tommi74fc5742020-04-27 10:43:06 +0200456 ASSERT_EQ(0u, stats.pause_count);
457 ASSERT_EQ(0u, stats.total_pauses_duration_ms);
458
459 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Tommid7e08c82020-05-10 11:24:43 +0200460 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 10:43:06 +0200461
462 // Pause.
463 fake_clock_.AdvanceTimeMilliseconds(5432);
464 statistics_proxy_->OnStreamInactive();
Tommid7e08c82020-05-10 11:24:43 +0200465 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 10:43:06 +0200466
467 stats = statistics_proxy_->GetStats();
468 EXPECT_EQ(1u, stats.pause_count);
469 EXPECT_EQ(5432u, stats.total_pauses_duration_ms);
470}
471
472TEST_F(ReceiveStatisticsProxy2Test, PauseBeforeFirstAndAfterLastFrameIgnored) {
Tommif6f45432022-05-20 15:21:20 +0200473 VideoReceiveStreamInterface::Stats stats = statistics_proxy_->GetStats();
Tommi74fc5742020-04-27 10:43:06 +0200474 ASSERT_EQ(0u, stats.pause_count);
475 ASSERT_EQ(0u, stats.total_pauses_duration_ms);
476
477 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
478
479 // Pause -> Frame -> Pause
480 fake_clock_.AdvanceTimeMilliseconds(5000);
481 statistics_proxy_->OnStreamInactive();
Tommid7e08c82020-05-10 11:24:43 +0200482 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 10:43:06 +0200483
484 fake_clock_.AdvanceTimeMilliseconds(30);
Tommid7e08c82020-05-10 11:24:43 +0200485 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 10:43:06 +0200486
487 fake_clock_.AdvanceTimeMilliseconds(5000);
488 statistics_proxy_->OnStreamInactive();
489
490 stats = statistics_proxy_->GetStats();
491 EXPECT_EQ(0u, stats.pause_count);
492 EXPECT_EQ(0u, stats.total_pauses_duration_ms);
493}
494
495TEST_F(ReceiveStatisticsProxy2Test, ReportsFramesDuration) {
Tommif6f45432022-05-20 15:21:20 +0200496 VideoReceiveStreamInterface::Stats stats = statistics_proxy_->GetStats();
Tommi74fc5742020-04-27 10:43:06 +0200497 ASSERT_EQ(0u, stats.total_frames_duration_ms);
498
499 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
500
501 // Emulate delay before first frame is rendered. This is needed to ensure
502 // that frame duration only covers time since first frame is rendered and
503 // not the total time.
504 fake_clock_.AdvanceTimeMilliseconds(5432);
505
506 for (int i = 0; i <= 10; ++i) {
507 fake_clock_.AdvanceTimeMilliseconds(30);
Tommid7e08c82020-05-10 11:24:43 +0200508 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 10:43:06 +0200509 }
510
511 stats = statistics_proxy_->GetStats();
512 EXPECT_EQ(10 * 30u, stats.total_frames_duration_ms);
513}
514
515TEST_F(ReceiveStatisticsProxy2Test, ReportsSumSquaredFrameDurations) {
Tommif6f45432022-05-20 15:21:20 +0200516 VideoReceiveStreamInterface::Stats stats = statistics_proxy_->GetStats();
Tommi74fc5742020-04-27 10:43:06 +0200517 ASSERT_EQ(0u, stats.sum_squared_frame_durations);
518
519 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
520 for (int i = 0; i <= 10; ++i) {
521 fake_clock_.AdvanceTimeMilliseconds(30);
Tommid7e08c82020-05-10 11:24:43 +0200522 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 10:43:06 +0200523 }
524
525 stats = statistics_proxy_->GetStats();
526 const double kExpectedSumSquaredFrameDurationsSecs =
527 10 * (30 / 1000.0 * 30 / 1000.0);
528 EXPECT_EQ(kExpectedSumSquaredFrameDurationsSecs,
529 stats.sum_squared_frame_durations);
530}
531
532TEST_F(ReceiveStatisticsProxy2Test, OnDecodedFrameWithoutQpQpSumWontExist) {
533 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
534 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
535 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
536 VideoContentType::UNSPECIFIED);
Tommid93bf122020-05-10 20:24:59 +0200537 EXPECT_EQ(absl::nullopt, FlushAndGetStats().qp_sum);
Tommi74fc5742020-04-27 10:43:06 +0200538}
539
540TEST_F(ReceiveStatisticsProxy2Test, OnDecodedFrameWithoutQpResetsQpSum) {
541 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
542 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
543 statistics_proxy_->OnDecodedFrame(frame, 3u, 0,
544 VideoContentType::UNSPECIFIED);
Tommid93bf122020-05-10 20:24:59 +0200545 EXPECT_EQ(3u, FlushAndGetStats().qp_sum);
Tommi74fc5742020-04-27 10:43:06 +0200546 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
547 VideoContentType::UNSPECIFIED);
Tommid93bf122020-05-10 20:24:59 +0200548 EXPECT_EQ(absl::nullopt, FlushAndGetStats().qp_sum);
Tommi74fc5742020-04-27 10:43:06 +0200549}
550
551TEST_F(ReceiveStatisticsProxy2Test, OnRenderedFrameIncreasesFramesRendered) {
552 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_rendered);
553 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
554 for (uint32_t i = 1; i <= 3; ++i) {
Tommid7e08c82020-05-10 11:24:43 +0200555 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 10:43:06 +0200556 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_rendered);
557 }
558}
559
560TEST_F(ReceiveStatisticsProxy2Test, GetStatsReportsSsrc) {
561 EXPECT_EQ(kRemoteSsrc, statistics_proxy_->GetStats().ssrc);
562}
563
564TEST_F(ReceiveStatisticsProxy2Test, GetStatsReportsIncomingPayloadType) {
565 const int kPayloadType = 111;
566 statistics_proxy_->OnIncomingPayloadType(kPayloadType);
Tommi674b0c82020-05-10 21:52:17 +0200567 loop_.Flush();
Tommi74fc5742020-04-27 10:43:06 +0200568 EXPECT_EQ(kPayloadType, statistics_proxy_->GetStats().current_payload_type);
569}
570
571TEST_F(ReceiveStatisticsProxy2Test, GetStatsReportsDecoderImplementationName) {
572 const char* kName = "decoderName";
573 statistics_proxy_->OnDecoderImplementationName(kName);
Tommi674b0c82020-05-10 21:52:17 +0200574 loop_.Flush();
Tommi74fc5742020-04-27 10:43:06 +0200575 EXPECT_STREQ(
576 kName, statistics_proxy_->GetStats().decoder_implementation_name.c_str());
577}
578
579TEST_F(ReceiveStatisticsProxy2Test, GetStatsReportsOnCompleteFrame) {
580 const int kFrameSizeBytes = 1000;
581 statistics_proxy_->OnCompleteFrame(true, kFrameSizeBytes,
582 VideoContentType::UNSPECIFIED);
Tommif6f45432022-05-20 15:21:20 +0200583 VideoReceiveStreamInterface::Stats stats = statistics_proxy_->GetStats();
Tommi74fc5742020-04-27 10:43:06 +0200584 EXPECT_EQ(1, stats.network_frame_rate);
585 EXPECT_EQ(1, stats.frame_counts.key_frames);
586 EXPECT_EQ(0, stats.frame_counts.delta_frames);
587}
588
589TEST_F(ReceiveStatisticsProxy2Test, GetStatsReportsOnDroppedFrame) {
590 unsigned int dropped_frames = 0;
591 for (int i = 0; i < 10; ++i) {
592 statistics_proxy_->OnDroppedFrames(i);
593 dropped_frames += i;
594 }
Tommif6f45432022-05-20 15:21:20 +0200595 VideoReceiveStreamInterface::Stats stats = FlushAndGetStats();
Tommi74fc5742020-04-27 10:43:06 +0200596 EXPECT_EQ(dropped_frames, stats.frames_dropped);
597}
598
599TEST_F(ReceiveStatisticsProxy2Test, GetStatsReportsDecodeTimingStats) {
600 const int kMaxDecodeMs = 2;
601 const int kCurrentDelayMs = 3;
602 const int kTargetDelayMs = 4;
603 const int kJitterBufferMs = 5;
604 const int kMinPlayoutDelayMs = 6;
605 const int kRenderDelayMs = 7;
606 const int64_t kRttMs = 8;
Tommi674b0c82020-05-10 21:52:17 +0200607 statistics_proxy_->OnRttUpdate(kRttMs);
Tommi74fc5742020-04-27 10:43:06 +0200608 statistics_proxy_->OnFrameBufferTimingsUpdated(
609 kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs, kJitterBufferMs,
610 kMinPlayoutDelayMs, kRenderDelayMs);
Tommif6f45432022-05-20 15:21:20 +0200611 VideoReceiveStreamInterface::Stats stats = FlushAndGetStats();
Tommi74fc5742020-04-27 10:43:06 +0200612 EXPECT_EQ(kMaxDecodeMs, stats.max_decode_ms);
613 EXPECT_EQ(kCurrentDelayMs, stats.current_delay_ms);
614 EXPECT_EQ(kTargetDelayMs, stats.target_delay_ms);
615 EXPECT_EQ(kJitterBufferMs, stats.jitter_buffer_ms);
616 EXPECT_EQ(kMinPlayoutDelayMs, stats.min_playout_delay_ms);
617 EXPECT_EQ(kRenderDelayMs, stats.render_delay_ms);
618}
619
620TEST_F(ReceiveStatisticsProxy2Test, GetStatsReportsRtcpPacketTypeCounts) {
621 const uint32_t kFirPackets = 33;
622 const uint32_t kPliPackets = 44;
623 const uint32_t kNackPackets = 55;
624 RtcpPacketTypeCounter counter;
625 counter.fir_packets = kFirPackets;
626 counter.pli_packets = kPliPackets;
627 counter.nack_packets = kNackPackets;
628 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
Tommif6f45432022-05-20 15:21:20 +0200629 VideoReceiveStreamInterface::Stats stats = statistics_proxy_->GetStats();
Tommi74fc5742020-04-27 10:43:06 +0200630 EXPECT_EQ(kFirPackets, stats.rtcp_packet_type_counts.fir_packets);
631 EXPECT_EQ(kPliPackets, stats.rtcp_packet_type_counts.pli_packets);
632 EXPECT_EQ(kNackPackets, stats.rtcp_packet_type_counts.nack_packets);
633}
634
635TEST_F(ReceiveStatisticsProxy2Test,
636 GetStatsReportsNoRtcpPacketTypeCountsForUnknownSsrc) {
637 RtcpPacketTypeCounter counter;
638 counter.fir_packets = 33;
639 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc + 1, counter);
640 EXPECT_EQ(0u,
641 statistics_proxy_->GetStats().rtcp_packet_type_counts.fir_packets);
642}
643
644TEST_F(ReceiveStatisticsProxy2Test, GetStatsReportsFrameCounts) {
645 const int kKeyFrames = 3;
646 const int kDeltaFrames = 22;
647 for (int i = 0; i < kKeyFrames; i++) {
648 statistics_proxy_->OnCompleteFrame(true, 0, VideoContentType::UNSPECIFIED);
649 }
650 for (int i = 0; i < kDeltaFrames; i++) {
651 statistics_proxy_->OnCompleteFrame(false, 0, VideoContentType::UNSPECIFIED);
652 }
653
Tommif6f45432022-05-20 15:21:20 +0200654 VideoReceiveStreamInterface::Stats stats = statistics_proxy_->GetStats();
Tommi74fc5742020-04-27 10:43:06 +0200655 EXPECT_EQ(kKeyFrames, stats.frame_counts.key_frames);
656 EXPECT_EQ(kDeltaFrames, stats.frame_counts.delta_frames);
657}
658
659TEST_F(ReceiveStatisticsProxy2Test, GetStatsReportsCName) {
660 const char* kName = "cName";
661 statistics_proxy_->OnCname(kRemoteSsrc, kName);
662 EXPECT_STREQ(kName, statistics_proxy_->GetStats().c_name.c_str());
663}
664
665TEST_F(ReceiveStatisticsProxy2Test, GetStatsReportsNoCNameForUnknownSsrc) {
666 const char* kName = "cName";
667 statistics_proxy_->OnCname(kRemoteSsrc + 1, kName);
668 EXPECT_STREQ("", statistics_proxy_->GetStats().c_name.c_str());
669}
670
671TEST_F(ReceiveStatisticsProxy2Test, ReportsLongestTimingFrameInfo) {
672 const int64_t kShortEndToEndDelay = 10;
673 const int64_t kMedEndToEndDelay = 20;
674 const int64_t kLongEndToEndDelay = 100;
675 const uint32_t kExpectedRtpTimestamp = 2;
676 TimingFrameInfo info;
677 absl::optional<TimingFrameInfo> result;
678 info.rtp_timestamp = kExpectedRtpTimestamp - 1;
679 info.capture_time_ms = 0;
680 info.decode_finish_ms = kShortEndToEndDelay;
681 statistics_proxy_->OnTimingFrameInfoUpdated(info);
682 info.rtp_timestamp =
683 kExpectedRtpTimestamp; // this frame should be reported in the end.
684 info.capture_time_ms = 0;
685 info.decode_finish_ms = kLongEndToEndDelay;
686 statistics_proxy_->OnTimingFrameInfoUpdated(info);
687 info.rtp_timestamp = kExpectedRtpTimestamp + 1;
688 info.capture_time_ms = 0;
689 info.decode_finish_ms = kMedEndToEndDelay;
690 statistics_proxy_->OnTimingFrameInfoUpdated(info);
Tommi674b0c82020-05-10 21:52:17 +0200691 result = FlushAndGetStats().timing_frame_info;
Tommi74fc5742020-04-27 10:43:06 +0200692 EXPECT_TRUE(result);
693 EXPECT_EQ(kExpectedRtpTimestamp, result->rtp_timestamp);
694}
695
696TEST_F(ReceiveStatisticsProxy2Test, RespectsReportingIntervalForTimingFrames) {
697 TimingFrameInfo info;
698 const int64_t kShortEndToEndDelay = 10;
699 const uint32_t kExpectedRtpTimestamp = 2;
700 const int64_t kShortDelayMs = 1000;
701 const int64_t kLongDelayMs = 10000;
702 absl::optional<TimingFrameInfo> result;
703 info.rtp_timestamp = kExpectedRtpTimestamp;
704 info.capture_time_ms = 0;
705 info.decode_finish_ms = kShortEndToEndDelay;
706 statistics_proxy_->OnTimingFrameInfoUpdated(info);
707 fake_clock_.AdvanceTimeMilliseconds(kShortDelayMs);
Tommi674b0c82020-05-10 21:52:17 +0200708 result = FlushAndGetStats().timing_frame_info;
Tommi74fc5742020-04-27 10:43:06 +0200709 EXPECT_TRUE(result);
710 EXPECT_EQ(kExpectedRtpTimestamp, result->rtp_timestamp);
711 fake_clock_.AdvanceTimeMilliseconds(kLongDelayMs);
712 result = statistics_proxy_->GetStats().timing_frame_info;
713 EXPECT_FALSE(result);
714}
715
716TEST_F(ReceiveStatisticsProxy2Test, LifetimeHistogramIsUpdated) {
717 const int64_t kTimeSec = 3;
718 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
719 // Need at least one frame to report stream lifetime.
720 statistics_proxy_->OnCompleteFrame(true, 1000, VideoContentType::UNSPECIFIED);
721 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
722 nullptr);
723 EXPECT_METRIC_EQ(
724 1, metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
725 EXPECT_METRIC_EQ(
726 1, metrics::NumEvents("WebRTC.Video.ReceiveStreamLifetimeInSeconds",
727 kTimeSec));
728}
729
730TEST_F(ReceiveStatisticsProxy2Test,
731 LifetimeHistogramNotReportedForEmptyStreams) {
732 const int64_t kTimeSec = 3;
733 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
734 // No frames received.
735 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
736 nullptr);
737 EXPECT_METRIC_EQ(
738 0, metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
739}
740
741TEST_F(ReceiveStatisticsProxy2Test, BadCallHistogramsAreUpdated) {
742 // Based on the tuning parameters this will produce 7 uncertain states,
743 // then 10 certainly bad states. There has to be 10 certain states before
744 // any histograms are recorded.
745 const int kNumBadSamples = 17;
746 // We only count one sample per second.
747 const int kBadFameIntervalMs = 1100;
748
749 StreamDataCounters counters;
750 counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
751
752 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
753
754 for (int i = 0; i < kNumBadSamples; ++i) {
755 fake_clock_.AdvanceTimeMilliseconds(kBadFameIntervalMs);
Tommid7e08c82020-05-10 11:24:43 +0200756 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 10:43:06 +0200757 }
758 statistics_proxy_->UpdateHistograms(absl::nullopt, counters, nullptr);
759 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.BadCall.Any"));
760 EXPECT_METRIC_EQ(1, metrics::NumEvents("WebRTC.Video.BadCall.Any", 100));
761
762 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.BadCall.FrameRate"));
763 EXPECT_METRIC_EQ(1,
764 metrics::NumEvents("WebRTC.Video.BadCall.FrameRate", 100));
765
766 EXPECT_METRIC_EQ(
767 0, metrics::NumSamples("WebRTC.Video.BadCall.FrameRateVariance"));
768
769 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.BadCall.Qp"));
770}
771
772TEST_F(ReceiveStatisticsProxy2Test, PacketLossHistogramIsUpdated) {
773 statistics_proxy_->UpdateHistograms(10, StreamDataCounters(), nullptr);
774 EXPECT_METRIC_EQ(
775 0, metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
776
777 // Restart
778 SetUp();
779
780 // Min run time has passed.
781 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
782 statistics_proxy_->UpdateHistograms(10, StreamDataCounters(), nullptr);
783 EXPECT_METRIC_EQ(
784 1, metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
785 EXPECT_METRIC_EQ(
786 1, metrics::NumEvents("WebRTC.Video.ReceivedPacketsLostInPercent", 10));
787}
788
789TEST_F(ReceiveStatisticsProxy2Test, GetStatsReportsPlayoutTimestamp) {
790 const int64_t kVideoNtpMs = 21;
791 const int64_t kSyncOffsetMs = 22;
792 const double kFreqKhz = 90.0;
793 EXPECT_EQ(absl::nullopt,
794 statistics_proxy_->GetStats().estimated_playout_ntp_timestamp_ms);
795 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs, kFreqKhz);
Tommi674b0c82020-05-10 21:52:17 +0200796 EXPECT_EQ(kVideoNtpMs, FlushAndGetStats().estimated_playout_ntp_timestamp_ms);
Tommi74fc5742020-04-27 10:43:06 +0200797 fake_clock_.AdvanceTimeMilliseconds(13);
798 EXPECT_EQ(kVideoNtpMs + 13,
799 statistics_proxy_->GetStats().estimated_playout_ntp_timestamp_ms);
800 fake_clock_.AdvanceTimeMilliseconds(5);
801 EXPECT_EQ(kVideoNtpMs + 13 + 5,
802 statistics_proxy_->GetStats().estimated_playout_ntp_timestamp_ms);
803}
804
805TEST_F(ReceiveStatisticsProxy2Test, GetStatsReportsAvSyncOffset) {
806 const int64_t kVideoNtpMs = 21;
807 const int64_t kSyncOffsetMs = 22;
808 const double kFreqKhz = 90.0;
809 EXPECT_EQ(std::numeric_limits<int>::max(),
810 statistics_proxy_->GetStats().sync_offset_ms);
811 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs, kFreqKhz);
Tommi674b0c82020-05-10 21:52:17 +0200812 EXPECT_EQ(kSyncOffsetMs, FlushAndGetStats().sync_offset_ms);
Tommi74fc5742020-04-27 10:43:06 +0200813}
814
815TEST_F(ReceiveStatisticsProxy2Test, AvSyncOffsetHistogramIsUpdated) {
816 const int64_t kVideoNtpMs = 21;
817 const int64_t kSyncOffsetMs = 22;
818 const double kFreqKhz = 90.0;
Tommi674b0c82020-05-10 21:52:17 +0200819 for (int i = 0; i < kMinRequiredSamples; ++i) {
Tommi74fc5742020-04-27 10:43:06 +0200820 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs,
821 kFreqKhz);
Tommi674b0c82020-05-10 21:52:17 +0200822 }
823 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 10:43:06 +0200824 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.AVSyncOffsetInMs"));
825 EXPECT_METRIC_EQ(
826 1, metrics::NumEvents("WebRTC.Video.AVSyncOffsetInMs", kSyncOffsetMs));
827}
828
829TEST_F(ReceiveStatisticsProxy2Test, RtpToNtpFrequencyOffsetHistogramIsUpdated) {
830 const int64_t kVideoNtpMs = 21;
831 const int64_t kSyncOffsetMs = 22;
832 const double kFreqKhz = 90.0;
833 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs, kFreqKhz);
834 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs,
835 kFreqKhz + 2.2);
Tommi674b0c82020-05-10 21:52:17 +0200836 loop_.Flush();
Tommi74fc5742020-04-27 10:43:06 +0200837 fake_clock_.AdvanceTimeMilliseconds(kFreqOffsetProcessIntervalInMs);
838 // Process interval passed, max diff: 2.
839 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs,
840 kFreqKhz + 1.1);
841 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs,
842 kFreqKhz - 4.2);
843 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs,
844 kFreqKhz - 0.9);
Tommi674b0c82020-05-10 21:52:17 +0200845 loop_.Flush();
Tommi74fc5742020-04-27 10:43:06 +0200846 fake_clock_.AdvanceTimeMilliseconds(kFreqOffsetProcessIntervalInMs);
847 // Process interval passed, max diff: 4.
848 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs, kFreqKhz);
Tommi674b0c82020-05-10 21:52:17 +0200849 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 10:43:06 +0200850 // Average reported: (2 + 4) / 2 = 3.
851 EXPECT_METRIC_EQ(1,
852 metrics::NumSamples("WebRTC.Video.RtpToNtpFreqOffsetInKhz"));
853 EXPECT_METRIC_EQ(
854 1, metrics::NumEvents("WebRTC.Video.RtpToNtpFreqOffsetInKhz", 3));
855}
856
857TEST_F(ReceiveStatisticsProxy2Test, Vp8QpHistogramIsUpdated) {
858 const int kQp = 22;
859
860 for (int i = 0; i < kMinRequiredSamples; ++i)
861 statistics_proxy_->OnPreDecode(kVideoCodecVP8, kQp);
862
Tommi674b0c82020-05-10 21:52:17 +0200863 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 10:43:06 +0200864 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
865 EXPECT_METRIC_EQ(1, metrics::NumEvents("WebRTC.Video.Decoded.Vp8.Qp", kQp));
866}
867
868TEST_F(ReceiveStatisticsProxy2Test,
869 Vp8QpHistogramIsNotUpdatedForTooFewSamples) {
870 const int kQp = 22;
871
872 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
873 statistics_proxy_->OnPreDecode(kVideoCodecVP8, kQp);
874
875 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
876 nullptr);
877 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
878}
879
880TEST_F(ReceiveStatisticsProxy2Test, Vp8QpHistogramIsNotUpdatedIfNoQpValue) {
881 for (int i = 0; i < kMinRequiredSamples; ++i)
882 statistics_proxy_->OnPreDecode(kVideoCodecVP8, -1);
883
884 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
885 nullptr);
886 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
887}
888
889TEST_F(ReceiveStatisticsProxy2Test,
890 KeyFrameHistogramNotUpdatedForTooFewSamples) {
891 const bool kIsKeyFrame = false;
892 const int kFrameSizeBytes = 1000;
893
894 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
895 statistics_proxy_->OnCompleteFrame(kIsKeyFrame, kFrameSizeBytes,
896 VideoContentType::UNSPECIFIED);
897
898 EXPECT_EQ(0, statistics_proxy_->GetStats().frame_counts.key_frames);
899 EXPECT_EQ(kMinRequiredSamples - 1,
900 statistics_proxy_->GetStats().frame_counts.delta_frames);
901
902 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
903 nullptr);
904 EXPECT_METRIC_EQ(
905 0, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
906}
907
908TEST_F(ReceiveStatisticsProxy2Test,
909 KeyFrameHistogramUpdatedForMinRequiredSamples) {
910 const bool kIsKeyFrame = false;
911 const int kFrameSizeBytes = 1000;
912
913 for (int i = 0; i < kMinRequiredSamples; ++i)
914 statistics_proxy_->OnCompleteFrame(kIsKeyFrame, kFrameSizeBytes,
915 VideoContentType::UNSPECIFIED);
916
917 EXPECT_EQ(0, statistics_proxy_->GetStats().frame_counts.key_frames);
918 EXPECT_EQ(kMinRequiredSamples,
919 statistics_proxy_->GetStats().frame_counts.delta_frames);
920
921 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
922 nullptr);
923 EXPECT_METRIC_EQ(
924 1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
925 EXPECT_METRIC_EQ(
926 1, metrics::NumEvents("WebRTC.Video.KeyFramesReceivedInPermille", 0));
927}
928
929TEST_F(ReceiveStatisticsProxy2Test, KeyFrameHistogramIsUpdated) {
930 const int kFrameSizeBytes = 1000;
931
932 for (int i = 0; i < kMinRequiredSamples; ++i)
933 statistics_proxy_->OnCompleteFrame(true, kFrameSizeBytes,
934 VideoContentType::UNSPECIFIED);
935
936 for (int i = 0; i < kMinRequiredSamples; ++i)
937 statistics_proxy_->OnCompleteFrame(false, kFrameSizeBytes,
938 VideoContentType::UNSPECIFIED);
939
940 EXPECT_EQ(kMinRequiredSamples,
941 statistics_proxy_->GetStats().frame_counts.key_frames);
942 EXPECT_EQ(kMinRequiredSamples,
943 statistics_proxy_->GetStats().frame_counts.delta_frames);
944
945 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
946 nullptr);
947 EXPECT_METRIC_EQ(
948 1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
949 EXPECT_METRIC_EQ(
950 1, metrics::NumEvents("WebRTC.Video.KeyFramesReceivedInPermille", 500));
951}
952
953TEST_F(ReceiveStatisticsProxy2Test,
954 TimingHistogramsNotUpdatedForTooFewSamples) {
955 const int kMaxDecodeMs = 2;
956 const int kCurrentDelayMs = 3;
957 const int kTargetDelayMs = 4;
958 const int kJitterBufferMs = 5;
959 const int kMinPlayoutDelayMs = 6;
960 const int kRenderDelayMs = 7;
961
962 for (int i = 0; i < kMinRequiredSamples - 1; ++i) {
963 statistics_proxy_->OnFrameBufferTimingsUpdated(
964 kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs, kJitterBufferMs,
965 kMinPlayoutDelayMs, kRenderDelayMs);
966 }
967
968 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
969 nullptr);
970 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
971 EXPECT_METRIC_EQ(0,
972 metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
973 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
974 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
975 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
976}
977
978TEST_F(ReceiveStatisticsProxy2Test, TimingHistogramsAreUpdated) {
979 const int kMaxDecodeMs = 2;
980 const int kCurrentDelayMs = 3;
981 const int kTargetDelayMs = 4;
982 const int kJitterBufferMs = 5;
983 const int kMinPlayoutDelayMs = 6;
984 const int kRenderDelayMs = 7;
985
986 for (int i = 0; i < kMinRequiredSamples; ++i) {
987 statistics_proxy_->OnFrameBufferTimingsUpdated(
988 kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs, kJitterBufferMs,
989 kMinPlayoutDelayMs, kRenderDelayMs);
990 }
991
Tommi674b0c82020-05-10 21:52:17 +0200992 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 10:43:06 +0200993 EXPECT_METRIC_EQ(1,
994 metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
995 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
996 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
997 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
998
999 EXPECT_METRIC_EQ(1, metrics::NumEvents("WebRTC.Video.JitterBufferDelayInMs",
1000 kJitterBufferMs));
1001 EXPECT_METRIC_EQ(
1002 1, metrics::NumEvents("WebRTC.Video.TargetDelayInMs", kTargetDelayMs));
1003 EXPECT_METRIC_EQ(
1004 1, metrics::NumEvents("WebRTC.Video.CurrentDelayInMs", kCurrentDelayMs));
1005 EXPECT_METRIC_EQ(
1006 1, metrics::NumEvents("WebRTC.Video.OnewayDelayInMs", kTargetDelayMs));
1007}
1008
1009TEST_F(ReceiveStatisticsProxy2Test, DoesNotReportStaleFramerates) {
1010 const int kDefaultFps = 30;
1011 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1012
1013 for (int i = 0; i < kDefaultFps; ++i) {
1014 // Since OnRenderedFrame is never called the fps in each sample will be 0,
1015 // i.e. bad
1016 frame.set_ntp_time_ms(fake_clock_.CurrentNtpInMilliseconds());
1017 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
1018 VideoContentType::UNSPECIFIED);
Tommid7e08c82020-05-10 11:24:43 +02001019 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 10:43:06 +02001020 fake_clock_.AdvanceTimeMilliseconds(1000 / kDefaultFps);
1021 }
1022
Tommid93bf122020-05-10 20:24:59 +02001023 loop_.Flush();
Tommi74fc5742020-04-27 10:43:06 +02001024 EXPECT_EQ(kDefaultFps, statistics_proxy_->GetStats().decode_frame_rate);
1025 EXPECT_EQ(kDefaultFps, statistics_proxy_->GetStats().render_frame_rate);
1026
1027 // FPS trackers in stats proxy have a 1000ms sliding window.
1028 fake_clock_.AdvanceTimeMilliseconds(1000);
1029 EXPECT_EQ(0, statistics_proxy_->GetStats().decode_frame_rate);
1030 EXPECT_EQ(0, statistics_proxy_->GetStats().render_frame_rate);
1031}
1032
1033TEST_F(ReceiveStatisticsProxy2Test, GetStatsReportsReceivedFrameStats) {
1034 EXPECT_EQ(0, statistics_proxy_->GetStats().width);
1035 EXPECT_EQ(0, statistics_proxy_->GetStats().height);
1036 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_rendered);
1037
Tommid7e08c82020-05-10 11:24:43 +02001038 statistics_proxy_->OnRenderedFrame(MetaData(CreateFrame(kWidth, kHeight)));
Tommi74fc5742020-04-27 10:43:06 +02001039
1040 EXPECT_EQ(kWidth, statistics_proxy_->GetStats().width);
1041 EXPECT_EQ(kHeight, statistics_proxy_->GetStats().height);
1042 EXPECT_EQ(1u, statistics_proxy_->GetStats().frames_rendered);
1043}
1044
1045TEST_F(ReceiveStatisticsProxy2Test,
1046 ReceivedFrameHistogramsAreNotUpdatedForTooFewSamples) {
Tommid7e08c82020-05-10 11:24:43 +02001047 for (int i = 0; i < kMinRequiredSamples - 1; ++i) {
1048 statistics_proxy_->OnRenderedFrame(MetaData(CreateFrame(kWidth, kHeight)));
1049 }
Tommi74fc5742020-04-27 10:43:06 +02001050
1051 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1052 nullptr);
1053 EXPECT_METRIC_EQ(0,
1054 metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
1055 EXPECT_METRIC_EQ(0,
1056 metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
1057 EXPECT_METRIC_EQ(0,
1058 metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
1059 EXPECT_METRIC_EQ(
1060 0, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
1061}
1062
1063TEST_F(ReceiveStatisticsProxy2Test, ReceivedFrameHistogramsAreUpdated) {
Tommid7e08c82020-05-10 11:24:43 +02001064 for (int i = 0; i < kMinRequiredSamples; ++i) {
1065 statistics_proxy_->OnRenderedFrame(MetaData(CreateFrame(kWidth, kHeight)));
1066 }
Tommi74fc5742020-04-27 10:43:06 +02001067
1068 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1069 nullptr);
1070 EXPECT_METRIC_EQ(1,
1071 metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
1072 EXPECT_METRIC_EQ(1,
1073 metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
1074 EXPECT_METRIC_EQ(1,
1075 metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
1076 EXPECT_METRIC_EQ(
1077 1, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
1078 EXPECT_METRIC_EQ(
1079 1, metrics::NumEvents("WebRTC.Video.ReceivedWidthInPixels", kWidth));
1080 EXPECT_METRIC_EQ(
1081 1, metrics::NumEvents("WebRTC.Video.ReceivedHeightInPixels", kHeight));
1082}
1083
1084TEST_F(ReceiveStatisticsProxy2Test, ZeroDelayReportedIfFrameNotDelayed) {
1085 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1086 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
1087 VideoContentType::UNSPECIFIED);
1088
1089 // Frame not delayed, delayed frames to render: 0%.
Tommid7e08c82020-05-10 11:24:43 +02001090 statistics_proxy_->OnRenderedFrame(
1091 MetaData(CreateFrameWithRenderTime(Now())));
Tommi74fc5742020-04-27 10:43:06 +02001092
1093 // Min run time has passed.
1094 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
Tommid93bf122020-05-10 20:24:59 +02001095 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 10:43:06 +02001096 EXPECT_METRIC_EQ(1,
1097 metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
1098 EXPECT_METRIC_EQ(
1099 1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 0));
1100 EXPECT_METRIC_EQ(0, metrics::NumSamples(
1101 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
1102}
1103
1104TEST_F(ReceiveStatisticsProxy2Test,
1105 DelayedFrameHistogramsAreNotUpdatedIfMinRuntimeHasNotPassed) {
1106 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1107 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
1108 VideoContentType::UNSPECIFIED);
1109
1110 // Frame not delayed, delayed frames to render: 0%.
Tommid7e08c82020-05-10 11:24:43 +02001111 statistics_proxy_->OnRenderedFrame(
1112 MetaData(CreateFrameWithRenderTime(Now())));
Tommi74fc5742020-04-27 10:43:06 +02001113
1114 // Min run time has not passed.
1115 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000) -
1116 1);
1117 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1118 nullptr);
1119 EXPECT_METRIC_EQ(0,
1120 metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
1121 EXPECT_METRIC_EQ(0, metrics::NumSamples(
1122 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
1123}
1124
1125TEST_F(ReceiveStatisticsProxy2Test,
1126 DelayedFramesHistogramsAreNotUpdatedIfNoRenderedFrames) {
1127 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1128 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
1129 VideoContentType::UNSPECIFIED);
1130
1131 // Min run time has passed. No rendered frames.
1132 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
1133 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1134 nullptr);
1135 EXPECT_METRIC_EQ(0,
1136 metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
1137 EXPECT_METRIC_EQ(0, metrics::NumSamples(
1138 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
1139}
1140
1141TEST_F(ReceiveStatisticsProxy2Test, DelayReportedIfFrameIsDelayed) {
1142 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1143 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
1144 VideoContentType::UNSPECIFIED);
1145
1146 // Frame delayed 1 ms, delayed frames to render: 100%.
Tommid7e08c82020-05-10 11:24:43 +02001147 statistics_proxy_->OnRenderedFrame(
1148 MetaData(CreateFrameWithRenderTimeMs(Now().ms() - 1)));
Tommi74fc5742020-04-27 10:43:06 +02001149
1150 // Min run time has passed.
1151 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
Tommid93bf122020-05-10 20:24:59 +02001152 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 10:43:06 +02001153 EXPECT_METRIC_EQ(1,
1154 metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
1155 EXPECT_METRIC_EQ(
1156 1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 100));
1157 EXPECT_METRIC_EQ(1, metrics::NumSamples(
1158 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
1159 EXPECT_METRIC_EQ(
1160 1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs",
1161 1));
1162}
1163
1164TEST_F(ReceiveStatisticsProxy2Test, AverageDelayOfDelayedFramesIsReported) {
1165 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1166 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
1167 VideoContentType::UNSPECIFIED);
1168
1169 // Two frames delayed (6 ms, 10 ms), delayed frames to render: 50%.
Tommid7e08c82020-05-10 11:24:43 +02001170 const int64_t kNowMs = Now().ms();
1171
1172 statistics_proxy_->OnRenderedFrame(
1173 MetaData(CreateFrameWithRenderTimeMs(kNowMs - 10)));
1174 statistics_proxy_->OnRenderedFrame(
1175 MetaData(CreateFrameWithRenderTimeMs(kNowMs - 6)));
1176 statistics_proxy_->OnRenderedFrame(
1177 MetaData(CreateFrameWithRenderTimeMs(kNowMs)));
1178 statistics_proxy_->OnRenderedFrame(
1179 MetaData(CreateFrameWithRenderTimeMs(kNowMs + 1)));
Tommi74fc5742020-04-27 10:43:06 +02001180
1181 // Min run time has passed.
1182 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000));
Tommid93bf122020-05-10 20:24:59 +02001183 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 10:43:06 +02001184 EXPECT_METRIC_EQ(1,
1185 metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
1186 EXPECT_METRIC_EQ(
1187 1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 50));
1188 EXPECT_METRIC_EQ(1, metrics::NumSamples(
1189 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
1190 EXPECT_METRIC_EQ(
1191 1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs",
1192 8));
1193}
1194
1195TEST_F(ReceiveStatisticsProxy2Test,
1196 RtcpHistogramsNotUpdatedIfMinRuntimeHasNotPassed) {
1197 StreamDataCounters data_counters;
1198 data_counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
1199
1200 fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000) -
1201 1);
1202
1203 RtcpPacketTypeCounter counter;
1204 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
1205
1206 statistics_proxy_->UpdateHistograms(absl::nullopt, data_counters, nullptr);
1207 EXPECT_METRIC_EQ(0,
1208 metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
1209 EXPECT_METRIC_EQ(0,
1210 metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
1211 EXPECT_METRIC_EQ(
1212 0, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
1213}
1214
1215TEST_F(ReceiveStatisticsProxy2Test, RtcpHistogramsAreUpdated) {
1216 StreamDataCounters data_counters;
1217 data_counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
1218 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1219
1220 const uint32_t kFirPackets = 100;
1221 const uint32_t kPliPackets = 200;
1222 const uint32_t kNackPackets = 300;
1223
1224 RtcpPacketTypeCounter counter;
1225 counter.fir_packets = kFirPackets;
1226 counter.pli_packets = kPliPackets;
1227 counter.nack_packets = kNackPackets;
1228 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
1229
1230 statistics_proxy_->UpdateHistograms(absl::nullopt, data_counters, nullptr);
1231 EXPECT_METRIC_EQ(1,
1232 metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
1233 EXPECT_METRIC_EQ(1,
1234 metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
1235 EXPECT_METRIC_EQ(
1236 1, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
1237 EXPECT_METRIC_EQ(
1238 1, metrics::NumEvents("WebRTC.Video.FirPacketsSentPerMinute",
1239 kFirPackets * 60 / metrics::kMinRunTimeInSeconds));
1240 EXPECT_METRIC_EQ(
1241 1, metrics::NumEvents("WebRTC.Video.PliPacketsSentPerMinute",
1242 kPliPackets * 60 / metrics::kMinRunTimeInSeconds));
1243 EXPECT_METRIC_EQ(
1244 1, metrics::NumEvents("WebRTC.Video.NackPacketsSentPerMinute",
1245 kNackPackets * 60 / metrics::kMinRunTimeInSeconds));
1246}
1247
1248class ReceiveStatisticsProxy2TestWithFreezeDuration
1249 : public ReceiveStatisticsProxy2Test,
1250 public ::testing::WithParamInterface<
1251 std::tuple<uint32_t, uint32_t, uint32_t>> {
1252 protected:
1253 const uint32_t frame_duration_ms_ = {std::get<0>(GetParam())};
1254 const uint32_t freeze_duration_ms_ = {std::get<1>(GetParam())};
1255 const uint32_t expected_freeze_count_ = {std::get<2>(GetParam())};
1256};
1257
1258// It is a freeze if:
1259// frame_duration_ms >= max(3 * avg_frame_duration, avg_frame_duration + 150)
1260// where avg_frame_duration is average duration of last 30 frames including
1261// the current one.
1262//
1263// Condition 1: 3 * avg_frame_duration > avg_frame_duration + 150
1264const auto kFreezeDetectionCond1Freeze = std::make_tuple(150, 483, 1);
1265const auto kFreezeDetectionCond1NotFreeze = std::make_tuple(150, 482, 0);
1266// Condition 2: 3 * avg_frame_duration < avg_frame_duration + 150
1267const auto kFreezeDetectionCond2Freeze = std::make_tuple(30, 185, 1);
1268const auto kFreezeDetectionCond2NotFreeze = std::make_tuple(30, 184, 0);
1269
1270INSTANTIATE_TEST_SUITE_P(_,
1271 ReceiveStatisticsProxy2TestWithFreezeDuration,
1272 ::testing::Values(kFreezeDetectionCond1Freeze,
1273 kFreezeDetectionCond1NotFreeze,
1274 kFreezeDetectionCond2Freeze,
1275 kFreezeDetectionCond2NotFreeze));
1276
1277TEST_P(ReceiveStatisticsProxy2TestWithFreezeDuration, FreezeDetection) {
Tommif6f45432022-05-20 15:21:20 +02001278 VideoReceiveStreamInterface::Stats stats = statistics_proxy_->GetStats();
Tommi74fc5742020-04-27 10:43:06 +02001279 EXPECT_EQ(0u, stats.freeze_count);
1280 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1281
1282 // Add a very long frame. This is need to verify that average frame
1283 // duration, which is supposed to be calculated as mean of durations of
1284 // last 30 frames, is calculated correctly.
Tommid7e08c82020-05-10 11:24:43 +02001285 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 10:43:06 +02001286 fake_clock_.AdvanceTimeMilliseconds(2000);
1287
1288 for (size_t i = 0;
1289 i <= VideoQualityObserver::kAvgInterframeDelaysWindowSizeFrames; ++i) {
1290 fake_clock_.AdvanceTimeMilliseconds(frame_duration_ms_);
Tommid7e08c82020-05-10 11:24:43 +02001291 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 10:43:06 +02001292 }
1293
1294 fake_clock_.AdvanceTimeMilliseconds(freeze_duration_ms_);
Tommid7e08c82020-05-10 11:24:43 +02001295 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 10:43:06 +02001296
1297 stats = statistics_proxy_->GetStats();
1298 EXPECT_EQ(stats.freeze_count, expected_freeze_count_);
1299}
1300
1301class ReceiveStatisticsProxy2TestWithContent
1302 : public ReceiveStatisticsProxy2Test,
1303 public ::testing::WithParamInterface<webrtc::VideoContentType> {
1304 protected:
1305 const webrtc::VideoContentType content_type_{GetParam()};
1306};
1307
1308INSTANTIATE_TEST_SUITE_P(ContentTypes,
1309 ReceiveStatisticsProxy2TestWithContent,
1310 ::testing::Values(VideoContentType::UNSPECIFIED,
1311 VideoContentType::SCREENSHARE));
1312
1313TEST_P(ReceiveStatisticsProxy2TestWithContent, InterFrameDelaysAreReported) {
1314 const int kInterFrameDelayMs = 33;
1315 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1316
1317 for (int i = 0; i < kMinRequiredSamples; ++i) {
1318 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
1319 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1320 }
1321 // One extra with double the interval.
1322 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1323 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
1324
Tommid93bf122020-05-10 20:24:59 +02001325 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 10:43:06 +02001326 const int kExpectedInterFrame =
1327 (kInterFrameDelayMs * (kMinRequiredSamples - 1) +
1328 kInterFrameDelayMs * 2) /
1329 kMinRequiredSamples;
1330 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
1331 EXPECT_METRIC_EQ(
1332 kExpectedInterFrame,
1333 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1334 EXPECT_METRIC_EQ(
1335 kInterFrameDelayMs * 2,
1336 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1337 } else {
1338 EXPECT_METRIC_EQ(kExpectedInterFrame,
1339 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
1340 EXPECT_METRIC_EQ(kInterFrameDelayMs * 2,
1341 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
1342 }
1343}
1344
1345TEST_P(ReceiveStatisticsProxy2TestWithContent,
1346 InterFrameDelaysPercentilesAreReported) {
1347 const int kInterFrameDelayMs = 33;
1348 const int kLastFivePercentsSamples = kMinRequiredSamples * 5 / 100;
1349 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1350
1351 for (int i = 0; i <= kMinRequiredSamples - kLastFivePercentsSamples; ++i) {
1352 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1353 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
1354 }
1355 // Last 5% of intervals are double in size.
1356 for (int i = 0; i < kLastFivePercentsSamples; ++i) {
1357 fake_clock_.AdvanceTimeMilliseconds(2 * kInterFrameDelayMs);
1358 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
1359 }
1360 // Final sample is outlier and 10 times as big.
1361 fake_clock_.AdvanceTimeMilliseconds(10 * kInterFrameDelayMs);
1362 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
1363
Tommid93bf122020-05-10 20:24:59 +02001364 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 10:43:06 +02001365 const int kExpectedInterFrame = kInterFrameDelayMs * 2;
1366 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
1367 EXPECT_METRIC_EQ(
1368 kExpectedInterFrame,
1369 metrics::MinSample(
1370 "WebRTC.Video.Screenshare.InterframeDelay95PercentileInMs"));
1371 } else {
1372 EXPECT_METRIC_EQ(
1373 kExpectedInterFrame,
1374 metrics::MinSample("WebRTC.Video.InterframeDelay95PercentileInMs"));
1375 }
1376}
1377
1378TEST_P(ReceiveStatisticsProxy2TestWithContent,
1379 MaxInterFrameDelayOnlyWithValidAverage) {
1380 const int kInterFrameDelayMs = 33;
1381 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1382
1383 for (int i = 0; i < kMinRequiredSamples; ++i) {
1384 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
1385 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1386 }
1387
Artem Titovab30d722021-07-27 16:22:11 +02001388 // `kMinRequiredSamples` samples, and thereby intervals, is required. That
Tommi74fc5742020-04-27 10:43:06 +02001389 // means we're one frame short of having a valid data set.
1390 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1391 nullptr);
1392 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
1393 EXPECT_METRIC_EQ(0,
1394 metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
1395 EXPECT_METRIC_EQ(
1396 0, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1397 EXPECT_METRIC_EQ(0, metrics::NumSamples(
1398 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1399}
1400
1401TEST_P(ReceiveStatisticsProxy2TestWithContent,
1402 MaxInterFrameDelayOnlyWithPause) {
1403 const int kInterFrameDelayMs = 33;
1404 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1405
1406 for (int i = 0; i <= kMinRequiredSamples; ++i) {
1407 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
1408 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1409 }
1410
Tommid93bf122020-05-10 20:24:59 +02001411 loop_.Flush();
Tommi74fc5742020-04-27 10:43:06 +02001412 // At this state, we should have a valid inter-frame delay.
1413 // Indicate stream paused and make a large jump in time.
1414 statistics_proxy_->OnStreamInactive();
1415 fake_clock_.AdvanceTimeMilliseconds(5000);
1416
Tommid7e08c82020-05-10 11:24:43 +02001417 // Insert two more frames. The interval during the pause should be
1418 // disregarded in the stats.
Tommi74fc5742020-04-27 10:43:06 +02001419 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
1420 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1421 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
1422
Tommid93bf122020-05-10 20:24:59 +02001423 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 10:43:06 +02001424 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
1425 EXPECT_METRIC_EQ(
1426 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1427 EXPECT_METRIC_EQ(1, metrics::NumSamples(
1428 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1429 EXPECT_METRIC_EQ(
1430 kInterFrameDelayMs,
1431 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1432 EXPECT_METRIC_EQ(
1433 kInterFrameDelayMs,
1434 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1435 } else {
1436 EXPECT_METRIC_EQ(1,
1437 metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
1438 EXPECT_METRIC_EQ(
1439 1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
1440 EXPECT_METRIC_EQ(kInterFrameDelayMs,
1441 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
1442 EXPECT_METRIC_EQ(kInterFrameDelayMs,
1443 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
1444 }
1445}
1446
1447TEST_P(ReceiveStatisticsProxy2TestWithContent, FreezesAreReported) {
1448 const int kInterFrameDelayMs = 33;
1449 const int kFreezeDelayMs = 200;
1450 const int kCallDurationMs =
1451 kMinRequiredSamples * kInterFrameDelayMs + kFreezeDelayMs;
1452 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1453
1454 for (int i = 0; i < kMinRequiredSamples; ++i) {
Tommid93bf122020-05-10 20:24:59 +02001455 VideoFrameMetaData meta = MetaData(frame);
Philipp Hanckea16a6a62022-04-25 12:21:30 +02001456 statistics_proxy_->OnDecodedFrame(
Philipp Hancke0359ba22022-05-05 15:55:36 +02001457 meta, absl::nullopt, 0, webrtc::TimeDelta::Millis(0),
1458 webrtc::TimeDelta::Millis(0), content_type_);
Tommid93bf122020-05-10 20:24:59 +02001459 statistics_proxy_->OnRenderedFrame(meta);
Tommi74fc5742020-04-27 10:43:06 +02001460 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1461 }
1462 // Add extra freeze.
1463 fake_clock_.AdvanceTimeMilliseconds(kFreezeDelayMs);
Tommid93bf122020-05-10 20:24:59 +02001464 VideoFrameMetaData meta = MetaData(frame);
Philipp Hanckea16a6a62022-04-25 12:21:30 +02001465 statistics_proxy_->OnDecodedFrame(
Philipp Hancke0359ba22022-05-05 15:55:36 +02001466 meta, absl::nullopt, 0, webrtc::TimeDelta::Millis(0),
1467 webrtc::TimeDelta::Millis(0), content_type_);
Tommid93bf122020-05-10 20:24:59 +02001468 statistics_proxy_->OnRenderedFrame(meta);
Tommi74fc5742020-04-27 10:43:06 +02001469
Tommid93bf122020-05-10 20:24:59 +02001470 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 10:43:06 +02001471 const int kExpectedTimeBetweenFreezes =
1472 kInterFrameDelayMs * (kMinRequiredSamples - 1);
1473 const int kExpectedNumberFreezesPerMinute = 60 * 1000 / kCallDurationMs;
1474 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
1475 EXPECT_METRIC_EQ(
1476 kFreezeDelayMs + kInterFrameDelayMs,
1477 metrics::MinSample("WebRTC.Video.Screenshare.MeanFreezeDurationMs"));
1478 EXPECT_METRIC_EQ(kExpectedTimeBetweenFreezes,
1479 metrics::MinSample(
1480 "WebRTC.Video.Screenshare.MeanTimeBetweenFreezesMs"));
1481 EXPECT_METRIC_EQ(
1482 kExpectedNumberFreezesPerMinute,
1483 metrics::MinSample("WebRTC.Video.Screenshare.NumberFreezesPerMinute"));
1484 } else {
1485 EXPECT_METRIC_EQ(kFreezeDelayMs + kInterFrameDelayMs,
1486 metrics::MinSample("WebRTC.Video.MeanFreezeDurationMs"));
1487 EXPECT_METRIC_EQ(
1488 kExpectedTimeBetweenFreezes,
1489 metrics::MinSample("WebRTC.Video.MeanTimeBetweenFreezesMs"));
1490 EXPECT_METRIC_EQ(kExpectedNumberFreezesPerMinute,
1491 metrics::MinSample("WebRTC.Video.NumberFreezesPerMinute"));
1492 }
1493}
1494
1495TEST_P(ReceiveStatisticsProxy2TestWithContent, HarmonicFrameRateIsReported) {
1496 const int kFrameDurationMs = 33;
1497 const int kFreezeDurationMs = 200;
1498 const int kPauseDurationMs = 10000;
1499 const int kCallDurationMs = kMinRequiredSamples * kFrameDurationMs +
1500 kFreezeDurationMs + kPauseDurationMs;
1501 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1502
1503 for (int i = 0; i < kMinRequiredSamples; ++i) {
1504 fake_clock_.AdvanceTimeMilliseconds(kFrameDurationMs);
1505 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Tommid7e08c82020-05-10 11:24:43 +02001506 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 10:43:06 +02001507 }
1508
1509 // Freezes and pauses should be included into harmonic frame rate.
1510 // Add freeze.
Tommid93bf122020-05-10 20:24:59 +02001511 loop_.Flush();
Tommi74fc5742020-04-27 10:43:06 +02001512 fake_clock_.AdvanceTimeMilliseconds(kFreezeDurationMs);
1513 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Tommid7e08c82020-05-10 11:24:43 +02001514 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 10:43:06 +02001515
1516 // Add pause.
Tommid93bf122020-05-10 20:24:59 +02001517 loop_.Flush();
Tommi74fc5742020-04-27 10:43:06 +02001518 fake_clock_.AdvanceTimeMilliseconds(kPauseDurationMs);
1519 statistics_proxy_->OnStreamInactive();
1520 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
Tommid7e08c82020-05-10 11:24:43 +02001521 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 10:43:06 +02001522
Tommid93bf122020-05-10 20:24:59 +02001523 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 10:43:06 +02001524 double kSumSquaredFrameDurationSecs =
1525 (kMinRequiredSamples - 1) *
1526 (kFrameDurationMs / 1000.0 * kFrameDurationMs / 1000.0);
1527 kSumSquaredFrameDurationSecs +=
1528 kFreezeDurationMs / 1000.0 * kFreezeDurationMs / 1000.0;
1529 kSumSquaredFrameDurationSecs +=
1530 kPauseDurationMs / 1000.0 * kPauseDurationMs / 1000.0;
1531 const int kExpectedHarmonicFrameRateFps =
1532 std::round(kCallDurationMs / (1000 * kSumSquaredFrameDurationSecs));
1533 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
1534 EXPECT_METRIC_EQ(
1535 kExpectedHarmonicFrameRateFps,
1536 metrics::MinSample("WebRTC.Video.Screenshare.HarmonicFrameRate"));
1537 } else {
1538 EXPECT_METRIC_EQ(kExpectedHarmonicFrameRateFps,
1539 metrics::MinSample("WebRTC.Video.HarmonicFrameRate"));
1540 }
1541}
1542
1543TEST_P(ReceiveStatisticsProxy2TestWithContent, PausesAreIgnored) {
1544 const int kInterFrameDelayMs = 33;
1545 const int kPauseDurationMs = 10000;
1546 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1547
1548 for (int i = 0; i <= kMinRequiredSamples; ++i) {
Tommid93bf122020-05-10 20:24:59 +02001549 VideoFrameMetaData meta = MetaData(frame);
Philipp Hanckea16a6a62022-04-25 12:21:30 +02001550 statistics_proxy_->OnDecodedFrame(
Philipp Hancke0359ba22022-05-05 15:55:36 +02001551 meta, absl::nullopt, 0, webrtc::TimeDelta::Millis(0),
1552 webrtc::TimeDelta::Millis(0), content_type_);
Tommid93bf122020-05-10 20:24:59 +02001553 statistics_proxy_->OnRenderedFrame(meta);
Tommi74fc5742020-04-27 10:43:06 +02001554 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1555 }
1556 // Add a pause.
1557 fake_clock_.AdvanceTimeMilliseconds(kPauseDurationMs);
1558 statistics_proxy_->OnStreamInactive();
Tommi74fc5742020-04-27 10:43:06 +02001559 // Second playback interval with triple the length.
1560 for (int i = 0; i <= kMinRequiredSamples * 3; ++i) {
Tommid93bf122020-05-10 20:24:59 +02001561 VideoFrameMetaData meta = MetaData(frame);
Philipp Hanckea16a6a62022-04-25 12:21:30 +02001562 statistics_proxy_->OnDecodedFrame(
Philipp Hancke0359ba22022-05-05 15:55:36 +02001563 meta, absl::nullopt, 0, webrtc::TimeDelta::Millis(0),
1564 webrtc::TimeDelta::Millis(0), content_type_);
Tommid93bf122020-05-10 20:24:59 +02001565 statistics_proxy_->OnRenderedFrame(meta);
Tommi74fc5742020-04-27 10:43:06 +02001566 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1567 }
1568
Tommid93bf122020-05-10 20:24:59 +02001569 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 10:43:06 +02001570 // Average of two playback intervals.
1571 const int kExpectedTimeBetweenFreezes =
1572 kInterFrameDelayMs * kMinRequiredSamples * 2;
1573 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
1574 EXPECT_METRIC_EQ(-1, metrics::MinSample(
1575 "WebRTC.Video.Screenshare.MeanFreezeDurationMs"));
1576 EXPECT_METRIC_EQ(kExpectedTimeBetweenFreezes,
1577 metrics::MinSample(
1578 "WebRTC.Video.Screenshare.MeanTimeBetweenFreezesMs"));
1579 } else {
1580 EXPECT_METRIC_EQ(-1,
1581 metrics::MinSample("WebRTC.Video.MeanFreezeDurationMs"));
1582 EXPECT_METRIC_EQ(
1583 kExpectedTimeBetweenFreezes,
1584 metrics::MinSample("WebRTC.Video.MeanTimeBetweenFreezesMs"));
1585 }
1586}
1587
1588TEST_P(ReceiveStatisticsProxy2TestWithContent, ManyPausesAtTheBeginning) {
1589 const int kInterFrameDelayMs = 33;
1590 const int kPauseDurationMs = 10000;
1591 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1592
1593 for (int i = 0; i <= kMinRequiredSamples; ++i) {
1594 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
1595 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1596
1597 statistics_proxy_->OnStreamInactive();
1598 fake_clock_.AdvanceTimeMilliseconds(kPauseDurationMs);
1599
1600 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
1601 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1602 }
1603
1604 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1605 nullptr);
Tommid7e08c82020-05-10 11:24:43 +02001606 // No freezes should be detected, as all long inter-frame delays were
1607 // pauses.
Tommi74fc5742020-04-27 10:43:06 +02001608 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
1609 EXPECT_METRIC_EQ(-1, metrics::MinSample(
1610 "WebRTC.Video.Screenshare.MeanFreezeDurationMs"));
1611 } else {
1612 EXPECT_METRIC_EQ(-1,
1613 metrics::MinSample("WebRTC.Video.MeanFreezeDurationMs"));
1614 }
1615}
1616
1617TEST_P(ReceiveStatisticsProxy2TestWithContent, TimeInHdReported) {
1618 const int kInterFrameDelayMs = 20;
1619 webrtc::VideoFrame frame_hd = CreateFrame(1280, 720);
1620 webrtc::VideoFrame frame_sd = CreateFrame(640, 360);
1621
1622 // HD frames.
1623 for (int i = 0; i < kMinRequiredSamples; ++i) {
Tommid93bf122020-05-10 20:24:59 +02001624 VideoFrameMetaData meta = MetaData(frame_hd);
Philipp Hanckea16a6a62022-04-25 12:21:30 +02001625 statistics_proxy_->OnDecodedFrame(
Philipp Hancke0359ba22022-05-05 15:55:36 +02001626 meta, absl::nullopt, 0, webrtc::TimeDelta::Millis(0),
1627 webrtc::TimeDelta::Millis(0), content_type_);
Tommid93bf122020-05-10 20:24:59 +02001628 statistics_proxy_->OnRenderedFrame(meta);
Tommi74fc5742020-04-27 10:43:06 +02001629 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1630 }
1631 // SD frames.
1632 for (int i = 0; i < 2 * kMinRequiredSamples; ++i) {
Tommid93bf122020-05-10 20:24:59 +02001633 VideoFrameMetaData meta = MetaData(frame_sd);
Philipp Hanckea16a6a62022-04-25 12:21:30 +02001634 statistics_proxy_->OnDecodedFrame(
Philipp Hancke0359ba22022-05-05 15:55:36 +02001635 meta, absl::nullopt, 0, webrtc::TimeDelta::Millis(0),
1636 webrtc::TimeDelta::Millis(0), content_type_);
Tommid93bf122020-05-10 20:24:59 +02001637 statistics_proxy_->OnRenderedFrame(meta);
Tommi74fc5742020-04-27 10:43:06 +02001638 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1639 }
1640 // Extra last frame.
Tommid7e08c82020-05-10 11:24:43 +02001641 statistics_proxy_->OnRenderedFrame(MetaData(frame_sd));
Tommi74fc5742020-04-27 10:43:06 +02001642
1643 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1644 nullptr);
1645 const int kExpectedTimeInHdPercents = 33;
1646 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
1647 EXPECT_METRIC_EQ(
1648 kExpectedTimeInHdPercents,
1649 metrics::MinSample("WebRTC.Video.Screenshare.TimeInHdPercentage"));
1650 } else {
1651 EXPECT_METRIC_EQ(kExpectedTimeInHdPercents,
1652 metrics::MinSample("WebRTC.Video.TimeInHdPercentage"));
1653 }
1654}
1655
1656TEST_P(ReceiveStatisticsProxy2TestWithContent, TimeInBlockyVideoReported) {
1657 const int kInterFrameDelayMs = 20;
1658 const int kHighQp = 80;
1659 const int kLowQp = 30;
1660 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1661
1662 // High quality frames.
1663 for (int i = 0; i < kMinRequiredSamples; ++i) {
Tommid93bf122020-05-10 20:24:59 +02001664 VideoFrameMetaData meta = MetaData(frame);
Philipp Hanckea16a6a62022-04-25 12:21:30 +02001665 statistics_proxy_->OnDecodedFrame(
Philipp Hancke0359ba22022-05-05 15:55:36 +02001666 meta, kLowQp, 0, webrtc::TimeDelta::Millis(0),
1667 webrtc::TimeDelta::Millis(0), content_type_);
Tommid93bf122020-05-10 20:24:59 +02001668 statistics_proxy_->OnRenderedFrame(meta);
Tommi74fc5742020-04-27 10:43:06 +02001669 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1670 }
1671 // Blocky frames.
1672 for (int i = 0; i < 2 * kMinRequiredSamples; ++i) {
Tommid93bf122020-05-10 20:24:59 +02001673 VideoFrameMetaData meta = MetaData(frame);
Philipp Hanckea16a6a62022-04-25 12:21:30 +02001674 statistics_proxy_->OnDecodedFrame(
Philipp Hancke0359ba22022-05-05 15:55:36 +02001675 meta, kHighQp, 0, webrtc::TimeDelta::Millis(0),
1676 webrtc::TimeDelta::Millis(0), content_type_);
Tommid93bf122020-05-10 20:24:59 +02001677 statistics_proxy_->OnRenderedFrame(meta);
Tommi74fc5742020-04-27 10:43:06 +02001678 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1679 }
1680 // Extra last frame.
1681 statistics_proxy_->OnDecodedFrame(frame, kHighQp, 0, content_type_);
Tommid7e08c82020-05-10 11:24:43 +02001682 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 10:43:06 +02001683
Tommid93bf122020-05-10 20:24:59 +02001684 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 10:43:06 +02001685 const int kExpectedTimeInHdPercents = 66;
1686 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
1687 EXPECT_METRIC_EQ(
1688 kExpectedTimeInHdPercents,
1689 metrics::MinSample(
1690 "WebRTC.Video.Screenshare.TimeInBlockyVideoPercentage"));
1691 } else {
1692 EXPECT_METRIC_EQ(
1693 kExpectedTimeInHdPercents,
1694 metrics::MinSample("WebRTC.Video.TimeInBlockyVideoPercentage"));
1695 }
1696}
1697
1698TEST_P(ReceiveStatisticsProxy2TestWithContent, DownscalesReported) {
1699 const int kInterFrameDelayMs = 2000; // To ensure long enough call duration.
1700
1701 webrtc::VideoFrame frame_hd = CreateFrame(1280, 720);
1702 webrtc::VideoFrame frame_sd = CreateFrame(640, 360);
1703 webrtc::VideoFrame frame_ld = CreateFrame(320, 180);
1704
1705 // Call once to pass content type.
1706 statistics_proxy_->OnDecodedFrame(frame_hd, absl::nullopt, 0, content_type_);
1707
Tommid93bf122020-05-10 20:24:59 +02001708 loop_.Flush();
Tommid7e08c82020-05-10 11:24:43 +02001709 statistics_proxy_->OnRenderedFrame(MetaData(frame_hd));
Tommi74fc5742020-04-27 10:43:06 +02001710 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1711
1712 // Downscale.
Tommid7e08c82020-05-10 11:24:43 +02001713 statistics_proxy_->OnRenderedFrame(MetaData(frame_sd));
Tommi74fc5742020-04-27 10:43:06 +02001714 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1715
1716 // Downscale.
Tommid7e08c82020-05-10 11:24:43 +02001717 statistics_proxy_->OnRenderedFrame(MetaData(frame_ld));
Tommi74fc5742020-04-27 10:43:06 +02001718 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1719
1720 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1721 nullptr);
1722 const int kExpectedDownscales = 30; // 2 per 4 seconds = 30 per minute.
1723 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
1724 EXPECT_METRIC_EQ(
1725 kExpectedDownscales,
Tommid7e08c82020-05-10 11:24:43 +02001726 metrics::MinSample("WebRTC.Video.Screenshare."
1727 "NumberResolutionDownswitchesPerMinute"));
Tommi74fc5742020-04-27 10:43:06 +02001728 } else {
1729 EXPECT_METRIC_EQ(kExpectedDownscales,
1730 metrics::MinSample(
1731 "WebRTC.Video.NumberResolutionDownswitchesPerMinute"));
1732 }
1733}
1734
1735TEST_P(ReceiveStatisticsProxy2TestWithContent, DecodeTimeReported) {
1736 const int kInterFrameDelayMs = 20;
1737 const int kLowQp = 30;
1738 const int kDecodeMs = 7;
1739
1740 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1741
1742 for (int i = 0; i < kMinRequiredSamples; ++i) {
1743 statistics_proxy_->OnDecodedFrame(frame, kLowQp, kDecodeMs, content_type_);
1744 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
1745 }
Tommid93bf122020-05-10 20:24:59 +02001746 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 10:43:06 +02001747 EXPECT_METRIC_EQ(
1748 1, metrics::NumEvents("WebRTC.Video.DecodeTimeInMs", kDecodeMs));
1749}
1750
1751TEST_P(ReceiveStatisticsProxy2TestWithContent,
1752 StatsAreSlicedOnSimulcastAndExperiment) {
1753 const uint8_t experiment_id = 1;
1754 webrtc::VideoContentType content_type = content_type_;
1755 videocontenttypehelpers::SetExperimentId(&content_type, experiment_id);
1756 const int kInterFrameDelayMs1 = 30;
1757 const int kInterFrameDelayMs2 = 50;
1758 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1759
1760 videocontenttypehelpers::SetSimulcastId(&content_type, 1);
1761 for (int i = 0; i <= kMinRequiredSamples; ++i) {
1762 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs1);
1763 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type);
1764 }
1765
1766 videocontenttypehelpers::SetSimulcastId(&content_type, 2);
1767 for (int i = 0; i <= kMinRequiredSamples; ++i) {
1768 fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs2);
1769 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type);
1770 }
Tommid93bf122020-05-10 20:24:59 +02001771 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 10:43:06 +02001772
1773 if (videocontenttypehelpers::IsScreenshare(content_type)) {
1774 EXPECT_METRIC_EQ(
1775 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1776 EXPECT_METRIC_EQ(1, metrics::NumSamples(
1777 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1778 EXPECT_METRIC_EQ(1, metrics::NumSamples(
1779 "WebRTC.Video.Screenshare.InterframeDelayInMs.S0"));
1780 EXPECT_METRIC_EQ(1,
1781 metrics::NumSamples(
1782 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs.S0"));
1783 EXPECT_METRIC_EQ(1, metrics::NumSamples(
1784 "WebRTC.Video.Screenshare.InterframeDelayInMs.S1"));
1785 EXPECT_METRIC_EQ(1,
1786 metrics::NumSamples(
1787 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs.S1"));
1788 EXPECT_METRIC_EQ(
1789 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"
1790 ".ExperimentGroup0"));
1791 EXPECT_METRIC_EQ(
1792 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"
1793 ".ExperimentGroup0"));
1794 EXPECT_METRIC_EQ(
1795 kInterFrameDelayMs1,
1796 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs.S0"));
1797 EXPECT_METRIC_EQ(
1798 kInterFrameDelayMs2,
1799 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs.S1"));
1800 EXPECT_METRIC_EQ(
1801 (kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1802 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1803 EXPECT_METRIC_EQ(
1804 kInterFrameDelayMs2,
1805 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1806 EXPECT_METRIC_EQ(
1807 (kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1808 metrics::MinSample(
1809 "WebRTC.Video.Screenshare.InterframeDelayInMs.ExperimentGroup0"));
1810 } else {
1811 EXPECT_METRIC_EQ(1,
1812 metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
1813 EXPECT_METRIC_EQ(
1814 1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
1815 EXPECT_METRIC_EQ(
1816 1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs.S0"));
1817 EXPECT_METRIC_EQ(
1818 1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs.S0"));
1819 EXPECT_METRIC_EQ(
1820 1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs.S1"));
1821 EXPECT_METRIC_EQ(
1822 1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs.S1"));
1823 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"
1824 ".ExperimentGroup0"));
1825 EXPECT_METRIC_EQ(1,
1826 metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"
1827 ".ExperimentGroup0"));
1828 EXPECT_METRIC_EQ(kInterFrameDelayMs1,
1829 metrics::MinSample("WebRTC.Video.InterframeDelayInMs.S0"));
1830 EXPECT_METRIC_EQ(kInterFrameDelayMs2,
1831 metrics::MinSample("WebRTC.Video.InterframeDelayInMs.S1"));
1832 EXPECT_METRIC_EQ((kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1833 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
1834 EXPECT_METRIC_EQ(kInterFrameDelayMs2,
1835 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
1836 EXPECT_METRIC_EQ((kInterFrameDelayMs1 + kInterFrameDelayMs2) / 2,
1837 metrics::MinSample(
1838 "WebRTC.Video.InterframeDelayInMs.ExperimentGroup0"));
1839 }
1840}
1841
Tommi74fc5742020-04-27 10:43:06 +02001842class ReceiveStatisticsProxy2TestWithDecodeTimeHistograms
Jonas Oreland8ca06132022-03-14 12:52:48 +01001843 : public ::testing::WithParamInterface<
Tommi74fc5742020-04-27 10:43:06 +02001844 std::tuple<bool, int, int, int, VideoCodecType, std::string>>,
1845 public ReceiveStatisticsProxy2Test {
1846 public:
1847 ReceiveStatisticsProxy2TestWithDecodeTimeHistograms()
Jonas Oreland8ca06132022-03-14 12:52:48 +01001848 : ReceiveStatisticsProxy2Test(
1849 std::get<0>(GetParam())
1850 ? "WebRTC-DecodeTimeHistogramsKillSwitch/Enabled/"
1851 : "") {}
Tommi74fc5742020-04-27 10:43:06 +02001852
1853 protected:
1854 const std::string kUmaPrefix = "WebRTC.Video.DecodeTimePerFrameInMs.";
1855 const int expected_number_of_samples_ = {std::get<1>(GetParam())};
1856 const int width_ = {std::get<2>(GetParam())};
1857 const int height_ = {std::get<3>(GetParam())};
1858 const VideoCodecType codec_type_ = {std::get<4>(GetParam())};
1859 const std::string implementation_name_ = {std::get<5>(GetParam())};
1860 const std::string uma_histogram_name_ =
1861 kUmaPrefix + (codec_type_ == kVideoCodecVP9 ? "Vp9." : "H264.") +
1862 (height_ == 2160 ? "4k." : "Hd.") +
1863 (implementation_name_.compare("ExternalDecoder") == 0 ? "Hw" : "Sw");
1864};
1865
1866TEST_P(ReceiveStatisticsProxy2TestWithDecodeTimeHistograms,
1867 DecodeTimeHistogramsUpdated) {
1868 constexpr int kNumberOfFrames = 10;
1869 constexpr int kDecodeTimeMs = 7;
1870 constexpr int kFrameDurationMs = 1000 / 60;
1871
1872 webrtc::VideoFrame frame = CreateFrame(width_, height_);
1873
1874 statistics_proxy_->OnDecoderImplementationName(implementation_name_.c_str());
1875 statistics_proxy_->OnPreDecode(codec_type_, /*qp=*/0);
1876
1877 for (int i = 0; i < kNumberOfFrames; ++i) {
1878 statistics_proxy_->OnDecodedFrame(frame, /*qp=*/absl::nullopt,
1879 kDecodeTimeMs,
1880 VideoContentType::UNSPECIFIED);
1881 fake_clock_.AdvanceTimeMilliseconds(kFrameDurationMs);
1882 }
1883
Tommid93bf122020-05-10 20:24:59 +02001884 loop_.Flush();
1885
Tommi74fc5742020-04-27 10:43:06 +02001886 EXPECT_METRIC_EQ(expected_number_of_samples_,
1887 metrics::NumSamples(uma_histogram_name_));
1888 EXPECT_METRIC_EQ(expected_number_of_samples_,
1889 metrics::NumEvents(uma_histogram_name_, kDecodeTimeMs));
1890}
1891
1892const auto kVp94kHw = std::make_tuple(/*killswitch=*/false,
1893 /*expected_number_of_samples=*/10,
1894 /*width=*/3840,
1895 /*height=*/2160,
1896 kVideoCodecVP9,
1897 /*implementation=*/"ExternalDecoder");
1898const auto kVp94kSw = std::make_tuple(/*killswitch=*/false,
1899 /*expected_number_of_samples=*/10,
1900 /*width=*/3840,
1901 /*height=*/2160,
1902 kVideoCodecVP9,
1903 /*implementation=*/"libvpx");
1904const auto kVp9HdHw = std::make_tuple(/*killswitch=*/false,
1905 /*expected_number_of_samples=*/10,
1906 /*width=*/1920,
1907 /*height=*/1080,
1908 kVideoCodecVP9,
1909 /*implementation=*/"ExternalDecoder");
1910const auto kVp9HdSw = std::make_tuple(/*killswitch=*/false,
1911 /*expected_number_of_samples=*/10,
1912 /*width=*/1920,
1913 /*height=*/1080,
1914 kVideoCodecVP9,
1915 /*implementation=*/"libvpx");
1916const auto kH2644kHw = std::make_tuple(/*killswitch=*/false,
1917 /*expected_number_of_samples=*/10,
1918 /*width=*/3840,
1919 /*height=*/2160,
1920 kVideoCodecH264,
1921 /*implementation=*/"ExternalDecoder");
1922const auto kH2644kSw = std::make_tuple(/*killswitch=*/false,
1923 /*expected_number_of_samples=*/10,
1924 /*width=*/3840,
1925 /*height=*/2160,
1926 kVideoCodecH264,
1927 /*implementation=*/"FFmpeg");
1928const auto kH264HdHw = std::make_tuple(/*killswitch=*/false,
1929 /*expected_number_of_samples=*/10,
1930 /*width=*/1920,
1931 /*height=*/1080,
1932 kVideoCodecH264,
1933 /*implementation=*/"ExternalDecoder");
1934const auto kH264HdSw = std::make_tuple(/*killswitch=*/false,
1935 /*expected_number_of_samples=*/10,
1936 /*width=*/1920,
1937 /*height=*/1080,
1938 kVideoCodecH264,
1939 /*implementation=*/"FFmpeg");
1940
1941INSTANTIATE_TEST_SUITE_P(AllHistogramsPopulated,
1942 ReceiveStatisticsProxy2TestWithDecodeTimeHistograms,
1943 ::testing::Values(kVp94kHw,
1944 kVp94kSw,
1945 kVp9HdHw,
1946 kVp9HdSw,
1947 kH2644kHw,
1948 kH2644kSw,
1949 kH264HdHw,
1950 kH264HdSw));
1951
1952const auto kKillswitchDisabled =
1953 std::make_tuple(/*killswitch=*/false,
1954 /*expected_number_of_samples=*/10,
1955 /*width=*/1920,
1956 /*height=*/1080,
1957 kVideoCodecVP9,
1958 /*implementation=*/"libvpx");
1959const auto kKillswitchEnabled =
1960 std::make_tuple(/*killswitch=*/true,
1961 /*expected_number_of_samples=*/0,
1962 /*width=*/1920,
1963 /*height=*/1080,
1964 kVideoCodecVP9,
1965 /*implementation=*/"libvpx");
1966
1967INSTANTIATE_TEST_SUITE_P(KillswitchEffective,
1968 ReceiveStatisticsProxy2TestWithDecodeTimeHistograms,
1969 ::testing::Values(kKillswitchDisabled,
1970 kKillswitchEnabled));
1971
1972} // namespace internal
1973} // namespace webrtc