blob: 0c628f7b83906046dff016621a90b3bf36831724 [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"
Evan Shrubsole1edeb922022-08-08 11:51:26 +000021#include "api/units/frequency.h"
22#include "api/units/time_delta.h"
Tommi74fc5742020-04-27 10:43:06 +020023#include "api/video/i420_buffer.h"
24#include "api/video/video_frame.h"
25#include "api/video/video_frame_buffer.h"
26#include "api/video/video_rotation.h"
Tommi553c8692020-05-05 15:35:45 +020027#include "rtc_base/thread.h"
Tommi74fc5742020-04-27 10:43:06 +020028#include "system_wrappers/include/metrics.h"
Tommi74fc5742020-04-27 10:43:06 +020029#include "test/gtest.h"
Jonas Oreland8ca06132022-03-14 12:52:48 +010030#include "test/scoped_key_value_config.h"
Evan Shrubsole1edeb922022-08-08 11:51:26 +000031#include "test/time_controller/simulated_time_controller.h"
Tommid7e08c82020-05-10 11:24:43 +020032#include "video/video_receive_stream2.h"
Tommi74fc5742020-04-27 10:43:06 +020033
34namespace webrtc {
35namespace internal {
36namespace {
Evan Shrubsole1edeb922022-08-08 11:51:26 +000037const TimeDelta kFreqOffsetProcessInterval = TimeDelta::Seconds(40);
Tommi74fc5742020-04-27 10:43:06 +020038const uint32_t kRemoteSsrc = 456;
39const int kMinRequiredSamples = 200;
40const int kWidth = 1280;
41const int kHeight = 720;
42} // namespace
43
44// TODO(sakal): ReceiveStatisticsProxy is lacking unittesting.
45class ReceiveStatisticsProxy2Test : public ::testing::Test {
46 public:
Evan Shrubsole1edeb922022-08-08 11:51:26 +000047 ReceiveStatisticsProxy2Test() : time_controller_(Timestamp::Millis(1234)) {
Tommi74fc5742020-04-27 10:43:06 +020048 metrics::Reset();
Evan Shrubsole09da10e2022-10-14 14:38:31 +000049 statistics_proxy_ = std::make_unique<ReceiveStatisticsProxy>(
50 kRemoteSsrc, time_controller_.GetClock(),
51 time_controller_.GetMainThread());
Tommi74fc5742020-04-27 10:43:06 +020052 }
53
Tommi553c8692020-05-05 15:35:45 +020054 ~ReceiveStatisticsProxy2Test() override { statistics_proxy_.reset(); }
55
56 protected:
Tommid93bf122020-05-10 20:24:59 +020057 // Convenience method to avoid too many explict flushes.
Tommif6f45432022-05-20 15:21:20 +020058 VideoReceiveStreamInterface::Stats FlushAndGetStats() {
Evan Shrubsole1edeb922022-08-08 11:51:26 +000059 time_controller_.AdvanceTime(TimeDelta::Zero());
Tommid93bf122020-05-10 20:24:59 +020060 return statistics_proxy_->GetStats();
61 }
62
63 void FlushAndUpdateHistograms(absl::optional<int> fraction_lost,
64 const StreamDataCounters& rtp_stats,
65 const StreamDataCounters* rtx_stats) {
Evan Shrubsole1edeb922022-08-08 11:51:26 +000066 time_controller_.AdvanceTime(TimeDelta::Zero());
Tommid93bf122020-05-10 20:24:59 +020067 statistics_proxy_->UpdateHistograms(fraction_lost, rtp_stats, rtx_stats);
68 }
69
Tommi74fc5742020-04-27 10:43:06 +020070 VideoFrame CreateFrame(int width, int height) {
71 return CreateVideoFrame(width, height, 0);
72 }
73
Tommid7e08c82020-05-10 11:24:43 +020074 VideoFrame CreateFrameWithRenderTime(Timestamp render_time) {
75 return CreateFrameWithRenderTimeMs(render_time.ms());
76 }
77
Tommi74fc5742020-04-27 10:43:06 +020078 VideoFrame CreateFrameWithRenderTimeMs(int64_t render_time_ms) {
79 return CreateVideoFrame(kWidth, kHeight, render_time_ms);
80 }
81
82 VideoFrame CreateVideoFrame(int width, int height, int64_t render_time_ms) {
83 VideoFrame frame =
84 VideoFrame::Builder()
85 .set_video_frame_buffer(I420Buffer::Create(width, height))
86 .set_timestamp_rtp(0)
87 .set_timestamp_ms(render_time_ms)
88 .set_rotation(kVideoRotation_0)
89 .build();
Evan Shrubsole1edeb922022-08-08 11:51:26 +000090 frame.set_ntp_time_ms(
91 time_controller_.GetClock()->CurrentNtpInMilliseconds());
Tommi74fc5742020-04-27 10:43:06 +020092 return frame;
93 }
94
Tommid7e08c82020-05-10 11:24:43 +020095 // Return the current fake time as a Timestamp.
Evan Shrubsole1edeb922022-08-08 11:51:26 +000096 Timestamp Now() { return time_controller_.GetClock()->CurrentTime(); }
Tommid7e08c82020-05-10 11:24:43 +020097
98 // Creates a VideoFrameMetaData instance with a timestamp.
99 VideoFrameMetaData MetaData(const VideoFrame& frame, Timestamp ts) {
100 return VideoFrameMetaData(frame, ts);
101 }
102
103 // Creates a VideoFrameMetaData instance with the current fake time.
104 VideoFrameMetaData MetaData(const VideoFrame& frame) {
105 return VideoFrameMetaData(frame, Now());
106 }
107
Jonas Oreland8ca06132022-03-14 12:52:48 +0100108 test::ScopedKeyValueConfig field_trials_;
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000109 GlobalSimulatedTimeController time_controller_;
Tommi74fc5742020-04-27 10:43:06 +0200110 std::unique_ptr<ReceiveStatisticsProxy> statistics_proxy_;
Tommi74fc5742020-04-27 10:43:06 +0200111};
112
113TEST_F(ReceiveStatisticsProxy2Test, OnDecodedFrameIncreasesFramesDecoded) {
114 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_decoded);
115 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
116 for (uint32_t i = 1; i <= 3; ++i) {
Philipp Hanckea204ad22022-07-08 18:43:25 +0200117 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Tommi74fc5742020-04-27 10:43:06 +0200118 VideoContentType::UNSPECIFIED);
Tommid93bf122020-05-10 20:24:59 +0200119 EXPECT_EQ(i, FlushAndGetStats().frames_decoded);
Tommi74fc5742020-04-27 10:43:06 +0200120 }
121}
122
123TEST_F(ReceiveStatisticsProxy2Test, DecodedFpsIsReported) {
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000124 const Frequency kFps = Frequency::Hertz(20);
125 const int kRequiredSamples =
126 TimeDelta::Seconds(metrics::kMinRunTimeInSeconds) * kFps;
Tommi74fc5742020-04-27 10:43:06 +0200127 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
128 for (int i = 0; i < kRequiredSamples; ++i) {
Philipp Hanckea204ad22022-07-08 18:43:25 +0200129 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Tommi74fc5742020-04-27 10:43:06 +0200130 VideoContentType::UNSPECIFIED);
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000131 time_controller_.AdvanceTime(1 / kFps);
Tommi74fc5742020-04-27 10:43:06 +0200132 }
Tommid93bf122020-05-10 20:24:59 +0200133 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 10:43:06 +0200134 EXPECT_METRIC_EQ(1,
135 metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000136 EXPECT_METRIC_EQ(1, metrics::NumEvents("WebRTC.Video.DecodedFramesPerSecond",
137 kFps.hertz()));
Tommi74fc5742020-04-27 10:43:06 +0200138}
139
140TEST_F(ReceiveStatisticsProxy2Test, DecodedFpsIsNotReportedForTooFewSamples) {
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000141 const Frequency kFps = Frequency::Hertz(20);
142 const int kRequiredSamples =
143 TimeDelta::Seconds(metrics::kMinRunTimeInSeconds) * kFps;
Tommi74fc5742020-04-27 10:43:06 +0200144 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
145 for (int i = 0; i < kRequiredSamples - 1; ++i) {
Philipp Hanckea204ad22022-07-08 18:43:25 +0200146 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Tommi74fc5742020-04-27 10:43:06 +0200147 VideoContentType::UNSPECIFIED);
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000148 time_controller_.AdvanceTime(1 / kFps);
Tommi74fc5742020-04-27 10:43:06 +0200149 }
Tommid93bf122020-05-10 20:24:59 +0200150 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 10:43:06 +0200151 EXPECT_METRIC_EQ(0,
152 metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
153}
154
155TEST_F(ReceiveStatisticsProxy2Test,
156 OnDecodedFrameWithQpDoesNotResetFramesDecodedOrTotalDecodeTime) {
157 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_decoded);
158 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Philipp Hanckea204ad22022-07-08 18:43:25 +0200159 TimeDelta expected_total_decode_time = TimeDelta::Zero();
Tommi74fc5742020-04-27 10:43:06 +0200160 unsigned int expected_frames_decoded = 0;
161 for (uint32_t i = 1; i <= 3; ++i) {
Philipp Hancked970b092022-06-17 07:34:23 +0200162 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
163 TimeDelta::Millis(1),
Tommi74fc5742020-04-27 10:43:06 +0200164 VideoContentType::UNSPECIFIED);
Philipp Hancked970b092022-06-17 07:34:23 +0200165 expected_total_decode_time += TimeDelta::Millis(1);
Tommi74fc5742020-04-27 10:43:06 +0200166 ++expected_frames_decoded;
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000167 time_controller_.AdvanceTime(TimeDelta::Zero());
Tommi74fc5742020-04-27 10:43:06 +0200168 EXPECT_EQ(expected_frames_decoded,
169 statistics_proxy_->GetStats().frames_decoded);
Philipp Hancked970b092022-06-17 07:34:23 +0200170 EXPECT_EQ(expected_total_decode_time,
171 statistics_proxy_->GetStats().total_decode_time);
Tommi74fc5742020-04-27 10:43:06 +0200172 }
Philipp Hancked970b092022-06-17 07:34:23 +0200173 statistics_proxy_->OnDecodedFrame(frame, 1u, TimeDelta::Millis(3),
Tommi74fc5742020-04-27 10:43:06 +0200174 VideoContentType::UNSPECIFIED);
175 ++expected_frames_decoded;
Philipp Hancked970b092022-06-17 07:34:23 +0200176 expected_total_decode_time += TimeDelta::Millis(3);
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000177 time_controller_.AdvanceTime(TimeDelta::Zero());
Tommi74fc5742020-04-27 10:43:06 +0200178 EXPECT_EQ(expected_frames_decoded,
179 statistics_proxy_->GetStats().frames_decoded);
Philipp Hancked970b092022-06-17 07:34:23 +0200180 EXPECT_EQ(expected_total_decode_time,
181 statistics_proxy_->GetStats().total_decode_time);
Tommi74fc5742020-04-27 10:43:06 +0200182}
183
Philipp Hanckea16a6a62022-04-25 12:21:30 +0200184TEST_F(ReceiveStatisticsProxy2Test, OnDecodedFrameIncreasesProcessingDelay) {
185 const TimeDelta kProcessingDelay = TimeDelta::Millis(10);
186 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_decoded);
187 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Philipp Hanckea204ad22022-07-08 18:43:25 +0200188 TimeDelta expected_total_processing_delay = TimeDelta::Zero();
Philipp Hanckea16a6a62022-04-25 12:21:30 +0200189 unsigned int expected_frames_decoded = 0;
190 // We set receive time fixed and increase the clock by 10ms
191 // in the loop which will increase the processing delay by
192 // 10/20/30ms respectively.
Alessio Bazzicaa1d03562022-09-19 18:05:29 +0200193 RtpPacketInfos::vector_type packet_infos = {RtpPacketInfo(
194 /*ssrc=*/{}, /*csrcs=*/{}, /*rtp_timestamp=*/{}, /*receive_time=*/Now())};
Philipp Hanckea16a6a62022-04-25 12:21:30 +0200195 frame.set_packet_infos(RtpPacketInfos(packet_infos));
196 for (int i = 1; i <= 3; ++i) {
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000197 time_controller_.AdvanceTime(kProcessingDelay);
Philipp Hancked970b092022-06-17 07:34:23 +0200198 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
199 TimeDelta::Millis(1),
Philipp Hanckea16a6a62022-04-25 12:21:30 +0200200 VideoContentType::UNSPECIFIED);
201 expected_total_processing_delay += i * kProcessingDelay;
202 ++expected_frames_decoded;
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000203 time_controller_.AdvanceTime(TimeDelta::Zero());
Philipp Hanckea16a6a62022-04-25 12:21:30 +0200204 EXPECT_EQ(expected_frames_decoded,
205 statistics_proxy_->GetStats().frames_decoded);
206 EXPECT_EQ(expected_total_processing_delay,
207 statistics_proxy_->GetStats().total_processing_delay);
208 }
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000209 time_controller_.AdvanceTime(kProcessingDelay);
Philipp Hancked970b092022-06-17 07:34:23 +0200210 statistics_proxy_->OnDecodedFrame(frame, 1u, TimeDelta::Millis(3),
Philipp Hanckea16a6a62022-04-25 12:21:30 +0200211 VideoContentType::UNSPECIFIED);
212 ++expected_frames_decoded;
213 expected_total_processing_delay += 4 * kProcessingDelay;
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000214 time_controller_.AdvanceTime(TimeDelta::Zero());
Philipp Hanckea16a6a62022-04-25 12:21:30 +0200215 EXPECT_EQ(expected_frames_decoded,
216 statistics_proxy_->GetStats().frames_decoded);
217 EXPECT_EQ(expected_total_processing_delay,
218 statistics_proxy_->GetStats().total_processing_delay);
219}
220
Philipp Hancke0359ba22022-05-05 15:55:36 +0200221TEST_F(ReceiveStatisticsProxy2Test, OnDecodedFrameIncreasesAssemblyTime) {
222 const TimeDelta kAssemblyTime = TimeDelta::Millis(7);
223 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_decoded);
224 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Philipp Hanckea204ad22022-07-08 18:43:25 +0200225 TimeDelta expected_total_assembly_time = TimeDelta::Zero();
Philipp Hancke0359ba22022-05-05 15:55:36 +0200226 unsigned int expected_frames_decoded = 0;
227 unsigned int expected_frames_assembled_from_multiple_packets = 0;
228
229 // A single-packet frame will not increase total assembly time
230 // and frames assembled.
Alessio Bazzicaa1d03562022-09-19 18:05:29 +0200231 RtpPacketInfos::vector_type single_packet_frame = {RtpPacketInfo(
232 /*ssrc=*/{}, /*csrcs=*/{}, /*rtp_timestamp=*/{}, /*receive_time=*/Now())};
Philipp Hancke0359ba22022-05-05 15:55:36 +0200233 frame.set_packet_infos(RtpPacketInfos(single_packet_frame));
Philipp Hancked970b092022-06-17 07:34:23 +0200234 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Millis(1),
Philipp Hancke0359ba22022-05-05 15:55:36 +0200235 VideoContentType::UNSPECIFIED);
236 ++expected_frames_decoded;
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000237 time_controller_.AdvanceTime(TimeDelta::Zero());
Philipp Hancke0359ba22022-05-05 15:55:36 +0200238 EXPECT_EQ(expected_total_assembly_time,
239 statistics_proxy_->GetStats().total_assembly_time);
240 EXPECT_EQ(
241 expected_frames_assembled_from_multiple_packets,
242 statistics_proxy_->GetStats().frames_assembled_from_multiple_packets);
243
244 // In an ordered frame the first and last packet matter.
245 RtpPacketInfos::vector_type ordered_frame = {
Alessio Bazzicaa1d03562022-09-19 18:05:29 +0200246 RtpPacketInfo(/*ssrc=*/{}, /*csrcs=*/{}, /*rtp_timestamp=*/{},
247 /*receive_time=*/Now()),
248 RtpPacketInfo(/*ssrc=*/{}, /*csrcs=*/{}, /*rtp_timestamp=*/{},
249 /*receive_time=*/Now() + kAssemblyTime),
250 RtpPacketInfo(/*ssrc=*/{}, /*csrcs=*/{}, /*rtp_timestamp=*/{},
251 /*receive_time=*/Now() + 2 * kAssemblyTime),
Philipp Hancke0359ba22022-05-05 15:55:36 +0200252 };
253 frame.set_packet_infos(RtpPacketInfos(ordered_frame));
Philipp Hancked970b092022-06-17 07:34:23 +0200254 statistics_proxy_->OnDecodedFrame(frame, 1u, TimeDelta::Millis(3),
Philipp Hancke0359ba22022-05-05 15:55:36 +0200255 VideoContentType::UNSPECIFIED);
256 ++expected_frames_decoded;
257 ++expected_frames_assembled_from_multiple_packets;
258 expected_total_assembly_time += 2 * kAssemblyTime;
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000259 time_controller_.AdvanceTime(TimeDelta::Zero());
Philipp Hancke0359ba22022-05-05 15:55:36 +0200260 EXPECT_EQ(expected_frames_decoded,
261 statistics_proxy_->GetStats().frames_decoded);
262 EXPECT_EQ(expected_total_assembly_time,
263 statistics_proxy_->GetStats().total_assembly_time);
264 EXPECT_EQ(
265 expected_frames_assembled_from_multiple_packets,
266 statistics_proxy_->GetStats().frames_assembled_from_multiple_packets);
267
268 // "First" and "last" are in receive time, not sequence number.
269 RtpPacketInfos::vector_type unordered_frame = {
Alessio Bazzicaa1d03562022-09-19 18:05:29 +0200270 RtpPacketInfo(/*ssrc=*/{}, /*csrcs=*/{}, /*rtp_timestamp=*/{},
271 /*receive_time=*/Now() + 2 * kAssemblyTime),
272 RtpPacketInfo(/*ssrc=*/{}, /*csrcs=*/{}, /*rtp_timestamp=*/{},
273 /*receive_time=*/Now()),
274 RtpPacketInfo(/*ssrc=*/{}, /*csrcs=*/{}, /*rtp_timestamp=*/{},
275 /*receive_time=*/Now() + kAssemblyTime),
Philipp Hancke0359ba22022-05-05 15:55:36 +0200276 };
277 frame.set_packet_infos(RtpPacketInfos(unordered_frame));
Philipp Hancked970b092022-06-17 07:34:23 +0200278 statistics_proxy_->OnDecodedFrame(frame, 1u, TimeDelta::Millis(3),
Philipp Hancke0359ba22022-05-05 15:55:36 +0200279 VideoContentType::UNSPECIFIED);
280 ++expected_frames_decoded;
281 ++expected_frames_assembled_from_multiple_packets;
282 expected_total_assembly_time += 2 * kAssemblyTime;
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000283 time_controller_.AdvanceTime(TimeDelta::Zero());
Philipp Hancke0359ba22022-05-05 15:55:36 +0200284 EXPECT_EQ(expected_frames_decoded,
285 statistics_proxy_->GetStats().frames_decoded);
286 EXPECT_EQ(expected_total_assembly_time,
287 statistics_proxy_->GetStats().total_assembly_time);
288 EXPECT_EQ(
289 expected_frames_assembled_from_multiple_packets,
290 statistics_proxy_->GetStats().frames_assembled_from_multiple_packets);
291}
292
Tommi74fc5742020-04-27 10:43:06 +0200293TEST_F(ReceiveStatisticsProxy2Test, OnDecodedFrameIncreasesQpSum) {
294 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
295 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Philipp Hanckea204ad22022-07-08 18:43:25 +0200296 statistics_proxy_->OnDecodedFrame(frame, 3u, TimeDelta::Zero(),
Tommi74fc5742020-04-27 10:43:06 +0200297 VideoContentType::UNSPECIFIED);
Tommid93bf122020-05-10 20:24:59 +0200298 EXPECT_EQ(3u, FlushAndGetStats().qp_sum);
Philipp Hanckea204ad22022-07-08 18:43:25 +0200299 statistics_proxy_->OnDecodedFrame(frame, 127u, TimeDelta::Zero(),
Tommi74fc5742020-04-27 10:43:06 +0200300 VideoContentType::UNSPECIFIED);
Tommid93bf122020-05-10 20:24:59 +0200301 EXPECT_EQ(130u, FlushAndGetStats().qp_sum);
Tommi74fc5742020-04-27 10:43:06 +0200302}
303
304TEST_F(ReceiveStatisticsProxy2Test, OnDecodedFrameIncreasesTotalDecodeTime) {
305 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
306 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Philipp Hancked970b092022-06-17 07:34:23 +0200307 statistics_proxy_->OnDecodedFrame(frame, 3u, TimeDelta::Millis(4),
Tommi74fc5742020-04-27 10:43:06 +0200308 VideoContentType::UNSPECIFIED);
Philipp Hancked970b092022-06-17 07:34:23 +0200309 EXPECT_EQ(4u, FlushAndGetStats().total_decode_time.ms());
310 statistics_proxy_->OnDecodedFrame(frame, 127u, TimeDelta::Millis(7),
Tommi74fc5742020-04-27 10:43:06 +0200311 VideoContentType::UNSPECIFIED);
Philipp Hancked970b092022-06-17 07:34:23 +0200312 EXPECT_EQ(11u, FlushAndGetStats().total_decode_time.ms());
Tommi74fc5742020-04-27 10:43:06 +0200313}
314
315TEST_F(ReceiveStatisticsProxy2Test, ReportsContentType) {
316 const std::string kRealtimeString("realtime");
317 const std::string kScreenshareString("screen");
318 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
319 EXPECT_EQ(kRealtimeString, videocontenttypehelpers::ToString(
320 statistics_proxy_->GetStats().content_type));
Philipp Hanckea204ad22022-07-08 18:43:25 +0200321 statistics_proxy_->OnDecodedFrame(frame, 3u, TimeDelta::Zero(),
Tommi74fc5742020-04-27 10:43:06 +0200322 VideoContentType::SCREENSHARE);
323 EXPECT_EQ(kScreenshareString,
Tommid93bf122020-05-10 20:24:59 +0200324 videocontenttypehelpers::ToString(FlushAndGetStats().content_type));
Philipp Hanckea204ad22022-07-08 18:43:25 +0200325 statistics_proxy_->OnDecodedFrame(frame, 3u, TimeDelta::Zero(),
Tommi74fc5742020-04-27 10:43:06 +0200326 VideoContentType::UNSPECIFIED);
Tommid93bf122020-05-10 20:24:59 +0200327 EXPECT_EQ(kRealtimeString,
328 videocontenttypehelpers::ToString(FlushAndGetStats().content_type));
Tommi74fc5742020-04-27 10:43:06 +0200329}
330
Tommi74fc5742020-04-27 10:43:06 +0200331TEST_F(ReceiveStatisticsProxy2Test, ReportsMaxInterframeDelay) {
332 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000333 const TimeDelta kInterframeDelay1 = TimeDelta::Millis(100);
334 const TimeDelta kInterframeDelay2 = TimeDelta::Millis(200);
335 const TimeDelta kInterframeDelay3 = TimeDelta::Millis(100);
Tommi74fc5742020-04-27 10:43:06 +0200336 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
Philipp Hanckea204ad22022-07-08 18:43:25 +0200337 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Tommi74fc5742020-04-27 10:43:06 +0200338 VideoContentType::UNSPECIFIED);
Tommid93bf122020-05-10 20:24:59 +0200339 EXPECT_EQ(-1, FlushAndGetStats().interframe_delay_max_ms);
Tommi74fc5742020-04-27 10:43:06 +0200340
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000341 time_controller_.AdvanceTime(kInterframeDelay1);
Philipp Hanckea204ad22022-07-08 18:43:25 +0200342 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Tommi74fc5742020-04-27 10:43:06 +0200343 VideoContentType::UNSPECIFIED);
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000344 EXPECT_EQ(kInterframeDelay1.ms(), FlushAndGetStats().interframe_delay_max_ms);
Tommi74fc5742020-04-27 10:43:06 +0200345
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000346 time_controller_.AdvanceTime(kInterframeDelay2);
Philipp Hanckea204ad22022-07-08 18:43:25 +0200347 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Tommi74fc5742020-04-27 10:43:06 +0200348 VideoContentType::UNSPECIFIED);
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000349 EXPECT_EQ(kInterframeDelay2.ms(), FlushAndGetStats().interframe_delay_max_ms);
Tommi74fc5742020-04-27 10:43:06 +0200350
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000351 time_controller_.AdvanceTime(kInterframeDelay3);
Philipp Hanckea204ad22022-07-08 18:43:25 +0200352 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Tommi74fc5742020-04-27 10:43:06 +0200353 VideoContentType::UNSPECIFIED);
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000354 // kInterframeDelay3 is smaller than kInterframeDelay2.
355 EXPECT_EQ(kInterframeDelay2.ms(), FlushAndGetStats().interframe_delay_max_ms);
Tommi74fc5742020-04-27 10:43:06 +0200356}
357
358TEST_F(ReceiveStatisticsProxy2Test, ReportInterframeDelayInWindow) {
359 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000360 const TimeDelta kInterframeDelay1 = TimeDelta::Millis(900);
361 const TimeDelta kInterframeDelay2 = TimeDelta::Millis(750);
362 const TimeDelta kInterframeDelay3 = TimeDelta::Millis(700);
Tommi74fc5742020-04-27 10:43:06 +0200363 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
Philipp Hanckea204ad22022-07-08 18:43:25 +0200364 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Tommi74fc5742020-04-27 10:43:06 +0200365 VideoContentType::UNSPECIFIED);
Tommid93bf122020-05-10 20:24:59 +0200366 EXPECT_EQ(-1, FlushAndGetStats().interframe_delay_max_ms);
Tommi74fc5742020-04-27 10:43:06 +0200367
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000368 time_controller_.AdvanceTime(kInterframeDelay1);
Philipp Hanckea204ad22022-07-08 18:43:25 +0200369 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Tommi74fc5742020-04-27 10:43:06 +0200370 VideoContentType::UNSPECIFIED);
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000371 EXPECT_EQ(kInterframeDelay1.ms(), FlushAndGetStats().interframe_delay_max_ms);
Tommi74fc5742020-04-27 10:43:06 +0200372
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000373 time_controller_.AdvanceTime(kInterframeDelay2);
Philipp Hanckea204ad22022-07-08 18:43:25 +0200374 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Tommi74fc5742020-04-27 10:43:06 +0200375 VideoContentType::UNSPECIFIED);
376 // Still first delay is the maximum
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000377 EXPECT_EQ(kInterframeDelay1.ms(), FlushAndGetStats().interframe_delay_max_ms);
Tommi74fc5742020-04-27 10:43:06 +0200378
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000379 time_controller_.AdvanceTime(kInterframeDelay3);
Philipp Hanckea204ad22022-07-08 18:43:25 +0200380 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Tommi74fc5742020-04-27 10:43:06 +0200381 VideoContentType::UNSPECIFIED);
382 // Now the first sample is out of the window, so the second is the maximum.
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000383 EXPECT_EQ(kInterframeDelay2.ms(), FlushAndGetStats().interframe_delay_max_ms);
Tommi74fc5742020-04-27 10:43:06 +0200384}
385
386TEST_F(ReceiveStatisticsProxy2Test, ReportsFreezeMetrics) {
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000387 const TimeDelta kFreezeDuration = TimeDelta::Seconds(1);
Tommi74fc5742020-04-27 10:43:06 +0200388
Tommif6f45432022-05-20 15:21:20 +0200389 VideoReceiveStreamInterface::Stats stats = statistics_proxy_->GetStats();
Tommi74fc5742020-04-27 10:43:06 +0200390 EXPECT_EQ(0u, stats.freeze_count);
391 EXPECT_FALSE(stats.total_freezes_duration_ms);
392
393 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
394 for (size_t i = 0; i < VideoQualityObserver::kMinFrameSamplesToDetectFreeze;
395 ++i) {
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000396 time_controller_.AdvanceTime(TimeDelta::Millis(30));
Tommid7e08c82020-05-10 11:24:43 +0200397 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 10:43:06 +0200398 }
399
400 // Freeze.
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000401 time_controller_.AdvanceTime(kFreezeDuration);
Tommid7e08c82020-05-10 11:24:43 +0200402 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 10:43:06 +0200403
404 stats = statistics_proxy_->GetStats();
405 EXPECT_EQ(1u, stats.freeze_count);
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000406 EXPECT_EQ(kFreezeDuration.ms(), stats.total_freezes_duration_ms);
Tommi74fc5742020-04-27 10:43:06 +0200407}
408
409TEST_F(ReceiveStatisticsProxy2Test, ReportsPauseMetrics) {
Tommif6f45432022-05-20 15:21:20 +0200410 VideoReceiveStreamInterface::Stats stats = statistics_proxy_->GetStats();
Tommi74fc5742020-04-27 10:43:06 +0200411 ASSERT_EQ(0u, stats.pause_count);
412 ASSERT_EQ(0u, stats.total_pauses_duration_ms);
413
414 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Tommid7e08c82020-05-10 11:24:43 +0200415 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 10:43:06 +0200416
417 // Pause.
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000418 time_controller_.AdvanceTime(TimeDelta::Millis(5432));
Tommi74fc5742020-04-27 10:43:06 +0200419 statistics_proxy_->OnStreamInactive();
Tommid7e08c82020-05-10 11:24:43 +0200420 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 10:43:06 +0200421
422 stats = statistics_proxy_->GetStats();
423 EXPECT_EQ(1u, stats.pause_count);
424 EXPECT_EQ(5432u, stats.total_pauses_duration_ms);
425}
426
427TEST_F(ReceiveStatisticsProxy2Test, PauseBeforeFirstAndAfterLastFrameIgnored) {
Tommif6f45432022-05-20 15:21:20 +0200428 VideoReceiveStreamInterface::Stats stats = statistics_proxy_->GetStats();
Tommi74fc5742020-04-27 10:43:06 +0200429 ASSERT_EQ(0u, stats.pause_count);
430 ASSERT_EQ(0u, stats.total_pauses_duration_ms);
431
432 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
433
434 // Pause -> Frame -> Pause
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000435 time_controller_.AdvanceTime(TimeDelta::Seconds(5));
Tommi74fc5742020-04-27 10:43:06 +0200436 statistics_proxy_->OnStreamInactive();
Tommid7e08c82020-05-10 11:24:43 +0200437 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 10:43:06 +0200438
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000439 time_controller_.AdvanceTime(TimeDelta::Millis(30));
Tommid7e08c82020-05-10 11:24:43 +0200440 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 10:43:06 +0200441
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000442 time_controller_.AdvanceTime(TimeDelta::Seconds(5));
Tommi74fc5742020-04-27 10:43:06 +0200443 statistics_proxy_->OnStreamInactive();
444
445 stats = statistics_proxy_->GetStats();
446 EXPECT_EQ(0u, stats.pause_count);
447 EXPECT_EQ(0u, stats.total_pauses_duration_ms);
448}
449
Sergey Silkined0dd8e2022-12-20 13:58:15 +0100450TEST_F(ReceiveStatisticsProxy2Test, ReportsTotalInterFrameDelay) {
Tommif6f45432022-05-20 15:21:20 +0200451 VideoReceiveStreamInterface::Stats stats = statistics_proxy_->GetStats();
Sergey Silkined0dd8e2022-12-20 13:58:15 +0100452 ASSERT_EQ(0.0, stats.total_inter_frame_delay);
Tommi74fc5742020-04-27 10:43:06 +0200453
454 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
455
456 // Emulate delay before first frame is rendered. This is needed to ensure
457 // that frame duration only covers time since first frame is rendered and
458 // not the total time.
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000459 time_controller_.AdvanceTime(TimeDelta::Millis(5432));
Tommi74fc5742020-04-27 10:43:06 +0200460 for (int i = 0; i <= 10; ++i) {
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000461 time_controller_.AdvanceTime(TimeDelta::Millis(30));
Tommid7e08c82020-05-10 11:24:43 +0200462 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 10:43:06 +0200463 }
464
465 stats = statistics_proxy_->GetStats();
Sergey Silkined0dd8e2022-12-20 13:58:15 +0100466 EXPECT_EQ(10 * 30 / 1000.0, stats.total_inter_frame_delay);
Tommi74fc5742020-04-27 10:43:06 +0200467}
468
Sergey Silkined0dd8e2022-12-20 13:58:15 +0100469TEST_F(ReceiveStatisticsProxy2Test, ReportsTotalSquaredInterFrameDelay) {
Tommif6f45432022-05-20 15:21:20 +0200470 VideoReceiveStreamInterface::Stats stats = statistics_proxy_->GetStats();
Sergey Silkined0dd8e2022-12-20 13:58:15 +0100471 ASSERT_EQ(0.0, stats.total_squared_inter_frame_delay);
Tommi74fc5742020-04-27 10:43:06 +0200472
473 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
474 for (int i = 0; i <= 10; ++i) {
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000475 time_controller_.AdvanceTime(TimeDelta::Millis(30));
Tommid7e08c82020-05-10 11:24:43 +0200476 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 10:43:06 +0200477 }
478
479 stats = statistics_proxy_->GetStats();
Sergey Silkined0dd8e2022-12-20 13:58:15 +0100480 const double kExpectedTotalSquaredInterFrameDelaySecs =
Tommi74fc5742020-04-27 10:43:06 +0200481 10 * (30 / 1000.0 * 30 / 1000.0);
Sergey Silkined0dd8e2022-12-20 13:58:15 +0100482 EXPECT_EQ(kExpectedTotalSquaredInterFrameDelaySecs,
483 stats.total_squared_inter_frame_delay);
Tommi74fc5742020-04-27 10:43:06 +0200484}
485
486TEST_F(ReceiveStatisticsProxy2Test, OnDecodedFrameWithoutQpQpSumWontExist) {
487 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
488 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
Philipp Hanckea204ad22022-07-08 18:43:25 +0200489 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Tommi74fc5742020-04-27 10:43:06 +0200490 VideoContentType::UNSPECIFIED);
Tommid93bf122020-05-10 20:24:59 +0200491 EXPECT_EQ(absl::nullopt, FlushAndGetStats().qp_sum);
Tommi74fc5742020-04-27 10:43:06 +0200492}
493
494TEST_F(ReceiveStatisticsProxy2Test, OnDecodedFrameWithoutQpResetsQpSum) {
495 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
496 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
Philipp Hanckea204ad22022-07-08 18:43:25 +0200497 statistics_proxy_->OnDecodedFrame(frame, 3u, TimeDelta::Zero(),
Tommi74fc5742020-04-27 10:43:06 +0200498 VideoContentType::UNSPECIFIED);
Tommid93bf122020-05-10 20:24:59 +0200499 EXPECT_EQ(3u, FlushAndGetStats().qp_sum);
Philipp Hanckea204ad22022-07-08 18:43:25 +0200500 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Tommi74fc5742020-04-27 10:43:06 +0200501 VideoContentType::UNSPECIFIED);
Tommid93bf122020-05-10 20:24:59 +0200502 EXPECT_EQ(absl::nullopt, FlushAndGetStats().qp_sum);
Tommi74fc5742020-04-27 10:43:06 +0200503}
504
505TEST_F(ReceiveStatisticsProxy2Test, OnRenderedFrameIncreasesFramesRendered) {
506 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_rendered);
507 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
508 for (uint32_t i = 1; i <= 3; ++i) {
Tommid7e08c82020-05-10 11:24:43 +0200509 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 10:43:06 +0200510 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_rendered);
511 }
512}
513
514TEST_F(ReceiveStatisticsProxy2Test, GetStatsReportsSsrc) {
515 EXPECT_EQ(kRemoteSsrc, statistics_proxy_->GetStats().ssrc);
516}
517
518TEST_F(ReceiveStatisticsProxy2Test, GetStatsReportsIncomingPayloadType) {
519 const int kPayloadType = 111;
520 statistics_proxy_->OnIncomingPayloadType(kPayloadType);
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000521 time_controller_.AdvanceTime(TimeDelta::Zero());
Tommi74fc5742020-04-27 10:43:06 +0200522 EXPECT_EQ(kPayloadType, statistics_proxy_->GetStats().current_payload_type);
523}
524
Evan Shrubsole09da10e2022-10-14 14:38:31 +0000525TEST_F(ReceiveStatisticsProxy2Test, GetStatsReportsDecoderInfo) {
526 auto init_stats = statistics_proxy_->GetStats();
527 EXPECT_EQ(init_stats.decoder_implementation_name, "unknown");
528 EXPECT_EQ(init_stats.power_efficient_decoder, absl::nullopt);
529
530 const VideoDecoder::DecoderInfo decoder_info{
531 .implementation_name = "decoderName", .is_hardware_accelerated = true};
532 statistics_proxy_->OnDecoderInfo(decoder_info);
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000533 time_controller_.AdvanceTime(TimeDelta::Zero());
Evan Shrubsole09da10e2022-10-14 14:38:31 +0000534 auto stats = statistics_proxy_->GetStats();
535 EXPECT_EQ(decoder_info.implementation_name,
536 stats.decoder_implementation_name);
537 EXPECT_TRUE(stats.power_efficient_decoder);
Tommi74fc5742020-04-27 10:43:06 +0200538}
539
540TEST_F(ReceiveStatisticsProxy2Test, GetStatsReportsOnCompleteFrame) {
541 const int kFrameSizeBytes = 1000;
542 statistics_proxy_->OnCompleteFrame(true, kFrameSizeBytes,
543 VideoContentType::UNSPECIFIED);
Tommif6f45432022-05-20 15:21:20 +0200544 VideoReceiveStreamInterface::Stats stats = statistics_proxy_->GetStats();
Tommi74fc5742020-04-27 10:43:06 +0200545 EXPECT_EQ(1, stats.network_frame_rate);
546 EXPECT_EQ(1, stats.frame_counts.key_frames);
547 EXPECT_EQ(0, stats.frame_counts.delta_frames);
548}
549
550TEST_F(ReceiveStatisticsProxy2Test, GetStatsReportsOnDroppedFrame) {
551 unsigned int dropped_frames = 0;
552 for (int i = 0; i < 10; ++i) {
553 statistics_proxy_->OnDroppedFrames(i);
554 dropped_frames += i;
555 }
Tommif6f45432022-05-20 15:21:20 +0200556 VideoReceiveStreamInterface::Stats stats = FlushAndGetStats();
Tommi74fc5742020-04-27 10:43:06 +0200557 EXPECT_EQ(dropped_frames, stats.frames_dropped);
558}
559
560TEST_F(ReceiveStatisticsProxy2Test, GetStatsReportsDecodeTimingStats) {
561 const int kMaxDecodeMs = 2;
562 const int kCurrentDelayMs = 3;
563 const int kTargetDelayMs = 4;
564 const int kJitterBufferMs = 5;
565 const int kMinPlayoutDelayMs = 6;
566 const int kRenderDelayMs = 7;
567 const int64_t kRttMs = 8;
Tommi674b0c82020-05-10 21:52:17 +0200568 statistics_proxy_->OnRttUpdate(kRttMs);
Tommi74fc5742020-04-27 10:43:06 +0200569 statistics_proxy_->OnFrameBufferTimingsUpdated(
570 kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs, kJitterBufferMs,
571 kMinPlayoutDelayMs, kRenderDelayMs);
Tommif6f45432022-05-20 15:21:20 +0200572 VideoReceiveStreamInterface::Stats stats = FlushAndGetStats();
Tommi74fc5742020-04-27 10:43:06 +0200573 EXPECT_EQ(kMaxDecodeMs, stats.max_decode_ms);
574 EXPECT_EQ(kCurrentDelayMs, stats.current_delay_ms);
575 EXPECT_EQ(kTargetDelayMs, stats.target_delay_ms);
576 EXPECT_EQ(kJitterBufferMs, stats.jitter_buffer_ms);
577 EXPECT_EQ(kMinPlayoutDelayMs, stats.min_playout_delay_ms);
578 EXPECT_EQ(kRenderDelayMs, stats.render_delay_ms);
579}
580
581TEST_F(ReceiveStatisticsProxy2Test, GetStatsReportsRtcpPacketTypeCounts) {
582 const uint32_t kFirPackets = 33;
583 const uint32_t kPliPackets = 44;
584 const uint32_t kNackPackets = 55;
585 RtcpPacketTypeCounter counter;
586 counter.fir_packets = kFirPackets;
587 counter.pli_packets = kPliPackets;
588 counter.nack_packets = kNackPackets;
589 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
Tommif6f45432022-05-20 15:21:20 +0200590 VideoReceiveStreamInterface::Stats stats = statistics_proxy_->GetStats();
Tommi74fc5742020-04-27 10:43:06 +0200591 EXPECT_EQ(kFirPackets, stats.rtcp_packet_type_counts.fir_packets);
592 EXPECT_EQ(kPliPackets, stats.rtcp_packet_type_counts.pli_packets);
593 EXPECT_EQ(kNackPackets, stats.rtcp_packet_type_counts.nack_packets);
594}
595
596TEST_F(ReceiveStatisticsProxy2Test,
597 GetStatsReportsNoRtcpPacketTypeCountsForUnknownSsrc) {
598 RtcpPacketTypeCounter counter;
599 counter.fir_packets = 33;
600 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc + 1, counter);
601 EXPECT_EQ(0u,
602 statistics_proxy_->GetStats().rtcp_packet_type_counts.fir_packets);
603}
604
605TEST_F(ReceiveStatisticsProxy2Test, GetStatsReportsFrameCounts) {
606 const int kKeyFrames = 3;
607 const int kDeltaFrames = 22;
608 for (int i = 0; i < kKeyFrames; i++) {
609 statistics_proxy_->OnCompleteFrame(true, 0, VideoContentType::UNSPECIFIED);
610 }
611 for (int i = 0; i < kDeltaFrames; i++) {
612 statistics_proxy_->OnCompleteFrame(false, 0, VideoContentType::UNSPECIFIED);
613 }
614
Tommif6f45432022-05-20 15:21:20 +0200615 VideoReceiveStreamInterface::Stats stats = statistics_proxy_->GetStats();
Tommi74fc5742020-04-27 10:43:06 +0200616 EXPECT_EQ(kKeyFrames, stats.frame_counts.key_frames);
617 EXPECT_EQ(kDeltaFrames, stats.frame_counts.delta_frames);
618}
619
620TEST_F(ReceiveStatisticsProxy2Test, GetStatsReportsCName) {
621 const char* kName = "cName";
622 statistics_proxy_->OnCname(kRemoteSsrc, kName);
623 EXPECT_STREQ(kName, statistics_proxy_->GetStats().c_name.c_str());
624}
625
626TEST_F(ReceiveStatisticsProxy2Test, GetStatsReportsNoCNameForUnknownSsrc) {
627 const char* kName = "cName";
628 statistics_proxy_->OnCname(kRemoteSsrc + 1, kName);
629 EXPECT_STREQ("", statistics_proxy_->GetStats().c_name.c_str());
630}
631
632TEST_F(ReceiveStatisticsProxy2Test, ReportsLongestTimingFrameInfo) {
633 const int64_t kShortEndToEndDelay = 10;
634 const int64_t kMedEndToEndDelay = 20;
635 const int64_t kLongEndToEndDelay = 100;
636 const uint32_t kExpectedRtpTimestamp = 2;
637 TimingFrameInfo info;
638 absl::optional<TimingFrameInfo> result;
639 info.rtp_timestamp = kExpectedRtpTimestamp - 1;
640 info.capture_time_ms = 0;
641 info.decode_finish_ms = kShortEndToEndDelay;
642 statistics_proxy_->OnTimingFrameInfoUpdated(info);
643 info.rtp_timestamp =
644 kExpectedRtpTimestamp; // this frame should be reported in the end.
645 info.capture_time_ms = 0;
646 info.decode_finish_ms = kLongEndToEndDelay;
647 statistics_proxy_->OnTimingFrameInfoUpdated(info);
648 info.rtp_timestamp = kExpectedRtpTimestamp + 1;
649 info.capture_time_ms = 0;
650 info.decode_finish_ms = kMedEndToEndDelay;
651 statistics_proxy_->OnTimingFrameInfoUpdated(info);
Tommi674b0c82020-05-10 21:52:17 +0200652 result = FlushAndGetStats().timing_frame_info;
Tommi74fc5742020-04-27 10:43:06 +0200653 EXPECT_TRUE(result);
654 EXPECT_EQ(kExpectedRtpTimestamp, result->rtp_timestamp);
655}
656
657TEST_F(ReceiveStatisticsProxy2Test, RespectsReportingIntervalForTimingFrames) {
658 TimingFrameInfo info;
659 const int64_t kShortEndToEndDelay = 10;
660 const uint32_t kExpectedRtpTimestamp = 2;
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000661 const TimeDelta kShortDelay = TimeDelta::Seconds(1);
662 const TimeDelta kLongDelay = TimeDelta::Seconds(10);
Tommi74fc5742020-04-27 10:43:06 +0200663 absl::optional<TimingFrameInfo> result;
664 info.rtp_timestamp = kExpectedRtpTimestamp;
665 info.capture_time_ms = 0;
666 info.decode_finish_ms = kShortEndToEndDelay;
667 statistics_proxy_->OnTimingFrameInfoUpdated(info);
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000668 time_controller_.AdvanceTime(kShortDelay);
Tommi674b0c82020-05-10 21:52:17 +0200669 result = FlushAndGetStats().timing_frame_info;
Tommi74fc5742020-04-27 10:43:06 +0200670 EXPECT_TRUE(result);
671 EXPECT_EQ(kExpectedRtpTimestamp, result->rtp_timestamp);
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000672 time_controller_.AdvanceTime(kLongDelay);
Tommi74fc5742020-04-27 10:43:06 +0200673 result = statistics_proxy_->GetStats().timing_frame_info;
674 EXPECT_FALSE(result);
675}
676
677TEST_F(ReceiveStatisticsProxy2Test, LifetimeHistogramIsUpdated) {
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000678 const TimeDelta kLifetime = TimeDelta::Seconds(3);
679 time_controller_.AdvanceTime(kLifetime);
Tommi74fc5742020-04-27 10:43:06 +0200680 // Need at least one frame to report stream lifetime.
681 statistics_proxy_->OnCompleteFrame(true, 1000, VideoContentType::UNSPECIFIED);
682 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
683 nullptr);
684 EXPECT_METRIC_EQ(
685 1, metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
686 EXPECT_METRIC_EQ(
687 1, metrics::NumEvents("WebRTC.Video.ReceiveStreamLifetimeInSeconds",
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000688 kLifetime.seconds()));
Tommi74fc5742020-04-27 10:43:06 +0200689}
690
691TEST_F(ReceiveStatisticsProxy2Test,
692 LifetimeHistogramNotReportedForEmptyStreams) {
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000693 const TimeDelta kLifetime = TimeDelta::Seconds(3);
694 time_controller_.AdvanceTime(kLifetime);
Tommi74fc5742020-04-27 10:43:06 +0200695 // No frames received.
696 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
697 nullptr);
698 EXPECT_METRIC_EQ(
699 0, metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
700}
701
702TEST_F(ReceiveStatisticsProxy2Test, BadCallHistogramsAreUpdated) {
703 // Based on the tuning parameters this will produce 7 uncertain states,
704 // then 10 certainly bad states. There has to be 10 certain states before
705 // any histograms are recorded.
706 const int kNumBadSamples = 17;
707 // We only count one sample per second.
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000708 const TimeDelta kBadFameInterval = TimeDelta::Millis(1100);
Tommi74fc5742020-04-27 10:43:06 +0200709
710 StreamDataCounters counters;
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000711 counters.first_packet_time_ms = Now().ms();
Tommi74fc5742020-04-27 10:43:06 +0200712
713 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
714
715 for (int i = 0; i < kNumBadSamples; ++i) {
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000716 time_controller_.AdvanceTime(kBadFameInterval);
Tommid7e08c82020-05-10 11:24:43 +0200717 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 10:43:06 +0200718 }
719 statistics_proxy_->UpdateHistograms(absl::nullopt, counters, nullptr);
720 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.BadCall.Any"));
721 EXPECT_METRIC_EQ(1, metrics::NumEvents("WebRTC.Video.BadCall.Any", 100));
722
723 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.BadCall.FrameRate"));
724 EXPECT_METRIC_EQ(1,
725 metrics::NumEvents("WebRTC.Video.BadCall.FrameRate", 100));
726
727 EXPECT_METRIC_EQ(
728 0, metrics::NumSamples("WebRTC.Video.BadCall.FrameRateVariance"));
729
730 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.BadCall.Qp"));
731}
732
733TEST_F(ReceiveStatisticsProxy2Test, PacketLossHistogramIsUpdated) {
734 statistics_proxy_->UpdateHistograms(10, StreamDataCounters(), nullptr);
735 EXPECT_METRIC_EQ(
736 0, metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
737
738 // Restart
739 SetUp();
740
741 // Min run time has passed.
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000742 time_controller_.AdvanceTime(
743 TimeDelta::Seconds(metrics::kMinRunTimeInSeconds));
Tommi74fc5742020-04-27 10:43:06 +0200744 statistics_proxy_->UpdateHistograms(10, StreamDataCounters(), nullptr);
745 EXPECT_METRIC_EQ(
746 1, metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
747 EXPECT_METRIC_EQ(
748 1, metrics::NumEvents("WebRTC.Video.ReceivedPacketsLostInPercent", 10));
749}
750
751TEST_F(ReceiveStatisticsProxy2Test, GetStatsReportsPlayoutTimestamp) {
752 const int64_t kVideoNtpMs = 21;
753 const int64_t kSyncOffsetMs = 22;
754 const double kFreqKhz = 90.0;
755 EXPECT_EQ(absl::nullopt,
756 statistics_proxy_->GetStats().estimated_playout_ntp_timestamp_ms);
757 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs, kFreqKhz);
Tommi674b0c82020-05-10 21:52:17 +0200758 EXPECT_EQ(kVideoNtpMs, FlushAndGetStats().estimated_playout_ntp_timestamp_ms);
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000759 time_controller_.AdvanceTime(TimeDelta::Millis(13));
Tommi74fc5742020-04-27 10:43:06 +0200760 EXPECT_EQ(kVideoNtpMs + 13,
761 statistics_proxy_->GetStats().estimated_playout_ntp_timestamp_ms);
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000762 time_controller_.AdvanceTime(TimeDelta::Millis(5));
Tommi74fc5742020-04-27 10:43:06 +0200763 EXPECT_EQ(kVideoNtpMs + 13 + 5,
764 statistics_proxy_->GetStats().estimated_playout_ntp_timestamp_ms);
765}
766
767TEST_F(ReceiveStatisticsProxy2Test, GetStatsReportsAvSyncOffset) {
768 const int64_t kVideoNtpMs = 21;
769 const int64_t kSyncOffsetMs = 22;
770 const double kFreqKhz = 90.0;
771 EXPECT_EQ(std::numeric_limits<int>::max(),
772 statistics_proxy_->GetStats().sync_offset_ms);
773 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs, kFreqKhz);
Tommi674b0c82020-05-10 21:52:17 +0200774 EXPECT_EQ(kSyncOffsetMs, FlushAndGetStats().sync_offset_ms);
Tommi74fc5742020-04-27 10:43:06 +0200775}
776
777TEST_F(ReceiveStatisticsProxy2Test, AvSyncOffsetHistogramIsUpdated) {
778 const int64_t kVideoNtpMs = 21;
779 const int64_t kSyncOffsetMs = 22;
780 const double kFreqKhz = 90.0;
Tommi674b0c82020-05-10 21:52:17 +0200781 for (int i = 0; i < kMinRequiredSamples; ++i) {
Tommi74fc5742020-04-27 10:43:06 +0200782 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs,
783 kFreqKhz);
Tommi674b0c82020-05-10 21:52:17 +0200784 }
785 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 10:43:06 +0200786 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.AVSyncOffsetInMs"));
787 EXPECT_METRIC_EQ(
788 1, metrics::NumEvents("WebRTC.Video.AVSyncOffsetInMs", kSyncOffsetMs));
789}
790
791TEST_F(ReceiveStatisticsProxy2Test, RtpToNtpFrequencyOffsetHistogramIsUpdated) {
792 const int64_t kVideoNtpMs = 21;
793 const int64_t kSyncOffsetMs = 22;
794 const double kFreqKhz = 90.0;
795 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs, kFreqKhz);
796 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs,
797 kFreqKhz + 2.2);
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000798 time_controller_.AdvanceTime(kFreqOffsetProcessInterval);
799 //) Process interval passed, max diff: 2.
Tommi74fc5742020-04-27 10:43:06 +0200800 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs,
801 kFreqKhz + 1.1);
802 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs,
803 kFreqKhz - 4.2);
804 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs,
805 kFreqKhz - 0.9);
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000806 time_controller_.AdvanceTime(kFreqOffsetProcessInterval);
807 //) Process interval passed, max diff: 4.
Tommi74fc5742020-04-27 10:43:06 +0200808 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs, kFreqKhz);
Tommi674b0c82020-05-10 21:52:17 +0200809 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 10:43:06 +0200810 // Average reported: (2 + 4) / 2 = 3.
811 EXPECT_METRIC_EQ(1,
812 metrics::NumSamples("WebRTC.Video.RtpToNtpFreqOffsetInKhz"));
813 EXPECT_METRIC_EQ(
814 1, metrics::NumEvents("WebRTC.Video.RtpToNtpFreqOffsetInKhz", 3));
815}
816
817TEST_F(ReceiveStatisticsProxy2Test, Vp8QpHistogramIsUpdated) {
818 const int kQp = 22;
819
820 for (int i = 0; i < kMinRequiredSamples; ++i)
821 statistics_proxy_->OnPreDecode(kVideoCodecVP8, kQp);
822
Tommi674b0c82020-05-10 21:52:17 +0200823 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 10:43:06 +0200824 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
825 EXPECT_METRIC_EQ(1, metrics::NumEvents("WebRTC.Video.Decoded.Vp8.Qp", kQp));
826}
827
828TEST_F(ReceiveStatisticsProxy2Test,
829 Vp8QpHistogramIsNotUpdatedForTooFewSamples) {
830 const int kQp = 22;
831
832 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
833 statistics_proxy_->OnPreDecode(kVideoCodecVP8, kQp);
834
835 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
836 nullptr);
837 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
838}
839
840TEST_F(ReceiveStatisticsProxy2Test, Vp8QpHistogramIsNotUpdatedIfNoQpValue) {
841 for (int i = 0; i < kMinRequiredSamples; ++i)
842 statistics_proxy_->OnPreDecode(kVideoCodecVP8, -1);
843
844 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
845 nullptr);
846 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
847}
848
849TEST_F(ReceiveStatisticsProxy2Test,
850 KeyFrameHistogramNotUpdatedForTooFewSamples) {
851 const bool kIsKeyFrame = false;
852 const int kFrameSizeBytes = 1000;
853
854 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
855 statistics_proxy_->OnCompleteFrame(kIsKeyFrame, kFrameSizeBytes,
856 VideoContentType::UNSPECIFIED);
857
858 EXPECT_EQ(0, statistics_proxy_->GetStats().frame_counts.key_frames);
859 EXPECT_EQ(kMinRequiredSamples - 1,
860 statistics_proxy_->GetStats().frame_counts.delta_frames);
861
862 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
863 nullptr);
864 EXPECT_METRIC_EQ(
865 0, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
866}
867
868TEST_F(ReceiveStatisticsProxy2Test,
869 KeyFrameHistogramUpdatedForMinRequiredSamples) {
870 const bool kIsKeyFrame = false;
871 const int kFrameSizeBytes = 1000;
872
873 for (int i = 0; i < kMinRequiredSamples; ++i)
874 statistics_proxy_->OnCompleteFrame(kIsKeyFrame, kFrameSizeBytes,
875 VideoContentType::UNSPECIFIED);
876
877 EXPECT_EQ(0, statistics_proxy_->GetStats().frame_counts.key_frames);
878 EXPECT_EQ(kMinRequiredSamples,
879 statistics_proxy_->GetStats().frame_counts.delta_frames);
880
881 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
882 nullptr);
883 EXPECT_METRIC_EQ(
884 1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
885 EXPECT_METRIC_EQ(
886 1, metrics::NumEvents("WebRTC.Video.KeyFramesReceivedInPermille", 0));
887}
888
889TEST_F(ReceiveStatisticsProxy2Test, KeyFrameHistogramIsUpdated) {
890 const int kFrameSizeBytes = 1000;
891
892 for (int i = 0; i < kMinRequiredSamples; ++i)
893 statistics_proxy_->OnCompleteFrame(true, kFrameSizeBytes,
894 VideoContentType::UNSPECIFIED);
895
896 for (int i = 0; i < kMinRequiredSamples; ++i)
897 statistics_proxy_->OnCompleteFrame(false, kFrameSizeBytes,
898 VideoContentType::UNSPECIFIED);
899
900 EXPECT_EQ(kMinRequiredSamples,
901 statistics_proxy_->GetStats().frame_counts.key_frames);
902 EXPECT_EQ(kMinRequiredSamples,
903 statistics_proxy_->GetStats().frame_counts.delta_frames);
904
905 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
906 nullptr);
907 EXPECT_METRIC_EQ(
908 1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
909 EXPECT_METRIC_EQ(
910 1, metrics::NumEvents("WebRTC.Video.KeyFramesReceivedInPermille", 500));
911}
912
913TEST_F(ReceiveStatisticsProxy2Test,
914 TimingHistogramsNotUpdatedForTooFewSamples) {
915 const int kMaxDecodeMs = 2;
916 const int kCurrentDelayMs = 3;
917 const int kTargetDelayMs = 4;
918 const int kJitterBufferMs = 5;
919 const int kMinPlayoutDelayMs = 6;
920 const int kRenderDelayMs = 7;
921
922 for (int i = 0; i < kMinRequiredSamples - 1; ++i) {
923 statistics_proxy_->OnFrameBufferTimingsUpdated(
924 kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs, kJitterBufferMs,
925 kMinPlayoutDelayMs, kRenderDelayMs);
926 }
927
928 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
929 nullptr);
930 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
931 EXPECT_METRIC_EQ(0,
932 metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
933 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
934 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
935 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
936}
937
938TEST_F(ReceiveStatisticsProxy2Test, TimingHistogramsAreUpdated) {
939 const int kMaxDecodeMs = 2;
940 const int kCurrentDelayMs = 3;
941 const int kTargetDelayMs = 4;
942 const int kJitterBufferMs = 5;
943 const int kMinPlayoutDelayMs = 6;
944 const int kRenderDelayMs = 7;
945
946 for (int i = 0; i < kMinRequiredSamples; ++i) {
947 statistics_proxy_->OnFrameBufferTimingsUpdated(
948 kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs, kJitterBufferMs,
949 kMinPlayoutDelayMs, kRenderDelayMs);
950 }
951
Tommi674b0c82020-05-10 21:52:17 +0200952 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 10:43:06 +0200953 EXPECT_METRIC_EQ(1,
954 metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
955 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
956 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
957 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
958
959 EXPECT_METRIC_EQ(1, metrics::NumEvents("WebRTC.Video.JitterBufferDelayInMs",
960 kJitterBufferMs));
961 EXPECT_METRIC_EQ(
962 1, metrics::NumEvents("WebRTC.Video.TargetDelayInMs", kTargetDelayMs));
963 EXPECT_METRIC_EQ(
964 1, metrics::NumEvents("WebRTC.Video.CurrentDelayInMs", kCurrentDelayMs));
965 EXPECT_METRIC_EQ(
966 1, metrics::NumEvents("WebRTC.Video.OnewayDelayInMs", kTargetDelayMs));
967}
968
969TEST_F(ReceiveStatisticsProxy2Test, DoesNotReportStaleFramerates) {
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000970 const Frequency kDefaultFps = Frequency::Hertz(30);
Tommi74fc5742020-04-27 10:43:06 +0200971 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
972
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000973 for (int i = 0; i < kDefaultFps.hertz(); ++i) {
Tommi74fc5742020-04-27 10:43:06 +0200974 // Since OnRenderedFrame is never called the fps in each sample will be 0,
975 // i.e. bad
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000976 frame.set_ntp_time_ms(
977 time_controller_.GetClock()->CurrentNtpInMilliseconds());
Philipp Hanckea204ad22022-07-08 18:43:25 +0200978 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Tommi74fc5742020-04-27 10:43:06 +0200979 VideoContentType::UNSPECIFIED);
Tommid7e08c82020-05-10 11:24:43 +0200980 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000981 time_controller_.AdvanceTime(1 / kDefaultFps);
Tommi74fc5742020-04-27 10:43:06 +0200982 }
983
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000984 // Why -1? Because RateStatistics does not consider the first frame in the
985 // rate as it will appear in the previous bucket.
986 EXPECT_EQ(kDefaultFps.hertz() - 1,
987 statistics_proxy_->GetStats().decode_frame_rate);
988 EXPECT_EQ(kDefaultFps.hertz() - 1,
989 statistics_proxy_->GetStats().render_frame_rate);
Tommi74fc5742020-04-27 10:43:06 +0200990
991 // FPS trackers in stats proxy have a 1000ms sliding window.
Evan Shrubsole1edeb922022-08-08 11:51:26 +0000992 time_controller_.AdvanceTime(TimeDelta::Seconds(1));
Tommi74fc5742020-04-27 10:43:06 +0200993 EXPECT_EQ(0, statistics_proxy_->GetStats().decode_frame_rate);
994 EXPECT_EQ(0, statistics_proxy_->GetStats().render_frame_rate);
995}
996
997TEST_F(ReceiveStatisticsProxy2Test, GetStatsReportsReceivedFrameStats) {
998 EXPECT_EQ(0, statistics_proxy_->GetStats().width);
999 EXPECT_EQ(0, statistics_proxy_->GetStats().height);
1000 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_rendered);
1001
Tommid7e08c82020-05-10 11:24:43 +02001002 statistics_proxy_->OnRenderedFrame(MetaData(CreateFrame(kWidth, kHeight)));
Tommi74fc5742020-04-27 10:43:06 +02001003
1004 EXPECT_EQ(kWidth, statistics_proxy_->GetStats().width);
1005 EXPECT_EQ(kHeight, statistics_proxy_->GetStats().height);
1006 EXPECT_EQ(1u, statistics_proxy_->GetStats().frames_rendered);
1007}
1008
1009TEST_F(ReceiveStatisticsProxy2Test,
1010 ReceivedFrameHistogramsAreNotUpdatedForTooFewSamples) {
Tommid7e08c82020-05-10 11:24:43 +02001011 for (int i = 0; i < kMinRequiredSamples - 1; ++i) {
1012 statistics_proxy_->OnRenderedFrame(MetaData(CreateFrame(kWidth, kHeight)));
1013 }
Tommi74fc5742020-04-27 10:43:06 +02001014
1015 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1016 nullptr);
1017 EXPECT_METRIC_EQ(0,
1018 metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
1019 EXPECT_METRIC_EQ(0,
1020 metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
1021 EXPECT_METRIC_EQ(0,
1022 metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
1023 EXPECT_METRIC_EQ(
1024 0, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
1025}
1026
1027TEST_F(ReceiveStatisticsProxy2Test, ReceivedFrameHistogramsAreUpdated) {
Tommid7e08c82020-05-10 11:24:43 +02001028 for (int i = 0; i < kMinRequiredSamples; ++i) {
1029 statistics_proxy_->OnRenderedFrame(MetaData(CreateFrame(kWidth, kHeight)));
1030 }
Tommi74fc5742020-04-27 10:43:06 +02001031
1032 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1033 nullptr);
1034 EXPECT_METRIC_EQ(1,
1035 metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
1036 EXPECT_METRIC_EQ(1,
1037 metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
1038 EXPECT_METRIC_EQ(1,
1039 metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
1040 EXPECT_METRIC_EQ(
1041 1, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
1042 EXPECT_METRIC_EQ(
1043 1, metrics::NumEvents("WebRTC.Video.ReceivedWidthInPixels", kWidth));
1044 EXPECT_METRIC_EQ(
1045 1, metrics::NumEvents("WebRTC.Video.ReceivedHeightInPixels", kHeight));
1046}
1047
1048TEST_F(ReceiveStatisticsProxy2Test, ZeroDelayReportedIfFrameNotDelayed) {
1049 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Philipp Hanckea204ad22022-07-08 18:43:25 +02001050 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Tommi74fc5742020-04-27 10:43:06 +02001051 VideoContentType::UNSPECIFIED);
1052
1053 // Frame not delayed, delayed frames to render: 0%.
Tommid7e08c82020-05-10 11:24:43 +02001054 statistics_proxy_->OnRenderedFrame(
1055 MetaData(CreateFrameWithRenderTime(Now())));
Tommi74fc5742020-04-27 10:43:06 +02001056
1057 // Min run time has passed.
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001058 time_controller_.AdvanceTime(
1059 TimeDelta::Seconds((metrics::kMinRunTimeInSeconds)));
Tommid93bf122020-05-10 20:24:59 +02001060 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 10:43:06 +02001061 EXPECT_METRIC_EQ(1,
1062 metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
1063 EXPECT_METRIC_EQ(
1064 1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 0));
1065 EXPECT_METRIC_EQ(0, metrics::NumSamples(
1066 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
1067}
1068
1069TEST_F(ReceiveStatisticsProxy2Test,
1070 DelayedFrameHistogramsAreNotUpdatedIfMinRuntimeHasNotPassed) {
1071 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Philipp Hanckea204ad22022-07-08 18:43:25 +02001072 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Tommi74fc5742020-04-27 10:43:06 +02001073 VideoContentType::UNSPECIFIED);
1074
1075 // Frame not delayed, delayed frames to render: 0%.
Tommid7e08c82020-05-10 11:24:43 +02001076 statistics_proxy_->OnRenderedFrame(
1077 MetaData(CreateFrameWithRenderTime(Now())));
Tommi74fc5742020-04-27 10:43:06 +02001078
1079 // Min run time has not passed.
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001080 time_controller_.AdvanceTime(
1081 TimeDelta::Seconds(metrics::kMinRunTimeInSeconds) - TimeDelta::Millis(1));
Tommi74fc5742020-04-27 10:43:06 +02001082 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1083 nullptr);
1084 EXPECT_METRIC_EQ(0,
1085 metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
1086 EXPECT_METRIC_EQ(0, metrics::NumSamples(
1087 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
1088}
1089
1090TEST_F(ReceiveStatisticsProxy2Test,
1091 DelayedFramesHistogramsAreNotUpdatedIfNoRenderedFrames) {
1092 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Philipp Hanckea204ad22022-07-08 18:43:25 +02001093 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Tommi74fc5742020-04-27 10:43:06 +02001094 VideoContentType::UNSPECIFIED);
1095
1096 // Min run time has passed. No rendered frames.
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001097 time_controller_.AdvanceTime(
1098 TimeDelta::Seconds((metrics::kMinRunTimeInSeconds)));
Tommi74fc5742020-04-27 10:43:06 +02001099 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1100 nullptr);
1101 EXPECT_METRIC_EQ(0,
1102 metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
1103 EXPECT_METRIC_EQ(0, metrics::NumSamples(
1104 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
1105}
1106
1107TEST_F(ReceiveStatisticsProxy2Test, DelayReportedIfFrameIsDelayed) {
1108 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Philipp Hanckea204ad22022-07-08 18:43:25 +02001109 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Tommi74fc5742020-04-27 10:43:06 +02001110 VideoContentType::UNSPECIFIED);
1111
1112 // Frame delayed 1 ms, delayed frames to render: 100%.
Tommid7e08c82020-05-10 11:24:43 +02001113 statistics_proxy_->OnRenderedFrame(
1114 MetaData(CreateFrameWithRenderTimeMs(Now().ms() - 1)));
Tommi74fc5742020-04-27 10:43:06 +02001115
1116 // Min run time has passed.
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001117 time_controller_.AdvanceTime(
1118 TimeDelta::Seconds(metrics::kMinRunTimeInSeconds));
Tommid93bf122020-05-10 20:24:59 +02001119 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 10:43:06 +02001120 EXPECT_METRIC_EQ(1,
1121 metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
1122 EXPECT_METRIC_EQ(
1123 1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 100));
1124 EXPECT_METRIC_EQ(1, metrics::NumSamples(
1125 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
1126 EXPECT_METRIC_EQ(
1127 1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs",
1128 1));
1129}
1130
1131TEST_F(ReceiveStatisticsProxy2Test, AverageDelayOfDelayedFramesIsReported) {
1132 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Philipp Hanckea204ad22022-07-08 18:43:25 +02001133 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Tommi74fc5742020-04-27 10:43:06 +02001134 VideoContentType::UNSPECIFIED);
1135
1136 // Two frames delayed (6 ms, 10 ms), delayed frames to render: 50%.
Tommid7e08c82020-05-10 11:24:43 +02001137 const int64_t kNowMs = Now().ms();
1138
1139 statistics_proxy_->OnRenderedFrame(
1140 MetaData(CreateFrameWithRenderTimeMs(kNowMs - 10)));
1141 statistics_proxy_->OnRenderedFrame(
1142 MetaData(CreateFrameWithRenderTimeMs(kNowMs - 6)));
1143 statistics_proxy_->OnRenderedFrame(
1144 MetaData(CreateFrameWithRenderTimeMs(kNowMs)));
1145 statistics_proxy_->OnRenderedFrame(
1146 MetaData(CreateFrameWithRenderTimeMs(kNowMs + 1)));
Tommi74fc5742020-04-27 10:43:06 +02001147
1148 // Min run time has passed.
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001149 time_controller_.AdvanceTime(
1150 TimeDelta::Seconds(metrics::kMinRunTimeInSeconds));
Tommid93bf122020-05-10 20:24:59 +02001151 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 10:43:06 +02001152 EXPECT_METRIC_EQ(1,
1153 metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
1154 EXPECT_METRIC_EQ(
1155 1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 50));
1156 EXPECT_METRIC_EQ(1, metrics::NumSamples(
1157 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
1158 EXPECT_METRIC_EQ(
1159 1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs",
1160 8));
1161}
1162
1163TEST_F(ReceiveStatisticsProxy2Test,
1164 RtcpHistogramsNotUpdatedIfMinRuntimeHasNotPassed) {
1165 StreamDataCounters data_counters;
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001166 data_counters.first_packet_time_ms =
1167 time_controller_.GetClock()->TimeInMilliseconds();
Tommi74fc5742020-04-27 10:43:06 +02001168
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001169 time_controller_.AdvanceTime(
1170 TimeDelta::Seconds(metrics::kMinRunTimeInSeconds) - TimeDelta::Millis(1));
Tommi74fc5742020-04-27 10:43:06 +02001171
1172 RtcpPacketTypeCounter counter;
1173 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
1174
1175 statistics_proxy_->UpdateHistograms(absl::nullopt, data_counters, nullptr);
1176 EXPECT_METRIC_EQ(0,
1177 metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
1178 EXPECT_METRIC_EQ(0,
1179 metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
1180 EXPECT_METRIC_EQ(
1181 0, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
1182}
1183
1184TEST_F(ReceiveStatisticsProxy2Test, RtcpHistogramsAreUpdated) {
1185 StreamDataCounters data_counters;
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001186 data_counters.first_packet_time_ms =
1187 time_controller_.GetClock()->TimeInMilliseconds();
1188 time_controller_.AdvanceTime(
1189 TimeDelta::Seconds(metrics::kMinRunTimeInSeconds));
Tommi74fc5742020-04-27 10:43:06 +02001190
1191 const uint32_t kFirPackets = 100;
1192 const uint32_t kPliPackets = 200;
1193 const uint32_t kNackPackets = 300;
1194
1195 RtcpPacketTypeCounter counter;
1196 counter.fir_packets = kFirPackets;
1197 counter.pli_packets = kPliPackets;
1198 counter.nack_packets = kNackPackets;
1199 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
1200
1201 statistics_proxy_->UpdateHistograms(absl::nullopt, data_counters, nullptr);
1202 EXPECT_METRIC_EQ(1,
1203 metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
1204 EXPECT_METRIC_EQ(1,
1205 metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
1206 EXPECT_METRIC_EQ(
1207 1, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
1208 EXPECT_METRIC_EQ(
1209 1, metrics::NumEvents("WebRTC.Video.FirPacketsSentPerMinute",
1210 kFirPackets * 60 / metrics::kMinRunTimeInSeconds));
1211 EXPECT_METRIC_EQ(
1212 1, metrics::NumEvents("WebRTC.Video.PliPacketsSentPerMinute",
1213 kPliPackets * 60 / metrics::kMinRunTimeInSeconds));
1214 EXPECT_METRIC_EQ(
1215 1, metrics::NumEvents("WebRTC.Video.NackPacketsSentPerMinute",
1216 kNackPackets * 60 / metrics::kMinRunTimeInSeconds));
1217}
1218
1219class ReceiveStatisticsProxy2TestWithFreezeDuration
1220 : public ReceiveStatisticsProxy2Test,
1221 public ::testing::WithParamInterface<
1222 std::tuple<uint32_t, uint32_t, uint32_t>> {
1223 protected:
1224 const uint32_t frame_duration_ms_ = {std::get<0>(GetParam())};
1225 const uint32_t freeze_duration_ms_ = {std::get<1>(GetParam())};
1226 const uint32_t expected_freeze_count_ = {std::get<2>(GetParam())};
1227};
1228
1229// It is a freeze if:
1230// frame_duration_ms >= max(3 * avg_frame_duration, avg_frame_duration + 150)
1231// where avg_frame_duration is average duration of last 30 frames including
1232// the current one.
1233//
1234// Condition 1: 3 * avg_frame_duration > avg_frame_duration + 150
1235const auto kFreezeDetectionCond1Freeze = std::make_tuple(150, 483, 1);
1236const auto kFreezeDetectionCond1NotFreeze = std::make_tuple(150, 482, 0);
1237// Condition 2: 3 * avg_frame_duration < avg_frame_duration + 150
1238const auto kFreezeDetectionCond2Freeze = std::make_tuple(30, 185, 1);
1239const auto kFreezeDetectionCond2NotFreeze = std::make_tuple(30, 184, 0);
1240
1241INSTANTIATE_TEST_SUITE_P(_,
1242 ReceiveStatisticsProxy2TestWithFreezeDuration,
1243 ::testing::Values(kFreezeDetectionCond1Freeze,
1244 kFreezeDetectionCond1NotFreeze,
1245 kFreezeDetectionCond2Freeze,
1246 kFreezeDetectionCond2NotFreeze));
1247
1248TEST_P(ReceiveStatisticsProxy2TestWithFreezeDuration, FreezeDetection) {
Tommif6f45432022-05-20 15:21:20 +02001249 VideoReceiveStreamInterface::Stats stats = statistics_proxy_->GetStats();
Tommi74fc5742020-04-27 10:43:06 +02001250 EXPECT_EQ(0u, stats.freeze_count);
1251 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1252
1253 // Add a very long frame. This is need to verify that average frame
1254 // duration, which is supposed to be calculated as mean of durations of
1255 // last 30 frames, is calculated correctly.
Tommid7e08c82020-05-10 11:24:43 +02001256 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001257 time_controller_.AdvanceTime(TimeDelta::Seconds(2));
Tommi74fc5742020-04-27 10:43:06 +02001258 for (size_t i = 0;
1259 i <= VideoQualityObserver::kAvgInterframeDelaysWindowSizeFrames; ++i) {
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001260 time_controller_.AdvanceTime(TimeDelta::Millis(frame_duration_ms_));
Tommid7e08c82020-05-10 11:24:43 +02001261 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 10:43:06 +02001262 }
1263
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001264 time_controller_.AdvanceTime(TimeDelta::Millis(freeze_duration_ms_));
Tommid7e08c82020-05-10 11:24:43 +02001265 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 10:43:06 +02001266
1267 stats = statistics_proxy_->GetStats();
1268 EXPECT_EQ(stats.freeze_count, expected_freeze_count_);
1269}
1270
1271class ReceiveStatisticsProxy2TestWithContent
1272 : public ReceiveStatisticsProxy2Test,
1273 public ::testing::WithParamInterface<webrtc::VideoContentType> {
1274 protected:
1275 const webrtc::VideoContentType content_type_{GetParam()};
1276};
1277
1278INSTANTIATE_TEST_SUITE_P(ContentTypes,
1279 ReceiveStatisticsProxy2TestWithContent,
1280 ::testing::Values(VideoContentType::UNSPECIFIED,
1281 VideoContentType::SCREENSHARE));
1282
1283TEST_P(ReceiveStatisticsProxy2TestWithContent, InterFrameDelaysAreReported) {
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001284 const TimeDelta kInterFrameDelay = TimeDelta::Millis(33);
Tommi74fc5742020-04-27 10:43:06 +02001285 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1286
1287 for (int i = 0; i < kMinRequiredSamples; ++i) {
Philipp Hanckea204ad22022-07-08 18:43:25 +02001288 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
1289 content_type_);
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001290 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 10:43:06 +02001291 }
1292 // One extra with double the interval.
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001293 time_controller_.AdvanceTime(kInterFrameDelay);
Philipp Hanckea204ad22022-07-08 18:43:25 +02001294 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Philipp Hancked970b092022-06-17 07:34:23 +02001295 content_type_);
Tommi74fc5742020-04-27 10:43:06 +02001296
Tommid93bf122020-05-10 20:24:59 +02001297 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001298 const TimeDelta kExpectedInterFrame =
1299 (kInterFrameDelay * (kMinRequiredSamples - 1) + kInterFrameDelay * 2) /
Tommi74fc5742020-04-27 10:43:06 +02001300 kMinRequiredSamples;
1301 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
1302 EXPECT_METRIC_EQ(
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001303 kExpectedInterFrame.ms(),
Tommi74fc5742020-04-27 10:43:06 +02001304 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1305 EXPECT_METRIC_EQ(
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001306 kInterFrameDelay.ms() * 2,
Tommi74fc5742020-04-27 10:43:06 +02001307 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1308 } else {
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001309 EXPECT_METRIC_EQ(kExpectedInterFrame.ms(),
Tommi74fc5742020-04-27 10:43:06 +02001310 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001311 EXPECT_METRIC_EQ(kInterFrameDelay.ms() * 2,
Tommi74fc5742020-04-27 10:43:06 +02001312 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
1313 }
1314}
1315
1316TEST_P(ReceiveStatisticsProxy2TestWithContent,
1317 InterFrameDelaysPercentilesAreReported) {
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001318 const TimeDelta kInterFrameDelay = TimeDelta::Millis(33);
Tommi74fc5742020-04-27 10:43:06 +02001319 const int kLastFivePercentsSamples = kMinRequiredSamples * 5 / 100;
1320 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1321
1322 for (int i = 0; i <= kMinRequiredSamples - kLastFivePercentsSamples; ++i) {
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001323 time_controller_.AdvanceTime(kInterFrameDelay);
Philipp Hanckea204ad22022-07-08 18:43:25 +02001324 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
1325 content_type_);
Tommi74fc5742020-04-27 10:43:06 +02001326 }
1327 // Last 5% of intervals are double in size.
1328 for (int i = 0; i < kLastFivePercentsSamples; ++i) {
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001329 time_controller_.AdvanceTime(2 * kInterFrameDelay);
Philipp Hanckea204ad22022-07-08 18:43:25 +02001330 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
1331 content_type_);
Tommi74fc5742020-04-27 10:43:06 +02001332 }
1333 // Final sample is outlier and 10 times as big.
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001334 time_controller_.AdvanceTime(10 * kInterFrameDelay);
Philipp Hanckea204ad22022-07-08 18:43:25 +02001335 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Philipp Hancked970b092022-06-17 07:34:23 +02001336 content_type_);
Tommi74fc5742020-04-27 10:43:06 +02001337
Tommid93bf122020-05-10 20:24:59 +02001338 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001339 const TimeDelta kExpectedInterFrame = kInterFrameDelay * 2;
Tommi74fc5742020-04-27 10:43:06 +02001340 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
1341 EXPECT_METRIC_EQ(
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001342 kExpectedInterFrame.ms(),
Tommi74fc5742020-04-27 10:43:06 +02001343 metrics::MinSample(
1344 "WebRTC.Video.Screenshare.InterframeDelay95PercentileInMs"));
1345 } else {
1346 EXPECT_METRIC_EQ(
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001347 kExpectedInterFrame.ms(),
Tommi74fc5742020-04-27 10:43:06 +02001348 metrics::MinSample("WebRTC.Video.InterframeDelay95PercentileInMs"));
1349 }
1350}
1351
1352TEST_P(ReceiveStatisticsProxy2TestWithContent,
1353 MaxInterFrameDelayOnlyWithValidAverage) {
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001354 const TimeDelta kInterFrameDelay = TimeDelta::Millis(33);
Tommi74fc5742020-04-27 10:43:06 +02001355 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1356
1357 for (int i = 0; i < kMinRequiredSamples; ++i) {
Philipp Hanckea204ad22022-07-08 18:43:25 +02001358 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
1359 content_type_);
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001360 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 10:43:06 +02001361 }
1362
Artem Titovab30d722021-07-27 16:22:11 +02001363 // `kMinRequiredSamples` samples, and thereby intervals, is required. That
Tommi74fc5742020-04-27 10:43:06 +02001364 // means we're one frame short of having a valid data set.
1365 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1366 nullptr);
1367 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
1368 EXPECT_METRIC_EQ(0,
1369 metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
1370 EXPECT_METRIC_EQ(
1371 0, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1372 EXPECT_METRIC_EQ(0, metrics::NumSamples(
1373 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1374}
1375
1376TEST_P(ReceiveStatisticsProxy2TestWithContent,
1377 MaxInterFrameDelayOnlyWithPause) {
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001378 const TimeDelta kInterFrameDelay = TimeDelta::Millis(33);
Tommi74fc5742020-04-27 10:43:06 +02001379 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1380
1381 for (int i = 0; i <= kMinRequiredSamples; ++i) {
Philipp Hanckea204ad22022-07-08 18:43:25 +02001382 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
1383 content_type_);
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001384 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 10:43:06 +02001385 }
1386
1387 // At this state, we should have a valid inter-frame delay.
1388 // Indicate stream paused and make a large jump in time.
1389 statistics_proxy_->OnStreamInactive();
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001390 time_controller_.AdvanceTime(TimeDelta::Seconds(5));
Tommid7e08c82020-05-10 11:24:43 +02001391 // Insert two more frames. The interval during the pause should be
1392 // disregarded in the stats.
Philipp Hanckea204ad22022-07-08 18:43:25 +02001393 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Philipp Hancked970b092022-06-17 07:34:23 +02001394 content_type_);
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001395 time_controller_.AdvanceTime(kInterFrameDelay);
Philipp Hanckea204ad22022-07-08 18:43:25 +02001396 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Philipp Hancked970b092022-06-17 07:34:23 +02001397 content_type_);
Tommi74fc5742020-04-27 10:43:06 +02001398
Tommid93bf122020-05-10 20:24:59 +02001399 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 10:43:06 +02001400 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
1401 EXPECT_METRIC_EQ(
1402 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1403 EXPECT_METRIC_EQ(1, metrics::NumSamples(
1404 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1405 EXPECT_METRIC_EQ(
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001406 kInterFrameDelay.ms(),
Tommi74fc5742020-04-27 10:43:06 +02001407 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1408 EXPECT_METRIC_EQ(
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001409 kInterFrameDelay.ms(),
Tommi74fc5742020-04-27 10:43:06 +02001410 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1411 } else {
1412 EXPECT_METRIC_EQ(1,
1413 metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
1414 EXPECT_METRIC_EQ(
1415 1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001416 EXPECT_METRIC_EQ(kInterFrameDelay.ms(),
Tommi74fc5742020-04-27 10:43:06 +02001417 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001418 EXPECT_METRIC_EQ(kInterFrameDelay.ms(),
Tommi74fc5742020-04-27 10:43:06 +02001419 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
1420 }
1421}
1422
1423TEST_P(ReceiveStatisticsProxy2TestWithContent, FreezesAreReported) {
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001424 const TimeDelta kInterFrameDelay = TimeDelta::Millis(33);
1425 const TimeDelta kFreezeDelay = TimeDelta::Millis(200);
1426 const TimeDelta kCallDuration =
1427 kMinRequiredSamples * kInterFrameDelay + kFreezeDelay;
Tommi74fc5742020-04-27 10:43:06 +02001428 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1429
1430 for (int i = 0; i < kMinRequiredSamples; ++i) {
Tommid93bf122020-05-10 20:24:59 +02001431 VideoFrameMetaData meta = MetaData(frame);
Philipp Hanckea204ad22022-07-08 18:43:25 +02001432 statistics_proxy_->OnDecodedFrame(meta, absl::nullopt, TimeDelta::Zero(),
1433 TimeDelta::Zero(), TimeDelta::Zero(),
1434 content_type_);
Tommid93bf122020-05-10 20:24:59 +02001435 statistics_proxy_->OnRenderedFrame(meta);
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001436 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 10:43:06 +02001437 }
1438 // Add extra freeze.
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001439 time_controller_.AdvanceTime(kFreezeDelay);
Tommid93bf122020-05-10 20:24:59 +02001440 VideoFrameMetaData meta = MetaData(frame);
Philipp Hanckea204ad22022-07-08 18:43:25 +02001441 statistics_proxy_->OnDecodedFrame(meta, absl::nullopt, TimeDelta::Zero(),
1442 TimeDelta::Zero(), TimeDelta::Zero(),
1443 content_type_);
Tommid93bf122020-05-10 20:24:59 +02001444 statistics_proxy_->OnRenderedFrame(meta);
Tommi74fc5742020-04-27 10:43:06 +02001445
Tommid93bf122020-05-10 20:24:59 +02001446 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001447 const TimeDelta kExpectedTimeBetweenFreezes =
1448 kInterFrameDelay * (kMinRequiredSamples - 1);
1449 const int kExpectedNumberFreezesPerMinute = 60 / kCallDuration.seconds();
Tommi74fc5742020-04-27 10:43:06 +02001450 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
1451 EXPECT_METRIC_EQ(
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001452 (kFreezeDelay + kInterFrameDelay).ms(),
Tommi74fc5742020-04-27 10:43:06 +02001453 metrics::MinSample("WebRTC.Video.Screenshare.MeanFreezeDurationMs"));
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001454 EXPECT_METRIC_EQ(kExpectedTimeBetweenFreezes.ms(),
Tommi74fc5742020-04-27 10:43:06 +02001455 metrics::MinSample(
1456 "WebRTC.Video.Screenshare.MeanTimeBetweenFreezesMs"));
1457 EXPECT_METRIC_EQ(
1458 kExpectedNumberFreezesPerMinute,
1459 metrics::MinSample("WebRTC.Video.Screenshare.NumberFreezesPerMinute"));
1460 } else {
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001461 EXPECT_METRIC_EQ((kFreezeDelay + kInterFrameDelay).ms(),
Tommi74fc5742020-04-27 10:43:06 +02001462 metrics::MinSample("WebRTC.Video.MeanFreezeDurationMs"));
1463 EXPECT_METRIC_EQ(
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001464 kExpectedTimeBetweenFreezes.ms(),
Tommi74fc5742020-04-27 10:43:06 +02001465 metrics::MinSample("WebRTC.Video.MeanTimeBetweenFreezesMs"));
1466 EXPECT_METRIC_EQ(kExpectedNumberFreezesPerMinute,
1467 metrics::MinSample("WebRTC.Video.NumberFreezesPerMinute"));
1468 }
1469}
1470
1471TEST_P(ReceiveStatisticsProxy2TestWithContent, HarmonicFrameRateIsReported) {
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001472 const TimeDelta kFrameDuration = TimeDelta::Millis(33);
1473 const TimeDelta kFreezeDuration = TimeDelta::Millis(200);
1474 const TimeDelta kPauseDuration = TimeDelta::Seconds(10);
1475 const TimeDelta kCallDuration =
1476 kMinRequiredSamples * kFrameDuration + kFreezeDuration + kPauseDuration;
Tommi74fc5742020-04-27 10:43:06 +02001477 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1478
1479 for (int i = 0; i < kMinRequiredSamples; ++i) {
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001480 time_controller_.AdvanceTime(kFrameDuration);
Philipp Hanckea204ad22022-07-08 18:43:25 +02001481 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
1482 content_type_);
Tommid7e08c82020-05-10 11:24:43 +02001483 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 10:43:06 +02001484 }
1485
1486 // Freezes and pauses should be included into harmonic frame rate.
1487 // Add freeze.
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001488 time_controller_.AdvanceTime(kFreezeDuration);
Philipp Hanckea204ad22022-07-08 18:43:25 +02001489 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Philipp Hancked970b092022-06-17 07:34:23 +02001490 content_type_);
Tommid7e08c82020-05-10 11:24:43 +02001491 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 10:43:06 +02001492
1493 // Add pause.
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001494 time_controller_.AdvanceTime(kPauseDuration);
Tommi74fc5742020-04-27 10:43:06 +02001495 statistics_proxy_->OnStreamInactive();
Philipp Hanckea204ad22022-07-08 18:43:25 +02001496 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Philipp Hancked970b092022-06-17 07:34:23 +02001497 content_type_);
Tommid7e08c82020-05-10 11:24:43 +02001498 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 10:43:06 +02001499
Tommid93bf122020-05-10 20:24:59 +02001500 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 10:43:06 +02001501 double kSumSquaredFrameDurationSecs =
1502 (kMinRequiredSamples - 1) *
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001503 (kFrameDuration.seconds<double>() * kFrameDuration.seconds<double>());
Tommi74fc5742020-04-27 10:43:06 +02001504 kSumSquaredFrameDurationSecs +=
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001505 kFreezeDuration.seconds<double>() * kFreezeDuration.seconds<double>();
Tommi74fc5742020-04-27 10:43:06 +02001506 kSumSquaredFrameDurationSecs +=
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001507 kPauseDuration.seconds<double>() * kPauseDuration.seconds<double>();
1508 const int kExpectedHarmonicFrameRateFps = std::round(
1509 kCallDuration.seconds<double>() / kSumSquaredFrameDurationSecs);
Tommi74fc5742020-04-27 10:43:06 +02001510 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
1511 EXPECT_METRIC_EQ(
1512 kExpectedHarmonicFrameRateFps,
1513 metrics::MinSample("WebRTC.Video.Screenshare.HarmonicFrameRate"));
1514 } else {
1515 EXPECT_METRIC_EQ(kExpectedHarmonicFrameRateFps,
1516 metrics::MinSample("WebRTC.Video.HarmonicFrameRate"));
1517 }
1518}
1519
1520TEST_P(ReceiveStatisticsProxy2TestWithContent, PausesAreIgnored) {
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001521 const TimeDelta kInterFrameDelay = TimeDelta::Millis(33);
1522 const TimeDelta kPauseDuration = TimeDelta::Seconds(10);
Tommi74fc5742020-04-27 10:43:06 +02001523 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1524
1525 for (int i = 0; i <= kMinRequiredSamples; ++i) {
Tommid93bf122020-05-10 20:24:59 +02001526 VideoFrameMetaData meta = MetaData(frame);
Philipp Hanckea204ad22022-07-08 18:43:25 +02001527 statistics_proxy_->OnDecodedFrame(meta, absl::nullopt, TimeDelta::Zero(),
1528 TimeDelta::Zero(), TimeDelta::Zero(),
1529 content_type_);
Tommid93bf122020-05-10 20:24:59 +02001530 statistics_proxy_->OnRenderedFrame(meta);
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001531 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 10:43:06 +02001532 }
1533 // Add a pause.
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001534 time_controller_.AdvanceTime(kPauseDuration);
Tommi74fc5742020-04-27 10:43:06 +02001535 statistics_proxy_->OnStreamInactive();
Tommi74fc5742020-04-27 10:43:06 +02001536 // Second playback interval with triple the length.
1537 for (int i = 0; i <= kMinRequiredSamples * 3; ++i) {
Tommid93bf122020-05-10 20:24:59 +02001538 VideoFrameMetaData meta = MetaData(frame);
Philipp Hanckea204ad22022-07-08 18:43:25 +02001539 statistics_proxy_->OnDecodedFrame(meta, absl::nullopt, TimeDelta::Zero(),
1540 TimeDelta::Zero(), TimeDelta::Zero(),
1541 content_type_);
Tommid93bf122020-05-10 20:24:59 +02001542 statistics_proxy_->OnRenderedFrame(meta);
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001543 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 10:43:06 +02001544 }
1545
Tommid93bf122020-05-10 20:24:59 +02001546 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 10:43:06 +02001547 // Average of two playback intervals.
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001548 const TimeDelta kExpectedTimeBetweenFreezes =
1549 kInterFrameDelay * kMinRequiredSamples * 2;
Tommi74fc5742020-04-27 10:43:06 +02001550 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
1551 EXPECT_METRIC_EQ(-1, metrics::MinSample(
1552 "WebRTC.Video.Screenshare.MeanFreezeDurationMs"));
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001553 EXPECT_METRIC_EQ(kExpectedTimeBetweenFreezes.ms(),
Tommi74fc5742020-04-27 10:43:06 +02001554 metrics::MinSample(
1555 "WebRTC.Video.Screenshare.MeanTimeBetweenFreezesMs"));
1556 } else {
1557 EXPECT_METRIC_EQ(-1,
1558 metrics::MinSample("WebRTC.Video.MeanFreezeDurationMs"));
1559 EXPECT_METRIC_EQ(
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001560 kExpectedTimeBetweenFreezes.ms(),
Tommi74fc5742020-04-27 10:43:06 +02001561 metrics::MinSample("WebRTC.Video.MeanTimeBetweenFreezesMs"));
1562 }
1563}
1564
1565TEST_P(ReceiveStatisticsProxy2TestWithContent, ManyPausesAtTheBeginning) {
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001566 const TimeDelta kInterFrameDelay = TimeDelta::Millis(33);
1567 const TimeDelta kPauseDuration = TimeDelta::Seconds(10);
Tommi74fc5742020-04-27 10:43:06 +02001568 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1569
1570 for (int i = 0; i <= kMinRequiredSamples; ++i) {
Philipp Hanckea204ad22022-07-08 18:43:25 +02001571 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
1572 content_type_);
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001573 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 10:43:06 +02001574 statistics_proxy_->OnStreamInactive();
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001575 time_controller_.AdvanceTime(kPauseDuration);
Philipp Hanckea204ad22022-07-08 18:43:25 +02001576 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
1577 content_type_);
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001578 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 10:43:06 +02001579 }
1580
1581 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1582 nullptr);
Tommid7e08c82020-05-10 11:24:43 +02001583 // No freezes should be detected, as all long inter-frame delays were
1584 // pauses.
Tommi74fc5742020-04-27 10:43:06 +02001585 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
1586 EXPECT_METRIC_EQ(-1, metrics::MinSample(
1587 "WebRTC.Video.Screenshare.MeanFreezeDurationMs"));
1588 } else {
1589 EXPECT_METRIC_EQ(-1,
1590 metrics::MinSample("WebRTC.Video.MeanFreezeDurationMs"));
1591 }
1592}
1593
1594TEST_P(ReceiveStatisticsProxy2TestWithContent, TimeInHdReported) {
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001595 const TimeDelta kInterFrameDelay = TimeDelta::Millis(20);
Tommi74fc5742020-04-27 10:43:06 +02001596 webrtc::VideoFrame frame_hd = CreateFrame(1280, 720);
1597 webrtc::VideoFrame frame_sd = CreateFrame(640, 360);
1598
1599 // HD frames.
1600 for (int i = 0; i < kMinRequiredSamples; ++i) {
Tommid93bf122020-05-10 20:24:59 +02001601 VideoFrameMetaData meta = MetaData(frame_hd);
Philipp Hanckea204ad22022-07-08 18:43:25 +02001602 statistics_proxy_->OnDecodedFrame(meta, absl::nullopt, TimeDelta::Zero(),
1603 TimeDelta::Zero(), TimeDelta::Zero(),
1604 content_type_);
Tommid93bf122020-05-10 20:24:59 +02001605 statistics_proxy_->OnRenderedFrame(meta);
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001606 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 10:43:06 +02001607 }
1608 // SD frames.
1609 for (int i = 0; i < 2 * kMinRequiredSamples; ++i) {
Tommid93bf122020-05-10 20:24:59 +02001610 VideoFrameMetaData meta = MetaData(frame_sd);
Philipp Hanckea204ad22022-07-08 18:43:25 +02001611 statistics_proxy_->OnDecodedFrame(meta, absl::nullopt, TimeDelta::Zero(),
1612 TimeDelta::Zero(), TimeDelta::Zero(),
1613 content_type_);
Tommid93bf122020-05-10 20:24:59 +02001614 statistics_proxy_->OnRenderedFrame(meta);
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001615 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 10:43:06 +02001616 }
1617 // Extra last frame.
Tommid7e08c82020-05-10 11:24:43 +02001618 statistics_proxy_->OnRenderedFrame(MetaData(frame_sd));
Tommi74fc5742020-04-27 10:43:06 +02001619
1620 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1621 nullptr);
1622 const int kExpectedTimeInHdPercents = 33;
1623 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
1624 EXPECT_METRIC_EQ(
1625 kExpectedTimeInHdPercents,
1626 metrics::MinSample("WebRTC.Video.Screenshare.TimeInHdPercentage"));
1627 } else {
1628 EXPECT_METRIC_EQ(kExpectedTimeInHdPercents,
1629 metrics::MinSample("WebRTC.Video.TimeInHdPercentage"));
1630 }
1631}
1632
1633TEST_P(ReceiveStatisticsProxy2TestWithContent, TimeInBlockyVideoReported) {
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001634 const TimeDelta kInterFrameDelay = TimeDelta::Millis(20);
Tommi74fc5742020-04-27 10:43:06 +02001635 const int kHighQp = 80;
1636 const int kLowQp = 30;
1637 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1638
1639 // High quality frames.
1640 for (int i = 0; i < kMinRequiredSamples; ++i) {
Tommid93bf122020-05-10 20:24:59 +02001641 VideoFrameMetaData meta = MetaData(frame);
Philipp Hanckea204ad22022-07-08 18:43:25 +02001642 statistics_proxy_->OnDecodedFrame(meta, kLowQp, TimeDelta::Zero(),
1643 TimeDelta::Zero(), TimeDelta::Zero(),
1644 content_type_);
Tommid93bf122020-05-10 20:24:59 +02001645 statistics_proxy_->OnRenderedFrame(meta);
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001646 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 10:43:06 +02001647 }
1648 // Blocky frames.
1649 for (int i = 0; i < 2 * kMinRequiredSamples; ++i) {
Tommid93bf122020-05-10 20:24:59 +02001650 VideoFrameMetaData meta = MetaData(frame);
Philipp Hanckea204ad22022-07-08 18:43:25 +02001651 statistics_proxy_->OnDecodedFrame(meta, kHighQp, TimeDelta::Zero(),
1652 TimeDelta::Zero(), TimeDelta::Zero(),
1653 content_type_);
Tommid93bf122020-05-10 20:24:59 +02001654 statistics_proxy_->OnRenderedFrame(meta);
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001655 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 10:43:06 +02001656 }
1657 // Extra last frame.
Philipp Hanckea204ad22022-07-08 18:43:25 +02001658 statistics_proxy_->OnDecodedFrame(frame, kHighQp, TimeDelta::Zero(),
Philipp Hancked970b092022-06-17 07:34:23 +02001659 content_type_);
Tommid7e08c82020-05-10 11:24:43 +02001660 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 10:43:06 +02001661
Tommid93bf122020-05-10 20:24:59 +02001662 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 10:43:06 +02001663 const int kExpectedTimeInHdPercents = 66;
1664 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
1665 EXPECT_METRIC_EQ(
1666 kExpectedTimeInHdPercents,
1667 metrics::MinSample(
1668 "WebRTC.Video.Screenshare.TimeInBlockyVideoPercentage"));
1669 } else {
1670 EXPECT_METRIC_EQ(
1671 kExpectedTimeInHdPercents,
1672 metrics::MinSample("WebRTC.Video.TimeInBlockyVideoPercentage"));
1673 }
1674}
1675
1676TEST_P(ReceiveStatisticsProxy2TestWithContent, DownscalesReported) {
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001677 // To ensure long enough call duration.
1678 const TimeDelta kInterFrameDelay = TimeDelta::Seconds(2);
Tommi74fc5742020-04-27 10:43:06 +02001679
1680 webrtc::VideoFrame frame_hd = CreateFrame(1280, 720);
1681 webrtc::VideoFrame frame_sd = CreateFrame(640, 360);
1682 webrtc::VideoFrame frame_ld = CreateFrame(320, 180);
1683
1684 // Call once to pass content type.
Philipp Hanckea204ad22022-07-08 18:43:25 +02001685 statistics_proxy_->OnDecodedFrame(frame_hd, absl::nullopt, TimeDelta::Zero(),
1686 content_type_);
Tommi74fc5742020-04-27 10:43:06 +02001687
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001688 time_controller_.AdvanceTime(TimeDelta::Zero());
Tommid7e08c82020-05-10 11:24:43 +02001689 statistics_proxy_->OnRenderedFrame(MetaData(frame_hd));
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001690 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 10:43:06 +02001691 // Downscale.
Tommid7e08c82020-05-10 11:24:43 +02001692 statistics_proxy_->OnRenderedFrame(MetaData(frame_sd));
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001693 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 10:43:06 +02001694 // Downscale.
Tommid7e08c82020-05-10 11:24:43 +02001695 statistics_proxy_->OnRenderedFrame(MetaData(frame_ld));
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001696 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 10:43:06 +02001697 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1698 nullptr);
1699 const int kExpectedDownscales = 30; // 2 per 4 seconds = 30 per minute.
Ilya Nikolaevskiya55a54d2022-12-08 11:00:21 +01001700 if (!videocontenttypehelpers::IsScreenshare(content_type_)) {
Tommi74fc5742020-04-27 10:43:06 +02001701 EXPECT_METRIC_EQ(kExpectedDownscales,
1702 metrics::MinSample(
1703 "WebRTC.Video.NumberResolutionDownswitchesPerMinute"));
1704 }
1705}
1706
1707TEST_P(ReceiveStatisticsProxy2TestWithContent, DecodeTimeReported) {
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001708 const TimeDelta kInterFrameDelay = TimeDelta::Millis(20);
Tommi74fc5742020-04-27 10:43:06 +02001709 const int kLowQp = 30;
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001710 const TimeDelta kDecodeTime = TimeDelta::Millis(7);
Tommi74fc5742020-04-27 10:43:06 +02001711
1712 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1713
1714 for (int i = 0; i < kMinRequiredSamples; ++i) {
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001715 statistics_proxy_->OnDecodedFrame(frame, kLowQp, kDecodeTime,
1716 content_type_);
1717 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 10:43:06 +02001718 }
Tommid93bf122020-05-10 20:24:59 +02001719 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 10:43:06 +02001720 EXPECT_METRIC_EQ(
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001721 1, metrics::NumEvents("WebRTC.Video.DecodeTimeInMs", kDecodeTime.ms()));
Tommi74fc5742020-04-27 10:43:06 +02001722}
1723
1724TEST_P(ReceiveStatisticsProxy2TestWithContent,
1725 StatsAreSlicedOnSimulcastAndExperiment) {
1726 const uint8_t experiment_id = 1;
1727 webrtc::VideoContentType content_type = content_type_;
1728 videocontenttypehelpers::SetExperimentId(&content_type, experiment_id);
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001729 const TimeDelta kInterFrameDelay1 = TimeDelta::Millis(30);
1730 const TimeDelta kInterFrameDelay2 = TimeDelta::Millis(50);
Tommi74fc5742020-04-27 10:43:06 +02001731 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1732
1733 videocontenttypehelpers::SetSimulcastId(&content_type, 1);
1734 for (int i = 0; i <= kMinRequiredSamples; ++i) {
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001735 time_controller_.AdvanceTime(kInterFrameDelay1);
Philipp Hanckea204ad22022-07-08 18:43:25 +02001736 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
1737 content_type);
Tommi74fc5742020-04-27 10:43:06 +02001738 }
1739
1740 videocontenttypehelpers::SetSimulcastId(&content_type, 2);
1741 for (int i = 0; i <= kMinRequiredSamples; ++i) {
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001742 time_controller_.AdvanceTime(kInterFrameDelay2);
Philipp Hanckea204ad22022-07-08 18:43:25 +02001743 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
1744 content_type);
Tommi74fc5742020-04-27 10:43:06 +02001745 }
Tommid93bf122020-05-10 20:24:59 +02001746 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 10:43:06 +02001747
1748 if (videocontenttypehelpers::IsScreenshare(content_type)) {
1749 EXPECT_METRIC_EQ(
1750 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1751 EXPECT_METRIC_EQ(1, metrics::NumSamples(
1752 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1753 EXPECT_METRIC_EQ(1, metrics::NumSamples(
1754 "WebRTC.Video.Screenshare.InterframeDelayInMs.S0"));
1755 EXPECT_METRIC_EQ(1,
1756 metrics::NumSamples(
1757 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs.S0"));
1758 EXPECT_METRIC_EQ(1, metrics::NumSamples(
1759 "WebRTC.Video.Screenshare.InterframeDelayInMs.S1"));
1760 EXPECT_METRIC_EQ(1,
1761 metrics::NumSamples(
1762 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs.S1"));
1763 EXPECT_METRIC_EQ(
1764 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"
1765 ".ExperimentGroup0"));
1766 EXPECT_METRIC_EQ(
1767 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"
1768 ".ExperimentGroup0"));
1769 EXPECT_METRIC_EQ(
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001770 kInterFrameDelay1.ms(),
Tommi74fc5742020-04-27 10:43:06 +02001771 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs.S0"));
1772 EXPECT_METRIC_EQ(
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001773 kInterFrameDelay2.ms(),
Tommi74fc5742020-04-27 10:43:06 +02001774 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs.S1"));
1775 EXPECT_METRIC_EQ(
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001776 ((kInterFrameDelay1 + kInterFrameDelay2) / 2).ms(),
Tommi74fc5742020-04-27 10:43:06 +02001777 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1778 EXPECT_METRIC_EQ(
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001779 kInterFrameDelay2.ms(),
Tommi74fc5742020-04-27 10:43:06 +02001780 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1781 EXPECT_METRIC_EQ(
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001782 ((kInterFrameDelay1 + kInterFrameDelay2) / 2).ms(),
Tommi74fc5742020-04-27 10:43:06 +02001783 metrics::MinSample(
1784 "WebRTC.Video.Screenshare.InterframeDelayInMs.ExperimentGroup0"));
1785 } else {
1786 EXPECT_METRIC_EQ(1,
1787 metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
1788 EXPECT_METRIC_EQ(
1789 1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
1790 EXPECT_METRIC_EQ(
1791 1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs.S0"));
1792 EXPECT_METRIC_EQ(
1793 1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs.S0"));
1794 EXPECT_METRIC_EQ(
1795 1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs.S1"));
1796 EXPECT_METRIC_EQ(
1797 1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs.S1"));
1798 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"
1799 ".ExperimentGroup0"));
1800 EXPECT_METRIC_EQ(1,
1801 metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"
1802 ".ExperimentGroup0"));
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001803 EXPECT_METRIC_EQ(kInterFrameDelay1.ms(),
Tommi74fc5742020-04-27 10:43:06 +02001804 metrics::MinSample("WebRTC.Video.InterframeDelayInMs.S0"));
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001805 EXPECT_METRIC_EQ(kInterFrameDelay2.ms(),
Tommi74fc5742020-04-27 10:43:06 +02001806 metrics::MinSample("WebRTC.Video.InterframeDelayInMs.S1"));
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001807 EXPECT_METRIC_EQ((kInterFrameDelay1 + kInterFrameDelay2).ms() / 2,
Tommi74fc5742020-04-27 10:43:06 +02001808 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001809 EXPECT_METRIC_EQ(kInterFrameDelay2.ms(),
Tommi74fc5742020-04-27 10:43:06 +02001810 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
Evan Shrubsole1edeb922022-08-08 11:51:26 +00001811 EXPECT_METRIC_EQ((kInterFrameDelay1 + kInterFrameDelay2).ms() / 2,
Tommi74fc5742020-04-27 10:43:06 +02001812 metrics::MinSample(
1813 "WebRTC.Video.InterframeDelayInMs.ExperimentGroup0"));
1814 }
1815}
1816
Tommi74fc5742020-04-27 10:43:06 +02001817} // namespace internal
1818} // namespace webrtc