blob: 22bed590efdedb453bd3c8f58b42ddd05cfc1d44 [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
Rasmus Brandt090fe082023-05-09 10:53:0111#include "video/receive_statistics_proxy.h"
Tommi74fc5742020-04-27 08:43:0612
13#include <limits>
14#include <memory>
Florent Castelli8037fc62024-08-29 13:00:4015#include <optional>
Tommi74fc5742020-04-27 08:43:0616#include <string>
17#include <tuple>
18#include <utility>
19
Tommi74fc5742020-04-27 08:43:0620#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"
Emil Vardar3f1e51d2024-08-27 12:14:3329#include "test/gmock.h"
Tommi74fc5742020-04-27 08:43:0630#include "test/gtest.h"
Jonas Oreland8ca06132022-03-14 11:52:4831#include "test/scoped_key_value_config.h"
Evan Shrubsole1edeb922022-08-08 11:51:2632#include "test/time_controller/simulated_time_controller.h"
Tommid7e08c82020-05-10 09:24:4333#include "video/video_receive_stream2.h"
Tommi74fc5742020-04-27 08:43:0634
35namespace webrtc {
36namespace internal {
37namespace {
Emil Vardar3f1e51d2024-08-27 12:14:3338using ::testing::DoubleEq;
39
Evan Shrubsole1edeb922022-08-08 11:51:2640const TimeDelta kFreqOffsetProcessInterval = TimeDelta::Seconds(40);
Tommi74fc5742020-04-27 08:43:0641const uint32_t kRemoteSsrc = 456;
42const int kMinRequiredSamples = 200;
43const int kWidth = 1280;
44const int kHeight = 720;
45} // namespace
46
47// TODO(sakal): ReceiveStatisticsProxy is lacking unittesting.
Rasmus Brandt090fe082023-05-09 10:53:0148class ReceiveStatisticsProxyTest : public ::testing::Test {
Tommi74fc5742020-04-27 08:43:0649 public:
Rasmus Brandt090fe082023-05-09 10:53:0150 ReceiveStatisticsProxyTest() : time_controller_(Timestamp::Millis(1234)) {
Tommi74fc5742020-04-27 08:43:0651 metrics::Reset();
Evan Shrubsole09da10e2022-10-14 14:38:3152 statistics_proxy_ = std::make_unique<ReceiveStatisticsProxy>(
53 kRemoteSsrc, time_controller_.GetClock(),
54 time_controller_.GetMainThread());
Tommi74fc5742020-04-27 08:43:0655 }
56
Rasmus Brandt090fe082023-05-09 10:53:0157 ~ReceiveStatisticsProxyTest() override { statistics_proxy_.reset(); }
Tommi553c8692020-05-05 13:35:4558
59 protected:
Tommid93bf122020-05-10 18:24:5960 // Convenience method to avoid too many explict flushes.
Tommif6f45432022-05-20 13:21:2061 VideoReceiveStreamInterface::Stats FlushAndGetStats() {
Evan Shrubsole1edeb922022-08-08 11:51:2662 time_controller_.AdvanceTime(TimeDelta::Zero());
Tommid93bf122020-05-10 18:24:5963 return statistics_proxy_->GetStats();
64 }
65
Florent Castelli8037fc62024-08-29 13:00:4066 void FlushAndUpdateHistograms(std::optional<int> fraction_lost,
Tommid93bf122020-05-10 18:24:5967 const StreamDataCounters& rtp_stats,
68 const StreamDataCounters* rtx_stats) {
Evan Shrubsole1edeb922022-08-08 11:51:2669 time_controller_.AdvanceTime(TimeDelta::Zero());
Tommid93bf122020-05-10 18:24:5970 statistics_proxy_->UpdateHistograms(fraction_lost, rtp_stats, rtx_stats);
71 }
72
Tommi74fc5742020-04-27 08:43:0673 VideoFrame CreateFrame(int width, int height) {
74 return CreateVideoFrame(width, height, 0);
75 }
76
Tommid7e08c82020-05-10 09:24:4377 VideoFrame CreateFrameWithRenderTime(Timestamp render_time) {
78 return CreateFrameWithRenderTimeMs(render_time.ms());
79 }
80
Tommi74fc5742020-04-27 08:43:0681 VideoFrame CreateFrameWithRenderTimeMs(int64_t render_time_ms) {
82 return CreateVideoFrame(kWidth, kHeight, render_time_ms);
83 }
84
85 VideoFrame CreateVideoFrame(int width, int height, int64_t render_time_ms) {
86 VideoFrame frame =
87 VideoFrame::Builder()
88 .set_video_frame_buffer(I420Buffer::Create(width, height))
Per K0fa90882024-03-13 08:52:4189 .set_rtp_timestamp(0)
Tommi74fc5742020-04-27 08:43:0690 .set_timestamp_ms(render_time_ms)
91 .set_rotation(kVideoRotation_0)
92 .build();
Evan Shrubsole1edeb922022-08-08 11:51:2693 frame.set_ntp_time_ms(
94 time_controller_.GetClock()->CurrentNtpInMilliseconds());
Tommi74fc5742020-04-27 08:43:0695 return frame;
96 }
97
Tommid7e08c82020-05-10 09:24:4398 // Return the current fake time as a Timestamp.
Evan Shrubsole1edeb922022-08-08 11:51:2699 Timestamp Now() { return time_controller_.GetClock()->CurrentTime(); }
Tommid7e08c82020-05-10 09:24:43100
101 // Creates a VideoFrameMetaData instance with a timestamp.
102 VideoFrameMetaData MetaData(const VideoFrame& frame, Timestamp ts) {
103 return VideoFrameMetaData(frame, ts);
104 }
105
106 // Creates a VideoFrameMetaData instance with the current fake time.
107 VideoFrameMetaData MetaData(const VideoFrame& frame) {
108 return VideoFrameMetaData(frame, Now());
109 }
110
Jonas Oreland8ca06132022-03-14 11:52:48111 test::ScopedKeyValueConfig field_trials_;
Evan Shrubsole1edeb922022-08-08 11:51:26112 GlobalSimulatedTimeController time_controller_;
Tommi74fc5742020-04-27 08:43:06113 std::unique_ptr<ReceiveStatisticsProxy> statistics_proxy_;
Tommi74fc5742020-04-27 08:43:06114};
115
Rasmus Brandt090fe082023-05-09 10:53:01116TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameIncreasesFramesDecoded) {
Tommi74fc5742020-04-27 08:43:06117 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_decoded);
118 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
119 for (uint32_t i = 1; i <= 3; ++i) {
Florent Castelli8037fc62024-08-29 13:00:40120 statistics_proxy_->OnDecodedFrame(frame, std::nullopt, TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:50121 VideoContentType::UNSPECIFIED,
122 VideoFrameType::kVideoFrameKey);
Tommid93bf122020-05-10 18:24:59123 EXPECT_EQ(i, FlushAndGetStats().frames_decoded);
Tommi74fc5742020-04-27 08:43:06124 }
125}
126
Rasmus Brandt090fe082023-05-09 10:53:01127TEST_F(ReceiveStatisticsProxyTest, DecodedFpsIsReported) {
Evan Shrubsole1edeb922022-08-08 11:51:26128 const Frequency kFps = Frequency::Hertz(20);
129 const int kRequiredSamples =
130 TimeDelta::Seconds(metrics::kMinRunTimeInSeconds) * kFps;
Tommi74fc5742020-04-27 08:43:06131 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
132 for (int i = 0; i < kRequiredSamples; ++i) {
Florent Castelli8037fc62024-08-29 13:00:40133 statistics_proxy_->OnDecodedFrame(frame, std::nullopt, TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:50134 VideoContentType::UNSPECIFIED,
135 VideoFrameType::kVideoFrameKey);
Evan Shrubsole1edeb922022-08-08 11:51:26136 time_controller_.AdvanceTime(1 / kFps);
Tommi74fc5742020-04-27 08:43:06137 }
Florent Castelli8037fc62024-08-29 13:00:40138 FlushAndUpdateHistograms(std::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 08:43:06139 EXPECT_METRIC_EQ(1,
140 metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
Evan Shrubsole1edeb922022-08-08 11:51:26141 EXPECT_METRIC_EQ(1, metrics::NumEvents("WebRTC.Video.DecodedFramesPerSecond",
142 kFps.hertz()));
Tommi74fc5742020-04-27 08:43:06143}
144
Rasmus Brandt090fe082023-05-09 10:53:01145TEST_F(ReceiveStatisticsProxyTest, DecodedFpsIsNotReportedForTooFewSamples) {
Evan Shrubsole1edeb922022-08-08 11:51:26146 const Frequency kFps = Frequency::Hertz(20);
147 const int kRequiredSamples =
148 TimeDelta::Seconds(metrics::kMinRunTimeInSeconds) * kFps;
Tommi74fc5742020-04-27 08:43:06149 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
150 for (int i = 0; i < kRequiredSamples - 1; ++i) {
Florent Castelli8037fc62024-08-29 13:00:40151 statistics_proxy_->OnDecodedFrame(frame, std::nullopt, TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:50152 VideoContentType::UNSPECIFIED,
153 VideoFrameType::kVideoFrameKey);
Evan Shrubsole1edeb922022-08-08 11:51:26154 time_controller_.AdvanceTime(1 / kFps);
Tommi74fc5742020-04-27 08:43:06155 }
Florent Castelli8037fc62024-08-29 13:00:40156 FlushAndUpdateHistograms(std::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 08:43:06157 EXPECT_METRIC_EQ(0,
158 metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
159}
160
Rasmus Brandt090fe082023-05-09 10:53:01161TEST_F(ReceiveStatisticsProxyTest,
Tommi74fc5742020-04-27 08:43:06162 OnDecodedFrameWithQpDoesNotResetFramesDecodedOrTotalDecodeTime) {
163 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_decoded);
164 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Philipp Hanckea204ad22022-07-08 16:43:25165 TimeDelta expected_total_decode_time = TimeDelta::Zero();
Tommi74fc5742020-04-27 08:43:06166 unsigned int expected_frames_decoded = 0;
167 for (uint32_t i = 1; i <= 3; ++i) {
Florent Castelli8037fc62024-08-29 13:00:40168 statistics_proxy_->OnDecodedFrame(frame, std::nullopt, TimeDelta::Millis(1),
169 VideoContentType::UNSPECIFIED,
170 VideoFrameType::kVideoFrameKey);
Philipp Hancked970b092022-06-17 05:34:23171 expected_total_decode_time += TimeDelta::Millis(1);
Tommi74fc5742020-04-27 08:43:06172 ++expected_frames_decoded;
Evan Shrubsole1edeb922022-08-08 11:51:26173 time_controller_.AdvanceTime(TimeDelta::Zero());
Tommi74fc5742020-04-27 08:43:06174 EXPECT_EQ(expected_frames_decoded,
175 statistics_proxy_->GetStats().frames_decoded);
Philipp Hancked970b092022-06-17 05:34:23176 EXPECT_EQ(expected_total_decode_time,
177 statistics_proxy_->GetStats().total_decode_time);
Tommi74fc5742020-04-27 08:43:06178 }
Philipp Hancked970b092022-06-17 05:34:23179 statistics_proxy_->OnDecodedFrame(frame, 1u, TimeDelta::Millis(3),
Philipp Hancke51657432023-08-15 08:20:50180 VideoContentType::UNSPECIFIED,
181 VideoFrameType::kVideoFrameKey);
Tommi74fc5742020-04-27 08:43:06182 ++expected_frames_decoded;
Philipp Hancked970b092022-06-17 05:34:23183 expected_total_decode_time += TimeDelta::Millis(3);
Evan Shrubsole1edeb922022-08-08 11:51:26184 time_controller_.AdvanceTime(TimeDelta::Zero());
Tommi74fc5742020-04-27 08:43:06185 EXPECT_EQ(expected_frames_decoded,
186 statistics_proxy_->GetStats().frames_decoded);
Philipp Hancked970b092022-06-17 05:34:23187 EXPECT_EQ(expected_total_decode_time,
188 statistics_proxy_->GetStats().total_decode_time);
Tommi74fc5742020-04-27 08:43:06189}
190
Rasmus Brandt090fe082023-05-09 10:53:01191TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameIncreasesProcessingDelay) {
Philipp Hanckea16a6a62022-04-25 10:21:30192 const TimeDelta kProcessingDelay = TimeDelta::Millis(10);
193 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_decoded);
194 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Philipp Hanckea204ad22022-07-08 16:43:25195 TimeDelta expected_total_processing_delay = TimeDelta::Zero();
Philipp Hanckea16a6a62022-04-25 10:21:30196 unsigned int expected_frames_decoded = 0;
197 // We set receive time fixed and increase the clock by 10ms
198 // in the loop which will increase the processing delay by
199 // 10/20/30ms respectively.
Alessio Bazzicaa1d03562022-09-19 16:05:29200 RtpPacketInfos::vector_type packet_infos = {RtpPacketInfo(
201 /*ssrc=*/{}, /*csrcs=*/{}, /*rtp_timestamp=*/{}, /*receive_time=*/Now())};
Philipp Hanckea16a6a62022-04-25 10:21:30202 frame.set_packet_infos(RtpPacketInfos(packet_infos));
203 for (int i = 1; i <= 3; ++i) {
Evan Shrubsole1edeb922022-08-08 11:51:26204 time_controller_.AdvanceTime(kProcessingDelay);
Florent Castelli8037fc62024-08-29 13:00:40205 statistics_proxy_->OnDecodedFrame(frame, std::nullopt, TimeDelta::Millis(1),
206 VideoContentType::UNSPECIFIED,
207 VideoFrameType::kVideoFrameKey);
Philipp Hanckea16a6a62022-04-25 10:21:30208 expected_total_processing_delay += i * kProcessingDelay;
209 ++expected_frames_decoded;
Evan Shrubsole1edeb922022-08-08 11:51:26210 time_controller_.AdvanceTime(TimeDelta::Zero());
Philipp Hanckea16a6a62022-04-25 10:21:30211 EXPECT_EQ(expected_frames_decoded,
212 statistics_proxy_->GetStats().frames_decoded);
213 EXPECT_EQ(expected_total_processing_delay,
214 statistics_proxy_->GetStats().total_processing_delay);
215 }
Evan Shrubsole1edeb922022-08-08 11:51:26216 time_controller_.AdvanceTime(kProcessingDelay);
Philipp Hancked970b092022-06-17 05:34:23217 statistics_proxy_->OnDecodedFrame(frame, 1u, TimeDelta::Millis(3),
Philipp Hancke51657432023-08-15 08:20:50218 VideoContentType::UNSPECIFIED,
219 VideoFrameType::kVideoFrameKey);
Philipp Hanckea16a6a62022-04-25 10:21:30220 ++expected_frames_decoded;
221 expected_total_processing_delay += 4 * kProcessingDelay;
Evan Shrubsole1edeb922022-08-08 11:51:26222 time_controller_.AdvanceTime(TimeDelta::Zero());
Philipp Hanckea16a6a62022-04-25 10:21:30223 EXPECT_EQ(expected_frames_decoded,
224 statistics_proxy_->GetStats().frames_decoded);
225 EXPECT_EQ(expected_total_processing_delay,
226 statistics_proxy_->GetStats().total_processing_delay);
227}
228
Rasmus Brandt090fe082023-05-09 10:53:01229TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameIncreasesAssemblyTime) {
Philipp Hancke0359ba22022-05-05 13:55:36230 const TimeDelta kAssemblyTime = TimeDelta::Millis(7);
231 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_decoded);
232 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Philipp Hanckea204ad22022-07-08 16:43:25233 TimeDelta expected_total_assembly_time = TimeDelta::Zero();
Philipp Hancke0359ba22022-05-05 13:55:36234 unsigned int expected_frames_decoded = 0;
235 unsigned int expected_frames_assembled_from_multiple_packets = 0;
236
237 // A single-packet frame will not increase total assembly time
238 // and frames assembled.
Alessio Bazzicaa1d03562022-09-19 16:05:29239 RtpPacketInfos::vector_type single_packet_frame = {RtpPacketInfo(
240 /*ssrc=*/{}, /*csrcs=*/{}, /*rtp_timestamp=*/{}, /*receive_time=*/Now())};
Philipp Hancke0359ba22022-05-05 13:55:36241 frame.set_packet_infos(RtpPacketInfos(single_packet_frame));
Florent Castelli8037fc62024-08-29 13:00:40242 statistics_proxy_->OnDecodedFrame(frame, std::nullopt, TimeDelta::Millis(1),
Philipp Hancke51657432023-08-15 08:20:50243 VideoContentType::UNSPECIFIED,
244 VideoFrameType::kVideoFrameKey);
Philipp Hancke0359ba22022-05-05 13:55:36245 ++expected_frames_decoded;
Evan Shrubsole1edeb922022-08-08 11:51:26246 time_controller_.AdvanceTime(TimeDelta::Zero());
Philipp Hancke0359ba22022-05-05 13:55:36247 EXPECT_EQ(expected_total_assembly_time,
248 statistics_proxy_->GetStats().total_assembly_time);
249 EXPECT_EQ(
250 expected_frames_assembled_from_multiple_packets,
251 statistics_proxy_->GetStats().frames_assembled_from_multiple_packets);
252
253 // In an ordered frame the first and last packet matter.
254 RtpPacketInfos::vector_type ordered_frame = {
Alessio Bazzicaa1d03562022-09-19 16:05:29255 RtpPacketInfo(/*ssrc=*/{}, /*csrcs=*/{}, /*rtp_timestamp=*/{},
256 /*receive_time=*/Now()),
257 RtpPacketInfo(/*ssrc=*/{}, /*csrcs=*/{}, /*rtp_timestamp=*/{},
258 /*receive_time=*/Now() + kAssemblyTime),
259 RtpPacketInfo(/*ssrc=*/{}, /*csrcs=*/{}, /*rtp_timestamp=*/{},
260 /*receive_time=*/Now() + 2 * kAssemblyTime),
Philipp Hancke0359ba22022-05-05 13:55:36261 };
262 frame.set_packet_infos(RtpPacketInfos(ordered_frame));
Philipp Hancked970b092022-06-17 05:34:23263 statistics_proxy_->OnDecodedFrame(frame, 1u, TimeDelta::Millis(3),
Philipp Hancke51657432023-08-15 08:20:50264 VideoContentType::UNSPECIFIED,
265 VideoFrameType::kVideoFrameKey);
Philipp Hancke0359ba22022-05-05 13:55:36266 ++expected_frames_decoded;
267 ++expected_frames_assembled_from_multiple_packets;
268 expected_total_assembly_time += 2 * kAssemblyTime;
Evan Shrubsole1edeb922022-08-08 11:51:26269 time_controller_.AdvanceTime(TimeDelta::Zero());
Philipp Hancke0359ba22022-05-05 13:55:36270 EXPECT_EQ(expected_frames_decoded,
271 statistics_proxy_->GetStats().frames_decoded);
272 EXPECT_EQ(expected_total_assembly_time,
273 statistics_proxy_->GetStats().total_assembly_time);
274 EXPECT_EQ(
275 expected_frames_assembled_from_multiple_packets,
276 statistics_proxy_->GetStats().frames_assembled_from_multiple_packets);
277
278 // "First" and "last" are in receive time, not sequence number.
279 RtpPacketInfos::vector_type unordered_frame = {
Alessio Bazzicaa1d03562022-09-19 16:05:29280 RtpPacketInfo(/*ssrc=*/{}, /*csrcs=*/{}, /*rtp_timestamp=*/{},
281 /*receive_time=*/Now() + 2 * kAssemblyTime),
282 RtpPacketInfo(/*ssrc=*/{}, /*csrcs=*/{}, /*rtp_timestamp=*/{},
283 /*receive_time=*/Now()),
284 RtpPacketInfo(/*ssrc=*/{}, /*csrcs=*/{}, /*rtp_timestamp=*/{},
285 /*receive_time=*/Now() + kAssemblyTime),
Philipp Hancke0359ba22022-05-05 13:55:36286 };
287 frame.set_packet_infos(RtpPacketInfos(unordered_frame));
Philipp Hancked970b092022-06-17 05:34:23288 statistics_proxy_->OnDecodedFrame(frame, 1u, TimeDelta::Millis(3),
Philipp Hancke51657432023-08-15 08:20:50289 VideoContentType::UNSPECIFIED,
290 VideoFrameType::kVideoFrameKey);
Philipp Hancke0359ba22022-05-05 13:55:36291 ++expected_frames_decoded;
292 ++expected_frames_assembled_from_multiple_packets;
293 expected_total_assembly_time += 2 * kAssemblyTime;
Evan Shrubsole1edeb922022-08-08 11:51:26294 time_controller_.AdvanceTime(TimeDelta::Zero());
Philipp Hancke0359ba22022-05-05 13:55:36295 EXPECT_EQ(expected_frames_decoded,
296 statistics_proxy_->GetStats().frames_decoded);
297 EXPECT_EQ(expected_total_assembly_time,
298 statistics_proxy_->GetStats().total_assembly_time);
299 EXPECT_EQ(
300 expected_frames_assembled_from_multiple_packets,
301 statistics_proxy_->GetStats().frames_assembled_from_multiple_packets);
302}
303
Rasmus Brandt090fe082023-05-09 10:53:01304TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameIncreasesQpSum) {
Florent Castelli8037fc62024-08-29 13:00:40305 EXPECT_EQ(std::nullopt, statistics_proxy_->GetStats().qp_sum);
Tommi74fc5742020-04-27 08:43:06306 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Philipp Hanckea204ad22022-07-08 16:43:25307 statistics_proxy_->OnDecodedFrame(frame, 3u, TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:50308 VideoContentType::UNSPECIFIED,
309 VideoFrameType::kVideoFrameKey);
Tommid93bf122020-05-10 18:24:59310 EXPECT_EQ(3u, FlushAndGetStats().qp_sum);
Philipp Hanckea204ad22022-07-08 16:43:25311 statistics_proxy_->OnDecodedFrame(frame, 127u, TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:50312 VideoContentType::UNSPECIFIED,
313 VideoFrameType::kVideoFrameDelta);
Tommid93bf122020-05-10 18:24:59314 EXPECT_EQ(130u, FlushAndGetStats().qp_sum);
Tommi74fc5742020-04-27 08:43:06315}
316
Rasmus Brandt090fe082023-05-09 10:53:01317TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameIncreasesTotalDecodeTime) {
Florent Castelli8037fc62024-08-29 13:00:40318 EXPECT_EQ(std::nullopt, statistics_proxy_->GetStats().qp_sum);
Tommi74fc5742020-04-27 08:43:06319 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Philipp Hancked970b092022-06-17 05:34:23320 statistics_proxy_->OnDecodedFrame(frame, 3u, TimeDelta::Millis(4),
Philipp Hancke51657432023-08-15 08:20:50321 VideoContentType::UNSPECIFIED,
322 VideoFrameType::kVideoFrameKey);
Philipp Hancked970b092022-06-17 05:34:23323 EXPECT_EQ(4u, FlushAndGetStats().total_decode_time.ms());
324 statistics_proxy_->OnDecodedFrame(frame, 127u, TimeDelta::Millis(7),
Philipp Hancke51657432023-08-15 08:20:50325 VideoContentType::UNSPECIFIED,
326 VideoFrameType::kVideoFrameDelta);
Philipp Hancked970b092022-06-17 05:34:23327 EXPECT_EQ(11u, FlushAndGetStats().total_decode_time.ms());
Tommi74fc5742020-04-27 08:43:06328}
329
Rasmus Brandt090fe082023-05-09 10:53:01330TEST_F(ReceiveStatisticsProxyTest, ReportsContentType) {
Tommi74fc5742020-04-27 08:43:06331 const std::string kRealtimeString("realtime");
332 const std::string kScreenshareString("screen");
333 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
334 EXPECT_EQ(kRealtimeString, videocontenttypehelpers::ToString(
335 statistics_proxy_->GetStats().content_type));
Philipp Hanckea204ad22022-07-08 16:43:25336 statistics_proxy_->OnDecodedFrame(frame, 3u, TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:50337 VideoContentType::SCREENSHARE,
338 VideoFrameType::kVideoFrameKey);
Tommi74fc5742020-04-27 08:43:06339 EXPECT_EQ(kScreenshareString,
Tommid93bf122020-05-10 18:24:59340 videocontenttypehelpers::ToString(FlushAndGetStats().content_type));
Philipp Hanckea204ad22022-07-08 16:43:25341 statistics_proxy_->OnDecodedFrame(frame, 3u, TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:50342 VideoContentType::UNSPECIFIED,
343 VideoFrameType::kVideoFrameDelta);
Tommid93bf122020-05-10 18:24:59344 EXPECT_EQ(kRealtimeString,
345 videocontenttypehelpers::ToString(FlushAndGetStats().content_type));
Tommi74fc5742020-04-27 08:43:06346}
347
Rasmus Brandt090fe082023-05-09 10:53:01348TEST_F(ReceiveStatisticsProxyTest, ReportsMaxInterframeDelay) {
Tommi74fc5742020-04-27 08:43:06349 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Evan Shrubsole1edeb922022-08-08 11:51:26350 const TimeDelta kInterframeDelay1 = TimeDelta::Millis(100);
351 const TimeDelta kInterframeDelay2 = TimeDelta::Millis(200);
352 const TimeDelta kInterframeDelay3 = TimeDelta::Millis(100);
Tommi74fc5742020-04-27 08:43:06353 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
Florent Castelli8037fc62024-08-29 13:00:40354 statistics_proxy_->OnDecodedFrame(frame, std::nullopt, TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:50355 VideoContentType::UNSPECIFIED,
356 VideoFrameType::kVideoFrameKey);
Tommid93bf122020-05-10 18:24:59357 EXPECT_EQ(-1, FlushAndGetStats().interframe_delay_max_ms);
Tommi74fc5742020-04-27 08:43:06358
Evan Shrubsole1edeb922022-08-08 11:51:26359 time_controller_.AdvanceTime(kInterframeDelay1);
Florent Castelli8037fc62024-08-29 13:00:40360 statistics_proxy_->OnDecodedFrame(frame, std::nullopt, TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:50361 VideoContentType::UNSPECIFIED,
362 VideoFrameType::kVideoFrameDelta);
Evan Shrubsole1edeb922022-08-08 11:51:26363 EXPECT_EQ(kInterframeDelay1.ms(), FlushAndGetStats().interframe_delay_max_ms);
Tommi74fc5742020-04-27 08:43:06364
Evan Shrubsole1edeb922022-08-08 11:51:26365 time_controller_.AdvanceTime(kInterframeDelay2);
Florent Castelli8037fc62024-08-29 13:00:40366 statistics_proxy_->OnDecodedFrame(frame, std::nullopt, TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:50367 VideoContentType::UNSPECIFIED,
368 VideoFrameType::kVideoFrameDelta);
Evan Shrubsole1edeb922022-08-08 11:51:26369 EXPECT_EQ(kInterframeDelay2.ms(), FlushAndGetStats().interframe_delay_max_ms);
Tommi74fc5742020-04-27 08:43:06370
Evan Shrubsole1edeb922022-08-08 11:51:26371 time_controller_.AdvanceTime(kInterframeDelay3);
Florent Castelli8037fc62024-08-29 13:00:40372 statistics_proxy_->OnDecodedFrame(frame, std::nullopt, TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:50373 VideoContentType::UNSPECIFIED,
374 VideoFrameType::kVideoFrameDelta);
Evan Shrubsole1edeb922022-08-08 11:51:26375 // kInterframeDelay3 is smaller than kInterframeDelay2.
376 EXPECT_EQ(kInterframeDelay2.ms(), FlushAndGetStats().interframe_delay_max_ms);
Tommi74fc5742020-04-27 08:43:06377}
378
Rasmus Brandt090fe082023-05-09 10:53:01379TEST_F(ReceiveStatisticsProxyTest, ReportInterframeDelayInWindow) {
Tommi74fc5742020-04-27 08:43:06380 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Evan Shrubsole1edeb922022-08-08 11:51:26381 const TimeDelta kInterframeDelay1 = TimeDelta::Millis(900);
382 const TimeDelta kInterframeDelay2 = TimeDelta::Millis(750);
383 const TimeDelta kInterframeDelay3 = TimeDelta::Millis(700);
Tommi74fc5742020-04-27 08:43:06384 EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
Florent Castelli8037fc62024-08-29 13:00:40385 statistics_proxy_->OnDecodedFrame(frame, std::nullopt, TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:50386 VideoContentType::UNSPECIFIED,
387 VideoFrameType::kVideoFrameKey);
Tommid93bf122020-05-10 18:24:59388 EXPECT_EQ(-1, FlushAndGetStats().interframe_delay_max_ms);
Tommi74fc5742020-04-27 08:43:06389
Evan Shrubsole1edeb922022-08-08 11:51:26390 time_controller_.AdvanceTime(kInterframeDelay1);
Florent Castelli8037fc62024-08-29 13:00:40391 statistics_proxy_->OnDecodedFrame(frame, std::nullopt, TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:50392 VideoContentType::UNSPECIFIED,
393 VideoFrameType::kVideoFrameDelta);
Evan Shrubsole1edeb922022-08-08 11:51:26394 EXPECT_EQ(kInterframeDelay1.ms(), FlushAndGetStats().interframe_delay_max_ms);
Tommi74fc5742020-04-27 08:43:06395
Evan Shrubsole1edeb922022-08-08 11:51:26396 time_controller_.AdvanceTime(kInterframeDelay2);
Florent Castelli8037fc62024-08-29 13:00:40397 statistics_proxy_->OnDecodedFrame(frame, std::nullopt, TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:50398 VideoContentType::UNSPECIFIED,
399 VideoFrameType::kVideoFrameDelta);
Tommi74fc5742020-04-27 08:43:06400 // Still first delay is the maximum
Evan Shrubsole1edeb922022-08-08 11:51:26401 EXPECT_EQ(kInterframeDelay1.ms(), FlushAndGetStats().interframe_delay_max_ms);
Tommi74fc5742020-04-27 08:43:06402
Evan Shrubsole1edeb922022-08-08 11:51:26403 time_controller_.AdvanceTime(kInterframeDelay3);
Florent Castelli8037fc62024-08-29 13:00:40404 statistics_proxy_->OnDecodedFrame(frame, std::nullopt, TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:50405 VideoContentType::UNSPECIFIED,
406 VideoFrameType::kVideoFrameDelta);
Tommi74fc5742020-04-27 08:43:06407 // Now the first sample is out of the window, so the second is the maximum.
Evan Shrubsole1edeb922022-08-08 11:51:26408 EXPECT_EQ(kInterframeDelay2.ms(), FlushAndGetStats().interframe_delay_max_ms);
Tommi74fc5742020-04-27 08:43:06409}
410
Rasmus Brandt090fe082023-05-09 10:53:01411TEST_F(ReceiveStatisticsProxyTest, ReportsFreezeMetrics) {
Evan Shrubsole1edeb922022-08-08 11:51:26412 const TimeDelta kFreezeDuration = TimeDelta::Seconds(1);
Tommi74fc5742020-04-27 08:43:06413
Tommif6f45432022-05-20 13:21:20414 VideoReceiveStreamInterface::Stats stats = statistics_proxy_->GetStats();
Tommi74fc5742020-04-27 08:43:06415 EXPECT_EQ(0u, stats.freeze_count);
416 EXPECT_FALSE(stats.total_freezes_duration_ms);
417
418 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
419 for (size_t i = 0; i < VideoQualityObserver::kMinFrameSamplesToDetectFreeze;
420 ++i) {
Evan Shrubsole1edeb922022-08-08 11:51:26421 time_controller_.AdvanceTime(TimeDelta::Millis(30));
Tommid7e08c82020-05-10 09:24:43422 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 08:43:06423 }
424
425 // Freeze.
Evan Shrubsole1edeb922022-08-08 11:51:26426 time_controller_.AdvanceTime(kFreezeDuration);
Tommid7e08c82020-05-10 09:24:43427 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 08:43:06428
429 stats = statistics_proxy_->GetStats();
430 EXPECT_EQ(1u, stats.freeze_count);
Evan Shrubsole1edeb922022-08-08 11:51:26431 EXPECT_EQ(kFreezeDuration.ms(), stats.total_freezes_duration_ms);
Tommi74fc5742020-04-27 08:43:06432}
433
Rasmus Brandt090fe082023-05-09 10:53:01434TEST_F(ReceiveStatisticsProxyTest, ReportsPauseMetrics) {
Tommif6f45432022-05-20 13:21:20435 VideoReceiveStreamInterface::Stats stats = statistics_proxy_->GetStats();
Tommi74fc5742020-04-27 08:43:06436 ASSERT_EQ(0u, stats.pause_count);
437 ASSERT_EQ(0u, stats.total_pauses_duration_ms);
438
439 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Tommid7e08c82020-05-10 09:24:43440 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 08:43:06441
442 // Pause.
Evan Shrubsole1edeb922022-08-08 11:51:26443 time_controller_.AdvanceTime(TimeDelta::Millis(5432));
Tommi74fc5742020-04-27 08:43:06444 statistics_proxy_->OnStreamInactive();
Tommid7e08c82020-05-10 09:24:43445 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 08:43:06446
447 stats = statistics_proxy_->GetStats();
448 EXPECT_EQ(1u, stats.pause_count);
449 EXPECT_EQ(5432u, stats.total_pauses_duration_ms);
450}
451
Rasmus Brandt090fe082023-05-09 10:53:01452TEST_F(ReceiveStatisticsProxyTest, PauseBeforeFirstAndAfterLastFrameIgnored) {
Tommif6f45432022-05-20 13:21:20453 VideoReceiveStreamInterface::Stats stats = statistics_proxy_->GetStats();
Tommi74fc5742020-04-27 08:43:06454 ASSERT_EQ(0u, stats.pause_count);
455 ASSERT_EQ(0u, stats.total_pauses_duration_ms);
456
457 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
458
459 // Pause -> Frame -> Pause
Evan Shrubsole1edeb922022-08-08 11:51:26460 time_controller_.AdvanceTime(TimeDelta::Seconds(5));
Tommi74fc5742020-04-27 08:43:06461 statistics_proxy_->OnStreamInactive();
Tommid7e08c82020-05-10 09:24:43462 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 08:43:06463
Evan Shrubsole1edeb922022-08-08 11:51:26464 time_controller_.AdvanceTime(TimeDelta::Millis(30));
Tommid7e08c82020-05-10 09:24:43465 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 08:43:06466
Evan Shrubsole1edeb922022-08-08 11:51:26467 time_controller_.AdvanceTime(TimeDelta::Seconds(5));
Tommi74fc5742020-04-27 08:43:06468 statistics_proxy_->OnStreamInactive();
469
470 stats = statistics_proxy_->GetStats();
471 EXPECT_EQ(0u, stats.pause_count);
472 EXPECT_EQ(0u, stats.total_pauses_duration_ms);
473}
474
Rasmus Brandt090fe082023-05-09 10:53:01475TEST_F(ReceiveStatisticsProxyTest, ReportsTotalInterFrameDelay) {
Tommif6f45432022-05-20 13:21:20476 VideoReceiveStreamInterface::Stats stats = statistics_proxy_->GetStats();
Sergey Silkined0dd8e2022-12-20 12:58:15477 ASSERT_EQ(0.0, stats.total_inter_frame_delay);
Tommi74fc5742020-04-27 08:43:06478
479 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
480
481 // Emulate delay before first frame is rendered. This is needed to ensure
482 // that frame duration only covers time since first frame is rendered and
483 // not the total time.
Evan Shrubsole1edeb922022-08-08 11:51:26484 time_controller_.AdvanceTime(TimeDelta::Millis(5432));
Tommi74fc5742020-04-27 08:43:06485 for (int i = 0; i <= 10; ++i) {
Evan Shrubsole1edeb922022-08-08 11:51:26486 time_controller_.AdvanceTime(TimeDelta::Millis(30));
Tommid7e08c82020-05-10 09:24:43487 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 08:43:06488 }
489
490 stats = statistics_proxy_->GetStats();
Sergey Silkined0dd8e2022-12-20 12:58:15491 EXPECT_EQ(10 * 30 / 1000.0, stats.total_inter_frame_delay);
Tommi74fc5742020-04-27 08:43:06492}
493
Rasmus Brandt090fe082023-05-09 10:53:01494TEST_F(ReceiveStatisticsProxyTest, ReportsTotalSquaredInterFrameDelay) {
Tommif6f45432022-05-20 13:21:20495 VideoReceiveStreamInterface::Stats stats = statistics_proxy_->GetStats();
Sergey Silkined0dd8e2022-12-20 12:58:15496 ASSERT_EQ(0.0, stats.total_squared_inter_frame_delay);
Tommi74fc5742020-04-27 08:43:06497
498 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
499 for (int i = 0; i <= 10; ++i) {
Evan Shrubsole1edeb922022-08-08 11:51:26500 time_controller_.AdvanceTime(TimeDelta::Millis(30));
Tommid7e08c82020-05-10 09:24:43501 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 08:43:06502 }
503
504 stats = statistics_proxy_->GetStats();
Sergey Silkined0dd8e2022-12-20 12:58:15505 const double kExpectedTotalSquaredInterFrameDelaySecs =
Tommi74fc5742020-04-27 08:43:06506 10 * (30 / 1000.0 * 30 / 1000.0);
Sergey Silkined0dd8e2022-12-20 12:58:15507 EXPECT_EQ(kExpectedTotalSquaredInterFrameDelaySecs,
508 stats.total_squared_inter_frame_delay);
Tommi74fc5742020-04-27 08:43:06509}
510
Rasmus Brandt090fe082023-05-09 10:53:01511TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameWithoutQpQpSumWontExist) {
Tommi74fc5742020-04-27 08:43:06512 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Florent Castelli8037fc62024-08-29 13:00:40513 EXPECT_EQ(std::nullopt, statistics_proxy_->GetStats().qp_sum);
514 statistics_proxy_->OnDecodedFrame(frame, std::nullopt, TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:50515 VideoContentType::UNSPECIFIED,
516 VideoFrameType::kVideoFrameKey);
Florent Castelli8037fc62024-08-29 13:00:40517 EXPECT_EQ(std::nullopt, FlushAndGetStats().qp_sum);
Tommi74fc5742020-04-27 08:43:06518}
519
Rasmus Brandt090fe082023-05-09 10:53:01520TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameWithoutQpResetsQpSum) {
Tommi74fc5742020-04-27 08:43:06521 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Florent Castelli8037fc62024-08-29 13:00:40522 EXPECT_EQ(std::nullopt, statistics_proxy_->GetStats().qp_sum);
Philipp Hanckea204ad22022-07-08 16:43:25523 statistics_proxy_->OnDecodedFrame(frame, 3u, TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:50524 VideoContentType::UNSPECIFIED,
525 VideoFrameType::kVideoFrameKey);
Tommid93bf122020-05-10 18:24:59526 EXPECT_EQ(3u, FlushAndGetStats().qp_sum);
Florent Castelli8037fc62024-08-29 13:00:40527 statistics_proxy_->OnDecodedFrame(frame, std::nullopt, TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:50528 VideoContentType::UNSPECIFIED,
529 VideoFrameType::kVideoFrameDelta);
Florent Castelli8037fc62024-08-29 13:00:40530 EXPECT_EQ(std::nullopt, FlushAndGetStats().qp_sum);
Tommi74fc5742020-04-27 08:43:06531}
532
Rasmus Brandt090fe082023-05-09 10:53:01533TEST_F(ReceiveStatisticsProxyTest, OnRenderedFrameIncreasesFramesRendered) {
Tommi74fc5742020-04-27 08:43:06534 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_rendered);
535 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
536 for (uint32_t i = 1; i <= 3; ++i) {
Tommid7e08c82020-05-10 09:24:43537 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 08:43:06538 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_rendered);
539 }
540}
541
Emil Vardar3f1e51d2024-08-27 12:14:33542TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsOnCorruptionScore) {
Florent Castelli8037fc62024-08-29 13:00:40543 EXPECT_EQ(std::nullopt, statistics_proxy_->GetStats().corruption_score_sum);
544 EXPECT_EQ(std::nullopt,
Emil Vardar3f1e51d2024-08-27 12:14:33545 statistics_proxy_->GetStats().corruption_score_squared_sum);
546 EXPECT_EQ(0u, statistics_proxy_->GetStats().corruption_score_count);
547
548 const std::vector<double> corruption_scores = {0.5, 0.25, 0.80};
549 const double kExpectedCorruptionScoreSum = 0.5 + 0.25 + 0.80;
550 const double kExpectedCorruptionScoreSquaredSum =
551 0.5 * 0.5 + 0.25 * 0.25 + 0.80 * 0.80;
552 for (size_t i = 0; i < corruption_scores.size(); ++i) {
553 statistics_proxy_->OnCorruptionScore(
554 /*corruption_score=*/corruption_scores[i],
555 VideoContentType::UNSPECIFIED);
556 }
557
558 VideoReceiveStreamInterface::Stats stats = statistics_proxy_->GetStats();
559 EXPECT_THAT(kExpectedCorruptionScoreSum,
560 DoubleEq(*stats.corruption_score_sum));
561 EXPECT_THAT(kExpectedCorruptionScoreSquaredSum,
562 DoubleEq(*stats.corruption_score_squared_sum));
563 EXPECT_EQ(3u, stats.corruption_score_count);
564}
565
Rasmus Brandt090fe082023-05-09 10:53:01566TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsSsrc) {
Tommi74fc5742020-04-27 08:43:06567 EXPECT_EQ(kRemoteSsrc, statistics_proxy_->GetStats().ssrc);
568}
569
Rasmus Brandt090fe082023-05-09 10:53:01570TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsIncomingPayloadType) {
Tommi74fc5742020-04-27 08:43:06571 const int kPayloadType = 111;
572 statistics_proxy_->OnIncomingPayloadType(kPayloadType);
Evan Shrubsole1edeb922022-08-08 11:51:26573 time_controller_.AdvanceTime(TimeDelta::Zero());
Tommi74fc5742020-04-27 08:43:06574 EXPECT_EQ(kPayloadType, statistics_proxy_->GetStats().current_payload_type);
575}
576
Rasmus Brandt090fe082023-05-09 10:53:01577TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsDecoderInfo) {
Evan Shrubsole09da10e2022-10-14 14:38:31578 auto init_stats = statistics_proxy_->GetStats();
Florent Castelli8037fc62024-08-29 13:00:40579 EXPECT_EQ(init_stats.decoder_implementation_name, std::nullopt);
580 EXPECT_EQ(init_stats.power_efficient_decoder, std::nullopt);
Evan Shrubsole09da10e2022-10-14 14:38:31581
582 const VideoDecoder::DecoderInfo decoder_info{
583 .implementation_name = "decoderName", .is_hardware_accelerated = true};
584 statistics_proxy_->OnDecoderInfo(decoder_info);
Evan Shrubsole1edeb922022-08-08 11:51:26585 time_controller_.AdvanceTime(TimeDelta::Zero());
Evan Shrubsole09da10e2022-10-14 14:38:31586 auto stats = statistics_proxy_->GetStats();
587 EXPECT_EQ(decoder_info.implementation_name,
588 stats.decoder_implementation_name);
589 EXPECT_TRUE(stats.power_efficient_decoder);
Tommi74fc5742020-04-27 08:43:06590}
591
Rasmus Brandt090fe082023-05-09 10:53:01592TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsOnCompleteFrame) {
Tommi74fc5742020-04-27 08:43:06593 const int kFrameSizeBytes = 1000;
594 statistics_proxy_->OnCompleteFrame(true, kFrameSizeBytes,
595 VideoContentType::UNSPECIFIED);
Tommif6f45432022-05-20 13:21:20596 VideoReceiveStreamInterface::Stats stats = statistics_proxy_->GetStats();
Tommi74fc5742020-04-27 08:43:06597 EXPECT_EQ(1, stats.network_frame_rate);
Philipp Hancke51657432023-08-15 08:20:50598 EXPECT_EQ(0, stats.frame_counts.key_frames);
Tommi74fc5742020-04-27 08:43:06599 EXPECT_EQ(0, stats.frame_counts.delta_frames);
600}
601
Rasmus Brandt090fe082023-05-09 10:53:01602TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsOnDroppedFrame) {
Tommi74fc5742020-04-27 08:43:06603 unsigned int dropped_frames = 0;
604 for (int i = 0; i < 10; ++i) {
605 statistics_proxy_->OnDroppedFrames(i);
606 dropped_frames += i;
607 }
Tommif6f45432022-05-20 13:21:20608 VideoReceiveStreamInterface::Stats stats = FlushAndGetStats();
Tommi74fc5742020-04-27 08:43:06609 EXPECT_EQ(dropped_frames, stats.frames_dropped);
610}
611
Rasmus Brandt090fe082023-05-09 10:53:01612TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsDecodeTimingStats) {
Tommi74fc5742020-04-27 08:43:06613 const int kMaxDecodeMs = 2;
614 const int kCurrentDelayMs = 3;
Rasmus Brandtf0820ff2023-05-25 07:37:16615 const TimeDelta kTargetDelay = TimeDelta::Millis(4);
Rasmus Brandt621cb292023-05-24 11:29:14616 const int kJitterDelayMs = 5;
Tommi74fc5742020-04-27 08:43:06617 const int kMinPlayoutDelayMs = 6;
618 const int kRenderDelayMs = 7;
619 const int64_t kRttMs = 8;
Rasmus Brandtf0820ff2023-05-25 07:37:16620 const TimeDelta kJitterBufferDelay = TimeDelta::Millis(9);
621 const TimeDelta kMinimumDelay = TimeDelta::Millis(1);
Tommi674b0c812020-05-10 19:52:17622 statistics_proxy_->OnRttUpdate(kRttMs);
Tommi74fc5742020-04-27 08:43:06623 statistics_proxy_->OnFrameBufferTimingsUpdated(
Rasmus Brandtf0820ff2023-05-25 07:37:16624 kMaxDecodeMs, kCurrentDelayMs, kTargetDelay.ms(), kJitterDelayMs,
Tommi74fc5742020-04-27 08:43:06625 kMinPlayoutDelayMs, kRenderDelayMs);
Rasmus Brandtf0820ff2023-05-25 07:37:16626 statistics_proxy_->OnDecodableFrame(kJitterBufferDelay, kTargetDelay,
627 kMinimumDelay);
Tommif6f45432022-05-20 13:21:20628 VideoReceiveStreamInterface::Stats stats = FlushAndGetStats();
Tommi74fc5742020-04-27 08:43:06629 EXPECT_EQ(kMaxDecodeMs, stats.max_decode_ms);
630 EXPECT_EQ(kCurrentDelayMs, stats.current_delay_ms);
Rasmus Brandtf0820ff2023-05-25 07:37:16631 EXPECT_EQ(kTargetDelay.ms(), stats.target_delay_ms);
Rasmus Brandt621cb292023-05-24 11:29:14632 EXPECT_EQ(kJitterDelayMs, stats.jitter_buffer_ms);
Tommi74fc5742020-04-27 08:43:06633 EXPECT_EQ(kMinPlayoutDelayMs, stats.min_playout_delay_ms);
634 EXPECT_EQ(kRenderDelayMs, stats.render_delay_ms);
Rasmus Brandtf0820ff2023-05-25 07:37:16635 EXPECT_EQ(kJitterBufferDelay, stats.jitter_buffer_delay);
636 EXPECT_EQ(kTargetDelay, stats.jitter_buffer_target_delay);
Rasmus Brandt621cb292023-05-24 11:29:14637 EXPECT_EQ(1u, stats.jitter_buffer_emitted_count);
Rasmus Brandtf0820ff2023-05-25 07:37:16638 EXPECT_EQ(kMinimumDelay, stats.jitter_buffer_minimum_delay);
Rasmus Brandt621cb292023-05-24 11:29:14639}
640
641TEST_F(ReceiveStatisticsProxyTest, CumulativeDecodeGetStatsAccumulate) {
Rasmus Brandtf0820ff2023-05-25 07:37:16642 const TimeDelta kJitterBufferDelay = TimeDelta::Millis(3);
643 const TimeDelta kTargetDelay = TimeDelta::Millis(2);
644 const TimeDelta kMinimumDelay = TimeDelta::Millis(1);
645 statistics_proxy_->OnDecodableFrame(kJitterBufferDelay, kTargetDelay,
646 kMinimumDelay);
647 statistics_proxy_->OnDecodableFrame(kJitterBufferDelay, kTargetDelay,
648 kMinimumDelay);
Rasmus Brandt621cb292023-05-24 11:29:14649 VideoReceiveStreamInterface::Stats stats = FlushAndGetStats();
Rasmus Brandtf0820ff2023-05-25 07:37:16650 EXPECT_EQ(2 * kJitterBufferDelay, stats.jitter_buffer_delay);
651 EXPECT_EQ(2 * kTargetDelay, stats.jitter_buffer_target_delay);
Rasmus Brandt621cb292023-05-24 11:29:14652 EXPECT_EQ(2u, stats.jitter_buffer_emitted_count);
Rasmus Brandtf0820ff2023-05-25 07:37:16653 EXPECT_EQ(2 * kMinimumDelay, stats.jitter_buffer_minimum_delay);
Tommi74fc5742020-04-27 08:43:06654}
655
Rasmus Brandt090fe082023-05-09 10:53:01656TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsRtcpPacketTypeCounts) {
Tommi74fc5742020-04-27 08:43:06657 const uint32_t kFirPackets = 33;
658 const uint32_t kPliPackets = 44;
659 const uint32_t kNackPackets = 55;
660 RtcpPacketTypeCounter counter;
661 counter.fir_packets = kFirPackets;
662 counter.pli_packets = kPliPackets;
663 counter.nack_packets = kNackPackets;
664 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
Tommif6f45432022-05-20 13:21:20665 VideoReceiveStreamInterface::Stats stats = statistics_proxy_->GetStats();
Tommi74fc5742020-04-27 08:43:06666 EXPECT_EQ(kFirPackets, stats.rtcp_packet_type_counts.fir_packets);
667 EXPECT_EQ(kPliPackets, stats.rtcp_packet_type_counts.pli_packets);
668 EXPECT_EQ(kNackPackets, stats.rtcp_packet_type_counts.nack_packets);
669}
670
Rasmus Brandt090fe082023-05-09 10:53:01671TEST_F(ReceiveStatisticsProxyTest,
Tommi74fc5742020-04-27 08:43:06672 GetStatsReportsNoRtcpPacketTypeCountsForUnknownSsrc) {
673 RtcpPacketTypeCounter counter;
674 counter.fir_packets = 33;
675 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc + 1, counter);
676 EXPECT_EQ(0u,
677 statistics_proxy_->GetStats().rtcp_packet_type_counts.fir_packets);
678}
679
Rasmus Brandt090fe082023-05-09 10:53:01680TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsFrameCounts) {
Tommi74fc5742020-04-27 08:43:06681 const int kKeyFrames = 3;
682 const int kDeltaFrames = 22;
Philipp Hancke51657432023-08-15 08:20:50683 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Tommi74fc5742020-04-27 08:43:06684 for (int i = 0; i < kKeyFrames; i++) {
Florent Castelli8037fc62024-08-29 13:00:40685 statistics_proxy_->OnDecodedFrame(frame, std::nullopt, TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:50686 VideoContentType::UNSPECIFIED,
687 VideoFrameType::kVideoFrameKey);
Tommi74fc5742020-04-27 08:43:06688 }
689 for (int i = 0; i < kDeltaFrames; i++) {
Florent Castelli8037fc62024-08-29 13:00:40690 statistics_proxy_->OnDecodedFrame(frame, std::nullopt, TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:50691 VideoContentType::UNSPECIFIED,
692 VideoFrameType::kVideoFrameDelta);
Tommi74fc5742020-04-27 08:43:06693 }
694
Tommif6f45432022-05-20 13:21:20695 VideoReceiveStreamInterface::Stats stats = statistics_proxy_->GetStats();
Philipp Hancke51657432023-08-15 08:20:50696 EXPECT_EQ(0, stats.frame_counts.key_frames);
697 EXPECT_EQ(0, stats.frame_counts.delta_frames);
Tommi74fc5742020-04-27 08:43:06698}
699
Rasmus Brandt090fe082023-05-09 10:53:01700TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsCName) {
Tommi74fc5742020-04-27 08:43:06701 const char* kName = "cName";
702 statistics_proxy_->OnCname(kRemoteSsrc, kName);
703 EXPECT_STREQ(kName, statistics_proxy_->GetStats().c_name.c_str());
704}
705
Rasmus Brandt090fe082023-05-09 10:53:01706TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsNoCNameForUnknownSsrc) {
Tommi74fc5742020-04-27 08:43:06707 const char* kName = "cName";
708 statistics_proxy_->OnCname(kRemoteSsrc + 1, kName);
709 EXPECT_STREQ("", statistics_proxy_->GetStats().c_name.c_str());
710}
711
Rasmus Brandt090fe082023-05-09 10:53:01712TEST_F(ReceiveStatisticsProxyTest, ReportsLongestTimingFrameInfo) {
Tommi74fc5742020-04-27 08:43:06713 const int64_t kShortEndToEndDelay = 10;
714 const int64_t kMedEndToEndDelay = 20;
715 const int64_t kLongEndToEndDelay = 100;
716 const uint32_t kExpectedRtpTimestamp = 2;
717 TimingFrameInfo info;
Florent Castelli8037fc62024-08-29 13:00:40718 std::optional<TimingFrameInfo> result;
Tommi74fc5742020-04-27 08:43:06719 info.rtp_timestamp = kExpectedRtpTimestamp - 1;
720 info.capture_time_ms = 0;
721 info.decode_finish_ms = kShortEndToEndDelay;
722 statistics_proxy_->OnTimingFrameInfoUpdated(info);
723 info.rtp_timestamp =
724 kExpectedRtpTimestamp; // this frame should be reported in the end.
725 info.capture_time_ms = 0;
726 info.decode_finish_ms = kLongEndToEndDelay;
727 statistics_proxy_->OnTimingFrameInfoUpdated(info);
728 info.rtp_timestamp = kExpectedRtpTimestamp + 1;
729 info.capture_time_ms = 0;
730 info.decode_finish_ms = kMedEndToEndDelay;
731 statistics_proxy_->OnTimingFrameInfoUpdated(info);
Tommi674b0c812020-05-10 19:52:17732 result = FlushAndGetStats().timing_frame_info;
Tommi74fc5742020-04-27 08:43:06733 EXPECT_TRUE(result);
734 EXPECT_EQ(kExpectedRtpTimestamp, result->rtp_timestamp);
735}
736
Rasmus Brandt090fe082023-05-09 10:53:01737TEST_F(ReceiveStatisticsProxyTest, RespectsReportingIntervalForTimingFrames) {
Tommi74fc5742020-04-27 08:43:06738 TimingFrameInfo info;
739 const int64_t kShortEndToEndDelay = 10;
740 const uint32_t kExpectedRtpTimestamp = 2;
Evan Shrubsole1edeb922022-08-08 11:51:26741 const TimeDelta kShortDelay = TimeDelta::Seconds(1);
742 const TimeDelta kLongDelay = TimeDelta::Seconds(10);
Florent Castelli8037fc62024-08-29 13:00:40743 std::optional<TimingFrameInfo> result;
Tommi74fc5742020-04-27 08:43:06744 info.rtp_timestamp = kExpectedRtpTimestamp;
745 info.capture_time_ms = 0;
746 info.decode_finish_ms = kShortEndToEndDelay;
747 statistics_proxy_->OnTimingFrameInfoUpdated(info);
Evan Shrubsole1edeb922022-08-08 11:51:26748 time_controller_.AdvanceTime(kShortDelay);
Tommi674b0c812020-05-10 19:52:17749 result = FlushAndGetStats().timing_frame_info;
Tommi74fc5742020-04-27 08:43:06750 EXPECT_TRUE(result);
751 EXPECT_EQ(kExpectedRtpTimestamp, result->rtp_timestamp);
Evan Shrubsole1edeb922022-08-08 11:51:26752 time_controller_.AdvanceTime(kLongDelay);
Tommi74fc5742020-04-27 08:43:06753 result = statistics_proxy_->GetStats().timing_frame_info;
754 EXPECT_FALSE(result);
755}
756
Rasmus Brandt090fe082023-05-09 10:53:01757TEST_F(ReceiveStatisticsProxyTest, LifetimeHistogramIsUpdated) {
Evan Shrubsole1edeb922022-08-08 11:51:26758 const TimeDelta kLifetime = TimeDelta::Seconds(3);
759 time_controller_.AdvanceTime(kLifetime);
Philipp Hancke51657432023-08-15 08:20:50760 // Need at least one decoded frame to report stream lifetime.
761
762 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Tommi74fc5742020-04-27 08:43:06763 statistics_proxy_->OnCompleteFrame(true, 1000, VideoContentType::UNSPECIFIED);
Philipp Hancke51657432023-08-15 08:20:50764 statistics_proxy_->OnDecodedFrame(
Florent Castelli8037fc62024-08-29 13:00:40765 frame, std::nullopt, TimeDelta::Millis(1000),
Philipp Hancke51657432023-08-15 08:20:50766 VideoContentType::UNSPECIFIED, VideoFrameType::kVideoFrameKey);
767 FlushAndGetStats();
768
Florent Castelli8037fc62024-08-29 13:00:40769 statistics_proxy_->UpdateHistograms(std::nullopt, StreamDataCounters(),
Tommi74fc5742020-04-27 08:43:06770 nullptr);
771 EXPECT_METRIC_EQ(
772 1, metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
773 EXPECT_METRIC_EQ(
774 1, metrics::NumEvents("WebRTC.Video.ReceiveStreamLifetimeInSeconds",
Evan Shrubsole1edeb922022-08-08 11:51:26775 kLifetime.seconds()));
Tommi74fc5742020-04-27 08:43:06776}
777
Rasmus Brandt090fe082023-05-09 10:53:01778TEST_F(ReceiveStatisticsProxyTest,
Tommi74fc5742020-04-27 08:43:06779 LifetimeHistogramNotReportedForEmptyStreams) {
Evan Shrubsole1edeb922022-08-08 11:51:26780 const TimeDelta kLifetime = TimeDelta::Seconds(3);
781 time_controller_.AdvanceTime(kLifetime);
Tommi74fc5742020-04-27 08:43:06782 // No frames received.
Florent Castelli8037fc62024-08-29 13:00:40783 statistics_proxy_->UpdateHistograms(std::nullopt, StreamDataCounters(),
Tommi74fc5742020-04-27 08:43:06784 nullptr);
785 EXPECT_METRIC_EQ(
786 0, metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
787}
788
Rasmus Brandt090fe082023-05-09 10:53:01789TEST_F(ReceiveStatisticsProxyTest, PacketLossHistogramIsUpdated) {
Tommi74fc5742020-04-27 08:43:06790 statistics_proxy_->UpdateHistograms(10, StreamDataCounters(), nullptr);
791 EXPECT_METRIC_EQ(
792 0, metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
793
794 // Restart
795 SetUp();
796
797 // Min run time has passed.
Evan Shrubsole1edeb922022-08-08 11:51:26798 time_controller_.AdvanceTime(
799 TimeDelta::Seconds(metrics::kMinRunTimeInSeconds));
Tommi74fc5742020-04-27 08:43:06800 statistics_proxy_->UpdateHistograms(10, StreamDataCounters(), nullptr);
801 EXPECT_METRIC_EQ(
802 1, metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
803 EXPECT_METRIC_EQ(
804 1, metrics::NumEvents("WebRTC.Video.ReceivedPacketsLostInPercent", 10));
805}
806
Rasmus Brandt090fe082023-05-09 10:53:01807TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsPlayoutTimestamp) {
Tommi74fc5742020-04-27 08:43:06808 const int64_t kVideoNtpMs = 21;
809 const int64_t kSyncOffsetMs = 22;
810 const double kFreqKhz = 90.0;
Florent Castelli8037fc62024-08-29 13:00:40811 EXPECT_EQ(std::nullopt,
Tommi74fc5742020-04-27 08:43:06812 statistics_proxy_->GetStats().estimated_playout_ntp_timestamp_ms);
813 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs, kFreqKhz);
Tommi674b0c812020-05-10 19:52:17814 EXPECT_EQ(kVideoNtpMs, FlushAndGetStats().estimated_playout_ntp_timestamp_ms);
Evan Shrubsole1edeb922022-08-08 11:51:26815 time_controller_.AdvanceTime(TimeDelta::Millis(13));
Tommi74fc5742020-04-27 08:43:06816 EXPECT_EQ(kVideoNtpMs + 13,
817 statistics_proxy_->GetStats().estimated_playout_ntp_timestamp_ms);
Evan Shrubsole1edeb922022-08-08 11:51:26818 time_controller_.AdvanceTime(TimeDelta::Millis(5));
Tommi74fc5742020-04-27 08:43:06819 EXPECT_EQ(kVideoNtpMs + 13 + 5,
820 statistics_proxy_->GetStats().estimated_playout_ntp_timestamp_ms);
821}
822
Rasmus Brandt090fe082023-05-09 10:53:01823TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsAvSyncOffset) {
Tommi74fc5742020-04-27 08:43:06824 const int64_t kVideoNtpMs = 21;
825 const int64_t kSyncOffsetMs = 22;
826 const double kFreqKhz = 90.0;
827 EXPECT_EQ(std::numeric_limits<int>::max(),
828 statistics_proxy_->GetStats().sync_offset_ms);
829 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs, kFreqKhz);
Tommi674b0c812020-05-10 19:52:17830 EXPECT_EQ(kSyncOffsetMs, FlushAndGetStats().sync_offset_ms);
Tommi74fc5742020-04-27 08:43:06831}
832
Rasmus Brandt090fe082023-05-09 10:53:01833TEST_F(ReceiveStatisticsProxyTest, AvSyncOffsetHistogramIsUpdated) {
Tommi74fc5742020-04-27 08:43:06834 const int64_t kVideoNtpMs = 21;
835 const int64_t kSyncOffsetMs = 22;
836 const double kFreqKhz = 90.0;
Tommi674b0c812020-05-10 19:52:17837 for (int i = 0; i < kMinRequiredSamples; ++i) {
Tommi74fc5742020-04-27 08:43:06838 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs,
839 kFreqKhz);
Tommi674b0c812020-05-10 19:52:17840 }
Florent Castelli8037fc62024-08-29 13:00:40841 FlushAndUpdateHistograms(std::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 08:43:06842 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.AVSyncOffsetInMs"));
843 EXPECT_METRIC_EQ(
844 1, metrics::NumEvents("WebRTC.Video.AVSyncOffsetInMs", kSyncOffsetMs));
845}
846
Rasmus Brandt090fe082023-05-09 10:53:01847TEST_F(ReceiveStatisticsProxyTest, RtpToNtpFrequencyOffsetHistogramIsUpdated) {
Tommi74fc5742020-04-27 08:43:06848 const int64_t kVideoNtpMs = 21;
849 const int64_t kSyncOffsetMs = 22;
850 const double kFreqKhz = 90.0;
851 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs, kFreqKhz);
852 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs,
853 kFreqKhz + 2.2);
Evan Shrubsole1edeb922022-08-08 11:51:26854 time_controller_.AdvanceTime(kFreqOffsetProcessInterval);
855 //) Process interval passed, max diff: 2.
Tommi74fc5742020-04-27 08:43:06856 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs,
857 kFreqKhz + 1.1);
858 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs,
859 kFreqKhz - 4.2);
860 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs,
861 kFreqKhz - 0.9);
Evan Shrubsole1edeb922022-08-08 11:51:26862 time_controller_.AdvanceTime(kFreqOffsetProcessInterval);
863 //) Process interval passed, max diff: 4.
Tommi74fc5742020-04-27 08:43:06864 statistics_proxy_->OnSyncOffsetUpdated(kVideoNtpMs, kSyncOffsetMs, kFreqKhz);
Florent Castelli8037fc62024-08-29 13:00:40865 FlushAndUpdateHistograms(std::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 08:43:06866 // Average reported: (2 + 4) / 2 = 3.
867 EXPECT_METRIC_EQ(1,
868 metrics::NumSamples("WebRTC.Video.RtpToNtpFreqOffsetInKhz"));
869 EXPECT_METRIC_EQ(
870 1, metrics::NumEvents("WebRTC.Video.RtpToNtpFreqOffsetInKhz", 3));
871}
872
Rasmus Brandt090fe082023-05-09 10:53:01873TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsUpdated) {
Tommi74fc5742020-04-27 08:43:06874 const int kQp = 22;
875
876 for (int i = 0; i < kMinRequiredSamples; ++i)
877 statistics_proxy_->OnPreDecode(kVideoCodecVP8, kQp);
878
Florent Castelli8037fc62024-08-29 13:00:40879 FlushAndUpdateHistograms(std::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 08:43:06880 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
881 EXPECT_METRIC_EQ(1, metrics::NumEvents("WebRTC.Video.Decoded.Vp8.Qp", kQp));
882}
883
Rasmus Brandt090fe082023-05-09 10:53:01884TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsNotUpdatedForTooFewSamples) {
Tommi74fc5742020-04-27 08:43:06885 const int kQp = 22;
886
887 for (int i = 0; i < kMinRequiredSamples - 1; ++i)
888 statistics_proxy_->OnPreDecode(kVideoCodecVP8, kQp);
889
Florent Castelli8037fc62024-08-29 13:00:40890 statistics_proxy_->UpdateHistograms(std::nullopt, StreamDataCounters(),
Tommi74fc5742020-04-27 08:43:06891 nullptr);
892 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
893}
894
Rasmus Brandt090fe082023-05-09 10:53:01895TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsNotUpdatedIfNoQpValue) {
Tommi74fc5742020-04-27 08:43:06896 for (int i = 0; i < kMinRequiredSamples; ++i)
897 statistics_proxy_->OnPreDecode(kVideoCodecVP8, -1);
898
Florent Castelli8037fc62024-08-29 13:00:40899 statistics_proxy_->UpdateHistograms(std::nullopt, StreamDataCounters(),
Tommi74fc5742020-04-27 08:43:06900 nullptr);
901 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp"));
902}
903
Rasmus Brandt090fe082023-05-09 10:53:01904TEST_F(ReceiveStatisticsProxyTest,
Tommi74fc5742020-04-27 08:43:06905 KeyFrameHistogramNotUpdatedForTooFewSamples) {
906 const bool kIsKeyFrame = false;
907 const int kFrameSizeBytes = 1000;
Philipp Hancke51657432023-08-15 08:20:50908 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Tommi74fc5742020-04-27 08:43:06909
Philipp Hancke51657432023-08-15 08:20:50910 for (int i = 0; i < kMinRequiredSamples - 1; ++i) {
Tommi74fc5742020-04-27 08:43:06911 statistics_proxy_->OnCompleteFrame(kIsKeyFrame, kFrameSizeBytes,
912 VideoContentType::UNSPECIFIED);
Philipp Hancke51657432023-08-15 08:20:50913 statistics_proxy_->OnDecodedFrame(
Florent Castelli8037fc62024-08-29 13:00:40914 frame, std::nullopt, TimeDelta::Millis(1000),
Philipp Hancke51657432023-08-15 08:20:50915 VideoContentType::UNSPECIFIED, VideoFrameType::kVideoFrameDelta);
916 }
917 FlushAndGetStats();
Tommi74fc5742020-04-27 08:43:06918
919 EXPECT_EQ(0, statistics_proxy_->GetStats().frame_counts.key_frames);
920 EXPECT_EQ(kMinRequiredSamples - 1,
921 statistics_proxy_->GetStats().frame_counts.delta_frames);
922
Florent Castelli8037fc62024-08-29 13:00:40923 statistics_proxy_->UpdateHistograms(std::nullopt, StreamDataCounters(),
Tommi74fc5742020-04-27 08:43:06924 nullptr);
925 EXPECT_METRIC_EQ(
926 0, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
927}
928
Rasmus Brandt090fe082023-05-09 10:53:01929TEST_F(ReceiveStatisticsProxyTest,
Tommi74fc5742020-04-27 08:43:06930 KeyFrameHistogramUpdatedForMinRequiredSamples) {
931 const bool kIsKeyFrame = false;
932 const int kFrameSizeBytes = 1000;
Philipp Hancke51657432023-08-15 08:20:50933 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Tommi74fc5742020-04-27 08:43:06934
Philipp Hancke51657432023-08-15 08:20:50935 for (int i = 0; i < kMinRequiredSamples; ++i) {
Tommi74fc5742020-04-27 08:43:06936 statistics_proxy_->OnCompleteFrame(kIsKeyFrame, kFrameSizeBytes,
937 VideoContentType::UNSPECIFIED);
Philipp Hancke51657432023-08-15 08:20:50938 statistics_proxy_->OnDecodedFrame(
Florent Castelli8037fc62024-08-29 13:00:40939 frame, std::nullopt, TimeDelta::Millis(1000),
Philipp Hancke51657432023-08-15 08:20:50940 VideoContentType::UNSPECIFIED, VideoFrameType::kVideoFrameDelta);
941 }
942 FlushAndGetStats();
Tommi74fc5742020-04-27 08:43:06943
944 EXPECT_EQ(0, statistics_proxy_->GetStats().frame_counts.key_frames);
945 EXPECT_EQ(kMinRequiredSamples,
946 statistics_proxy_->GetStats().frame_counts.delta_frames);
947
Florent Castelli8037fc62024-08-29 13:00:40948 statistics_proxy_->UpdateHistograms(std::nullopt, StreamDataCounters(),
Tommi74fc5742020-04-27 08:43:06949 nullptr);
950 EXPECT_METRIC_EQ(
951 1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
952 EXPECT_METRIC_EQ(
953 1, metrics::NumEvents("WebRTC.Video.KeyFramesReceivedInPermille", 0));
954}
955
Rasmus Brandt090fe082023-05-09 10:53:01956TEST_F(ReceiveStatisticsProxyTest, KeyFrameHistogramIsUpdated) {
Tommi74fc5742020-04-27 08:43:06957 const int kFrameSizeBytes = 1000;
Philipp Hancke51657432023-08-15 08:20:50958 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Tommi74fc5742020-04-27 08:43:06959
Philipp Hancke51657432023-08-15 08:20:50960 for (int i = 0; i < kMinRequiredSamples; ++i) {
Tommi74fc5742020-04-27 08:43:06961 statistics_proxy_->OnCompleteFrame(true, kFrameSizeBytes,
962 VideoContentType::UNSPECIFIED);
Philipp Hancke51657432023-08-15 08:20:50963 statistics_proxy_->OnDecodedFrame(
Florent Castelli8037fc62024-08-29 13:00:40964 frame, std::nullopt, TimeDelta::Millis(1000),
Philipp Hancke51657432023-08-15 08:20:50965 VideoContentType::UNSPECIFIED, VideoFrameType::kVideoFrameKey);
966 }
967 for (int i = 0; i < kMinRequiredSamples; ++i) {
Tommi74fc5742020-04-27 08:43:06968 statistics_proxy_->OnCompleteFrame(false, kFrameSizeBytes,
969 VideoContentType::UNSPECIFIED);
Philipp Hancke51657432023-08-15 08:20:50970 statistics_proxy_->OnDecodedFrame(
Florent Castelli8037fc62024-08-29 13:00:40971 frame, std::nullopt, TimeDelta::Millis(1000),
Philipp Hancke51657432023-08-15 08:20:50972 VideoContentType::UNSPECIFIED, VideoFrameType::kVideoFrameDelta);
973 }
974 FlushAndGetStats();
Tommi74fc5742020-04-27 08:43:06975
976 EXPECT_EQ(kMinRequiredSamples,
977 statistics_proxy_->GetStats().frame_counts.key_frames);
978 EXPECT_EQ(kMinRequiredSamples,
979 statistics_proxy_->GetStats().frame_counts.delta_frames);
980
Florent Castelli8037fc62024-08-29 13:00:40981 statistics_proxy_->UpdateHistograms(std::nullopt, StreamDataCounters(),
Tommi74fc5742020-04-27 08:43:06982 nullptr);
983 EXPECT_METRIC_EQ(
984 1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
985 EXPECT_METRIC_EQ(
986 1, metrics::NumEvents("WebRTC.Video.KeyFramesReceivedInPermille", 500));
987}
988
Rasmus Brandt090fe082023-05-09 10:53:01989TEST_F(ReceiveStatisticsProxyTest, TimingHistogramsNotUpdatedForTooFewSamples) {
Tommi74fc5742020-04-27 08:43:06990 const int kMaxDecodeMs = 2;
991 const int kCurrentDelayMs = 3;
992 const int kTargetDelayMs = 4;
Rasmus Brandt621cb292023-05-24 11:29:14993 const int kJitterDelayMs = 5;
Tommi74fc5742020-04-27 08:43:06994 const int kMinPlayoutDelayMs = 6;
995 const int kRenderDelayMs = 7;
996
997 for (int i = 0; i < kMinRequiredSamples - 1; ++i) {
998 statistics_proxy_->OnFrameBufferTimingsUpdated(
Rasmus Brandt621cb292023-05-24 11:29:14999 kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs, kJitterDelayMs,
Tommi74fc5742020-04-27 08:43:061000 kMinPlayoutDelayMs, kRenderDelayMs);
1001 }
1002
Florent Castelli8037fc62024-08-29 13:00:401003 statistics_proxy_->UpdateHistograms(std::nullopt, StreamDataCounters(),
Tommi74fc5742020-04-27 08:43:061004 nullptr);
1005 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
1006 EXPECT_METRIC_EQ(0,
1007 metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
1008 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
1009 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
1010 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
1011}
1012
Rasmus Brandt090fe082023-05-09 10:53:011013TEST_F(ReceiveStatisticsProxyTest, TimingHistogramsAreUpdated) {
Tommi74fc5742020-04-27 08:43:061014 const int kMaxDecodeMs = 2;
1015 const int kCurrentDelayMs = 3;
1016 const int kTargetDelayMs = 4;
Rasmus Brandt621cb292023-05-24 11:29:141017 const int kJitterDelayMs = 5;
Tommi74fc5742020-04-27 08:43:061018 const int kMinPlayoutDelayMs = 6;
1019 const int kRenderDelayMs = 7;
1020
1021 for (int i = 0; i < kMinRequiredSamples; ++i) {
1022 statistics_proxy_->OnFrameBufferTimingsUpdated(
Rasmus Brandt621cb292023-05-24 11:29:141023 kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs, kJitterDelayMs,
Tommi74fc5742020-04-27 08:43:061024 kMinPlayoutDelayMs, kRenderDelayMs);
1025 }
1026
Florent Castelli8037fc62024-08-29 13:00:401027 FlushAndUpdateHistograms(std::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 08:43:061028 EXPECT_METRIC_EQ(1,
1029 metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
1030 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
1031 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
1032 EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
1033
1034 EXPECT_METRIC_EQ(1, metrics::NumEvents("WebRTC.Video.JitterBufferDelayInMs",
Rasmus Brandt621cb292023-05-24 11:29:141035 kJitterDelayMs));
Tommi74fc5742020-04-27 08:43:061036 EXPECT_METRIC_EQ(
1037 1, metrics::NumEvents("WebRTC.Video.TargetDelayInMs", kTargetDelayMs));
1038 EXPECT_METRIC_EQ(
1039 1, metrics::NumEvents("WebRTC.Video.CurrentDelayInMs", kCurrentDelayMs));
1040 EXPECT_METRIC_EQ(
1041 1, metrics::NumEvents("WebRTC.Video.OnewayDelayInMs", kTargetDelayMs));
1042}
1043
Rasmus Brandt090fe082023-05-09 10:53:011044TEST_F(ReceiveStatisticsProxyTest, DoesNotReportStaleFramerates) {
Evan Shrubsole1edeb922022-08-08 11:51:261045 const Frequency kDefaultFps = Frequency::Hertz(30);
Tommi74fc5742020-04-27 08:43:061046 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1047
Evan Shrubsole1edeb922022-08-08 11:51:261048 for (int i = 0; i < kDefaultFps.hertz(); ++i) {
Tommi74fc5742020-04-27 08:43:061049 // Since OnRenderedFrame is never called the fps in each sample will be 0,
1050 // i.e. bad
Evan Shrubsole1edeb922022-08-08 11:51:261051 frame.set_ntp_time_ms(
1052 time_controller_.GetClock()->CurrentNtpInMilliseconds());
Florent Castelli8037fc62024-08-29 13:00:401053 statistics_proxy_->OnDecodedFrame(frame, std::nullopt, TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:501054 VideoContentType::UNSPECIFIED,
1055 VideoFrameType::kVideoFrameKey);
Tommid7e08c82020-05-10 09:24:431056 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Evan Shrubsole1edeb922022-08-08 11:51:261057 time_controller_.AdvanceTime(1 / kDefaultFps);
Tommi74fc5742020-04-27 08:43:061058 }
1059
Evan Shrubsole1edeb922022-08-08 11:51:261060 // Why -1? Because RateStatistics does not consider the first frame in the
1061 // rate as it will appear in the previous bucket.
1062 EXPECT_EQ(kDefaultFps.hertz() - 1,
1063 statistics_proxy_->GetStats().decode_frame_rate);
1064 EXPECT_EQ(kDefaultFps.hertz() - 1,
1065 statistics_proxy_->GetStats().render_frame_rate);
Tommi74fc5742020-04-27 08:43:061066
1067 // FPS trackers in stats proxy have a 1000ms sliding window.
Evan Shrubsole1edeb922022-08-08 11:51:261068 time_controller_.AdvanceTime(TimeDelta::Seconds(1));
Tommi74fc5742020-04-27 08:43:061069 EXPECT_EQ(0, statistics_proxy_->GetStats().decode_frame_rate);
1070 EXPECT_EQ(0, statistics_proxy_->GetStats().render_frame_rate);
1071}
1072
Rasmus Brandt090fe082023-05-09 10:53:011073TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsReceivedFrameStats) {
Tommi74fc5742020-04-27 08:43:061074 EXPECT_EQ(0, statistics_proxy_->GetStats().width);
1075 EXPECT_EQ(0, statistics_proxy_->GetStats().height);
1076 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_rendered);
1077
Tommid7e08c82020-05-10 09:24:431078 statistics_proxy_->OnRenderedFrame(MetaData(CreateFrame(kWidth, kHeight)));
Tommi74fc5742020-04-27 08:43:061079
1080 EXPECT_EQ(kWidth, statistics_proxy_->GetStats().width);
1081 EXPECT_EQ(kHeight, statistics_proxy_->GetStats().height);
1082 EXPECT_EQ(1u, statistics_proxy_->GetStats().frames_rendered);
1083}
1084
Rasmus Brandt090fe082023-05-09 10:53:011085TEST_F(ReceiveStatisticsProxyTest,
Tommi74fc5742020-04-27 08:43:061086 ReceivedFrameHistogramsAreNotUpdatedForTooFewSamples) {
Tommid7e08c82020-05-10 09:24:431087 for (int i = 0; i < kMinRequiredSamples - 1; ++i) {
1088 statistics_proxy_->OnRenderedFrame(MetaData(CreateFrame(kWidth, kHeight)));
1089 }
Tommi74fc5742020-04-27 08:43:061090
Florent Castelli8037fc62024-08-29 13:00:401091 statistics_proxy_->UpdateHistograms(std::nullopt, StreamDataCounters(),
Tommi74fc5742020-04-27 08:43:061092 nullptr);
1093 EXPECT_METRIC_EQ(0,
1094 metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
1095 EXPECT_METRIC_EQ(0,
1096 metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
1097 EXPECT_METRIC_EQ(0,
1098 metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
1099 EXPECT_METRIC_EQ(
1100 0, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
1101}
1102
Rasmus Brandt090fe082023-05-09 10:53:011103TEST_F(ReceiveStatisticsProxyTest, ReceivedFrameHistogramsAreUpdated) {
Tommid7e08c82020-05-10 09:24:431104 for (int i = 0; i < kMinRequiredSamples; ++i) {
1105 statistics_proxy_->OnRenderedFrame(MetaData(CreateFrame(kWidth, kHeight)));
1106 }
Tommi74fc5742020-04-27 08:43:061107
Florent Castelli8037fc62024-08-29 13:00:401108 statistics_proxy_->UpdateHistograms(std::nullopt, StreamDataCounters(),
Tommi74fc5742020-04-27 08:43:061109 nullptr);
1110 EXPECT_METRIC_EQ(1,
1111 metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
1112 EXPECT_METRIC_EQ(1,
1113 metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
1114 EXPECT_METRIC_EQ(1,
1115 metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
1116 EXPECT_METRIC_EQ(
1117 1, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
1118 EXPECT_METRIC_EQ(
1119 1, metrics::NumEvents("WebRTC.Video.ReceivedWidthInPixels", kWidth));
1120 EXPECT_METRIC_EQ(
1121 1, metrics::NumEvents("WebRTC.Video.ReceivedHeightInPixels", kHeight));
1122}
1123
Rasmus Brandt090fe082023-05-09 10:53:011124TEST_F(ReceiveStatisticsProxyTest, ZeroDelayReportedIfFrameNotDelayed) {
Tommi74fc5742020-04-27 08:43:061125 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Florent Castelli8037fc62024-08-29 13:00:401126 statistics_proxy_->OnDecodedFrame(frame, std::nullopt, TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:501127 VideoContentType::UNSPECIFIED,
1128 VideoFrameType::kVideoFrameKey);
Tommi74fc5742020-04-27 08:43:061129
1130 // Frame not delayed, delayed frames to render: 0%.
Tommid7e08c82020-05-10 09:24:431131 statistics_proxy_->OnRenderedFrame(
1132 MetaData(CreateFrameWithRenderTime(Now())));
Tommi74fc5742020-04-27 08:43:061133
1134 // Min run time has passed.
Evan Shrubsole1edeb922022-08-08 11:51:261135 time_controller_.AdvanceTime(
1136 TimeDelta::Seconds((metrics::kMinRunTimeInSeconds)));
Florent Castelli8037fc62024-08-29 13:00:401137 FlushAndUpdateHistograms(std::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 08:43:061138 EXPECT_METRIC_EQ(1,
1139 metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
1140 EXPECT_METRIC_EQ(
1141 1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 0));
1142 EXPECT_METRIC_EQ(0, metrics::NumSamples(
1143 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
1144}
1145
Rasmus Brandt090fe082023-05-09 10:53:011146TEST_F(ReceiveStatisticsProxyTest,
Tommi74fc5742020-04-27 08:43:061147 DelayedFrameHistogramsAreNotUpdatedIfMinRuntimeHasNotPassed) {
1148 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Florent Castelli8037fc62024-08-29 13:00:401149 statistics_proxy_->OnDecodedFrame(frame, std::nullopt, TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:501150 VideoContentType::UNSPECIFIED,
1151 VideoFrameType::kVideoFrameKey);
Tommi74fc5742020-04-27 08:43:061152
1153 // Frame not delayed, delayed frames to render: 0%.
Tommid7e08c82020-05-10 09:24:431154 statistics_proxy_->OnRenderedFrame(
1155 MetaData(CreateFrameWithRenderTime(Now())));
Tommi74fc5742020-04-27 08:43:061156
1157 // Min run time has not passed.
Evan Shrubsole1edeb922022-08-08 11:51:261158 time_controller_.AdvanceTime(
1159 TimeDelta::Seconds(metrics::kMinRunTimeInSeconds) - TimeDelta::Millis(1));
Florent Castelli8037fc62024-08-29 13:00:401160 statistics_proxy_->UpdateHistograms(std::nullopt, StreamDataCounters(),
Tommi74fc5742020-04-27 08:43:061161 nullptr);
1162 EXPECT_METRIC_EQ(0,
1163 metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
1164 EXPECT_METRIC_EQ(0, metrics::NumSamples(
1165 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
1166}
1167
Rasmus Brandt090fe082023-05-09 10:53:011168TEST_F(ReceiveStatisticsProxyTest,
Tommi74fc5742020-04-27 08:43:061169 DelayedFramesHistogramsAreNotUpdatedIfNoRenderedFrames) {
1170 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Florent Castelli8037fc62024-08-29 13:00:401171 statistics_proxy_->OnDecodedFrame(frame, std::nullopt, TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:501172 VideoContentType::UNSPECIFIED,
1173 VideoFrameType::kVideoFrameKey);
Tommi74fc5742020-04-27 08:43:061174
1175 // Min run time has passed. No rendered frames.
Evan Shrubsole1edeb922022-08-08 11:51:261176 time_controller_.AdvanceTime(
1177 TimeDelta::Seconds((metrics::kMinRunTimeInSeconds)));
Florent Castelli8037fc62024-08-29 13:00:401178 statistics_proxy_->UpdateHistograms(std::nullopt, StreamDataCounters(),
Tommi74fc5742020-04-27 08:43:061179 nullptr);
1180 EXPECT_METRIC_EQ(0,
1181 metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
1182 EXPECT_METRIC_EQ(0, metrics::NumSamples(
1183 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
1184}
1185
Rasmus Brandt090fe082023-05-09 10:53:011186TEST_F(ReceiveStatisticsProxyTest, DelayReportedIfFrameIsDelayed) {
Tommi74fc5742020-04-27 08:43:061187 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Florent Castelli8037fc62024-08-29 13:00:401188 statistics_proxy_->OnDecodedFrame(frame, std::nullopt, TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:501189 VideoContentType::UNSPECIFIED,
1190 VideoFrameType::kVideoFrameKey);
Tommi74fc5742020-04-27 08:43:061191
1192 // Frame delayed 1 ms, delayed frames to render: 100%.
Tommid7e08c82020-05-10 09:24:431193 statistics_proxy_->OnRenderedFrame(
1194 MetaData(CreateFrameWithRenderTimeMs(Now().ms() - 1)));
Tommi74fc5742020-04-27 08:43:061195
1196 // Min run time has passed.
Evan Shrubsole1edeb922022-08-08 11:51:261197 time_controller_.AdvanceTime(
1198 TimeDelta::Seconds(metrics::kMinRunTimeInSeconds));
Florent Castelli8037fc62024-08-29 13:00:401199 FlushAndUpdateHistograms(std::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 08:43:061200 EXPECT_METRIC_EQ(1,
1201 metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
1202 EXPECT_METRIC_EQ(
1203 1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 100));
1204 EXPECT_METRIC_EQ(1, metrics::NumSamples(
1205 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
1206 EXPECT_METRIC_EQ(
1207 1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs",
1208 1));
1209}
1210
Rasmus Brandt090fe082023-05-09 10:53:011211TEST_F(ReceiveStatisticsProxyTest, AverageDelayOfDelayedFramesIsReported) {
Tommi74fc5742020-04-27 08:43:061212 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
Florent Castelli8037fc62024-08-29 13:00:401213 statistics_proxy_->OnDecodedFrame(frame, std::nullopt, TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:501214 VideoContentType::UNSPECIFIED,
1215 VideoFrameType::kVideoFrameKey);
Tommi74fc5742020-04-27 08:43:061216
1217 // Two frames delayed (6 ms, 10 ms), delayed frames to render: 50%.
Tommid7e08c82020-05-10 09:24:431218 const int64_t kNowMs = Now().ms();
1219
1220 statistics_proxy_->OnRenderedFrame(
1221 MetaData(CreateFrameWithRenderTimeMs(kNowMs - 10)));
1222 statistics_proxy_->OnRenderedFrame(
1223 MetaData(CreateFrameWithRenderTimeMs(kNowMs - 6)));
1224 statistics_proxy_->OnRenderedFrame(
1225 MetaData(CreateFrameWithRenderTimeMs(kNowMs)));
1226 statistics_proxy_->OnRenderedFrame(
1227 MetaData(CreateFrameWithRenderTimeMs(kNowMs + 1)));
Tommi74fc5742020-04-27 08:43:061228
1229 // Min run time has passed.
Evan Shrubsole1edeb922022-08-08 11:51:261230 time_controller_.AdvanceTime(
1231 TimeDelta::Seconds(metrics::kMinRunTimeInSeconds));
Florent Castelli8037fc62024-08-29 13:00:401232 FlushAndUpdateHistograms(std::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 08:43:061233 EXPECT_METRIC_EQ(1,
1234 metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
1235 EXPECT_METRIC_EQ(
1236 1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 50));
1237 EXPECT_METRIC_EQ(1, metrics::NumSamples(
1238 "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs"));
1239 EXPECT_METRIC_EQ(
1240 1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs",
1241 8));
1242}
1243
Rasmus Brandt090fe082023-05-09 10:53:011244TEST_F(ReceiveStatisticsProxyTest,
Tommi74fc5742020-04-27 08:43:061245 RtcpHistogramsNotUpdatedIfMinRuntimeHasNotPassed) {
1246 StreamDataCounters data_counters;
Danil Chapovalov0f1a2c52023-05-26 09:30:261247 data_counters.first_packet_time = time_controller_.GetClock()->CurrentTime();
Tommi74fc5742020-04-27 08:43:061248
Evan Shrubsole1edeb922022-08-08 11:51:261249 time_controller_.AdvanceTime(
1250 TimeDelta::Seconds(metrics::kMinRunTimeInSeconds) - TimeDelta::Millis(1));
Tommi74fc5742020-04-27 08:43:061251
1252 RtcpPacketTypeCounter counter;
1253 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
1254
Florent Castelli8037fc62024-08-29 13:00:401255 statistics_proxy_->UpdateHistograms(std::nullopt, data_counters, nullptr);
Tommi74fc5742020-04-27 08:43:061256 EXPECT_METRIC_EQ(0,
1257 metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
1258 EXPECT_METRIC_EQ(0,
1259 metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
1260 EXPECT_METRIC_EQ(
1261 0, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
1262}
1263
Rasmus Brandt090fe082023-05-09 10:53:011264TEST_F(ReceiveStatisticsProxyTest, RtcpHistogramsAreUpdated) {
Tommi74fc5742020-04-27 08:43:061265 StreamDataCounters data_counters;
Danil Chapovalov0f1a2c52023-05-26 09:30:261266 data_counters.first_packet_time = time_controller_.GetClock()->CurrentTime();
Evan Shrubsole1edeb922022-08-08 11:51:261267 time_controller_.AdvanceTime(
1268 TimeDelta::Seconds(metrics::kMinRunTimeInSeconds));
Tommi74fc5742020-04-27 08:43:061269
1270 const uint32_t kFirPackets = 100;
1271 const uint32_t kPliPackets = 200;
1272 const uint32_t kNackPackets = 300;
1273
1274 RtcpPacketTypeCounter counter;
1275 counter.fir_packets = kFirPackets;
1276 counter.pli_packets = kPliPackets;
1277 counter.nack_packets = kNackPackets;
1278 statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter);
1279
Florent Castelli8037fc62024-08-29 13:00:401280 statistics_proxy_->UpdateHistograms(std::nullopt, data_counters, nullptr);
Tommi74fc5742020-04-27 08:43:061281 EXPECT_METRIC_EQ(1,
1282 metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
1283 EXPECT_METRIC_EQ(1,
1284 metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
1285 EXPECT_METRIC_EQ(
1286 1, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
1287 EXPECT_METRIC_EQ(
1288 1, metrics::NumEvents("WebRTC.Video.FirPacketsSentPerMinute",
1289 kFirPackets * 60 / metrics::kMinRunTimeInSeconds));
1290 EXPECT_METRIC_EQ(
1291 1, metrics::NumEvents("WebRTC.Video.PliPacketsSentPerMinute",
1292 kPliPackets * 60 / metrics::kMinRunTimeInSeconds));
1293 EXPECT_METRIC_EQ(
1294 1, metrics::NumEvents("WebRTC.Video.NackPacketsSentPerMinute",
1295 kNackPackets * 60 / metrics::kMinRunTimeInSeconds));
1296}
1297
Rasmus Brandt090fe082023-05-09 10:53:011298class ReceiveStatisticsProxyTestWithFreezeDuration
1299 : public ReceiveStatisticsProxyTest,
Tommi74fc5742020-04-27 08:43:061300 public ::testing::WithParamInterface<
1301 std::tuple<uint32_t, uint32_t, uint32_t>> {
1302 protected:
1303 const uint32_t frame_duration_ms_ = {std::get<0>(GetParam())};
1304 const uint32_t freeze_duration_ms_ = {std::get<1>(GetParam())};
1305 const uint32_t expected_freeze_count_ = {std::get<2>(GetParam())};
1306};
1307
1308// It is a freeze if:
1309// frame_duration_ms >= max(3 * avg_frame_duration, avg_frame_duration + 150)
1310// where avg_frame_duration is average duration of last 30 frames including
1311// the current one.
1312//
1313// Condition 1: 3 * avg_frame_duration > avg_frame_duration + 150
1314const auto kFreezeDetectionCond1Freeze = std::make_tuple(150, 483, 1);
1315const auto kFreezeDetectionCond1NotFreeze = std::make_tuple(150, 482, 0);
1316// Condition 2: 3 * avg_frame_duration < avg_frame_duration + 150
1317const auto kFreezeDetectionCond2Freeze = std::make_tuple(30, 185, 1);
1318const auto kFreezeDetectionCond2NotFreeze = std::make_tuple(30, 184, 0);
1319
1320INSTANTIATE_TEST_SUITE_P(_,
Rasmus Brandt090fe082023-05-09 10:53:011321 ReceiveStatisticsProxyTestWithFreezeDuration,
Tommi74fc5742020-04-27 08:43:061322 ::testing::Values(kFreezeDetectionCond1Freeze,
1323 kFreezeDetectionCond1NotFreeze,
1324 kFreezeDetectionCond2Freeze,
1325 kFreezeDetectionCond2NotFreeze));
1326
Rasmus Brandt090fe082023-05-09 10:53:011327TEST_P(ReceiveStatisticsProxyTestWithFreezeDuration, FreezeDetection) {
Tommif6f45432022-05-20 13:21:201328 VideoReceiveStreamInterface::Stats stats = statistics_proxy_->GetStats();
Tommi74fc5742020-04-27 08:43:061329 EXPECT_EQ(0u, stats.freeze_count);
1330 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1331
1332 // Add a very long frame. This is need to verify that average frame
1333 // duration, which is supposed to be calculated as mean of durations of
1334 // last 30 frames, is calculated correctly.
Tommid7e08c82020-05-10 09:24:431335 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Evan Shrubsole1edeb922022-08-08 11:51:261336 time_controller_.AdvanceTime(TimeDelta::Seconds(2));
Tommi74fc5742020-04-27 08:43:061337 for (size_t i = 0;
1338 i <= VideoQualityObserver::kAvgInterframeDelaysWindowSizeFrames; ++i) {
Evan Shrubsole1edeb922022-08-08 11:51:261339 time_controller_.AdvanceTime(TimeDelta::Millis(frame_duration_ms_));
Tommid7e08c82020-05-10 09:24:431340 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 08:43:061341 }
1342
Evan Shrubsole1edeb922022-08-08 11:51:261343 time_controller_.AdvanceTime(TimeDelta::Millis(freeze_duration_ms_));
Tommid7e08c82020-05-10 09:24:431344 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 08:43:061345
1346 stats = statistics_proxy_->GetStats();
1347 EXPECT_EQ(stats.freeze_count, expected_freeze_count_);
1348}
1349
Rasmus Brandt090fe082023-05-09 10:53:011350class ReceiveStatisticsProxyTestWithContent
1351 : public ReceiveStatisticsProxyTest,
Tommi74fc5742020-04-27 08:43:061352 public ::testing::WithParamInterface<webrtc::VideoContentType> {
1353 protected:
1354 const webrtc::VideoContentType content_type_{GetParam()};
1355};
1356
1357INSTANTIATE_TEST_SUITE_P(ContentTypes,
Rasmus Brandt090fe082023-05-09 10:53:011358 ReceiveStatisticsProxyTestWithContent,
Tommi74fc5742020-04-27 08:43:061359 ::testing::Values(VideoContentType::UNSPECIFIED,
1360 VideoContentType::SCREENSHARE));
1361
Rasmus Brandt090fe082023-05-09 10:53:011362TEST_P(ReceiveStatisticsProxyTestWithContent, InterFrameDelaysAreReported) {
Evan Shrubsole1edeb922022-08-08 11:51:261363 const TimeDelta kInterFrameDelay = TimeDelta::Millis(33);
Tommi74fc5742020-04-27 08:43:061364 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1365
1366 for (int i = 0; i < kMinRequiredSamples; ++i) {
Florent Castelli8037fc62024-08-29 13:00:401367 statistics_proxy_->OnDecodedFrame(frame, std::nullopt, TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:501368 content_type_,
1369 VideoFrameType::kVideoFrameKey);
Evan Shrubsole1edeb922022-08-08 11:51:261370 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 08:43:061371 }
1372 // One extra with double the interval.
Evan Shrubsole1edeb922022-08-08 11:51:261373 time_controller_.AdvanceTime(kInterFrameDelay);
Florent Castelli8037fc62024-08-29 13:00:401374 statistics_proxy_->OnDecodedFrame(frame, std::nullopt, TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:501375 content_type_,
1376 VideoFrameType::kVideoFrameDelta);
Tommi74fc5742020-04-27 08:43:061377
Florent Castelli8037fc62024-08-29 13:00:401378 FlushAndUpdateHistograms(std::nullopt, StreamDataCounters(), nullptr);
Evan Shrubsole1edeb922022-08-08 11:51:261379 const TimeDelta kExpectedInterFrame =
1380 (kInterFrameDelay * (kMinRequiredSamples - 1) + kInterFrameDelay * 2) /
Tommi74fc5742020-04-27 08:43:061381 kMinRequiredSamples;
1382 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
1383 EXPECT_METRIC_EQ(
Evan Shrubsole1edeb922022-08-08 11:51:261384 kExpectedInterFrame.ms(),
Tommi74fc5742020-04-27 08:43:061385 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1386 EXPECT_METRIC_EQ(
Evan Shrubsole1edeb922022-08-08 11:51:261387 kInterFrameDelay.ms() * 2,
Tommi74fc5742020-04-27 08:43:061388 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1389 } else {
Evan Shrubsole1edeb922022-08-08 11:51:261390 EXPECT_METRIC_EQ(kExpectedInterFrame.ms(),
Tommi74fc5742020-04-27 08:43:061391 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
Evan Shrubsole1edeb922022-08-08 11:51:261392 EXPECT_METRIC_EQ(kInterFrameDelay.ms() * 2,
Tommi74fc5742020-04-27 08:43:061393 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
1394 }
1395}
1396
Rasmus Brandt090fe082023-05-09 10:53:011397TEST_P(ReceiveStatisticsProxyTestWithContent,
Tommi74fc5742020-04-27 08:43:061398 InterFrameDelaysPercentilesAreReported) {
Evan Shrubsole1edeb922022-08-08 11:51:261399 const TimeDelta kInterFrameDelay = TimeDelta::Millis(33);
Tommi74fc5742020-04-27 08:43:061400 const int kLastFivePercentsSamples = kMinRequiredSamples * 5 / 100;
1401 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1402
1403 for (int i = 0; i <= kMinRequiredSamples - kLastFivePercentsSamples; ++i) {
Evan Shrubsole1edeb922022-08-08 11:51:261404 time_controller_.AdvanceTime(kInterFrameDelay);
Florent Castelli8037fc62024-08-29 13:00:401405 statistics_proxy_->OnDecodedFrame(frame, std::nullopt, TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:501406 content_type_,
1407 VideoFrameType::kVideoFrameKey);
Tommi74fc5742020-04-27 08:43:061408 }
1409 // Last 5% of intervals are double in size.
1410 for (int i = 0; i < kLastFivePercentsSamples; ++i) {
Evan Shrubsole1edeb922022-08-08 11:51:261411 time_controller_.AdvanceTime(2 * kInterFrameDelay);
Florent Castelli8037fc62024-08-29 13:00:401412 statistics_proxy_->OnDecodedFrame(frame, std::nullopt, TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:501413 content_type_,
1414 VideoFrameType::kVideoFrameKey);
Tommi74fc5742020-04-27 08:43:061415 }
1416 // Final sample is outlier and 10 times as big.
Evan Shrubsole1edeb922022-08-08 11:51:261417 time_controller_.AdvanceTime(10 * kInterFrameDelay);
Florent Castelli8037fc62024-08-29 13:00:401418 statistics_proxy_->OnDecodedFrame(frame, std::nullopt, TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:501419 content_type_,
1420 VideoFrameType::kVideoFrameKey);
Tommi74fc5742020-04-27 08:43:061421
Florent Castelli8037fc62024-08-29 13:00:401422 FlushAndUpdateHistograms(std::nullopt, StreamDataCounters(), nullptr);
Evan Shrubsole1edeb922022-08-08 11:51:261423 const TimeDelta kExpectedInterFrame = kInterFrameDelay * 2;
Tommi74fc5742020-04-27 08:43:061424 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
1425 EXPECT_METRIC_EQ(
Evan Shrubsole1edeb922022-08-08 11:51:261426 kExpectedInterFrame.ms(),
Tommi74fc5742020-04-27 08:43:061427 metrics::MinSample(
1428 "WebRTC.Video.Screenshare.InterframeDelay95PercentileInMs"));
1429 } else {
1430 EXPECT_METRIC_EQ(
Evan Shrubsole1edeb922022-08-08 11:51:261431 kExpectedInterFrame.ms(),
Tommi74fc5742020-04-27 08:43:061432 metrics::MinSample("WebRTC.Video.InterframeDelay95PercentileInMs"));
1433 }
1434}
1435
Rasmus Brandt090fe082023-05-09 10:53:011436TEST_P(ReceiveStatisticsProxyTestWithContent,
Tommi74fc5742020-04-27 08:43:061437 MaxInterFrameDelayOnlyWithValidAverage) {
Evan Shrubsole1edeb922022-08-08 11:51:261438 const TimeDelta kInterFrameDelay = TimeDelta::Millis(33);
Tommi74fc5742020-04-27 08:43:061439 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1440
1441 for (int i = 0; i < kMinRequiredSamples; ++i) {
Florent Castelli8037fc62024-08-29 13:00:401442 statistics_proxy_->OnDecodedFrame(frame, std::nullopt, TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:501443 content_type_,
1444 VideoFrameType::kVideoFrameKey);
Evan Shrubsole1edeb922022-08-08 11:51:261445 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 08:43:061446 }
1447
Artem Titovab30d722021-07-27 14:22:111448 // `kMinRequiredSamples` samples, and thereby intervals, is required. That
Tommi74fc5742020-04-27 08:43:061449 // means we're one frame short of having a valid data set.
Florent Castelli8037fc62024-08-29 13:00:401450 statistics_proxy_->UpdateHistograms(std::nullopt, StreamDataCounters(),
Tommi74fc5742020-04-27 08:43:061451 nullptr);
1452 EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
1453 EXPECT_METRIC_EQ(0,
1454 metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
1455 EXPECT_METRIC_EQ(
1456 0, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1457 EXPECT_METRIC_EQ(0, metrics::NumSamples(
1458 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1459}
1460
Rasmus Brandt090fe082023-05-09 10:53:011461TEST_P(ReceiveStatisticsProxyTestWithContent, MaxInterFrameDelayOnlyWithPause) {
Evan Shrubsole1edeb922022-08-08 11:51:261462 const TimeDelta kInterFrameDelay = TimeDelta::Millis(33);
Tommi74fc5742020-04-27 08:43:061463 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1464
1465 for (int i = 0; i <= kMinRequiredSamples; ++i) {
Florent Castelli8037fc62024-08-29 13:00:401466 statistics_proxy_->OnDecodedFrame(frame, std::nullopt, TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:501467 content_type_,
1468 VideoFrameType::kVideoFrameKey);
Evan Shrubsole1edeb922022-08-08 11:51:261469 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 08:43:061470 }
1471
1472 // At this state, we should have a valid inter-frame delay.
1473 // Indicate stream paused and make a large jump in time.
1474 statistics_proxy_->OnStreamInactive();
Evan Shrubsole1edeb922022-08-08 11:51:261475 time_controller_.AdvanceTime(TimeDelta::Seconds(5));
Tommid7e08c82020-05-10 09:24:431476 // Insert two more frames. The interval during the pause should be
1477 // disregarded in the stats.
Florent Castelli8037fc62024-08-29 13:00:401478 statistics_proxy_->OnDecodedFrame(frame, std::nullopt, TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:501479 content_type_,
1480 VideoFrameType::kVideoFrameKey);
Evan Shrubsole1edeb922022-08-08 11:51:261481 time_controller_.AdvanceTime(kInterFrameDelay);
Florent Castelli8037fc62024-08-29 13:00:401482 statistics_proxy_->OnDecodedFrame(frame, std::nullopt, TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:501483 content_type_,
1484 VideoFrameType::kVideoFrameDelta);
Tommi74fc5742020-04-27 08:43:061485
Florent Castelli8037fc62024-08-29 13:00:401486 FlushAndUpdateHistograms(std::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 08:43:061487 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
1488 EXPECT_METRIC_EQ(
1489 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1490 EXPECT_METRIC_EQ(1, metrics::NumSamples(
1491 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1492 EXPECT_METRIC_EQ(
Evan Shrubsole1edeb922022-08-08 11:51:261493 kInterFrameDelay.ms(),
Tommi74fc5742020-04-27 08:43:061494 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayInMs"));
1495 EXPECT_METRIC_EQ(
Evan Shrubsole1edeb922022-08-08 11:51:261496 kInterFrameDelay.ms(),
Tommi74fc5742020-04-27 08:43:061497 metrics::MinSample("WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
1498 } else {
1499 EXPECT_METRIC_EQ(1,
1500 metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
1501 EXPECT_METRIC_EQ(
1502 1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
Evan Shrubsole1edeb922022-08-08 11:51:261503 EXPECT_METRIC_EQ(kInterFrameDelay.ms(),
Tommi74fc5742020-04-27 08:43:061504 metrics::MinSample("WebRTC.Video.InterframeDelayInMs"));
Evan Shrubsole1edeb922022-08-08 11:51:261505 EXPECT_METRIC_EQ(kInterFrameDelay.ms(),
Tommi74fc5742020-04-27 08:43:061506 metrics::MinSample("WebRTC.Video.InterframeDelayMaxInMs"));
1507 }
1508}
1509
Emil Vardar3f1e51d2024-08-27 12:14:331510TEST_P(ReceiveStatisticsProxyTestWithContent, CorruptionScore) {
1511 const std::vector<double> corruption_scores = {0.5, 0.25, 0.80};
1512 const int kCorruptionLikelihoodPermille =
1513 static_cast<int>((0.5 + 0.25 + 0.80) / 3 * 1000);
1514 for (size_t i = 0; i < corruption_scores.size(); ++i) {
1515 statistics_proxy_->OnCorruptionScore(
1516 /*corruption_score=*/corruption_scores[i], content_type_);
1517 }
1518
1519 FlushAndGetStats();
1520 EXPECT_EQ(3u, statistics_proxy_->GetStats().corruption_score_count);
1521
Florent Castelli8037fc62024-08-29 13:00:401522 statistics_proxy_->UpdateHistograms(std::nullopt, StreamDataCounters(),
Emil Vardar3f1e51d2024-08-27 12:14:331523 nullptr);
1524 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
1525 EXPECT_METRIC_EQ(
1526 1, metrics::NumSamples(
1527 "WebRTC.Video.Screenshare.CorruptionLikelihoodPermille"));
1528 EXPECT_METRIC_EQ(
1529 1, metrics::NumEvents(
1530 "WebRTC.Video.Screenshare.CorruptionLikelihoodPermille",
1531 kCorruptionLikelihoodPermille));
1532 EXPECT_METRIC_EQ(
1533 0, metrics::NumSamples("WebRTC.Video.CorruptionLikelihoodPermille"));
1534 } else {
1535 EXPECT_METRIC_EQ(
1536 1, metrics::NumSamples("WebRTC.Video.CorruptionLikelihoodPermille"));
1537 EXPECT_METRIC_EQ(
1538 1, metrics::NumEvents("WebRTC.Video.CorruptionLikelihoodPermille",
1539 kCorruptionLikelihoodPermille));
1540 EXPECT_METRIC_EQ(
1541 0, metrics::NumSamples(
1542 "WebRTC.Video.Screenshare.CorruptionLikelihoodPermille"));
1543 }
1544}
1545
Rasmus Brandt090fe082023-05-09 10:53:011546TEST_P(ReceiveStatisticsProxyTestWithContent, FreezesAreReported) {
Evan Shrubsole1edeb922022-08-08 11:51:261547 const TimeDelta kInterFrameDelay = TimeDelta::Millis(33);
1548 const TimeDelta kFreezeDelay = TimeDelta::Millis(200);
1549 const TimeDelta kCallDuration =
1550 kMinRequiredSamples * kInterFrameDelay + kFreezeDelay;
Tommi74fc5742020-04-27 08:43:061551 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1552
1553 for (int i = 0; i < kMinRequiredSamples; ++i) {
Tommid93bf122020-05-10 18:24:591554 VideoFrameMetaData meta = MetaData(frame);
Philipp Hancke51657432023-08-15 08:20:501555 statistics_proxy_->OnDecodedFrame(
Florent Castelli8037fc62024-08-29 13:00:401556 meta, std::nullopt, TimeDelta::Zero(), TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:501557 TimeDelta::Zero(), content_type_, VideoFrameType::kVideoFrameKey);
Tommid93bf122020-05-10 18:24:591558 statistics_proxy_->OnRenderedFrame(meta);
Evan Shrubsole1edeb922022-08-08 11:51:261559 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 08:43:061560 }
1561 // Add extra freeze.
Evan Shrubsole1edeb922022-08-08 11:51:261562 time_controller_.AdvanceTime(kFreezeDelay);
Tommid93bf122020-05-10 18:24:591563 VideoFrameMetaData meta = MetaData(frame);
Philipp Hancke51657432023-08-15 08:20:501564 statistics_proxy_->OnDecodedFrame(
Florent Castelli8037fc62024-08-29 13:00:401565 meta, std::nullopt, TimeDelta::Zero(), TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:501566 TimeDelta::Zero(), content_type_, VideoFrameType::kVideoFrameDelta);
Tommid93bf122020-05-10 18:24:591567 statistics_proxy_->OnRenderedFrame(meta);
Tommi74fc5742020-04-27 08:43:061568
Florent Castelli8037fc62024-08-29 13:00:401569 FlushAndUpdateHistograms(std::nullopt, StreamDataCounters(), nullptr);
Evan Shrubsole1edeb922022-08-08 11:51:261570 const TimeDelta kExpectedTimeBetweenFreezes =
1571 kInterFrameDelay * (kMinRequiredSamples - 1);
1572 const int kExpectedNumberFreezesPerMinute = 60 / kCallDuration.seconds();
Tommi74fc5742020-04-27 08:43:061573 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
1574 EXPECT_METRIC_EQ(
Evan Shrubsole1edeb922022-08-08 11:51:261575 (kFreezeDelay + kInterFrameDelay).ms(),
Tommi74fc5742020-04-27 08:43:061576 metrics::MinSample("WebRTC.Video.Screenshare.MeanFreezeDurationMs"));
Evan Shrubsole1edeb922022-08-08 11:51:261577 EXPECT_METRIC_EQ(kExpectedTimeBetweenFreezes.ms(),
Tommi74fc5742020-04-27 08:43:061578 metrics::MinSample(
1579 "WebRTC.Video.Screenshare.MeanTimeBetweenFreezesMs"));
1580 EXPECT_METRIC_EQ(
1581 kExpectedNumberFreezesPerMinute,
1582 metrics::MinSample("WebRTC.Video.Screenshare.NumberFreezesPerMinute"));
1583 } else {
Evan Shrubsole1edeb922022-08-08 11:51:261584 EXPECT_METRIC_EQ((kFreezeDelay + kInterFrameDelay).ms(),
Tommi74fc5742020-04-27 08:43:061585 metrics::MinSample("WebRTC.Video.MeanFreezeDurationMs"));
1586 EXPECT_METRIC_EQ(
Evan Shrubsole1edeb922022-08-08 11:51:261587 kExpectedTimeBetweenFreezes.ms(),
Tommi74fc5742020-04-27 08:43:061588 metrics::MinSample("WebRTC.Video.MeanTimeBetweenFreezesMs"));
1589 EXPECT_METRIC_EQ(kExpectedNumberFreezesPerMinute,
1590 metrics::MinSample("WebRTC.Video.NumberFreezesPerMinute"));
1591 }
1592}
1593
Rasmus Brandt090fe082023-05-09 10:53:011594TEST_P(ReceiveStatisticsProxyTestWithContent, HarmonicFrameRateIsReported) {
Evan Shrubsole1edeb922022-08-08 11:51:261595 const TimeDelta kFrameDuration = TimeDelta::Millis(33);
1596 const TimeDelta kFreezeDuration = TimeDelta::Millis(200);
1597 const TimeDelta kPauseDuration = TimeDelta::Seconds(10);
1598 const TimeDelta kCallDuration =
1599 kMinRequiredSamples * kFrameDuration + kFreezeDuration + kPauseDuration;
Tommi74fc5742020-04-27 08:43:061600 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1601
1602 for (int i = 0; i < kMinRequiredSamples; ++i) {
Evan Shrubsole1edeb922022-08-08 11:51:261603 time_controller_.AdvanceTime(kFrameDuration);
Florent Castelli8037fc62024-08-29 13:00:401604 statistics_proxy_->OnDecodedFrame(frame, std::nullopt, TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:501605 content_type_,
1606 VideoFrameType::kVideoFrameKey);
Tommid7e08c82020-05-10 09:24:431607 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 08:43:061608 }
1609
1610 // Freezes and pauses should be included into harmonic frame rate.
1611 // Add freeze.
Evan Shrubsole1edeb922022-08-08 11:51:261612 time_controller_.AdvanceTime(kFreezeDuration);
Florent Castelli8037fc62024-08-29 13:00:401613 statistics_proxy_->OnDecodedFrame(frame, std::nullopt, TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:501614 content_type_,
1615 VideoFrameType::kVideoFrameDelta);
Tommid7e08c82020-05-10 09:24:431616 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 08:43:061617
1618 // Add pause.
Evan Shrubsole1edeb922022-08-08 11:51:261619 time_controller_.AdvanceTime(kPauseDuration);
Tommi74fc5742020-04-27 08:43:061620 statistics_proxy_->OnStreamInactive();
Florent Castelli8037fc62024-08-29 13:00:401621 statistics_proxy_->OnDecodedFrame(frame, std::nullopt, TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:501622 content_type_,
1623 VideoFrameType::kVideoFrameDelta);
Tommid7e08c82020-05-10 09:24:431624 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 08:43:061625
Florent Castelli8037fc62024-08-29 13:00:401626 FlushAndUpdateHistograms(std::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 08:43:061627 double kSumSquaredFrameDurationSecs =
1628 (kMinRequiredSamples - 1) *
Evan Shrubsole1edeb922022-08-08 11:51:261629 (kFrameDuration.seconds<double>() * kFrameDuration.seconds<double>());
Tommi74fc5742020-04-27 08:43:061630 kSumSquaredFrameDurationSecs +=
Evan Shrubsole1edeb922022-08-08 11:51:261631 kFreezeDuration.seconds<double>() * kFreezeDuration.seconds<double>();
Tommi74fc5742020-04-27 08:43:061632 kSumSquaredFrameDurationSecs +=
Evan Shrubsole1edeb922022-08-08 11:51:261633 kPauseDuration.seconds<double>() * kPauseDuration.seconds<double>();
1634 const int kExpectedHarmonicFrameRateFps = std::round(
1635 kCallDuration.seconds<double>() / kSumSquaredFrameDurationSecs);
Tommi74fc5742020-04-27 08:43:061636 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
1637 EXPECT_METRIC_EQ(
1638 kExpectedHarmonicFrameRateFps,
1639 metrics::MinSample("WebRTC.Video.Screenshare.HarmonicFrameRate"));
1640 } else {
1641 EXPECT_METRIC_EQ(kExpectedHarmonicFrameRateFps,
1642 metrics::MinSample("WebRTC.Video.HarmonicFrameRate"));
1643 }
1644}
1645
Rasmus Brandt090fe082023-05-09 10:53:011646TEST_P(ReceiveStatisticsProxyTestWithContent, PausesAreIgnored) {
Evan Shrubsole1edeb922022-08-08 11:51:261647 const TimeDelta kInterFrameDelay = TimeDelta::Millis(33);
1648 const TimeDelta kPauseDuration = TimeDelta::Seconds(10);
Tommi74fc5742020-04-27 08:43:061649 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1650
1651 for (int i = 0; i <= kMinRequiredSamples; ++i) {
Tommid93bf122020-05-10 18:24:591652 VideoFrameMetaData meta = MetaData(frame);
Philipp Hancke51657432023-08-15 08:20:501653 statistics_proxy_->OnDecodedFrame(
Florent Castelli8037fc62024-08-29 13:00:401654 meta, std::nullopt, TimeDelta::Zero(), TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:501655 TimeDelta::Zero(), content_type_, VideoFrameType::kVideoFrameKey);
Tommid93bf122020-05-10 18:24:591656 statistics_proxy_->OnRenderedFrame(meta);
Evan Shrubsole1edeb922022-08-08 11:51:261657 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 08:43:061658 }
1659 // Add a pause.
Evan Shrubsole1edeb922022-08-08 11:51:261660 time_controller_.AdvanceTime(kPauseDuration);
Tommi74fc5742020-04-27 08:43:061661 statistics_proxy_->OnStreamInactive();
Tommi74fc5742020-04-27 08:43:061662 // Second playback interval with triple the length.
1663 for (int i = 0; i <= kMinRequiredSamples * 3; ++i) {
Tommid93bf122020-05-10 18:24:591664 VideoFrameMetaData meta = MetaData(frame);
Philipp Hancke51657432023-08-15 08:20:501665 statistics_proxy_->OnDecodedFrame(
Florent Castelli8037fc62024-08-29 13:00:401666 meta, std::nullopt, TimeDelta::Zero(), TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:501667 TimeDelta::Zero(), content_type_, VideoFrameType::kVideoFrameDelta);
Tommid93bf122020-05-10 18:24:591668 statistics_proxy_->OnRenderedFrame(meta);
Evan Shrubsole1edeb922022-08-08 11:51:261669 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 08:43:061670 }
1671
Florent Castelli8037fc62024-08-29 13:00:401672 FlushAndUpdateHistograms(std::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 08:43:061673 // Average of two playback intervals.
Evan Shrubsole1edeb922022-08-08 11:51:261674 const TimeDelta kExpectedTimeBetweenFreezes =
1675 kInterFrameDelay * kMinRequiredSamples * 2;
Tommi74fc5742020-04-27 08:43:061676 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
1677 EXPECT_METRIC_EQ(-1, metrics::MinSample(
1678 "WebRTC.Video.Screenshare.MeanFreezeDurationMs"));
Evan Shrubsole1edeb922022-08-08 11:51:261679 EXPECT_METRIC_EQ(kExpectedTimeBetweenFreezes.ms(),
Tommi74fc5742020-04-27 08:43:061680 metrics::MinSample(
1681 "WebRTC.Video.Screenshare.MeanTimeBetweenFreezesMs"));
1682 } else {
1683 EXPECT_METRIC_EQ(-1,
1684 metrics::MinSample("WebRTC.Video.MeanFreezeDurationMs"));
1685 EXPECT_METRIC_EQ(
Evan Shrubsole1edeb922022-08-08 11:51:261686 kExpectedTimeBetweenFreezes.ms(),
Tommi74fc5742020-04-27 08:43:061687 metrics::MinSample("WebRTC.Video.MeanTimeBetweenFreezesMs"));
1688 }
1689}
1690
Rasmus Brandt090fe082023-05-09 10:53:011691TEST_P(ReceiveStatisticsProxyTestWithContent, ManyPausesAtTheBeginning) {
Evan Shrubsole1edeb922022-08-08 11:51:261692 const TimeDelta kInterFrameDelay = TimeDelta::Millis(33);
1693 const TimeDelta kPauseDuration = TimeDelta::Seconds(10);
Tommi74fc5742020-04-27 08:43:061694 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1695
1696 for (int i = 0; i <= kMinRequiredSamples; ++i) {
Florent Castelli8037fc62024-08-29 13:00:401697 statistics_proxy_->OnDecodedFrame(frame, std::nullopt, TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:501698 content_type_,
1699 VideoFrameType::kVideoFrameKey);
Evan Shrubsole1edeb922022-08-08 11:51:261700 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 08:43:061701 statistics_proxy_->OnStreamInactive();
Evan Shrubsole1edeb922022-08-08 11:51:261702 time_controller_.AdvanceTime(kPauseDuration);
Florent Castelli8037fc62024-08-29 13:00:401703 statistics_proxy_->OnDecodedFrame(frame, std::nullopt, TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:501704 content_type_,
1705 VideoFrameType::kVideoFrameDelta);
Evan Shrubsole1edeb922022-08-08 11:51:261706 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 08:43:061707 }
1708
Florent Castelli8037fc62024-08-29 13:00:401709 statistics_proxy_->UpdateHistograms(std::nullopt, StreamDataCounters(),
Tommi74fc5742020-04-27 08:43:061710 nullptr);
Tommid7e08c82020-05-10 09:24:431711 // No freezes should be detected, as all long inter-frame delays were
1712 // pauses.
Tommi74fc5742020-04-27 08:43:061713 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
1714 EXPECT_METRIC_EQ(-1, metrics::MinSample(
1715 "WebRTC.Video.Screenshare.MeanFreezeDurationMs"));
1716 } else {
1717 EXPECT_METRIC_EQ(-1,
1718 metrics::MinSample("WebRTC.Video.MeanFreezeDurationMs"));
1719 }
1720}
1721
Rasmus Brandt090fe082023-05-09 10:53:011722TEST_P(ReceiveStatisticsProxyTestWithContent, TimeInHdReported) {
Evan Shrubsole1edeb922022-08-08 11:51:261723 const TimeDelta kInterFrameDelay = TimeDelta::Millis(20);
Tommi74fc5742020-04-27 08:43:061724 webrtc::VideoFrame frame_hd = CreateFrame(1280, 720);
1725 webrtc::VideoFrame frame_sd = CreateFrame(640, 360);
1726
1727 // HD frames.
1728 for (int i = 0; i < kMinRequiredSamples; ++i) {
Tommid93bf122020-05-10 18:24:591729 VideoFrameMetaData meta = MetaData(frame_hd);
Philipp Hancke51657432023-08-15 08:20:501730 statistics_proxy_->OnDecodedFrame(
Florent Castelli8037fc62024-08-29 13:00:401731 meta, std::nullopt, TimeDelta::Zero(), TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:501732 TimeDelta::Zero(), content_type_, VideoFrameType::kVideoFrameKey);
Tommid93bf122020-05-10 18:24:591733 statistics_proxy_->OnRenderedFrame(meta);
Evan Shrubsole1edeb922022-08-08 11:51:261734 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 08:43:061735 }
1736 // SD frames.
1737 for (int i = 0; i < 2 * kMinRequiredSamples; ++i) {
Tommid93bf122020-05-10 18:24:591738 VideoFrameMetaData meta = MetaData(frame_sd);
Philipp Hancke51657432023-08-15 08:20:501739 statistics_proxy_->OnDecodedFrame(
Florent Castelli8037fc62024-08-29 13:00:401740 meta, std::nullopt, TimeDelta::Zero(), TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:501741 TimeDelta::Zero(), content_type_, VideoFrameType::kVideoFrameKey);
Tommid93bf122020-05-10 18:24:591742 statistics_proxy_->OnRenderedFrame(meta);
Evan Shrubsole1edeb922022-08-08 11:51:261743 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 08:43:061744 }
1745 // Extra last frame.
Tommid7e08c82020-05-10 09:24:431746 statistics_proxy_->OnRenderedFrame(MetaData(frame_sd));
Tommi74fc5742020-04-27 08:43:061747
Florent Castelli8037fc62024-08-29 13:00:401748 statistics_proxy_->UpdateHistograms(std::nullopt, StreamDataCounters(),
Tommi74fc5742020-04-27 08:43:061749 nullptr);
1750 const int kExpectedTimeInHdPercents = 33;
1751 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
1752 EXPECT_METRIC_EQ(
1753 kExpectedTimeInHdPercents,
1754 metrics::MinSample("WebRTC.Video.Screenshare.TimeInHdPercentage"));
1755 } else {
1756 EXPECT_METRIC_EQ(kExpectedTimeInHdPercents,
1757 metrics::MinSample("WebRTC.Video.TimeInHdPercentage"));
1758 }
1759}
1760
Rasmus Brandt090fe082023-05-09 10:53:011761TEST_P(ReceiveStatisticsProxyTestWithContent, TimeInBlockyVideoReported) {
Evan Shrubsole1edeb922022-08-08 11:51:261762 const TimeDelta kInterFrameDelay = TimeDelta::Millis(20);
Tommi74fc5742020-04-27 08:43:061763 const int kHighQp = 80;
1764 const int kLowQp = 30;
1765 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1766
1767 // High quality frames.
1768 for (int i = 0; i < kMinRequiredSamples; ++i) {
Tommid93bf122020-05-10 18:24:591769 VideoFrameMetaData meta = MetaData(frame);
Philipp Hancke51657432023-08-15 08:20:501770 statistics_proxy_->OnDecodedFrame(
1771 meta, kLowQp, TimeDelta::Zero(), TimeDelta::Zero(), TimeDelta::Zero(),
1772 content_type_, VideoFrameType::kVideoFrameKey);
Tommid93bf122020-05-10 18:24:591773 statistics_proxy_->OnRenderedFrame(meta);
Evan Shrubsole1edeb922022-08-08 11:51:261774 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 08:43:061775 }
1776 // Blocky frames.
1777 for (int i = 0; i < 2 * kMinRequiredSamples; ++i) {
Tommid93bf122020-05-10 18:24:591778 VideoFrameMetaData meta = MetaData(frame);
Philipp Hancke51657432023-08-15 08:20:501779 statistics_proxy_->OnDecodedFrame(
1780 meta, kHighQp, TimeDelta::Zero(), TimeDelta::Zero(), TimeDelta::Zero(),
1781 content_type_, VideoFrameType::kVideoFrameKey);
Tommid93bf122020-05-10 18:24:591782 statistics_proxy_->OnRenderedFrame(meta);
Evan Shrubsole1edeb922022-08-08 11:51:261783 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 08:43:061784 }
1785 // Extra last frame.
Philipp Hanckea204ad22022-07-08 16:43:251786 statistics_proxy_->OnDecodedFrame(frame, kHighQp, TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:501787 content_type_,
1788 VideoFrameType::kVideoFrameKey);
Tommid7e08c82020-05-10 09:24:431789 statistics_proxy_->OnRenderedFrame(MetaData(frame));
Tommi74fc5742020-04-27 08:43:061790
Florent Castelli8037fc62024-08-29 13:00:401791 FlushAndUpdateHistograms(std::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 08:43:061792 const int kExpectedTimeInHdPercents = 66;
1793 if (videocontenttypehelpers::IsScreenshare(content_type_)) {
1794 EXPECT_METRIC_EQ(
1795 kExpectedTimeInHdPercents,
1796 metrics::MinSample(
1797 "WebRTC.Video.Screenshare.TimeInBlockyVideoPercentage"));
1798 } else {
1799 EXPECT_METRIC_EQ(
1800 kExpectedTimeInHdPercents,
1801 metrics::MinSample("WebRTC.Video.TimeInBlockyVideoPercentage"));
1802 }
1803}
1804
Rasmus Brandt090fe082023-05-09 10:53:011805TEST_P(ReceiveStatisticsProxyTestWithContent, DownscalesReported) {
Evan Shrubsole1edeb922022-08-08 11:51:261806 // To ensure long enough call duration.
1807 const TimeDelta kInterFrameDelay = TimeDelta::Seconds(2);
Tommi74fc5742020-04-27 08:43:061808
1809 webrtc::VideoFrame frame_hd = CreateFrame(1280, 720);
1810 webrtc::VideoFrame frame_sd = CreateFrame(640, 360);
1811 webrtc::VideoFrame frame_ld = CreateFrame(320, 180);
1812
1813 // Call once to pass content type.
Florent Castelli8037fc62024-08-29 13:00:401814 statistics_proxy_->OnDecodedFrame(frame_hd, std::nullopt, TimeDelta::Zero(),
Philipp Hancke51657432023-08-15 08:20:501815 content_type_,
1816 VideoFrameType::kVideoFrameKey);
Tommi74fc5742020-04-27 08:43:061817
Evan Shrubsole1edeb922022-08-08 11:51:261818 time_controller_.AdvanceTime(TimeDelta::Zero());
Tommid7e08c82020-05-10 09:24:431819 statistics_proxy_->OnRenderedFrame(MetaData(frame_hd));
Evan Shrubsole1edeb922022-08-08 11:51:261820 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 08:43:061821 // Downscale.
Tommid7e08c82020-05-10 09:24:431822 statistics_proxy_->OnRenderedFrame(MetaData(frame_sd));
Evan Shrubsole1edeb922022-08-08 11:51:261823 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 08:43:061824 // Downscale.
Tommid7e08c82020-05-10 09:24:431825 statistics_proxy_->OnRenderedFrame(MetaData(frame_ld));
Evan Shrubsole1edeb922022-08-08 11:51:261826 time_controller_.AdvanceTime(kInterFrameDelay);
Florent Castelli8037fc62024-08-29 13:00:401827 statistics_proxy_->UpdateHistograms(std::nullopt, StreamDataCounters(),
Tommi74fc5742020-04-27 08:43:061828 nullptr);
1829 const int kExpectedDownscales = 30; // 2 per 4 seconds = 30 per minute.
Ilya Nikolaevskiya55a54d2022-12-08 10:00:211830 if (!videocontenttypehelpers::IsScreenshare(content_type_)) {
Tommi74fc5742020-04-27 08:43:061831 EXPECT_METRIC_EQ(kExpectedDownscales,
1832 metrics::MinSample(
1833 "WebRTC.Video.NumberResolutionDownswitchesPerMinute"));
1834 }
1835}
1836
Rasmus Brandt090fe082023-05-09 10:53:011837TEST_P(ReceiveStatisticsProxyTestWithContent, DecodeTimeReported) {
Evan Shrubsole1edeb922022-08-08 11:51:261838 const TimeDelta kInterFrameDelay = TimeDelta::Millis(20);
Tommi74fc5742020-04-27 08:43:061839 const int kLowQp = 30;
Evan Shrubsole1edeb922022-08-08 11:51:261840 const TimeDelta kDecodeTime = TimeDelta::Millis(7);
Tommi74fc5742020-04-27 08:43:061841
1842 webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
1843
1844 for (int i = 0; i < kMinRequiredSamples; ++i) {
Philipp Hancke51657432023-08-15 08:20:501845 statistics_proxy_->OnDecodedFrame(frame, kLowQp, kDecodeTime, content_type_,
1846 VideoFrameType::kVideoFrameKey);
Evan Shrubsole1edeb922022-08-08 11:51:261847 time_controller_.AdvanceTime(kInterFrameDelay);
Tommi74fc5742020-04-27 08:43:061848 }
Florent Castelli8037fc62024-08-29 13:00:401849 FlushAndUpdateHistograms(std::nullopt, StreamDataCounters(), nullptr);
Tommi74fc5742020-04-27 08:43:061850 EXPECT_METRIC_EQ(
Evan Shrubsole1edeb922022-08-08 11:51:261851 1, metrics::NumEvents("WebRTC.Video.DecodeTimeInMs", kDecodeTime.ms()));
Tommi74fc5742020-04-27 08:43:061852}
1853
Tommi74fc5742020-04-27 08:43:061854} // namespace internal
1855} // namespace webrtc