blob: 0c628f7b83906046dff016621a90b3bf36831724 [file] [log] [blame]
Tommi74fc5742020-04-27 08:43:061/*
Tommi553c8692020-05-05 13:35:452 * Copyright 2020 The WebRTC project authors. All Rights Reserved.
Tommi74fc5742020-04-27 08:43:063 *
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:2621#include "api/units/frequency.h"
22#include "api/units/time_delta.h"
Tommi74fc5742020-04-27 08:43:0623#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 13:35:4527#include "rtc_base/thread.h"
Tommi74fc5742020-04-27 08:43:0628#include "system_wrappers/include/metrics.h"
Tommi74fc5742020-04-27 08:43:0629#include "test/gtest.h"
Jonas Oreland8ca06132022-03-14 11:52:4830#include "test/scoped_key_value_config.h"
Evan Shrubsole1edeb922022-08-08 11:51:2631#include "test/time_controller/simulated_time_controller.h"
Tommid7e08c82020-05-10 09:24:4332#include "video/video_receive_stream2.h"
Tommi74fc5742020-04-27 08:43:0633
34namespace webrtc {
35namespace internal {
36namespace {
Evan Shrubsole1edeb922022-08-08 11:51:2637const TimeDelta kFreqOffsetProcessInterval = TimeDelta::Seconds(40);
Tommi74fc5742020-04-27 08:43:0638const 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:2647 ReceiveStatisticsProxy2Test() : time_controller_(Timestamp::Millis(1234)) {
Tommi74fc5742020-04-27 08:43:0648 metrics::Reset();
Evan Shrubsole09da10e2022-10-14 14:38:3149 statistics_proxy_ = std::make_unique<ReceiveStatisticsProxy>(
50 kRemoteSsrc, time_controller_.GetClock(),
51 time_controller_.GetMainThread());
Tommi74fc5742020-04-27 08:43:0652 }
53
Tommi553c8692020-05-05 13:35:4554 ~ReceiveStatisticsProxy2Test() override { statistics_proxy_.reset(); }
55
56 protected:
Tommid93bf122020-05-10 18:24:5957 // Convenience method to avoid too many explict flushes.
Tommif6f45432022-05-20 13:21:2058 VideoReceiveStreamInterface::Stats FlushAndGetStats() {
Evan Shrubsole1edeb922022-08-08 11:51:2659 time_controller_.AdvanceTime(TimeDelta::Zero());
Tommid93bf122020-05-10 18:24:5960 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:2666 time_controller_.AdvanceTime(TimeDelta::Zero());
Tommid93bf122020-05-10 18:24:5967 statistics_proxy_->UpdateHistograms(fraction_lost, rtp_stats, rtx_stats);
68 }
69
Tommi74fc5742020-04-27 08:43:0670 VideoFrame CreateFrame(int width, int height) {
71 return CreateVideoFrame(width, height, 0);
72 }
73
Tommid7e08c82020-05-10 09:24:4374 VideoFrame CreateFrameWithRenderTime(Timestamp render_time) {
75 return CreateFrameWithRenderTimeMs(render_time.ms());
76 }
77
Tommi74fc5742020-04-27 08:43:0678 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:2690 frame.set_ntp_time_ms(
91 time_controller_.GetClock()->CurrentNtpInMilliseconds());
Tommi74fc5742020-04-27 08:43:0692 return frame;
93 }
94
Tommid7e08c82020-05-10 09:24:4395 // Return the current fake time as a Timestamp.
Evan Shrubsole1edeb922022-08-08 11:51:2696 Timestamp Now() { return time_controller_.GetClock()->CurrentTime(); }
Tommid7e08c82020-05-10 09:24:4397
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 11:52:48108 test::ScopedKeyValueConfig field_trials_;
Evan Shrubsole1edeb922022-08-08 11:51:26109 GlobalSimulatedTimeController time_controller_;
Tommi74fc5742020-04-27 08:43:06110 std::unique_ptr<ReceiveStatisticsProxy> statistics_proxy_;
Tommi74fc5742020-04-27 08:43:06111};
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 16:43:25117 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Tommi74fc5742020-04-27 08:43:06118 VideoContentType::UNSPECIFIED);
Tommid93bf122020-05-10 18:24:59119 EXPECT_EQ(i, FlushAndGetStats().frames_decoded);
Tommi74fc5742020-04-27 08:43:06120 }
121}
122
123TEST_F(ReceiveStatisticsProxy2Test, DecodedFpsIsReported) {
Evan Shrubsole1edeb922022-08-08 11:51:26124 const Frequency kFps = Frequency::Hertz(20);
125 const int kRequiredSamples =
126 TimeDelta::Seconds(metrics::kMinRunTimeInSeconds) * kFps;
Tommi74fc5742020-04-27 08:43:06127 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
128 for (int i = 0; i < kRequiredSamples; ++i) {
Philipp Hanckea204ad22022-07-08 16:43:25129 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Tommi74fc5742020-04-27 08:43:06130 VideoContentType::UNSPECIFIED);
Evan Shrubsole1edeb922022-08-08 11:51:26131 time_controller_.AdvanceTime(1 / kFps);
Tommi74fc5742020-04-27 08:43:06132 }
Tommid93bf122020-05-10 18:24:59133 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 08:43:06134 EXPECT_METRIC_EQ(1,
135 metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
Evan Shrubsole1edeb922022-08-08 11:51:26136 EXPECT_METRIC_EQ(1, metrics::NumEvents("WebRTC.Video.DecodedFramesPerSecond",
137 kFps.hertz()));
Tommi74fc5742020-04-27 08:43:06138}
139
140TEST_F(ReceiveStatisticsProxy2Test, DecodedFpsIsNotReportedForTooFewSamples) {
Evan Shrubsole1edeb922022-08-08 11:51:26141 const Frequency kFps = Frequency::Hertz(20);
142 const int kRequiredSamples =
143 TimeDelta::Seconds(metrics::kMinRunTimeInSeconds) * kFps;
Tommi74fc5742020-04-27 08:43:06144 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
145 for (int i = 0; i < kRequiredSamples - 1; ++i) {
Philipp Hanckea204ad22022-07-08 16:43:25146 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Tommi74fc5742020-04-27 08:43:06147 VideoContentType::UNSPECIFIED);
Evan Shrubsole1edeb922022-08-08 11:51:26148 time_controller_.AdvanceTime(1 / kFps);
Tommi74fc5742020-04-27 08:43:06149 }
Tommid93bf122020-05-10 18:24:59150 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 08:43:06151 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 16:43:25159 TimeDelta expected_total_decode_time = TimeDelta::Zero();
Tommi74fc5742020-04-27 08:43:06160 unsigned int expected_frames_decoded = 0;
161 for (uint32_t i = 1; i <= 3; ++i) {
Philipp Hancked970b092022-06-17 05:34:23162 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
163 TimeDelta::Millis(1),
Tommi74fc5742020-04-27 08:43:06164 VideoContentType::UNSPECIFIED);
Philipp Hancked970b092022-06-17 05:34:23165 expected_total_decode_time += TimeDelta::Millis(1);
Tommi74fc5742020-04-27 08:43:06166 ++expected_frames_decoded;
Evan Shrubsole1edeb922022-08-08 11:51:26167 time_controller_.AdvanceTime(TimeDelta::Zero());
Tommi74fc5742020-04-27 08:43:06168 EXPECT_EQ(expected_frames_decoded,
169 statistics_proxy_->GetStats().frames_decoded);
Philipp Hancked970b092022-06-17 05:34:23170 EXPECT_EQ(expected_total_decode_time,
171 statistics_proxy_->GetStats().total_decode_time);
Tommi74fc5742020-04-27 08:43:06172 }
Philipp Hancked970b092022-06-17 05:34:23173 statistics_proxy_->OnDecodedFrame(frame, 1u, TimeDelta::Millis(3),
Tommi74fc5742020-04-27 08:43:06174 VideoContentType::UNSPECIFIED);
175 ++expected_frames_decoded;
Philipp Hancked970b092022-06-17 05:34:23176 expected_total_decode_time += TimeDelta::Millis(3);
Evan Shrubsole1edeb922022-08-08 11:51:26177 time_controller_.AdvanceTime(TimeDelta::Zero());
Tommi74fc5742020-04-27 08:43:06178 EXPECT_EQ(expected_frames_decoded,
179 statistics_proxy_->GetStats().frames_decoded);
Philipp Hancked970b092022-06-17 05:34:23180 EXPECT_EQ(expected_total_decode_time,
181 statistics_proxy_->GetStats().total_decode_time);
Tommi74fc5742020-04-27 08:43:06182}
183
Philipp Hanckea16a6a62022-04-25 10:21:30184TEST_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 16:43:25188 TimeDelta expected_total_processing_delay = TimeDelta::Zero();
Philipp Hanckea16a6a62022-04-25 10:21:30189 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 16:05:29193 RtpPacketInfos::vector_type packet_infos = {RtpPacketInfo(
194 /*ssrc=*/{}, /*csrcs=*/{}, /*rtp_timestamp=*/{}, /*receive_time=*/Now())};
Philipp Hanckea16a6a62022-04-25 10:21:30195 frame.set_packet_infos(RtpPacketInfos(packet_infos));
196 for (int i = 1; i <= 3; ++i) {
Evan Shrubsole1edeb922022-08-08 11:51:26197 time_controller_.AdvanceTime(kProcessingDelay);
Philipp Hancked970b092022-06-17 05:34:23198 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
199 TimeDelta::Millis(1),
Philipp Hanckea16a6a62022-04-25 10:21:30200 VideoContentType::UNSPECIFIED);
201 expected_total_processing_delay += i * kProcessingDelay;
202 ++expected_frames_decoded;
Evan Shrubsole1edeb922022-08-08 11:51:26203 time_controller_.AdvanceTime(TimeDelta::Zero());
Philipp Hanckea16a6a62022-04-25 10:21:30204 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:26209 time_controller_.AdvanceTime(kProcessingDelay);
Philipp Hancked970b092022-06-17 05:34:23210 statistics_proxy_->OnDecodedFrame(frame, 1u, TimeDelta::Millis(3),
Philipp Hanckea16a6a62022-04-25 10:21:30211 VideoContentType::UNSPECIFIED);
212 ++expected_frames_decoded;
213 expected_total_processing_delay += 4 * kProcessingDelay;
Evan Shrubsole1edeb922022-08-08 11:51:26214 time_controller_.AdvanceTime(TimeDelta::Zero());
Philipp Hanckea16a6a62022-04-25 10:21:30215 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 13:55:36221TEST_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 16:43:25225 TimeDelta expected_total_assembly_time = TimeDelta::Zero();
Philipp Hancke0359ba22022-05-05 13:55:36226 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 16:05:29231 RtpPacketInfos::vector_type single_packet_frame = {RtpPacketInfo(
232 /*ssrc=*/{}, /*csrcs=*/{}, /*rtp_timestamp=*/{}, /*receive_time=*/Now())};
Philipp Hancke0359ba22022-05-05 13:55:36233 frame.set_packet_infos(RtpPacketInfos(single_packet_frame));
Philipp Hancked970b092022-06-17 05:34:23234 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Millis(1),
Philipp Hancke0359ba22022-05-05 13:55:36235 VideoContentType::UNSPECIFIED);
236 ++expected_frames_decoded;
Evan Shrubsole1edeb922022-08-08 11:51:26237 time_controller_.AdvanceTime(TimeDelta::Zero());
Philipp Hancke0359ba22022-05-05 13:55:36238 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 16:05:29246 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 13:55:36252 };
253 frame.set_packet_infos(RtpPacketInfos(ordered_frame));
Philipp Hancked970b092022-06-17 05:34:23254 statistics_proxy_->OnDecodedFrame(frame, 1u, TimeDelta::Millis(3),
Philipp Hancke0359ba22022-05-05 13:55:36255 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:26259 time_controller_.AdvanceTime(TimeDelta::Zero());
Philipp Hancke0359ba22022-05-05 13:55:36260 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 16:05:29270 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 13:55:36276 };
277 frame.set_packet_infos(RtpPacketInfos(unordered_frame));
Philipp Hancked970b092022-06-17 05:34:23278 statistics_proxy_->OnDecodedFrame(frame, 1u, TimeDelta::Millis(3),
Philipp Hancke0359ba22022-05-05 13:55:36279 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:26283 time_controller_.AdvanceTime(TimeDelta::Zero());
Philipp Hancke0359ba22022-05-05 13:55:36284 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 08:43:06293TEST_F(ReceiveStatisticsProxy2Test, OnDecodedFrameIncreasesQpSum) {
294 EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
295 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Philipp Hanckea204ad22022-07-08 16:43:25296 statistics_proxy_->OnDecodedFrame(frame, 3u, TimeDelta::Zero(),
Tommi74fc5742020-04-27 08:43:06297 VideoContentType::UNSPECIFIED);
Tommid93bf122020-05-10 18:24:59298 EXPECT_EQ(3u, FlushAndGetStats().qp_sum);
Philipp Hanckea204ad22022-07-08 16:43:25299 statistics_proxy_->OnDecodedFrame(frame, 127u, TimeDelta::Zero(),
Tommi74fc5742020-04-27 08:43:06300 VideoContentType::UNSPECIFIED);
Tommid93bf122020-05-10 18:24:59301 EXPECT_EQ(130u, FlushAndGetStats().qp_sum);
Tommi74fc5742020-04-27 08:43:06302}
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 05:34:23307 statistics_proxy_->OnDecodedFrame(frame, 3u, TimeDelta::Millis(4),
Tommi74fc5742020-04-27 08:43:06308 VideoContentType::UNSPECIFIED);
Philipp Hancked970b092022-06-17 05:34:23309 EXPECT_EQ(4u, FlushAndGetStats().total_decode_time.ms());
310 statistics_proxy_->OnDecodedFrame(frame, 127u, TimeDelta::Millis(7),
Tommi74fc5742020-04-27 08:43:06311 VideoContentType::UNSPECIFIED);
Philipp Hancked970b092022-06-17 05:34:23312 EXPECT_EQ(11u, FlushAndGetStats().total_decode_time.ms());
Tommi74fc5742020-04-27 08:43:06313}
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 16:43:25321 statistics_proxy_->OnDecodedFrame(frame, 3u, TimeDelta::Zero(),
Tommi74fc5742020-04-27 08:43:06322 VideoContentType::SCREENSHARE);
323 EXPECT_EQ(kScreenshareString,
Tommid93bf122020-05-10 18:24:59324 videocontenttypehelpers::ToString(FlushAndGetStats().content_type));
Philipp Hanckea204ad22022-07-08 16:43:25325 statistics_proxy_->OnDecodedFrame(frame, 3u, TimeDelta::Zero(),
Tommi74fc5742020-04-27 08:43:06326 VideoContentType::UNSPECIFIED);
Tommid93bf122020-05-10 18:24:59327 EXPECT_EQ(kRealtimeString,
328 videocontenttypehelpers::ToString(FlushAndGetStats().content_type));
Tommi74fc5742020-04-27 08:43:06329}
330
Tommi74fc5742020-04-27 08:43:06331TEST_F(ReceiveStatisticsProxy2Test, ReportsMaxInterframeDelay) {
332 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Evan Shrubsole1edeb922022-08-08 11:51:26333 const TimeDelta kInterframeDelay1 = TimeDelta::Millis(100);
334 const TimeDelta kInterframeDelay2 = TimeDelta::Millis(200);
335 const TimeDelta kInterframeDelay3 = TimeDelta::Millis(100);
Tommi74fc5742020-04-27 08:43:06336 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
Philipp Hanckea204ad22022-07-08 16:43:25337 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Tommi74fc5742020-04-27 08:43:06338 VideoContentType::UNSPECIFIED);
Tommid93bf122020-05-10 18:24:59339 EXPECT_EQ(-1, FlushAndGetStats().interframe_delay_max_ms);
Tommi74fc5742020-04-27 08:43:06340
Evan Shrubsole1edeb922022-08-08 11:51:26341 time_controller_.AdvanceTime(kInterframeDelay1);
Philipp Hanckea204ad22022-07-08 16:43:25342 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Tommi74fc5742020-04-27 08:43:06343 VideoContentType::UNSPECIFIED);
Evan Shrubsole1edeb922022-08-08 11:51:26344 EXPECT_EQ(kInterframeDelay1.ms(), FlushAndGetStats().interframe_delay_max_ms);
Tommi74fc5742020-04-27 08:43:06345
Evan Shrubsole1edeb922022-08-08 11:51:26346 time_controller_.AdvanceTime(kInterframeDelay2);
Philipp Hanckea204ad22022-07-08 16:43:25347 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Tommi74fc5742020-04-27 08:43:06348 VideoContentType::UNSPECIFIED);
Evan Shrubsole1edeb922022-08-08 11:51:26349 EXPECT_EQ(kInterframeDelay2.ms(), FlushAndGetStats().interframe_delay_max_ms);
Tommi74fc5742020-04-27 08:43:06350
Evan Shrubsole1edeb922022-08-08 11:51:26351 time_controller_.AdvanceTime(kInterframeDelay3);
Philipp Hanckea204ad22022-07-08 16:43:25352 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Tommi74fc5742020-04-27 08:43:06353 VideoContentType::UNSPECIFIED);
Evan Shrubsole1edeb922022-08-08 11:51:26354 // kInterframeDelay3 is smaller than kInterframeDelay2.
355 EXPECT_EQ(kInterframeDelay2.ms(), FlushAndGetStats().interframe_delay_max_ms);
Tommi74fc5742020-04-27 08:43:06356}
357
358TEST_F(ReceiveStatisticsProxy2Test, ReportInterframeDelayInWindow) {
359 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Evan Shrubsole1edeb922022-08-08 11:51:26360 const TimeDelta kInterframeDelay1 = TimeDelta::Millis(900);
361 const TimeDelta kInterframeDelay2 = TimeDelta::Millis(750);
362 const TimeDelta kInterframeDelay3 = TimeDelta::Millis(700);
Tommi74fc5742020-04-27 08:43:06363 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
Philipp Hanckea204ad22022-07-08 16:43:25364 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Tommi74fc5742020-04-27 08:43:06365 VideoContentType::UNSPECIFIED);
Tommid93bf122020-05-10 18:24:59366 EXPECT_EQ(-1, FlushAndGetStats().interframe_delay_max_ms);
Tommi74fc5742020-04-27 08:43:06367
Evan Shrubsole1edeb922022-08-08 11:51:26368 time_controller_.AdvanceTime(kInterframeDelay1);
Philipp Hanckea204ad22022-07-08 16:43:25369 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Tommi74fc5742020-04-27 08:43:06370 VideoContentType::UNSPECIFIED);
Evan Shrubsole1edeb922022-08-08 11:51:26371 EXPECT_EQ(kInterframeDelay1.ms(), FlushAndGetStats().interframe_delay_max_ms);
Tommi74fc5742020-04-27 08:43:06372
Evan Shrubsole1edeb922022-08-08 11:51:26373 time_controller_.AdvanceTime(kInterframeDelay2);
Philipp Hanckea204ad22022-07-08 16:43:25374 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Tommi74fc5742020-04-27 08:43:06375 VideoContentType::UNSPECIFIED);
376 // Still first delay is the maximum
Evan Shrubsole1edeb922022-08-08 11:51:26377 EXPECT_EQ(kInterframeDelay1.ms(), FlushAndGetStats().interframe_delay_max_ms);
Tommi74fc5742020-04-27 08:43:06378
Evan Shrubsole1edeb922022-08-08 11:51:26379 time_controller_.AdvanceTime(kInterframeDelay3);
Philipp Hanckea204ad22022-07-08 16:43:25380 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Tommi74fc5742020-04-27 08:43:06381 VideoContentType::UNSPECIFIED);
382 // Now the first sample is out of the window, so the second is the maximum.
Evan Shrubsole1edeb922022-08-08 11:51:26383 EXPECT_EQ(kInterframeDelay2.ms(), FlushAndGetStats().interframe_delay_max_ms);
Tommi74fc5742020-04-27 08:43:06384}
385
386TEST_F(ReceiveStatisticsProxy2Test, ReportsFreezeMetrics) {
Evan Shrubsole1edeb922022-08-08 11:51:26387 const TimeDelta kFreezeDuration = TimeDelta::Seconds(1);
Tommi74fc5742020-04-27 08:43:06388
Tommif6f45432022-05-20 13:21:20389 VideoReceiveStreamInterface::Stats stats = statistics_proxy_->GetStats();
Tommi74fc5742020-04-27 08:43:06390 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:26396 time_controller_.AdvanceTime(TimeDelta::Millis(30));
Tommid7e08c82020-05-10 09:24:43397 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 08:43:06398 }
399
400 // Freeze.
Evan Shrubsole1edeb922022-08-08 11:51:26401 time_controller_.AdvanceTime(kFreezeDuration);
Tommid7e08c82020-05-10 09:24:43402 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 08:43:06403
404 stats = statistics_proxy_->GetStats();
405 EXPECT_EQ(1u, stats.freeze_count);
Evan Shrubsole1edeb922022-08-08 11:51:26406 EXPECT_EQ(kFreezeDuration.ms(), stats.total_freezes_duration_ms);
Tommi74fc5742020-04-27 08:43:06407}
408
409TEST_F(ReceiveStatisticsProxy2Test, ReportsPauseMetrics) {
Tommif6f45432022-05-20 13:21:20410 VideoReceiveStreamInterface::Stats stats = statistics_proxy_->GetStats();
Tommi74fc5742020-04-27 08:43:06411 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 09:24:43415 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 08:43:06416
417 // Pause.
Evan Shrubsole1edeb922022-08-08 11:51:26418 time_controller_.AdvanceTime(TimeDelta::Millis(5432));
Tommi74fc5742020-04-27 08:43:06419 statistics_proxy_->OnStreamInactive();
Tommid7e08c82020-05-10 09:24:43420 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 08:43:06421
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 13:21:20428 VideoReceiveStreamInterface::Stats stats = statistics_proxy_->GetStats();
Tommi74fc5742020-04-27 08:43:06429 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:26435 time_controller_.AdvanceTime(TimeDelta::Seconds(5));
Tommi74fc5742020-04-27 08:43:06436 statistics_proxy_->OnStreamInactive();
Tommid7e08c82020-05-10 09:24:43437 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 08:43:06438
Evan Shrubsole1edeb922022-08-08 11:51:26439 time_controller_.AdvanceTime(TimeDelta::Millis(30));
Tommid7e08c82020-05-10 09:24:43440 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 08:43:06441
Evan Shrubsole1edeb922022-08-08 11:51:26442 time_controller_.AdvanceTime(TimeDelta::Seconds(5));
Tommi74fc5742020-04-27 08:43:06443 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 12:58:15450TEST_F(ReceiveStatisticsProxy2Test, ReportsTotalInterFrameDelay) {
Tommif6f45432022-05-20 13:21:20451 VideoReceiveStreamInterface::Stats stats = statistics_proxy_->GetStats();
Sergey Silkined0dd8e2022-12-20 12:58:15452 ASSERT_EQ(0.0, stats.total_inter_frame_delay);
Tommi74fc5742020-04-27 08:43:06453
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:26459 time_controller_.AdvanceTime(TimeDelta::Millis(5432));
Tommi74fc5742020-04-27 08:43:06460 for (int i = 0; i <= 10; ++i) {
Evan Shrubsole1edeb922022-08-08 11:51:26461 time_controller_.AdvanceTime(TimeDelta::Millis(30));
Tommid7e08c82020-05-10 09:24:43462 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 08:43:06463 }
464
465 stats = statistics_proxy_->GetStats();
Sergey Silkined0dd8e2022-12-20 12:58:15466 EXPECT_EQ(10 * 30 / 1000.0, stats.total_inter_frame_delay);
Tommi74fc5742020-04-27 08:43:06467}
468
Sergey Silkined0dd8e2022-12-20 12:58:15469TEST_F(ReceiveStatisticsProxy2Test, ReportsTotalSquaredInterFrameDelay) {
Tommif6f45432022-05-20 13:21:20470 VideoReceiveStreamInterface::Stats stats = statistics_proxy_->GetStats();
Sergey Silkined0dd8e2022-12-20 12:58:15471 ASSERT_EQ(0.0, stats.total_squared_inter_frame_delay);
Tommi74fc5742020-04-27 08:43:06472
473 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
474 for (int i = 0; i <= 10; ++i) {
Evan Shrubsole1edeb922022-08-08 11:51:26475 time_controller_.AdvanceTime(TimeDelta::Millis(30));
Tommid7e08c82020-05-10 09:24:43476 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 08:43:06477 }
478
479 stats = statistics_proxy_->GetStats();
Sergey Silkined0dd8e2022-12-20 12:58:15480 const double kExpectedTotalSquaredInterFrameDelaySecs =
Tommi74fc5742020-04-27 08:43:06481 10 * (30 / 1000.0 * 30 / 1000.0);
Sergey Silkined0dd8e2022-12-20 12:58:15482 EXPECT_EQ(kExpectedTotalSquaredInterFrameDelaySecs,
483 stats.total_squared_inter_frame_delay);
Tommi74fc5742020-04-27 08:43:06484}
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 16:43:25489 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Tommi74fc5742020-04-27 08:43:06490 VideoContentType::UNSPECIFIED);
Tommid93bf122020-05-10 18:24:59491 EXPECT_EQ(absl::nullopt, FlushAndGetStats().qp_sum);
Tommi74fc5742020-04-27 08:43:06492}
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 16:43:25497 statistics_proxy_->OnDecodedFrame(frame, 3u, TimeDelta::Zero(),
Tommi74fc5742020-04-27 08:43:06498 VideoContentType::UNSPECIFIED);
Tommid93bf122020-05-10 18:24:59499 EXPECT_EQ(3u, FlushAndGetStats().qp_sum);
Philipp Hanckea204ad22022-07-08 16:43:25500 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Tommi74fc5742020-04-27 08:43:06501 VideoContentType::UNSPECIFIED);
Tommid93bf122020-05-10 18:24:59502 EXPECT_EQ(absl::nullopt, FlushAndGetStats().qp_sum);
Tommi74fc5742020-04-27 08:43:06503}
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 09:24:43509 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 08:43:06510 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:26521 time_controller_.AdvanceTime(TimeDelta::Zero());
Tommi74fc5742020-04-27 08:43:06522 EXPECT_EQ(kPayloadType, statistics_proxy_->GetStats().current_payload_type);
523}
524
Evan Shrubsole09da10e2022-10-14 14:38:31525TEST_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:26533 time_controller_.AdvanceTime(TimeDelta::Zero());
Evan Shrubsole09da10e2022-10-14 14:38:31534 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 08:43:06538}
539
540TEST_F(ReceiveStatisticsProxy2Test, GetStatsReportsOnCompleteFrame) {
541 const int kFrameSizeBytes = 1000;
542 statistics_proxy_->OnCompleteFrame(true, kFrameSizeBytes,
543 VideoContentType::UNSPECIFIED);
Tommif6f45432022-05-20 13:21:20544 VideoReceiveStreamInterface::Stats stats = statistics_proxy_->GetStats();
Tommi74fc5742020-04-27 08:43:06545 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 13:21:20556 VideoReceiveStreamInterface::Stats stats = FlushAndGetStats();
Tommi74fc5742020-04-27 08:43:06557 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;
Tommi674b0c812020-05-10 19:52:17568 statistics_proxy_->OnRttUpdate(kRttMs);
Tommi74fc5742020-04-27 08:43:06569 statistics_proxy_->OnFrameBufferTimingsUpdated(
570 kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs, kJitterBufferMs,
571 kMinPlayoutDelayMs, kRenderDelayMs);
Tommif6f45432022-05-20 13:21:20572 VideoReceiveStreamInterface::Stats stats = FlushAndGetStats();
Tommi74fc5742020-04-27 08:43:06573 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 13:21:20590 VideoReceiveStreamInterface::Stats stats = statistics_proxy_->GetStats();
Tommi74fc5742020-04-27 08:43:06591 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 13:21:20615 VideoReceiveStreamInterface::Stats stats = statistics_proxy_->GetStats();
Tommi74fc5742020-04-27 08:43:06616 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);
Tommi674b0c812020-05-10 19:52:17652 result = FlushAndGetStats().timing_frame_info;
Tommi74fc5742020-04-27 08:43:06653 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:26661 const TimeDelta kShortDelay = TimeDelta::Seconds(1);
662 const TimeDelta kLongDelay = TimeDelta::Seconds(10);
Tommi74fc5742020-04-27 08:43:06663 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:26668 time_controller_.AdvanceTime(kShortDelay);
Tommi674b0c812020-05-10 19:52:17669 result = FlushAndGetStats().timing_frame_info;
Tommi74fc5742020-04-27 08:43:06670 EXPECT_TRUE(result);
671 EXPECT_EQ(kExpectedRtpTimestamp, result->rtp_timestamp);
Evan Shrubsole1edeb922022-08-08 11:51:26672 time_controller_.AdvanceTime(kLongDelay);
Tommi74fc5742020-04-27 08:43:06673 result = statistics_proxy_->GetStats().timing_frame_info;
674 EXPECT_FALSE(result);
675}
676
677TEST_F(ReceiveStatisticsProxy2Test, LifetimeHistogramIsUpdated) {
Evan Shrubsole1edeb922022-08-08 11:51:26678 const TimeDelta kLifetime = TimeDelta::Seconds(3);
679 time_controller_.AdvanceTime(kLifetime);
Tommi74fc5742020-04-27 08:43:06680 // 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:26688 kLifetime.seconds()));
Tommi74fc5742020-04-27 08:43:06689}
690
691TEST_F(ReceiveStatisticsProxy2Test,
692 LifetimeHistogramNotReportedForEmptyStreams) {
Evan Shrubsole1edeb922022-08-08 11:51:26693 const TimeDelta kLifetime = TimeDelta::Seconds(3);
694 time_controller_.AdvanceTime(kLifetime);
Tommi74fc5742020-04-27 08:43:06695 // 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:26708 const TimeDelta kBadFameInterval = TimeDelta::Millis(1100);
Tommi74fc5742020-04-27 08:43:06709
710 StreamDataCounters counters;
Evan Shrubsole1edeb922022-08-08 11:51:26711 counters.first_packet_time_ms = Now().ms();
Tommi74fc5742020-04-27 08:43:06712
713 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
714
715 for (int i = 0; i < kNumBadSamples; ++i) {
Evan Shrubsole1edeb922022-08-08 11:51:26716 time_controller_.AdvanceTime(kBadFameInterval);
Tommid7e08c82020-05-10 09:24:43717 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 08:43:06718 }
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:26742 time_controller_.AdvanceTime(
743 TimeDelta::Seconds(metrics::kMinRunTimeInSeconds));
Tommi74fc5742020-04-27 08:43:06744 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);
Tommi674b0c812020-05-10 19:52:17758 EXPECT_EQ(kVideoNtpMs, FlushAndGetStats().estimated_playout_ntp_timestamp_ms);
Evan Shrubsole1edeb922022-08-08 11:51:26759 time_controller_.AdvanceTime(TimeDelta::Millis(13));
Tommi74fc5742020-04-27 08:43:06760 EXPECT_EQ(kVideoNtpMs + 13,
761 statistics_proxy_->GetStats().estimated_playout_ntp_timestamp_ms);
Evan Shrubsole1edeb922022-08-08 11:51:26762 time_controller_.AdvanceTime(TimeDelta::Millis(5));
Tommi74fc5742020-04-27 08:43:06763 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);
Tommi674b0c812020-05-10 19:52:17774 EXPECT_EQ(kSyncOffsetMs, FlushAndGetStats().sync_offset_ms);
Tommi74fc5742020-04-27 08:43:06775}
776
777TEST_F(ReceiveStatisticsProxy2Test, AvSyncOffsetHistogramIsUpdated) {
778 const int64_t kVideoNtpMs = 21;
779 const int64_t kSyncOffsetMs = 22;
780 const double kFreqKhz = 90.0;
Tommi674b0c812020-05-10 19:52:17781 for (int i = 0; i < kMinRequiredSamples; ++i) {
Tommi74fc5742020-04-27 08:43:06782 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs,
783 kFreqKhz);
Tommi674b0c812020-05-10 19:52:17784 }
785 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 08:43:06786 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:26798 time_controller_.AdvanceTime(kFreqOffsetProcessInterval);
799 //) Process interval passed, max diff: 2.
Tommi74fc5742020-04-27 08:43:06800 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:26806 time_controller_.AdvanceTime(kFreqOffsetProcessInterval);
807 //) Process interval passed, max diff: 4.
Tommi74fc5742020-04-27 08:43:06808 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs, kFreqKhz);
Tommi674b0c812020-05-10 19:52:17809 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 08:43:06810 // 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
Tommi674b0c812020-05-10 19:52:17823 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 08:43:06824 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
Tommi674b0c812020-05-10 19:52:17952 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 08:43:06953 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:26970 const Frequency kDefaultFps = Frequency::Hertz(30);
Tommi74fc5742020-04-27 08:43:06971 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
972
Evan Shrubsole1edeb922022-08-08 11:51:26973 for (int i = 0; i < kDefaultFps.hertz(); ++i) {
Tommi74fc5742020-04-27 08:43:06974 // Since OnRenderedFrame is never called the fps in each sample will be 0,
975 // i.e. bad
Evan Shrubsole1edeb922022-08-08 11:51:26976 frame.set_ntp_time_ms(
977 time_controller_.GetClock()->CurrentNtpInMilliseconds());
Philipp Hanckea204ad22022-07-08 16:43:25978 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Tommi74fc5742020-04-27 08:43:06979 VideoContentType::UNSPECIFIED);
Tommid7e08c82020-05-10 09:24:43980 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Evan Shrubsole1edeb922022-08-08 11:51:26981 time_controller_.AdvanceTime(1 / kDefaultFps);
Tommi74fc5742020-04-27 08:43:06982 }
983
Evan Shrubsole1edeb922022-08-08 11:51:26984 // 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 08:43:06990
991 // FPS trackers in stats proxy have a 1000ms sliding window.
Evan Shrubsole1edeb922022-08-08 11:51:26992 time_controller_.AdvanceTime(TimeDelta::Seconds(1));
Tommi74fc5742020-04-27 08:43:06993 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 09:24:431002 statistics_proxy_->OnRenderedFrame(MetaData(CreateFrame(kWidth, kHeight)));
Tommi74fc5742020-04-27 08:43:061003
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 09:24:431011 for (int i = 0; i < kMinRequiredSamples - 1; ++i) {
1012 statistics_proxy_->OnRenderedFrame(MetaData(CreateFrame(kWidth, kHeight)));
1013 }
Tommi74fc5742020-04-27 08:43:061014
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 09:24:431028 for (int i = 0; i < kMinRequiredSamples; ++i) {
1029 statistics_proxy_->OnRenderedFrame(MetaData(CreateFrame(kWidth, kHeight)));
1030 }
Tommi74fc5742020-04-27 08:43:061031
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 16:43:251050 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Tommi74fc5742020-04-27 08:43:061051 VideoContentType::UNSPECIFIED);
1052
1053 // Frame not delayed, delayed frames to render: 0%.
Tommid7e08c82020-05-10 09:24:431054 statistics_proxy_->OnRenderedFrame(
1055 MetaData(CreateFrameWithRenderTime(Now())));
Tommi74fc5742020-04-27 08:43:061056
1057 // Min run time has passed.
Evan Shrubsole1edeb922022-08-08 11:51:261058 time_controller_.AdvanceTime(
1059 TimeDelta::Seconds((metrics::kMinRunTimeInSeconds)));
Tommid93bf122020-05-10 18:24:591060 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 08:43:061061 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 16:43:251072 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Tommi74fc5742020-04-27 08:43:061073 VideoContentType::UNSPECIFIED);
1074
1075 // Frame not delayed, delayed frames to render: 0%.
Tommid7e08c82020-05-10 09:24:431076 statistics_proxy_->OnRenderedFrame(
1077 MetaData(CreateFrameWithRenderTime(Now())));
Tommi74fc5742020-04-27 08:43:061078
1079 // Min run time has not passed.
Evan Shrubsole1edeb922022-08-08 11:51:261080 time_controller_.AdvanceTime(
1081 TimeDelta::Seconds(metrics::kMinRunTimeInSeconds) - TimeDelta::Millis(1));
Tommi74fc5742020-04-27 08:43:061082 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 16:43:251093 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Tommi74fc5742020-04-27 08:43:061094 VideoContentType::UNSPECIFIED);
1095
1096 // Min run time has passed. No rendered frames.
Evan Shrubsole1edeb922022-08-08 11:51:261097 time_controller_.AdvanceTime(
1098 TimeDelta::Seconds((metrics::kMinRunTimeInSeconds)));
Tommi74fc5742020-04-27 08:43:061099 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 16:43:251109 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Tommi74fc5742020-04-27 08:43:061110 VideoContentType::UNSPECIFIED);
1111
1112 // Frame delayed 1 ms, delayed frames to render: 100%.
Tommid7e08c82020-05-10 09:24:431113 statistics_proxy_->OnRenderedFrame(
1114 MetaData(CreateFrameWithRenderTimeMs(Now().ms() - 1)));
Tommi74fc5742020-04-27 08:43:061115
1116 // Min run time has passed.
Evan Shrubsole1edeb922022-08-08 11:51:261117 time_controller_.AdvanceTime(
1118 TimeDelta::Seconds(metrics::kMinRunTimeInSeconds));
Tommid93bf122020-05-10 18:24:591119 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 08:43:061120 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 16:43:251133 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Tommi74fc5742020-04-27 08:43:061134 VideoContentType::UNSPECIFIED);
1135
1136 // Two frames delayed (6 ms, 10 ms), delayed frames to render: 50%.
Tommid7e08c82020-05-10 09:24:431137 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 08:43:061147
1148 // Min run time has passed.
Evan Shrubsole1edeb922022-08-08 11:51:261149 time_controller_.AdvanceTime(
1150 TimeDelta::Seconds(metrics::kMinRunTimeInSeconds));
Tommid93bf122020-05-10 18:24:591151 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 08:43:061152 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:261166 data_counters.first_packet_time_ms =
1167 time_controller_.GetClock()->TimeInMilliseconds();
Tommi74fc5742020-04-27 08:43:061168
Evan Shrubsole1edeb922022-08-08 11:51:261169 time_controller_.AdvanceTime(
1170 TimeDelta::Seconds(metrics::kMinRunTimeInSeconds) - TimeDelta::Millis(1));
Tommi74fc5742020-04-27 08:43:061171
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:261186 data_counters.first_packet_time_ms =
1187 time_controller_.GetClock()->TimeInMilliseconds();
1188 time_controller_.AdvanceTime(
1189 TimeDelta::Seconds(metrics::kMinRunTimeInSeconds));
Tommi74fc5742020-04-27 08:43:061190
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 13:21:201249 VideoReceiveStreamInterface::Stats stats = statistics_proxy_->GetStats();
Tommi74fc5742020-04-27 08:43:061250 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 09:24:431256 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Evan Shrubsole1edeb922022-08-08 11:51:261257 time_controller_.AdvanceTime(TimeDelta::Seconds(2));
Tommi74fc5742020-04-27 08:43:061258 for (size_t i = 0;
1259 i <= VideoQualityObserver::kAvgInterframeDelaysWindowSizeFrames; ++i) {
Evan Shrubsole1edeb922022-08-08 11:51:261260 time_controller_.AdvanceTime(TimeDelta::Millis(frame_duration_ms_));
Tommid7e08c82020-05-10 09:24:431261 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 08:43:061262 }
1263
Evan Shrubsole1edeb922022-08-08 11:51:261264 time_controller_.AdvanceTime(TimeDelta::Millis(freeze_duration_ms_));
Tommid7e08c82020-05-10 09:24:431265 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 08:43:061266
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:261284 const TimeDelta kInterFrameDelay = TimeDelta::Millis(33);
Tommi74fc5742020-04-27 08:43:061285 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1286
1287 for (int i = 0; i < kMinRequiredSamples; ++i) {
Philipp Hanckea204ad22022-07-08 16:43:251288 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
1289 content_type_);
Evan Shrubsole1edeb922022-08-08 11:51:261290 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 08:43:061291 }
1292 // One extra with double the interval.
Evan Shrubsole1edeb922022-08-08 11:51:261293 time_controller_.AdvanceTime(kInterFrameDelay);
Philipp Hanckea204ad22022-07-08 16:43:251294 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Philipp Hancked970b092022-06-17 05:34:231295 content_type_);
Tommi74fc5742020-04-27 08:43:061296
Tommid93bf122020-05-10 18:24:591297 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Evan Shrubsole1edeb922022-08-08 11:51:261298 const TimeDelta kExpectedInterFrame =
1299 (kInterFrameDelay * (kMinRequiredSamples - 1) + kInterFrameDelay * 2) /
Tommi74fc5742020-04-27 08:43:061300 kMinRequiredSamples;
1301 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
1302 EXPECT_METRIC_EQ(
Evan Shrubsole1edeb922022-08-08 11:51:261303 kExpectedInterFrame.ms(),
Tommi74fc5742020-04-27 08:43:061304 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1305 EXPECT_METRIC_EQ(
Evan Shrubsole1edeb922022-08-08 11:51:261306 kInterFrameDelay.ms() * 2,
Tommi74fc5742020-04-27 08:43:061307 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1308 } else {
Evan Shrubsole1edeb922022-08-08 11:51:261309 EXPECT_METRIC_EQ(kExpectedInterFrame.ms(),
Tommi74fc5742020-04-27 08:43:061310 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
Evan Shrubsole1edeb922022-08-08 11:51:261311 EXPECT_METRIC_EQ(kInterFrameDelay.ms() * 2,
Tommi74fc5742020-04-27 08:43:061312 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
1313 }
1314}
1315
1316TEST_P(ReceiveStatisticsProxy2TestWithContent,
1317 InterFrameDelaysPercentilesAreReported) {
Evan Shrubsole1edeb922022-08-08 11:51:261318 const TimeDelta kInterFrameDelay = TimeDelta::Millis(33);
Tommi74fc5742020-04-27 08:43:061319 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:261323 time_controller_.AdvanceTime(kInterFrameDelay);
Philipp Hanckea204ad22022-07-08 16:43:251324 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
1325 content_type_);
Tommi74fc5742020-04-27 08:43:061326 }
1327 // Last 5% of intervals are double in size.
1328 for (int i = 0; i < kLastFivePercentsSamples; ++i) {
Evan Shrubsole1edeb922022-08-08 11:51:261329 time_controller_.AdvanceTime(2 * kInterFrameDelay);
Philipp Hanckea204ad22022-07-08 16:43:251330 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
1331 content_type_);
Tommi74fc5742020-04-27 08:43:061332 }
1333 // Final sample is outlier and 10 times as big.
Evan Shrubsole1edeb922022-08-08 11:51:261334 time_controller_.AdvanceTime(10 * kInterFrameDelay);
Philipp Hanckea204ad22022-07-08 16:43:251335 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Philipp Hancked970b092022-06-17 05:34:231336 content_type_);
Tommi74fc5742020-04-27 08:43:061337
Tommid93bf122020-05-10 18:24:591338 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Evan Shrubsole1edeb922022-08-08 11:51:261339 const TimeDelta kExpectedInterFrame = kInterFrameDelay * 2;
Tommi74fc5742020-04-27 08:43:061340 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
1341 EXPECT_METRIC_EQ(
Evan Shrubsole1edeb922022-08-08 11:51:261342 kExpectedInterFrame.ms(),
Tommi74fc5742020-04-27 08:43:061343 metrics::MinSample(
1344 "WebRTC.Video.Screenshare.InterframeDelay95PercentileInMs"));
1345 } else {
1346 EXPECT_METRIC_EQ(
Evan Shrubsole1edeb922022-08-08 11:51:261347 kExpectedInterFrame.ms(),
Tommi74fc5742020-04-27 08:43:061348 metrics::MinSample("WebRTC.Video.InterframeDelay95PercentileInMs"));
1349 }
1350}
1351
1352TEST_P(ReceiveStatisticsProxy2TestWithContent,
1353 MaxInterFrameDelayOnlyWithValidAverage) {
Evan Shrubsole1edeb922022-08-08 11:51:261354 const TimeDelta kInterFrameDelay = TimeDelta::Millis(33);
Tommi74fc5742020-04-27 08:43:061355 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1356
1357 for (int i = 0; i < kMinRequiredSamples; ++i) {
Philipp Hanckea204ad22022-07-08 16:43:251358 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
1359 content_type_);
Evan Shrubsole1edeb922022-08-08 11:51:261360 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 08:43:061361 }
1362
Artem Titovab30d722021-07-27 14:22:111363 // `kMinRequiredSamples` samples, and thereby intervals, is required. That
Tommi74fc5742020-04-27 08:43:061364 // 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:261378 const TimeDelta kInterFrameDelay = TimeDelta::Millis(33);
Tommi74fc5742020-04-27 08:43:061379 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1380
1381 for (int i = 0; i <= kMinRequiredSamples; ++i) {
Philipp Hanckea204ad22022-07-08 16:43:251382 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
1383 content_type_);
Evan Shrubsole1edeb922022-08-08 11:51:261384 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 08:43:061385 }
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:261390 time_controller_.AdvanceTime(TimeDelta::Seconds(5));
Tommid7e08c82020-05-10 09:24:431391 // Insert two more frames. The interval during the pause should be
1392 // disregarded in the stats.
Philipp Hanckea204ad22022-07-08 16:43:251393 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Philipp Hancked970b092022-06-17 05:34:231394 content_type_);
Evan Shrubsole1edeb922022-08-08 11:51:261395 time_controller_.AdvanceTime(kInterFrameDelay);
Philipp Hanckea204ad22022-07-08 16:43:251396 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Philipp Hancked970b092022-06-17 05:34:231397 content_type_);
Tommi74fc5742020-04-27 08:43:061398
Tommid93bf122020-05-10 18:24:591399 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 08:43:061400 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:261406 kInterFrameDelay.ms(),
Tommi74fc5742020-04-27 08:43:061407 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1408 EXPECT_METRIC_EQ(
Evan Shrubsole1edeb922022-08-08 11:51:261409 kInterFrameDelay.ms(),
Tommi74fc5742020-04-27 08:43:061410 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:261416 EXPECT_METRIC_EQ(kInterFrameDelay.ms(),
Tommi74fc5742020-04-27 08:43:061417 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
Evan Shrubsole1edeb922022-08-08 11:51:261418 EXPECT_METRIC_EQ(kInterFrameDelay.ms(),
Tommi74fc5742020-04-27 08:43:061419 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
1420 }
1421}
1422
1423TEST_P(ReceiveStatisticsProxy2TestWithContent, FreezesAreReported) {
Evan Shrubsole1edeb922022-08-08 11:51:261424 const TimeDelta kInterFrameDelay = TimeDelta::Millis(33);
1425 const TimeDelta kFreezeDelay = TimeDelta::Millis(200);
1426 const TimeDelta kCallDuration =
1427 kMinRequiredSamples * kInterFrameDelay + kFreezeDelay;
Tommi74fc5742020-04-27 08:43:061428 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1429
1430 for (int i = 0; i < kMinRequiredSamples; ++i) {
Tommid93bf122020-05-10 18:24:591431 VideoFrameMetaData meta = MetaData(frame);
Philipp Hanckea204ad22022-07-08 16:43:251432 statistics_proxy_->OnDecodedFrame(meta, absl::nullopt, TimeDelta::Zero(),
1433 TimeDelta::Zero(), TimeDelta::Zero(),
1434 content_type_);
Tommid93bf122020-05-10 18:24:591435 statistics_proxy_->OnRenderedFrame(meta);
Evan Shrubsole1edeb922022-08-08 11:51:261436 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 08:43:061437 }
1438 // Add extra freeze.
Evan Shrubsole1edeb922022-08-08 11:51:261439 time_controller_.AdvanceTime(kFreezeDelay);
Tommid93bf122020-05-10 18:24:591440 VideoFrameMetaData meta = MetaData(frame);
Philipp Hanckea204ad22022-07-08 16:43:251441 statistics_proxy_->OnDecodedFrame(meta, absl::nullopt, TimeDelta::Zero(),
1442 TimeDelta::Zero(), TimeDelta::Zero(),
1443 content_type_);
Tommid93bf122020-05-10 18:24:591444 statistics_proxy_->OnRenderedFrame(meta);
Tommi74fc5742020-04-27 08:43:061445
Tommid93bf122020-05-10 18:24:591446 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Evan Shrubsole1edeb922022-08-08 11:51:261447 const TimeDelta kExpectedTimeBetweenFreezes =
1448 kInterFrameDelay * (kMinRequiredSamples - 1);
1449 const int kExpectedNumberFreezesPerMinute = 60 / kCallDuration.seconds();
Tommi74fc5742020-04-27 08:43:061450 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
1451 EXPECT_METRIC_EQ(
Evan Shrubsole1edeb922022-08-08 11:51:261452 (kFreezeDelay + kInterFrameDelay).ms(),
Tommi74fc5742020-04-27 08:43:061453 metrics::MinSample("WebRTC.Video.Screenshare.MeanFreezeDurationMs"));
Evan Shrubsole1edeb922022-08-08 11:51:261454 EXPECT_METRIC_EQ(kExpectedTimeBetweenFreezes.ms(),
Tommi74fc5742020-04-27 08:43:061455 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:261461 EXPECT_METRIC_EQ((kFreezeDelay + kInterFrameDelay).ms(),
Tommi74fc5742020-04-27 08:43:061462 metrics::MinSample("WebRTC.Video.MeanFreezeDurationMs"));
1463 EXPECT_METRIC_EQ(
Evan Shrubsole1edeb922022-08-08 11:51:261464 kExpectedTimeBetweenFreezes.ms(),
Tommi74fc5742020-04-27 08:43:061465 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:261472 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 08:43:061477 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1478
1479 for (int i = 0; i < kMinRequiredSamples; ++i) {
Evan Shrubsole1edeb922022-08-08 11:51:261480 time_controller_.AdvanceTime(kFrameDuration);
Philipp Hanckea204ad22022-07-08 16:43:251481 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
1482 content_type_);
Tommid7e08c82020-05-10 09:24:431483 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 08:43:061484 }
1485
1486 // Freezes and pauses should be included into harmonic frame rate.
1487 // Add freeze.
Evan Shrubsole1edeb922022-08-08 11:51:261488 time_controller_.AdvanceTime(kFreezeDuration);
Philipp Hanckea204ad22022-07-08 16:43:251489 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Philipp Hancked970b092022-06-17 05:34:231490 content_type_);
Tommid7e08c82020-05-10 09:24:431491 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 08:43:061492
1493 // Add pause.
Evan Shrubsole1edeb922022-08-08 11:51:261494 time_controller_.AdvanceTime(kPauseDuration);
Tommi74fc5742020-04-27 08:43:061495 statistics_proxy_->OnStreamInactive();
Philipp Hanckea204ad22022-07-08 16:43:251496 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
Philipp Hancked970b092022-06-17 05:34:231497 content_type_);
Tommid7e08c82020-05-10 09:24:431498 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 08:43:061499
Tommid93bf122020-05-10 18:24:591500 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 08:43:061501 double kSumSquaredFrameDurationSecs =
1502 (kMinRequiredSamples - 1) *
Evan Shrubsole1edeb922022-08-08 11:51:261503 (kFrameDuration.seconds<double>() * kFrameDuration.seconds<double>());
Tommi74fc5742020-04-27 08:43:061504 kSumSquaredFrameDurationSecs +=
Evan Shrubsole1edeb922022-08-08 11:51:261505 kFreezeDuration.seconds<double>() * kFreezeDuration.seconds<double>();
Tommi74fc5742020-04-27 08:43:061506 kSumSquaredFrameDurationSecs +=
Evan Shrubsole1edeb922022-08-08 11:51:261507 kPauseDuration.seconds<double>() * kPauseDuration.seconds<double>();
1508 const int kExpectedHarmonicFrameRateFps = std::round(
1509 kCallDuration.seconds<double>() / kSumSquaredFrameDurationSecs);
Tommi74fc5742020-04-27 08:43:061510 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:261521 const TimeDelta kInterFrameDelay = TimeDelta::Millis(33);
1522 const TimeDelta kPauseDuration = TimeDelta::Seconds(10);
Tommi74fc5742020-04-27 08:43:061523 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1524
1525 for (int i = 0; i <= kMinRequiredSamples; ++i) {
Tommid93bf122020-05-10 18:24:591526 VideoFrameMetaData meta = MetaData(frame);
Philipp Hanckea204ad22022-07-08 16:43:251527 statistics_proxy_->OnDecodedFrame(meta, absl::nullopt, TimeDelta::Zero(),
1528 TimeDelta::Zero(), TimeDelta::Zero(),
1529 content_type_);
Tommid93bf122020-05-10 18:24:591530 statistics_proxy_->OnRenderedFrame(meta);
Evan Shrubsole1edeb922022-08-08 11:51:261531 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 08:43:061532 }
1533 // Add a pause.
Evan Shrubsole1edeb922022-08-08 11:51:261534 time_controller_.AdvanceTime(kPauseDuration);
Tommi74fc5742020-04-27 08:43:061535 statistics_proxy_->OnStreamInactive();
Tommi74fc5742020-04-27 08:43:061536 // Second playback interval with triple the length.
1537 for (int i = 0; i <= kMinRequiredSamples * 3; ++i) {
Tommid93bf122020-05-10 18:24:591538 VideoFrameMetaData meta = MetaData(frame);
Philipp Hanckea204ad22022-07-08 16:43:251539 statistics_proxy_->OnDecodedFrame(meta, absl::nullopt, TimeDelta::Zero(),
1540 TimeDelta::Zero(), TimeDelta::Zero(),
1541 content_type_);
Tommid93bf122020-05-10 18:24:591542 statistics_proxy_->OnRenderedFrame(meta);
Evan Shrubsole1edeb922022-08-08 11:51:261543 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 08:43:061544 }
1545
Tommid93bf122020-05-10 18:24:591546 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 08:43:061547 // Average of two playback intervals.
Evan Shrubsole1edeb922022-08-08 11:51:261548 const TimeDelta kExpectedTimeBetweenFreezes =
1549 kInterFrameDelay * kMinRequiredSamples * 2;
Tommi74fc5742020-04-27 08:43:061550 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
1551 EXPECT_METRIC_EQ(-1, metrics::MinSample(
1552 "WebRTC.Video.Screenshare.MeanFreezeDurationMs"));
Evan Shrubsole1edeb922022-08-08 11:51:261553 EXPECT_METRIC_EQ(kExpectedTimeBetweenFreezes.ms(),
Tommi74fc5742020-04-27 08:43:061554 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:261560 kExpectedTimeBetweenFreezes.ms(),
Tommi74fc5742020-04-27 08:43:061561 metrics::MinSample("WebRTC.Video.MeanTimeBetweenFreezesMs"));
1562 }
1563}
1564
1565TEST_P(ReceiveStatisticsProxy2TestWithContent, ManyPausesAtTheBeginning) {
Evan Shrubsole1edeb922022-08-08 11:51:261566 const TimeDelta kInterFrameDelay = TimeDelta::Millis(33);
1567 const TimeDelta kPauseDuration = TimeDelta::Seconds(10);
Tommi74fc5742020-04-27 08:43:061568 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1569
1570 for (int i = 0; i <= kMinRequiredSamples; ++i) {
Philipp Hanckea204ad22022-07-08 16:43:251571 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
1572 content_type_);
Evan Shrubsole1edeb922022-08-08 11:51:261573 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 08:43:061574 statistics_proxy_->OnStreamInactive();
Evan Shrubsole1edeb922022-08-08 11:51:261575 time_controller_.AdvanceTime(kPauseDuration);
Philipp Hanckea204ad22022-07-08 16:43:251576 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
1577 content_type_);
Evan Shrubsole1edeb922022-08-08 11:51:261578 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 08:43:061579 }
1580
1581 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1582 nullptr);
Tommid7e08c82020-05-10 09:24:431583 // No freezes should be detected, as all long inter-frame delays were
1584 // pauses.
Tommi74fc5742020-04-27 08:43:061585 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:261595 const TimeDelta kInterFrameDelay = TimeDelta::Millis(20);
Tommi74fc5742020-04-27 08:43:061596 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 18:24:591601 VideoFrameMetaData meta = MetaData(frame_hd);
Philipp Hanckea204ad22022-07-08 16:43:251602 statistics_proxy_->OnDecodedFrame(meta, absl::nullopt, TimeDelta::Zero(),
1603 TimeDelta::Zero(), TimeDelta::Zero(),
1604 content_type_);
Tommid93bf122020-05-10 18:24:591605 statistics_proxy_->OnRenderedFrame(meta);
Evan Shrubsole1edeb922022-08-08 11:51:261606 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 08:43:061607 }
1608 // SD frames.
1609 for (int i = 0; i < 2 * kMinRequiredSamples; ++i) {
Tommid93bf122020-05-10 18:24:591610 VideoFrameMetaData meta = MetaData(frame_sd);
Philipp Hanckea204ad22022-07-08 16:43:251611 statistics_proxy_->OnDecodedFrame(meta, absl::nullopt, TimeDelta::Zero(),
1612 TimeDelta::Zero(), TimeDelta::Zero(),
1613 content_type_);
Tommid93bf122020-05-10 18:24:591614 statistics_proxy_->OnRenderedFrame(meta);
Evan Shrubsole1edeb922022-08-08 11:51:261615 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 08:43:061616 }
1617 // Extra last frame.
Tommid7e08c82020-05-10 09:24:431618 statistics_proxy_->OnRenderedFrame(MetaData(frame_sd));
Tommi74fc5742020-04-27 08:43:061619
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:261634 const TimeDelta kInterFrameDelay = TimeDelta::Millis(20);
Tommi74fc5742020-04-27 08:43:061635 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 18:24:591641 VideoFrameMetaData meta = MetaData(frame);
Philipp Hanckea204ad22022-07-08 16:43:251642 statistics_proxy_->OnDecodedFrame(meta, kLowQp, TimeDelta::Zero(),
1643 TimeDelta::Zero(), TimeDelta::Zero(),
1644 content_type_);
Tommid93bf122020-05-10 18:24:591645 statistics_proxy_->OnRenderedFrame(meta);
Evan Shrubsole1edeb922022-08-08 11:51:261646 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 08:43:061647 }
1648 // Blocky frames.
1649 for (int i = 0; i < 2 * kMinRequiredSamples; ++i) {
Tommid93bf122020-05-10 18:24:591650 VideoFrameMetaData meta = MetaData(frame);
Philipp Hanckea204ad22022-07-08 16:43:251651 statistics_proxy_->OnDecodedFrame(meta, kHighQp, TimeDelta::Zero(),
1652 TimeDelta::Zero(), TimeDelta::Zero(),
1653 content_type_);
Tommid93bf122020-05-10 18:24:591654 statistics_proxy_->OnRenderedFrame(meta);
Evan Shrubsole1edeb922022-08-08 11:51:261655 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 08:43:061656 }
1657 // Extra last frame.
Philipp Hanckea204ad22022-07-08 16:43:251658 statistics_proxy_->OnDecodedFrame(frame, kHighQp, TimeDelta::Zero(),
Philipp Hancked970b092022-06-17 05:34:231659 content_type_);
Tommid7e08c82020-05-10 09:24:431660 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 08:43:061661
Tommid93bf122020-05-10 18:24:591662 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 08:43:061663 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:261677 // To ensure long enough call duration.
1678 const TimeDelta kInterFrameDelay = TimeDelta::Seconds(2);
Tommi74fc5742020-04-27 08:43:061679
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 16:43:251685 statistics_proxy_->OnDecodedFrame(frame_hd, absl::nullopt, TimeDelta::Zero(),
1686 content_type_);
Tommi74fc5742020-04-27 08:43:061687
Evan Shrubsole1edeb922022-08-08 11:51:261688 time_controller_.AdvanceTime(TimeDelta::Zero());
Tommid7e08c82020-05-10 09:24:431689 statistics_proxy_->OnRenderedFrame(MetaData(frame_hd));
Evan Shrubsole1edeb922022-08-08 11:51:261690 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 08:43:061691 // Downscale.
Tommid7e08c82020-05-10 09:24:431692 statistics_proxy_->OnRenderedFrame(MetaData(frame_sd));
Evan Shrubsole1edeb922022-08-08 11:51:261693 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 08:43:061694 // Downscale.
Tommid7e08c82020-05-10 09:24:431695 statistics_proxy_->OnRenderedFrame(MetaData(frame_ld));
Evan Shrubsole1edeb922022-08-08 11:51:261696 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 08:43:061697 statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(),
1698 nullptr);
1699 const int kExpectedDownscales = 30; // 2 per 4 seconds = 30 per minute.
Ilya Nikolaevskiya55a54d2022-12-08 10:00:211700 if (!videocontenttypehelpers::IsScreenshare(content_type_)) {
Tommi74fc5742020-04-27 08:43:061701 EXPECT_METRIC_EQ(kExpectedDownscales,
1702 metrics::MinSample(
1703 "WebRTC.Video.NumberResolutionDownswitchesPerMinute"));
1704 }
1705}
1706
1707TEST_P(ReceiveStatisticsProxy2TestWithContent, DecodeTimeReported) {
Evan Shrubsole1edeb922022-08-08 11:51:261708 const TimeDelta kInterFrameDelay = TimeDelta::Millis(20);
Tommi74fc5742020-04-27 08:43:061709 const int kLowQp = 30;
Evan Shrubsole1edeb922022-08-08 11:51:261710 const TimeDelta kDecodeTime = TimeDelta::Millis(7);
Tommi74fc5742020-04-27 08:43:061711
1712 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1713
1714 for (int i = 0; i < kMinRequiredSamples; ++i) {
Evan Shrubsole1edeb922022-08-08 11:51:261715 statistics_proxy_->OnDecodedFrame(frame, kLowQp, kDecodeTime,
1716 content_type_);
1717 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 08:43:061718 }
Tommid93bf122020-05-10 18:24:591719 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 08:43:061720 EXPECT_METRIC_EQ(
Evan Shrubsole1edeb922022-08-08 11:51:261721 1, metrics::NumEvents("WebRTC.Video.DecodeTimeInMs", kDecodeTime.ms()));
Tommi74fc5742020-04-27 08:43:061722}
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:261729 const TimeDelta kInterFrameDelay1 = TimeDelta::Millis(30);
1730 const TimeDelta kInterFrameDelay2 = TimeDelta::Millis(50);
Tommi74fc5742020-04-27 08:43:061731 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:261735 time_controller_.AdvanceTime(kInterFrameDelay1);
Philipp Hanckea204ad22022-07-08 16:43:251736 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
1737 content_type);
Tommi74fc5742020-04-27 08:43:061738 }
1739
1740 videocontenttypehelpers::SetSimulcastId(&content_type, 2);
1741 for (int i = 0; i <= kMinRequiredSamples; ++i) {
Evan Shrubsole1edeb922022-08-08 11:51:261742 time_controller_.AdvanceTime(kInterFrameDelay2);
Philipp Hanckea204ad22022-07-08 16:43:251743 statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Zero(),
1744 content_type);
Tommi74fc5742020-04-27 08:43:061745 }
Tommid93bf122020-05-10 18:24:591746 FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 08:43:061747
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:261770 kInterFrameDelay1.ms(),
Tommi74fc5742020-04-27 08:43:061771 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs.S0"));
1772 EXPECT_METRIC_EQ(
Evan Shrubsole1edeb922022-08-08 11:51:261773 kInterFrameDelay2.ms(),
Tommi74fc5742020-04-27 08:43:061774 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs.S1"));
1775 EXPECT_METRIC_EQ(
Evan Shrubsole1edeb922022-08-08 11:51:261776 ((kInterFrameDelay1 + kInterFrameDelay2) / 2).ms(),
Tommi74fc5742020-04-27 08:43:061777 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1778 EXPECT_METRIC_EQ(
Evan Shrubsole1edeb922022-08-08 11:51:261779 kInterFrameDelay2.ms(),
Tommi74fc5742020-04-27 08:43:061780 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1781 EXPECT_METRIC_EQ(
Evan Shrubsole1edeb922022-08-08 11:51:261782 ((kInterFrameDelay1 + kInterFrameDelay2) / 2).ms(),
Tommi74fc5742020-04-27 08:43:061783 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:261803 EXPECT_METRIC_EQ(kInterFrameDelay1.ms(),
Tommi74fc5742020-04-27 08:43:061804 metrics::MinSample("WebRTC.Video.InterframeDelayInMs.S0"));
Evan Shrubsole1edeb922022-08-08 11:51:261805 EXPECT_METRIC_EQ(kInterFrameDelay2.ms(),
Tommi74fc5742020-04-27 08:43:061806 metrics::MinSample("WebRTC.Video.InterframeDelayInMs.S1"));
Evan Shrubsole1edeb922022-08-08 11:51:261807 EXPECT_METRIC_EQ((kInterFrameDelay1 + kInterFrameDelay2).ms() / 2,
Tommi74fc5742020-04-27 08:43:061808 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
Evan Shrubsole1edeb922022-08-08 11:51:261809 EXPECT_METRIC_EQ(kInterFrameDelay2.ms(),
Tommi74fc5742020-04-27 08:43:061810 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
Evan Shrubsole1edeb922022-08-08 11:51:261811 EXPECT_METRIC_EQ((kInterFrameDelay1 + kInterFrameDelay2).ms() / 2,
Tommi74fc5742020-04-27 08:43:061812 metrics::MinSample(
1813 "WebRTC.Video.InterframeDelayInMs.ExperimentGroup0"));
1814 }
1815}
1816
Tommi74fc5742020-04-27 08:43:061817} // namespace internal
1818} // namespace webrtc