blob: 237b14299e82819b60117deb10152bd3a14f4d58 [file] [log] [blame]
Markus Handellb4e96d42021-11-05 11:00:551/*
2 * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "video/frame_cadence_adapter.h"
12
Per Ke975b442024-03-27 10:28:4413#include <cstdint>
14#include <memory>
Markus Handellb4e96d42021-11-05 11:00:5515#include <utility>
16#include <vector>
17
Danil Chapovalov95eeaa72022-07-06 08:14:2918#include "absl/functional/any_invocable.h"
Zhaoliang Maf089d7e2024-01-08 02:44:1519#include "api/metronome/test/fake_metronome.h"
Markus Handell90a7e2c2021-12-29 22:32:3020#include "api/task_queue/default_task_queue_factory.h"
Markus Handell28c71802021-11-08 09:11:5521#include "api/task_queue/task_queue_base.h"
Markus Handell8d87c462021-12-16 10:37:1622#include "api/task_queue/task_queue_factory.h"
Danil Chapovalov95eeaa72022-07-06 08:14:2923#include "api/units/time_delta.h"
Markus Handell8d87c462021-12-16 10:37:1624#include "api/units/timestamp.h"
Markus Handellb4e96d42021-11-05 11:00:5525#include "api/video/nv12_buffer.h"
26#include "api/video/video_frame.h"
Markus Handell90a7e2c2021-12-29 22:32:3027#include "rtc_base/event.h"
Markus Handellf2827c42023-09-02 07:41:1028#include "rtc_base/logging.h"
Markus Handellee225432021-11-29 11:35:1229#include "rtc_base/rate_statistics.h"
Markus Handelle864dec2024-08-07 14:11:1830#include "rtc_base/task_queue_for_test.h"
Markus Handell29dd8d82021-12-15 11:19:1531#include "rtc_base/time_utils.h"
Markus Handellb4e96d42021-11-05 11:00:5532#include "system_wrappers/include/metrics.h"
Markus Handell29dd8d82021-12-15 11:19:1533#include "system_wrappers/include/ntp_time.h"
Markus Handell90a7e2c2021-12-29 22:32:3034#include "system_wrappers/include/sleep.h"
Markus Handellb4e96d42021-11-05 11:00:5535#include "test/gmock.h"
36#include "test/gtest.h"
Jonas Oreland8ca06132022-03-14 11:52:4837#include "test/scoped_key_value_config.h"
Markus Handell28c71802021-11-08 09:11:5538#include "test/time_controller/simulated_time_controller.h"
Markus Handellb4e96d42021-11-05 11:00:5539
40namespace webrtc {
41namespace {
42
Markus Handell9a478b52021-11-18 15:07:0143using ::testing::_;
Markus Handellb4e96d42021-11-05 11:00:5544using ::testing::ElementsAre;
henrikab7ec0572024-01-09 09:48:5245using ::testing::InSequence;
Markus Handell29dd8d82021-12-15 11:19:1546using ::testing::Invoke;
Markus Handell8fa86192023-08-31 09:59:0647using ::testing::InvokeWithoutArgs;
Markus Handellb4e96d42021-11-05 11:00:5548using ::testing::Mock;
henrikab7ec0572024-01-09 09:48:5249using ::testing::NiceMock;
Markus Handellb4e96d42021-11-05 11:00:5550using ::testing::Pair;
Markus Handellcb237f82021-12-29 20:31:5751using ::testing::Values;
Markus Handellb4e96d42021-11-05 11:00:5552
53VideoFrame CreateFrame() {
54 return VideoFrame::Builder()
55 .set_video_frame_buffer(
56 rtc::make_ref_counted<NV12Buffer>(/*width=*/16, /*height=*/16))
57 .build();
58}
59
Markus Handell29dd8d82021-12-15 11:19:1560VideoFrame CreateFrameWithTimestamps(
61 GlobalSimulatedTimeController* time_controller) {
62 return VideoFrame::Builder()
63 .set_video_frame_buffer(
64 rtc::make_ref_counted<NV12Buffer>(/*width=*/16, /*height=*/16))
65 .set_ntp_time_ms(time_controller->GetClock()->CurrentNtpInMilliseconds())
66 .set_timestamp_us(time_controller->GetClock()->CurrentTime().us())
67 .build();
68}
69
Jonas Oreland8ca06132022-03-14 11:52:4870std::unique_ptr<FrameCadenceAdapterInterface> CreateAdapter(
Jonas Orelande62c2f22022-03-29 09:04:4871 const FieldTrialsView& field_trials,
Jonas Oreland8ca06132022-03-14 11:52:4872 Clock* clock) {
Zhaoliang Maf089d7e2024-01-08 02:44:1573 return FrameCadenceAdapterInterface::Create(
74 clock, TaskQueueBase::Current(), /*metronome=*/nullptr,
75 /*worker_queue=*/nullptr, field_trials);
Markus Handell28c71802021-11-08 09:11:5576}
77
Markus Handellb4e96d42021-11-05 11:00:5578class MockCallback : public FrameCadenceAdapterInterface::Callback {
79 public:
Markus Handell84c016a2023-11-23 12:41:4480 MOCK_METHOD(void, OnFrame, (Timestamp, bool, const VideoFrame&), (override));
Markus Handellb4e96d42021-11-05 11:00:5581 MOCK_METHOD(void, OnDiscardedFrame, (), (override));
Markus Handell818e7fb2021-12-30 12:01:3382 MOCK_METHOD(void, RequestRefreshFrame, (), (override));
Markus Handellb4e96d42021-11-05 11:00:5583};
84
Markus Handell9a478b52021-11-18 15:07:0185TEST(FrameCadenceAdapterTest, CountsOutstandingFramesToProcess) {
Jonas Oreland8ca06132022-03-14 11:52:4886 test::ScopedKeyValueConfig no_field_trials;
Markus Handell9a478b52021-11-18 15:07:0187 GlobalSimulatedTimeController time_controller(Timestamp::Millis(1));
88 MockCallback callback;
Jonas Oreland8ca06132022-03-14 11:52:4889 auto adapter = CreateAdapter(no_field_trials, time_controller.GetClock());
Markus Handell9a478b52021-11-18 15:07:0190 adapter->Initialize(&callback);
Markus Handell84c016a2023-11-23 12:41:4491 EXPECT_CALL(callback, OnFrame(_, true, _)).Times(1);
92 EXPECT_CALL(callback, OnFrame(_, false, _)).Times(1);
Markus Handell9a478b52021-11-18 15:07:0193 auto frame = CreateFrame();
94 adapter->OnFrame(frame);
95 adapter->OnFrame(frame);
96 time_controller.AdvanceTime(TimeDelta::Zero());
Markus Handell84c016a2023-11-23 12:41:4497 EXPECT_CALL(callback, OnFrame(_, false, _)).Times(1);
Markus Handell9a478b52021-11-18 15:07:0198 adapter->OnFrame(frame);
99 time_controller.AdvanceTime(TimeDelta::Zero());
100}
101
Markus Handellee225432021-11-29 11:35:12102TEST(FrameCadenceAdapterTest, FrameRateFollowsRateStatisticsByDefault) {
Jonas Oreland8ca06132022-03-14 11:52:48103 test::ScopedKeyValueConfig no_field_trials;
Philipp Hanckea204ad22022-07-08 16:43:25104 GlobalSimulatedTimeController time_controller(Timestamp::Zero());
Jonas Oreland8ca06132022-03-14 11:52:48105 auto adapter = CreateAdapter(no_field_trials, time_controller.GetClock());
Per Ke975b442024-03-27 10:28:44106 MockCallback callback;
107 adapter->Initialize(&callback);
Markus Handellee225432021-11-29 11:35:12108
109 // Create an "oracle" rate statistics which should be followed on a sequence
110 // of frames.
111 RateStatistics rate(
112 FrameCadenceAdapterInterface::kFrameRateAveragingWindowSizeMs, 1000);
113
114 for (int frame = 0; frame != 10; ++frame) {
115 time_controller.AdvanceTime(TimeDelta::Millis(10));
Per Ke975b442024-03-27 10:28:44116 absl::optional<int64_t> expected_fps =
117 rate.Rate(time_controller.GetClock()->TimeInMilliseconds());
Markus Handellee225432021-11-29 11:35:12118 rate.Update(1, time_controller.GetClock()->TimeInMilliseconds());
Per Ke975b442024-03-27 10:28:44119 // FrameCadanceAdapter::OnFrame post the frame to another sequence.
120 adapter->OnFrame(CreateFrameWithTimestamps(&time_controller));
121 time_controller.AdvanceTime(TimeDelta::Millis(0));
122 EXPECT_EQ(expected_fps, adapter->GetInputFrameRateFps())
Markus Handellee225432021-11-29 11:35:12123 << " failed for frame " << frame;
124 }
125}
126
Markus Handellee225432021-11-29 11:35:12127TEST(FrameCadenceAdapterTest, FrameRateFollowsMaxFpsWhenZeroHertzActivated) {
Philipp Hanckea204ad22022-07-08 16:43:25128 GlobalSimulatedTimeController time_controller(Timestamp::Zero());
Markus Handella57229b2024-04-16 08:40:45129 test::ScopedKeyValueConfig no_field_trials;
130 auto adapter = CreateAdapter(no_field_trials, time_controller.GetClock());
Per Ke975b442024-03-27 10:28:44131 MockCallback callback;
132 adapter->Initialize(&callback);
Markus Handell8d87c462021-12-16 10:37:16133 adapter->SetZeroHertzModeEnabled(
134 FrameCadenceAdapterInterface::ZeroHertzModeParams{});
Markus Handellee225432021-11-29 11:35:12135 adapter->OnConstraintsChanged(VideoTrackSourceConstraints{0, 1});
136 for (int frame = 0; frame != 10; ++frame) {
137 time_controller.AdvanceTime(TimeDelta::Millis(10));
Per Ke975b442024-03-27 10:28:44138 // FrameCadanceAdapter::OnFrame post the frame to another sequence.
139 adapter->OnFrame(CreateFrameWithTimestamps(&time_controller));
140 time_controller.AdvanceTime(TimeDelta::Millis(0));
Markus Handellee225432021-11-29 11:35:12141 EXPECT_EQ(adapter->GetInputFrameRateFps(), 1u);
142 }
143}
144
henrika644025c2023-11-07 17:22:02145TEST(FrameCadenceAdapterTest, ZeroHertzAdapterSupportsMaxFpsChange) {
henrika644025c2023-11-07 17:22:02146 GlobalSimulatedTimeController time_controller(Timestamp::Zero());
Markus Handella57229b2024-04-16 08:40:45147 test::ScopedKeyValueConfig no_field_trials;
148 auto adapter = CreateAdapter(no_field_trials, time_controller.GetClock());
henrika644025c2023-11-07 17:22:02149 MockCallback callback;
150 adapter->Initialize(&callback);
151 adapter->SetZeroHertzModeEnabled(
152 FrameCadenceAdapterInterface::ZeroHertzModeParams{});
153 adapter->OnConstraintsChanged(VideoTrackSourceConstraints{0, 1});
154 time_controller.AdvanceTime(TimeDelta::Zero());
155 EXPECT_EQ(adapter->GetInputFrameRateFps(), 1u);
156 adapter->OnFrame(CreateFrame());
157 time_controller.AdvanceTime(TimeDelta::Seconds(1));
158 adapter->OnConstraintsChanged(VideoTrackSourceConstraints{0, 2});
159 time_controller.AdvanceTime(TimeDelta::Zero());
160 EXPECT_EQ(adapter->GetInputFrameRateFps(), 2u);
161 adapter->OnFrame(CreateFrame());
162 // Ensure that the max_fps has been changed from 1 to 2 fps even if it was
163 // changed while zero hertz was already active.
164 EXPECT_CALL(callback, OnFrame);
165 time_controller.AdvanceTime(TimeDelta::Millis(500));
166}
167
Markus Handellee225432021-11-29 11:35:12168TEST(FrameCadenceAdapterTest,
169 FrameRateFollowsRateStatisticsAfterZeroHertzDeactivated) {
Philipp Hanckea204ad22022-07-08 16:43:25170 GlobalSimulatedTimeController time_controller(Timestamp::Zero());
Markus Handella57229b2024-04-16 08:40:45171 test::ScopedKeyValueConfig no_field_trials;
172 auto adapter = CreateAdapter(no_field_trials, time_controller.GetClock());
Per Ke975b442024-03-27 10:28:44173 MockCallback callback;
174 adapter->Initialize(&callback);
Markus Handell8d87c462021-12-16 10:37:16175 adapter->SetZeroHertzModeEnabled(
176 FrameCadenceAdapterInterface::ZeroHertzModeParams{});
Markus Handellee225432021-11-29 11:35:12177 adapter->OnConstraintsChanged(VideoTrackSourceConstraints{0, 1});
178 RateStatistics rate(
179 FrameCadenceAdapterInterface::kFrameRateAveragingWindowSizeMs, 1000);
180 constexpr int MAX = 10;
181 for (int frame = 0; frame != MAX; ++frame) {
182 time_controller.AdvanceTime(TimeDelta::Millis(10));
183 rate.Update(1, time_controller.GetClock()->TimeInMilliseconds());
Per Ke975b442024-03-27 10:28:44184 adapter->OnFrame(CreateFrameWithTimestamps(&time_controller));
185 time_controller.AdvanceTime(TimeDelta::Millis(0));
Markus Handellee225432021-11-29 11:35:12186 }
187 // Turn off zero hertz on the next-last frame; after the last frame we
188 // should see a value that tracks the rate oracle.
Markus Handell8d87c462021-12-16 10:37:16189 adapter->SetZeroHertzModeEnabled(absl::nullopt);
Markus Handellee225432021-11-29 11:35:12190 // Last frame.
191 time_controller.AdvanceTime(TimeDelta::Millis(10));
Per Ke975b442024-03-27 10:28:44192 adapter->OnFrame(CreateFrameWithTimestamps(&time_controller));
193 time_controller.AdvanceTime(TimeDelta::Millis(0));
Markus Handellee225432021-11-29 11:35:12194
195 EXPECT_EQ(rate.Rate(time_controller.GetClock()->TimeInMilliseconds()),
196 adapter->GetInputFrameRateFps());
197}
198
Markus Handell29dd8d82021-12-15 11:19:15199TEST(FrameCadenceAdapterTest, ForwardsFramesDelayed) {
Markus Handell29dd8d82021-12-15 11:19:15200 MockCallback callback;
Philipp Hanckea204ad22022-07-08 16:43:25201 GlobalSimulatedTimeController time_controller(Timestamp::Zero());
Markus Handella57229b2024-04-16 08:40:45202 test::ScopedKeyValueConfig no_field_trials;
203 auto adapter = CreateAdapter(no_field_trials, time_controller.GetClock());
Markus Handell29dd8d82021-12-15 11:19:15204 adapter->Initialize(&callback);
Markus Handell8d87c462021-12-16 10:37:16205 adapter->SetZeroHertzModeEnabled(
206 FrameCadenceAdapterInterface::ZeroHertzModeParams{});
Markus Handell29dd8d82021-12-15 11:19:15207 adapter->OnConstraintsChanged(VideoTrackSourceConstraints{0, 1});
208 constexpr int kNumFrames = 3;
209 NtpTime original_ntp_time = time_controller.GetClock()->CurrentNtpTime();
210 auto frame = CreateFrameWithTimestamps(&time_controller);
211 int64_t original_timestamp_us = frame.timestamp_us();
212 for (int index = 0; index != kNumFrames; ++index) {
213 EXPECT_CALL(callback, OnFrame).Times(0);
214 adapter->OnFrame(frame);
215 EXPECT_CALL(callback, OnFrame)
Markus Handell84c016a2023-11-23 12:41:44216 .WillOnce(Invoke([&](Timestamp post_time, bool,
Markus Handell29dd8d82021-12-15 11:19:15217 const VideoFrame& frame) {
218 EXPECT_EQ(post_time, time_controller.GetClock()->CurrentTime());
219 EXPECT_EQ(frame.timestamp_us(),
220 original_timestamp_us + index * rtc::kNumMicrosecsPerSec);
221 EXPECT_EQ(frame.ntp_time_ms(), original_ntp_time.ToMs() +
222 index * rtc::kNumMillisecsPerSec);
223 }));
224 time_controller.AdvanceTime(TimeDelta::Seconds(1));
225 frame = CreateFrameWithTimestamps(&time_controller);
226 }
227}
228
Markus Handell8fa86192023-08-31 09:59:06229TEST(FrameCadenceAdapterTest, DelayedProcessingUnderSlightContention) {
Markus Handell8fa86192023-08-31 09:59:06230 GlobalSimulatedTimeController time_controller(Timestamp::Zero());
Markus Handella57229b2024-04-16 08:40:45231 test::ScopedKeyValueConfig no_field_trials;
232 auto adapter = CreateAdapter(no_field_trials, time_controller.GetClock());
Markus Handell8fa86192023-08-31 09:59:06233 MockCallback callback;
234 adapter->Initialize(&callback);
235 adapter->SetZeroHertzModeEnabled(
236 FrameCadenceAdapterInterface::ZeroHertzModeParams{});
237 adapter->OnConstraintsChanged(VideoTrackSourceConstraints{0, 1});
238
239 // Expect frame delivery at 1 sec despite target sequence not running
240 // callbacks for the time skipped.
241 constexpr TimeDelta time_skipped = TimeDelta::Millis(999);
242 EXPECT_CALL(callback, OnFrame).WillOnce(InvokeWithoutArgs([&] {
243 EXPECT_EQ(time_controller.GetClock()->CurrentTime(),
244 Timestamp::Zero() + TimeDelta::Seconds(1));
245 }));
246 adapter->OnFrame(CreateFrame());
247 time_controller.SkipForwardBy(time_skipped);
248 time_controller.AdvanceTime(TimeDelta::Seconds(1) - time_skipped);
249}
250
251TEST(FrameCadenceAdapterTest, DelayedProcessingUnderHeavyContention) {
Markus Handell8fa86192023-08-31 09:59:06252 GlobalSimulatedTimeController time_controller(Timestamp::Zero());
Markus Handella57229b2024-04-16 08:40:45253 test::ScopedKeyValueConfig no_field_trials;
254 auto adapter = CreateAdapter(no_field_trials, time_controller.GetClock());
Markus Handell8fa86192023-08-31 09:59:06255 MockCallback callback;
256 adapter->Initialize(&callback);
257 adapter->SetZeroHertzModeEnabled(
258 FrameCadenceAdapterInterface::ZeroHertzModeParams{});
259 adapter->OnConstraintsChanged(VideoTrackSourceConstraints{0, 1});
260
261 // Expect frame delivery at origin + `time_skipped` when the target sequence
262 // is not running callbacks for the initial 1+ sec.
263 constexpr TimeDelta time_skipped =
264 TimeDelta::Seconds(1) + TimeDelta::Micros(1);
265 EXPECT_CALL(callback, OnFrame).WillOnce(InvokeWithoutArgs([&] {
266 EXPECT_EQ(time_controller.GetClock()->CurrentTime(),
267 Timestamp::Zero() + time_skipped);
268 }));
269 adapter->OnFrame(CreateFrame());
270 time_controller.SkipForwardBy(time_skipped);
henrikab7ec0572024-01-09 09:48:52271 time_controller.AdvanceTime(TimeDelta::Zero());
Markus Handell8fa86192023-08-31 09:59:06272}
273
Markus Handell29dd8d82021-12-15 11:19:15274TEST(FrameCadenceAdapterTest, RepeatsFramesDelayed) {
275 // Logic in the frame cadence adapter avoids modifying frame NTP and render
276 // timestamps if these timestamps looks unset, which is the case when the
277 // clock is initialized running from 0. For this reason we choose the
278 // `time_controller` initialization constant to something arbitrary which is
279 // not 0.
Markus Handell29dd8d82021-12-15 11:19:15280 MockCallback callback;
281 GlobalSimulatedTimeController time_controller(Timestamp::Millis(47892223));
Markus Handella57229b2024-04-16 08:40:45282 test::ScopedKeyValueConfig no_field_trials;
283 auto adapter = CreateAdapter(no_field_trials, time_controller.GetClock());
Markus Handell29dd8d82021-12-15 11:19:15284 adapter->Initialize(&callback);
Markus Handell8d87c462021-12-16 10:37:16285 adapter->SetZeroHertzModeEnabled(
286 FrameCadenceAdapterInterface::ZeroHertzModeParams{});
Markus Handell29dd8d82021-12-15 11:19:15287 adapter->OnConstraintsChanged(VideoTrackSourceConstraints{0, 1});
288 NtpTime original_ntp_time = time_controller.GetClock()->CurrentNtpTime();
289
290 // Send one frame, expect 2 subsequent repeats.
291 auto frame = CreateFrameWithTimestamps(&time_controller);
292 int64_t original_timestamp_us = frame.timestamp_us();
293 adapter->OnFrame(frame);
294
295 EXPECT_CALL(callback, OnFrame)
Markus Handell84c016a2023-11-23 12:41:44296 .WillOnce(Invoke([&](Timestamp post_time, bool, const VideoFrame& frame) {
Markus Handell29dd8d82021-12-15 11:19:15297 EXPECT_EQ(post_time, time_controller.GetClock()->CurrentTime());
298 EXPECT_EQ(frame.timestamp_us(), original_timestamp_us);
299 EXPECT_EQ(frame.ntp_time_ms(), original_ntp_time.ToMs());
300 }));
301 time_controller.AdvanceTime(TimeDelta::Seconds(1));
302 Mock::VerifyAndClearExpectations(&callback);
303
304 EXPECT_CALL(callback, OnFrame)
Markus Handell84c016a2023-11-23 12:41:44305 .WillOnce(Invoke([&](Timestamp post_time, bool, const VideoFrame& frame) {
Markus Handell29dd8d82021-12-15 11:19:15306 EXPECT_EQ(post_time, time_controller.GetClock()->CurrentTime());
307 EXPECT_EQ(frame.timestamp_us(),
308 original_timestamp_us + rtc::kNumMicrosecsPerSec);
309 EXPECT_EQ(frame.ntp_time_ms(),
310 original_ntp_time.ToMs() + rtc::kNumMillisecsPerSec);
311 }));
312 time_controller.AdvanceTime(TimeDelta::Seconds(1));
313 Mock::VerifyAndClearExpectations(&callback);
314
315 EXPECT_CALL(callback, OnFrame)
Markus Handell84c016a2023-11-23 12:41:44316 .WillOnce(Invoke([&](Timestamp post_time, bool, const VideoFrame& frame) {
Markus Handell29dd8d82021-12-15 11:19:15317 EXPECT_EQ(post_time, time_controller.GetClock()->CurrentTime());
318 EXPECT_EQ(frame.timestamp_us(),
319 original_timestamp_us + 2 * rtc::kNumMicrosecsPerSec);
320 EXPECT_EQ(frame.ntp_time_ms(),
321 original_ntp_time.ToMs() + 2 * rtc::kNumMillisecsPerSec);
322 }));
323 time_controller.AdvanceTime(TimeDelta::Seconds(1));
324}
325
326TEST(FrameCadenceAdapterTest,
327 RepeatsFramesWithoutTimestampsWithUnsetTimestamps) {
328 // Logic in the frame cadence adapter avoids modifying frame NTP and render
329 // timestamps if these timestamps looks unset, which is the case when the
330 // clock is initialized running from 0. In this test we deliberately don't set
331 // it to zero, but select unset timestamps in the frames (via CreateFrame())
332 // and verify that the timestamp modifying logic doesn't depend on the current
333 // time.
Markus Handell29dd8d82021-12-15 11:19:15334 MockCallback callback;
335 GlobalSimulatedTimeController time_controller(Timestamp::Millis(4711));
Markus Handella57229b2024-04-16 08:40:45336 test::ScopedKeyValueConfig no_field_trials;
337 auto adapter = CreateAdapter(no_field_trials, time_controller.GetClock());
Markus Handell29dd8d82021-12-15 11:19:15338 adapter->Initialize(&callback);
Markus Handell8d87c462021-12-16 10:37:16339 adapter->SetZeroHertzModeEnabled(
340 FrameCadenceAdapterInterface::ZeroHertzModeParams{});
Markus Handell29dd8d82021-12-15 11:19:15341 adapter->OnConstraintsChanged(VideoTrackSourceConstraints{0, 1});
342
343 // Send one frame, expect a repeat.
344 adapter->OnFrame(CreateFrame());
345 EXPECT_CALL(callback, OnFrame)
Markus Handell84c016a2023-11-23 12:41:44346 .WillOnce(Invoke([&](Timestamp post_time, bool, const VideoFrame& frame) {
Markus Handell29dd8d82021-12-15 11:19:15347 EXPECT_EQ(post_time, time_controller.GetClock()->CurrentTime());
348 EXPECT_EQ(frame.timestamp_us(), 0);
349 EXPECT_EQ(frame.ntp_time_ms(), 0);
350 }));
351 time_controller.AdvanceTime(TimeDelta::Seconds(1));
352 Mock::VerifyAndClearExpectations(&callback);
353 EXPECT_CALL(callback, OnFrame)
Markus Handell84c016a2023-11-23 12:41:44354 .WillOnce(Invoke([&](Timestamp post_time, bool, const VideoFrame& frame) {
Markus Handell29dd8d82021-12-15 11:19:15355 EXPECT_EQ(post_time, time_controller.GetClock()->CurrentTime());
356 EXPECT_EQ(frame.timestamp_us(), 0);
357 EXPECT_EQ(frame.ntp_time_ms(), 0);
358 }));
359 time_controller.AdvanceTime(TimeDelta::Seconds(1));
360}
361
362TEST(FrameCadenceAdapterTest, StopsRepeatingFramesDelayed) {
363 // At 1s, the initially scheduled frame appears.
364 // At 2s, the repeated initial frame appears.
365 // At 2.5s, we schedule another new frame.
366 // At 3.5s, we receive this frame.
Markus Handell29dd8d82021-12-15 11:19:15367 MockCallback callback;
Philipp Hanckea204ad22022-07-08 16:43:25368 GlobalSimulatedTimeController time_controller(Timestamp::Zero());
Markus Handella57229b2024-04-16 08:40:45369 test::ScopedKeyValueConfig no_field_trials;
370 auto adapter = CreateAdapter(no_field_trials, time_controller.GetClock());
Markus Handell29dd8d82021-12-15 11:19:15371 adapter->Initialize(&callback);
Markus Handell8d87c462021-12-16 10:37:16372 adapter->SetZeroHertzModeEnabled(
373 FrameCadenceAdapterInterface::ZeroHertzModeParams{});
Markus Handell29dd8d82021-12-15 11:19:15374 adapter->OnConstraintsChanged(VideoTrackSourceConstraints{0, 1});
375 NtpTime original_ntp_time = time_controller.GetClock()->CurrentNtpTime();
376
377 // Send one frame, expect 1 subsequent repeat.
378 adapter->OnFrame(CreateFrameWithTimestamps(&time_controller));
379 EXPECT_CALL(callback, OnFrame).Times(2);
380 time_controller.AdvanceTime(TimeDelta::Seconds(2.5));
381 Mock::VerifyAndClearExpectations(&callback);
382
383 // Send the new frame at 2.5s, which should appear after 3.5s.
384 adapter->OnFrame(CreateFrameWithTimestamps(&time_controller));
385 EXPECT_CALL(callback, OnFrame)
Markus Handell84c016a2023-11-23 12:41:44386 .WillOnce(Invoke([&](Timestamp, bool, const VideoFrame& frame) {
Markus Handell29dd8d82021-12-15 11:19:15387 EXPECT_EQ(frame.timestamp_us(), 5 * rtc::kNumMicrosecsPerSec / 2);
388 EXPECT_EQ(frame.ntp_time_ms(),
389 original_ntp_time.ToMs() + 5u * rtc::kNumMillisecsPerSec / 2);
390 }));
391 time_controller.AdvanceTime(TimeDelta::Seconds(1));
392}
393
Markus Handell2e0f4f02021-12-21 18:14:58394TEST(FrameCadenceAdapterTest, RequestsRefreshFrameOnKeyFrameRequestWhenNew) {
Markus Handell2e0f4f02021-12-21 18:14:58395 MockCallback callback;
Philipp Hanckea204ad22022-07-08 16:43:25396 GlobalSimulatedTimeController time_controller(Timestamp::Zero());
Markus Handella57229b2024-04-16 08:40:45397 test::ScopedKeyValueConfig no_field_trials;
398 auto adapter = CreateAdapter(no_field_trials, time_controller.GetClock());
Markus Handell2e0f4f02021-12-21 18:14:58399 adapter->Initialize(&callback);
400 adapter->SetZeroHertzModeEnabled(
401 FrameCadenceAdapterInterface::ZeroHertzModeParams{});
Markus Handellf5a50792022-06-16 12:25:15402 constexpr int kMaxFps = 10;
403 adapter->OnConstraintsChanged(VideoTrackSourceConstraints{0, kMaxFps});
Markus Handell818e7fb2021-12-30 12:01:33404 EXPECT_CALL(callback, RequestRefreshFrame);
Markus Handellf5a50792022-06-16 12:25:15405 time_controller.AdvanceTime(
406 TimeDelta::Seconds(1) *
407 FrameCadenceAdapterInterface::kOnDiscardedFrameRefreshFramePeriod /
408 kMaxFps);
Markus Handell818e7fb2021-12-30 12:01:33409 adapter->ProcessKeyFrameRequest();
Markus Handell2e0f4f02021-12-21 18:14:58410}
411
412TEST(FrameCadenceAdapterTest, IgnoresKeyFrameRequestShortlyAfterFrame) {
Markus Handell2e0f4f02021-12-21 18:14:58413 MockCallback callback;
Philipp Hanckea204ad22022-07-08 16:43:25414 GlobalSimulatedTimeController time_controller(Timestamp::Zero());
Markus Handella57229b2024-04-16 08:40:45415 test::ScopedKeyValueConfig no_field_trials;
416 auto adapter = CreateAdapter(no_field_trials, time_controller.GetClock());
Markus Handell2e0f4f02021-12-21 18:14:58417 adapter->Initialize(&callback);
418 adapter->SetZeroHertzModeEnabled(
419 FrameCadenceAdapterInterface::ZeroHertzModeParams{});
420 adapter->OnConstraintsChanged(VideoTrackSourceConstraints{0, 10});
421 adapter->OnFrame(CreateFrame());
422 time_controller.AdvanceTime(TimeDelta::Zero());
Markus Handell818e7fb2021-12-30 12:01:33423 EXPECT_CALL(callback, RequestRefreshFrame).Times(0);
424 adapter->ProcessKeyFrameRequest();
Markus Handell2e0f4f02021-12-21 18:14:58425}
426
Markus Handellf7f0b212022-05-24 16:39:39427TEST(FrameCadenceAdapterTest, RequestsRefreshFramesUntilArrival) {
Markus Handellf7f0b212022-05-24 16:39:39428 MockCallback callback;
Philipp Hanckea204ad22022-07-08 16:43:25429 GlobalSimulatedTimeController time_controller(Timestamp::Zero());
Markus Handella57229b2024-04-16 08:40:45430 test::ScopedKeyValueConfig no_field_trials;
431 auto adapter = CreateAdapter(no_field_trials, time_controller.GetClock());
Markus Handellf7f0b212022-05-24 16:39:39432 adapter->Initialize(&callback);
433 adapter->SetZeroHertzModeEnabled(
434 FrameCadenceAdapterInterface::ZeroHertzModeParams{});
435 constexpr int kMaxFps = 10;
436 adapter->OnConstraintsChanged(VideoTrackSourceConstraints{0, kMaxFps});
437
Markus Handellf5a50792022-06-16 12:25:15438 // We should see max_fps + 1 -
439 // FrameCadenceAdapterInterface::kOnDiscardedFrameRefreshFramePeriod refresh
440 // frame requests during the one second we wait until we send a single frame,
441 // after which refresh frame requests should cease (we should see no such
442 // requests during a second).
443 EXPECT_CALL(callback, RequestRefreshFrame)
444 .Times(kMaxFps + 1 -
445 FrameCadenceAdapterInterface::kOnDiscardedFrameRefreshFramePeriod);
Markus Handellf7f0b212022-05-24 16:39:39446 time_controller.AdvanceTime(TimeDelta::Seconds(1));
447 Mock::VerifyAndClearExpectations(&callback);
448 adapter->OnFrame(CreateFrame());
449 EXPECT_CALL(callback, RequestRefreshFrame).Times(0);
450 time_controller.AdvanceTime(TimeDelta::Seconds(1));
451}
452
Markus Handellf5a50792022-06-16 12:25:15453TEST(FrameCadenceAdapterTest, RequestsRefreshAfterFrameDrop) {
Markus Handellf5a50792022-06-16 12:25:15454 MockCallback callback;
Philipp Hanckea204ad22022-07-08 16:43:25455 GlobalSimulatedTimeController time_controller(Timestamp::Zero());
Markus Handella57229b2024-04-16 08:40:45456 test::ScopedKeyValueConfig no_field_trials;
457 auto adapter = CreateAdapter(no_field_trials, time_controller.GetClock());
Markus Handellf5a50792022-06-16 12:25:15458 adapter->Initialize(&callback);
459 adapter->SetZeroHertzModeEnabled(
460 FrameCadenceAdapterInterface::ZeroHertzModeParams{});
461 constexpr int kMaxFps = 10;
462 adapter->OnConstraintsChanged(VideoTrackSourceConstraints{0, kMaxFps});
463
464 EXPECT_CALL(callback, RequestRefreshFrame).Times(0);
465
466 // Send a frame through to cancel the initial delayed timer waiting for first
467 // frame entry.
468 adapter->OnFrame(CreateFrame());
469 time_controller.AdvanceTime(TimeDelta::Seconds(1));
470 Mock::VerifyAndClearExpectations(&callback);
471
472 // Send a dropped frame indication without any following frames received.
473 // After FrameCadenceAdapterInterface::kOnDiscardedFrameRefreshFramePeriod
474 // frame periods, we should receive a first refresh request.
475 adapter->OnDiscardedFrame();
476 EXPECT_CALL(callback, RequestRefreshFrame);
477 time_controller.AdvanceTime(
478 TimeDelta::Seconds(1) *
479 FrameCadenceAdapterInterface::kOnDiscardedFrameRefreshFramePeriod /
480 kMaxFps);
481 Mock::VerifyAndClearExpectations(&callback);
482
483 // We will now receive a refresh frame request for every frame period.
484 EXPECT_CALL(callback, RequestRefreshFrame).Times(kMaxFps);
485 time_controller.AdvanceTime(TimeDelta::Seconds(1));
486 Mock::VerifyAndClearExpectations(&callback);
487
488 // After a frame is passed the requests will cease.
489 EXPECT_CALL(callback, RequestRefreshFrame).Times(0);
490 adapter->OnFrame(CreateFrame());
491 time_controller.AdvanceTime(TimeDelta::Seconds(1));
492}
493
494TEST(FrameCadenceAdapterTest, OmitsRefreshAfterFrameDropWithTimelyFrameEntry) {
Markus Handellf5a50792022-06-16 12:25:15495 MockCallback callback;
Philipp Hanckea204ad22022-07-08 16:43:25496 GlobalSimulatedTimeController time_controller(Timestamp::Zero());
Markus Handella57229b2024-04-16 08:40:45497 test::ScopedKeyValueConfig no_field_trials;
498 auto adapter = CreateAdapter(no_field_trials, time_controller.GetClock());
Markus Handellf5a50792022-06-16 12:25:15499 adapter->Initialize(&callback);
500 adapter->SetZeroHertzModeEnabled(
501 FrameCadenceAdapterInterface::ZeroHertzModeParams{});
502 constexpr int kMaxFps = 10;
503 adapter->OnConstraintsChanged(VideoTrackSourceConstraints{0, kMaxFps});
504
505 // Send a frame through to cancel the initial delayed timer waiting for first
506 // frame entry.
507 EXPECT_CALL(callback, RequestRefreshFrame).Times(0);
508 adapter->OnFrame(CreateFrame());
509 time_controller.AdvanceTime(TimeDelta::Seconds(1));
510 Mock::VerifyAndClearExpectations(&callback);
511
512 // Send a frame drop indication. No refresh frames should be requested
513 // until FrameCadenceAdapterInterface::kOnDiscardedFrameRefreshFramePeriod
514 // intervals pass. Stop short of this.
515 EXPECT_CALL(callback, RequestRefreshFrame).Times(0);
516 adapter->OnDiscardedFrame();
517 time_controller.AdvanceTime(
518 TimeDelta::Seconds(1) *
519 FrameCadenceAdapterInterface::kOnDiscardedFrameRefreshFramePeriod /
520 kMaxFps -
521 TimeDelta::Micros(1));
522 Mock::VerifyAndClearExpectations(&callback);
523
524 // Send a frame. The timer to request the refresh frame should be cancelled by
525 // the reception, so no refreshes should be requested.
526 EXPECT_CALL(callback, RequestRefreshFrame).Times(0);
527 adapter->OnFrame(CreateFrame());
528 time_controller.AdvanceTime(TimeDelta::Seconds(1));
529 Mock::VerifyAndClearExpectations(&callback);
530}
531
Markus Handell5a77e512022-09-01 12:51:50532TEST(FrameCadenceAdapterTest, AcceptsUnconfiguredLayerFeedback) {
533 // This is a regression test for bugs.webrtc.org/14417.
Markus Handell5a77e512022-09-01 12:51:50534 MockCallback callback;
535 GlobalSimulatedTimeController time_controller(Timestamp::Zero());
Markus Handella57229b2024-04-16 08:40:45536 test::ScopedKeyValueConfig no_field_trials;
537 auto adapter = CreateAdapter(no_field_trials, time_controller.GetClock());
Markus Handell5a77e512022-09-01 12:51:50538 adapter->Initialize(&callback);
539 adapter->SetZeroHertzModeEnabled(
540 FrameCadenceAdapterInterface::ZeroHertzModeParams{.num_simulcast_layers =
541 1});
542 constexpr int kMaxFps = 10;
543 adapter->OnConstraintsChanged(VideoTrackSourceConstraints{0, kMaxFps});
544 time_controller.AdvanceTime(TimeDelta::Zero());
545
546 adapter->UpdateLayerQualityConvergence(2, false);
547 adapter->UpdateLayerStatus(2, false);
548}
549
Markus Handellfb98b012023-09-13 22:31:11550TEST(FrameCadenceAdapterTest, IgnoresDropInducedCallbacksPostDestruction) {
Markus Handellfb98b012023-09-13 22:31:11551 auto callback = std::make_unique<MockCallback>();
552 GlobalSimulatedTimeController time_controller(Timestamp::Zero());
553 auto queue = time_controller.GetTaskQueueFactory()->CreateTaskQueue(
554 "queue", TaskQueueFactory::Priority::NORMAL);
Markus Handella57229b2024-04-16 08:40:45555 test::ScopedKeyValueConfig no_field_trials;
Markus Handellfb98b012023-09-13 22:31:11556 auto adapter = FrameCadenceAdapterInterface::Create(
Zhaoliang Maf089d7e2024-01-08 02:44:15557 time_controller.GetClock(), queue.get(), /*metronome=*/nullptr,
Markus Handella57229b2024-04-16 08:40:45558 /*worker_queue=*/nullptr, no_field_trials);
Markus Handellfb98b012023-09-13 22:31:11559 queue->PostTask([&adapter, &callback] {
560 adapter->Initialize(callback.get());
561 adapter->SetZeroHertzModeEnabled(
562 FrameCadenceAdapterInterface::ZeroHertzModeParams{});
563 });
564 time_controller.AdvanceTime(TimeDelta::Zero());
565 constexpr int kMaxFps = 10;
566 adapter->OnConstraintsChanged(VideoTrackSourceConstraints{0, kMaxFps});
567 adapter->OnDiscardedFrame();
568 time_controller.AdvanceTime(TimeDelta::Zero());
569 callback = nullptr;
570 queue->PostTask([adapter = std::move(adapter)]() mutable {});
571 time_controller.AdvanceTime(3 * TimeDelta::Seconds(1) / kMaxFps);
572}
573
Zhaoliang Maf089d7e2024-01-08 02:44:15574TEST(FrameCadenceAdapterTest, EncodeFramesAreAlignedWithMetronomeTick) {
Zhaoliang Maf089d7e2024-01-08 02:44:15575 GlobalSimulatedTimeController time_controller(Timestamp::Zero());
576 // Here the metronome interval is 33ms, because the metronome is not
577 // infrequent then the encode tasks are aligned with the tick period.
578 static constexpr TimeDelta kTickPeriod = TimeDelta::Millis(33);
579 auto queue = time_controller.GetTaskQueueFactory()->CreateTaskQueue(
580 "queue", TaskQueueFactory::Priority::NORMAL);
581 auto worker_queue = time_controller.GetTaskQueueFactory()->CreateTaskQueue(
582 "work_queue", TaskQueueFactory::Priority::NORMAL);
Markus Handelle864dec2024-08-07 14:11:18583 test::FakeMetronome metronome(kTickPeriod);
Markus Handella57229b2024-04-16 08:40:45584 test::ScopedKeyValueConfig no_field_trials;
Zhaoliang Maf089d7e2024-01-08 02:44:15585 auto adapter = FrameCadenceAdapterInterface::Create(
586 time_controller.GetClock(), queue.get(), &metronome, worker_queue.get(),
Markus Handella57229b2024-04-16 08:40:45587 no_field_trials);
Zhaoliang Maf089d7e2024-01-08 02:44:15588 MockCallback callback;
589 adapter->Initialize(&callback);
590 auto frame = CreateFrame();
591
592 // `callback->OnFrame()` would not be called if only 32ms went by after
593 // `adapter->OnFrame()`.
594 EXPECT_CALL(callback, OnFrame(_, false, _)).Times(0);
595 adapter->OnFrame(frame);
596 time_controller.AdvanceTime(TimeDelta::Millis(32));
597 Mock::VerifyAndClearExpectations(&callback);
598
599 // `callback->OnFrame()` should be called if 33ms went by after
600 // `adapter->OnFrame()`.
601 EXPECT_CALL(callback, OnFrame(_, false, _)).Times(1);
602 time_controller.AdvanceTime(TimeDelta::Millis(1));
603 Mock::VerifyAndClearExpectations(&callback);
604
605 // `callback->OnFrame()` would not be called if only 32ms went by after
606 // `adapter->OnFrame()`.
607 EXPECT_CALL(callback, OnFrame(_, false, _)).Times(0);
608 // Send two frame before next tick.
609 adapter->OnFrame(frame);
610 adapter->OnFrame(frame);
611 time_controller.AdvanceTime(TimeDelta::Millis(32));
612 Mock::VerifyAndClearExpectations(&callback);
613
614 // `callback->OnFrame()` should be called if 33ms went by after
615 // `adapter->OnFrame()`.
616 EXPECT_CALL(callback, OnFrame(_, false, _)).Times(2);
617 time_controller.AdvanceTime(TimeDelta::Millis(1));
618 Mock::VerifyAndClearExpectations(&callback);
619
620 // Change the metronome tick period to 67ms (15Hz).
621 metronome.SetTickPeriod(TimeDelta::Millis(67));
622 // Expect the encode would happen immediately.
623 EXPECT_CALL(callback, OnFrame(_, false, _)).Times(1);
624 adapter->OnFrame(frame);
625 time_controller.AdvanceTime(TimeDelta::Zero());
626 Mock::VerifyAndClearExpectations(&callback);
627
628 // Change the metronome tick period to 16ms (60Hz).
629 metronome.SetTickPeriod(TimeDelta::Millis(16));
630 // Expect the encode would not happen if only 15ms went by after
631 // `adapter->OnFrame()`.
632 EXPECT_CALL(callback, OnFrame(_, false, _)).Times(0);
633 adapter->OnFrame(frame);
634 time_controller.AdvanceTime(TimeDelta::Millis(15));
635 Mock::VerifyAndClearExpectations(&callback);
636 // `callback->OnFrame()` should be called if 16ms went by after
637 // `adapter->OnFrame()`.
638 EXPECT_CALL(callback, OnFrame(_, false, _)).Times(1);
639 time_controller.AdvanceTime(TimeDelta::Millis(1));
640 Mock::VerifyAndClearExpectations(&callback);
641
642 rtc::Event finalized;
643 queue->PostTask([&] {
644 adapter = nullptr;
645 finalized.Set();
646 });
647 finalized.Wait(rtc::Event::kForever);
648}
649
Markus Handelle864dec2024-08-07 14:11:18650TEST(FrameCadenceAdapterTest, ShutdownUnderMetronome) {
651 // Regression test for crbug.com/356423094.
652 // The current thread takes the role of worker queue.
653 GlobalSimulatedTimeController time_controller(Timestamp::Zero());
654 static constexpr TimeDelta kTickPeriod = TimeDelta::Millis(100);
655 auto queue = time_controller.GetTaskQueueFactory()->CreateTaskQueue(
656 "queue", TaskQueueFactory::Priority::NORMAL);
657 test::FakeMetronome metronome(kTickPeriod);
658 test::ScopedKeyValueConfig no_field_trials;
659 auto adapter = FrameCadenceAdapterInterface::Create(
660 time_controller.GetClock(), queue.get(), &metronome,
661 TaskQueueBase::Current(), no_field_trials);
662 MockCallback callback;
663 EXPECT_CALL(callback, OnFrame).Times(0);
664 adapter->Initialize(&callback);
665
666 // Pass a frame, this is expected to trigger an encode call in the future.
667 adapter->OnFrame(CreateFrame());
668
669 // Then post destruction of the adapter and destroy the encode queue from the
670 // worker (i.e. current).
671 SendTask(queue.get(), [&] { adapter = nullptr; });
672 queue = nullptr;
673
674 // Now that we advance time, there should be no encoding happening.
675 time_controller.AdvanceTime(TimeDelta::Millis(100));
676}
677
Markus Handellcb237f82021-12-29 20:31:57678class FrameCadenceAdapterSimulcastLayersParamTest
679 : public ::testing::TestWithParam<int> {
680 public:
681 static constexpr int kMaxFpsHz = 8;
682 static constexpr TimeDelta kMinFrameDelay =
683 TimeDelta::Millis(1000 / kMaxFpsHz);
684 static constexpr TimeDelta kIdleFrameDelay =
685 FrameCadenceAdapterInterface::kZeroHertzIdleRepeatRatePeriod;
Markus Handell2e0f4f02021-12-21 18:14:58686
Markus Handellcb237f82021-12-29 20:31:57687 FrameCadenceAdapterSimulcastLayersParamTest() {
688 adapter_->Initialize(&callback_);
689 adapter_->OnConstraintsChanged(VideoTrackSourceConstraints{0, kMaxFpsHz});
690 time_controller_.AdvanceTime(TimeDelta::Zero());
691 adapter_->SetZeroHertzModeEnabled(
692 FrameCadenceAdapterInterface::ZeroHertzModeParams{});
Markus Handell5a77e512022-09-01 12:51:50693 const size_t num_spatial_layers = GetParam();
Markus Handellcb237f82021-12-29 20:31:57694 adapter_->SetZeroHertzModeEnabled(
695 FrameCadenceAdapterInterface::ZeroHertzModeParams{num_spatial_layers});
696 }
697
698 int NumSpatialLayers() const { return GetParam(); }
699
700 protected:
Markus Handella57229b2024-04-16 08:40:45701 test::ScopedKeyValueConfig no_field_trials_;
Markus Handellcb237f82021-12-29 20:31:57702 MockCallback callback_;
Philipp Hanckea204ad22022-07-08 16:43:25703 GlobalSimulatedTimeController time_controller_{Timestamp::Zero()};
Markus Handellcb237f82021-12-29 20:31:57704 const std::unique_ptr<FrameCadenceAdapterInterface> adapter_{
Markus Handella57229b2024-04-16 08:40:45705 CreateAdapter(no_field_trials_, time_controller_.GetClock())};
Markus Handellcb237f82021-12-29 20:31:57706};
707
708TEST_P(FrameCadenceAdapterSimulcastLayersParamTest,
709 LayerReconfigurationResetsConvergenceInfo) {
710 // Assumes layer reconfiguration has just happened.
711 // Verify the state is unconverged.
712 adapter_->OnFrame(CreateFrame());
713 EXPECT_CALL(callback_, OnFrame).Times(kMaxFpsHz);
714 time_controller_.AdvanceTime(kMaxFpsHz * kMinFrameDelay);
Markus Handell2e0f4f02021-12-21 18:14:58715}
716
Markus Handellcb237f82021-12-29 20:31:57717TEST_P(FrameCadenceAdapterSimulcastLayersParamTest,
718 IgnoresKeyFrameRequestWhileShortRepeating) {
719 // Plot:
720 // 1. 0 * kMinFrameDelay: Start unconverged. Frame -> adapter.
721 // 2. 1 * kMinFrameDelay: Frame -> callback.
722 // 3. 2 * kMinFrameDelay: 1st short repeat.
723 // Since we're unconverged we assume the process continues.
724 adapter_->OnFrame(CreateFrame());
725 time_controller_.AdvanceTime(2 * kMinFrameDelay);
Markus Handell818e7fb2021-12-30 12:01:33726 EXPECT_CALL(callback_, RequestRefreshFrame).Times(0);
727 adapter_->ProcessKeyFrameRequest();
Markus Handellcb237f82021-12-29 20:31:57728
729 // Expect short repeating as ususal.
730 EXPECT_CALL(callback_, OnFrame).Times(8);
731 time_controller_.AdvanceTime(8 * kMinFrameDelay);
732}
733
734TEST_P(FrameCadenceAdapterSimulcastLayersParamTest,
735 IgnoresKeyFrameRequestJustBeforeIdleRepeating) {
736 // (Only for > 0 spatial layers as we assume not converged with 0 layers)
737 if (NumSpatialLayers() == 0)
738 return;
739
740 // Plot:
741 // 1. 0 * kMinFrameDelay: Start converged. Frame -> adapter.
742 // 2. 1 * kMinFrameDelay: Frame -> callback. New repeat scheduled at
743 // (kMaxFpsHz + 1) * kMinFrameDelay.
744 // 3. kMaxFpsHz * kMinFrameDelay: Process keyframe.
745 // 4. (kMaxFpsHz + N) * kMinFrameDelay (1 <= N <= kMaxFpsHz): Short repeats
746 // due to not converged.
747 for (int i = 0; i != NumSpatialLayers(); i++) {
748 adapter_->UpdateLayerStatus(i, /*enabled=*/true);
749 adapter_->UpdateLayerQualityConvergence(i, /*converged=*/true);
750 }
751 adapter_->OnFrame(CreateFrame());
752 time_controller_.AdvanceTime(kIdleFrameDelay);
Markus Handell2e0f4f02021-12-21 18:14:58753
754 // We process the key frame request kMinFrameDelay before the first idle
Markus Handellcb237f82021-12-29 20:31:57755 // repeat should happen. The resulting repeats should happen spaced by
756 // kMinFrameDelay before we get new convergence info.
Markus Handell818e7fb2021-12-30 12:01:33757 EXPECT_CALL(callback_, RequestRefreshFrame).Times(0);
758 adapter_->ProcessKeyFrameRequest();
Markus Handellcb237f82021-12-29 20:31:57759 EXPECT_CALL(callback_, OnFrame).Times(kMaxFpsHz);
760 time_controller_.AdvanceTime(kMaxFpsHz * kMinFrameDelay);
Markus Handell2e0f4f02021-12-21 18:14:58761}
762
Markus Handellcb237f82021-12-29 20:31:57763TEST_P(FrameCadenceAdapterSimulcastLayersParamTest,
764 IgnoresKeyFrameRequestShortRepeatsBeforeIdleRepeat) {
765 // (Only for > 0 spatial layers as we assume not converged with 0 layers)
766 if (NumSpatialLayers() == 0)
767 return;
768 // Plot:
769 // 1. 0 * kMinFrameDelay: Start converged. Frame -> adapter.
770 // 2. 1 * kMinFrameDelay: Frame -> callback. New repeat scheduled at
771 // (kMaxFpsHz + 1) * kMinFrameDelay.
772 // 3. 2 * kMinFrameDelay: Process keyframe.
773 // 4. (2 + N) * kMinFrameDelay (1 <= N <= kMaxFpsHz): Short repeats due to not
774 // converged.
775 for (int i = 0; i != NumSpatialLayers(); i++) {
776 adapter_->UpdateLayerStatus(i, /*enabled=*/true);
777 adapter_->UpdateLayerQualityConvergence(i, /*converged=*/true);
778 }
779 adapter_->OnFrame(CreateFrame());
780 time_controller_.AdvanceTime(2 * kMinFrameDelay);
Markus Handell2e0f4f02021-12-21 18:14:58781
Markus Handellcb237f82021-12-29 20:31:57782 // We process the key frame request (kMaxFpsHz - 1) * kMinFrameDelay before
783 // the first idle repeat should happen. The resulting repeats should happen
784 // spaced kMinFrameDelay before we get new convergence info.
Markus Handell818e7fb2021-12-30 12:01:33785 EXPECT_CALL(callback_, RequestRefreshFrame).Times(0);
786 adapter_->ProcessKeyFrameRequest();
Markus Handellcb237f82021-12-29 20:31:57787 EXPECT_CALL(callback_, OnFrame).Times(kMaxFpsHz);
788 time_controller_.AdvanceTime(kMaxFpsHz * kMinFrameDelay);
Markus Handell2e0f4f02021-12-21 18:14:58789}
790
Markus Handellcb237f82021-12-29 20:31:57791INSTANTIATE_TEST_SUITE_P(,
792 FrameCadenceAdapterSimulcastLayersParamTest,
793 Values(0, 1, 2));
Markus Handelle59fee82021-12-23 08:29:23794
Markus Handell8d87c462021-12-16 10:37:16795class ZeroHertzLayerQualityConvergenceTest : public ::testing::Test {
796 public:
797 static constexpr TimeDelta kMinFrameDelay = TimeDelta::Millis(100);
798 static constexpr TimeDelta kIdleFrameDelay =
799 FrameCadenceAdapterInterface::kZeroHertzIdleRepeatRatePeriod;
henrika8f16ce92023-12-04 13:03:52800 // Restricts non-idle repeat rate to 5 fps (default is 10 fps);
801 static constexpr int kRestrictedMaxFps = 5;
Markus Handell8d87c462021-12-16 10:37:16802
803 ZeroHertzLayerQualityConvergenceTest() {
804 adapter_->Initialize(&callback_);
805 adapter_->SetZeroHertzModeEnabled(
806 FrameCadenceAdapterInterface::ZeroHertzModeParams{
807 /*num_simulcast_layers=*/2});
808 adapter_->OnConstraintsChanged(VideoTrackSourceConstraints{
809 /*min_fps=*/0, /*max_fps=*/TimeDelta::Seconds(1) / kMinFrameDelay});
810 time_controller_.AdvanceTime(TimeDelta::Zero());
811 }
812
813 void PassFrame() { adapter_->OnFrame(CreateFrame()); }
814
815 void ExpectFrameEntriesAtDelaysFromNow(
816 std::initializer_list<TimeDelta> list) {
817 Timestamp origin = time_controller_.GetClock()->CurrentTime();
818 for (auto delay : list) {
Markus Handell84c016a2023-11-23 12:41:44819 EXPECT_CALL(callback_, OnFrame(origin + delay, false, _));
Markus Handell8d87c462021-12-16 10:37:16820 time_controller_.AdvanceTime(origin + delay -
821 time_controller_.GetClock()->CurrentTime());
822 }
823 }
824
Danil Chapovalov95eeaa72022-07-06 08:14:29825 void ScheduleDelayed(TimeDelta delay, absl::AnyInvocable<void() &&> task) {
826 TaskQueueBase::Current()->PostDelayedTask(std::move(task), delay);
Markus Handell8d87c462021-12-16 10:37:16827 }
828
829 protected:
Markus Handella57229b2024-04-16 08:40:45830 test::ScopedKeyValueConfig no_field_trials_;
Markus Handell8d87c462021-12-16 10:37:16831 MockCallback callback_;
Philipp Hanckea204ad22022-07-08 16:43:25832 GlobalSimulatedTimeController time_controller_{Timestamp::Zero()};
Markus Handell8d87c462021-12-16 10:37:16833 std::unique_ptr<FrameCadenceAdapterInterface> adapter_{
Markus Handella57229b2024-04-16 08:40:45834 CreateAdapter(no_field_trials_, time_controller_.GetClock())};
Markus Handell8d87c462021-12-16 10:37:16835};
836
Markus Handelle59fee82021-12-23 08:29:23837TEST_F(ZeroHertzLayerQualityConvergenceTest, InitialStateUnconverged) {
838 // As the layer count is just configured, assume we start out as unconverged.
Markus Handell8d87c462021-12-16 10:37:16839 PassFrame();
840 ExpectFrameEntriesAtDelaysFromNow({
Markus Handelle59fee82021-12-23 08:29:23841 1 * kMinFrameDelay, // Original frame emitted
842 2 * kMinFrameDelay, // Short repeats.
843 3 * kMinFrameDelay, // ...
Markus Handell8d87c462021-12-16 10:37:16844 });
845}
846
847TEST_F(ZeroHertzLayerQualityConvergenceTest, UnconvergedAfterLayersEnabled) {
848 // With newly enabled layers we assume quality is unconverged.
849 adapter_->UpdateLayerStatus(0, /*enabled=*/true);
850 adapter_->UpdateLayerStatus(1, /*enabled=*/true);
851 PassFrame();
852 ExpectFrameEntriesAtDelaysFromNow({
853 kMinFrameDelay, // Original frame emitted
854 2 * kMinFrameDelay, // Unconverged repeats.
855 3 * kMinFrameDelay, // ...
856 });
857}
858
859TEST_F(ZeroHertzLayerQualityConvergenceTest,
860 RepeatsPassedFramesUntilConvergence) {
861 ScheduleDelayed(TimeDelta::Zero(), [&] {
862 adapter_->UpdateLayerStatus(0, /*enabled=*/true);
863 adapter_->UpdateLayerStatus(1, /*enabled=*/true);
864 PassFrame();
865 });
866 ScheduleDelayed(2.5 * kMinFrameDelay, [&] {
867 adapter_->UpdateLayerQualityConvergence(/*spatial_index=*/1, true);
868 });
869 ScheduleDelayed(3.5 * kMinFrameDelay, [&] {
870 adapter_->UpdateLayerQualityConvergence(/*spatial_index=*/0, true);
871 });
872 ScheduleDelayed(8 * kMinFrameDelay, [&] { PassFrame(); });
873 ScheduleDelayed(9.5 * kMinFrameDelay, [&] {
874 adapter_->UpdateLayerQualityConvergence(/*spatial_index=*/0, true);
875 });
876 ScheduleDelayed(10.5 * kMinFrameDelay, [&] {
877 adapter_->UpdateLayerQualityConvergence(/*spatial_index=*/1, true);
878 });
879 ExpectFrameEntriesAtDelaysFromNow({
880 kMinFrameDelay, // Original frame emitted
881 2 * kMinFrameDelay, // Repeat from kMinFrameDelay.
882
883 // 2.5 * kMinFrameDelay: Converged in layer 1, layer 0 still unconverged.
884 3 * kMinFrameDelay, // Repeat from 2 * kMinFrameDelay.
885
886 // 3.5 * kMinFrameDelay: Converged in layer 0 as well.
887 4 * kMinFrameDelay, // Repeat from 3 * kMinFrameDelay. An idle repeat is
888 // scheduled for kIdleFrameDelay + 3 *
889 // kMinFrameDelay.
890
891 // A new frame is passed at 8 * kMinFrameDelay.
892 9 * kMinFrameDelay, // Original frame emitted
893
894 // 9.5 * kMinFrameDelay: Converged in layer 0, layer 1 still unconverged.
895 10 * kMinFrameDelay, // Repeat from 9 * kMinFrameDelay.
896 // 10.5 * kMinFrameDelay: Converged in layer 0 as well.
897 11 * kMinFrameDelay, // Idle repeats from 1000.
898 11 * kMinFrameDelay + kIdleFrameDelay, // ...
899 11 * kMinFrameDelay + 2 * kIdleFrameDelay, // ...
900 // ...
901 });
902}
903
henrika8f16ce92023-12-04 13:03:52904TEST_F(ZeroHertzLayerQualityConvergenceTest,
905 UnconvergedRepeatRateAdaptsDownWhenRestricted) {
906 PassFrame();
907 ScheduleDelayed(1.5 * kMinFrameDelay, [&] {
908 adapter_->UpdateVideoSourceRestrictions(kRestrictedMaxFps);
909 });
910 ExpectFrameEntriesAtDelaysFromNow({
911 1 * kMinFrameDelay, // Original frame emitted at non-restricted rate.
912
913 // 1.5 * kMinFrameDelay: restricts max fps to 5 fps which should result
914 // in a new non-idle repeat delay of 2 * kMinFrameDelay.
915 2 * kMinFrameDelay, // Unconverged repeat at non-restricted rate.
916 4 * kMinFrameDelay, // Unconverged repeats at restricted rate. This
917 // happens 2 * kMinFrameDelay after the last frame.
918 6 * kMinFrameDelay, // ...
919 });
920}
921
922TEST_F(ZeroHertzLayerQualityConvergenceTest,
923 UnconvergedRepeatRateAdaptsUpWhenGoingFromRestrictedToUnrestricted) {
924 PassFrame();
925 ScheduleDelayed(1.5 * kMinFrameDelay, [&] {
926 adapter_->UpdateVideoSourceRestrictions(kRestrictedMaxFps);
927 });
928 ScheduleDelayed(5.5 * kMinFrameDelay, [&] {
929 adapter_->UpdateVideoSourceRestrictions(absl::nullopt);
930 });
931 ExpectFrameEntriesAtDelaysFromNow({
932 1 * kMinFrameDelay, // Original frame emitted at non-restricted rate.
933
934 // 1.5 * kMinFrameDelay: restricts max fps to 5 fps which should result
935 // in a new non-idle repeat delay of 2 * kMinFrameDelay.
936 2 * kMinFrameDelay, // Unconverged repeat at non-restricted rate.
937 4 * kMinFrameDelay, // Unconverged repeat at restricted rate.
938
939 // 5.5 * kMinFrameDelay: removes frame-rate restriction and we should
940 // then go back to 10 fps as unconverged repeat rate.
941 6 * kMinFrameDelay, // Last unconverged repeat at restricted rate.
942 7 * kMinFrameDelay, // Back to unconverged repeat at non-restricted rate.
943 8 * kMinFrameDelay, // We are now unrestricted.
944 9 * kMinFrameDelay, // ...
945 });
946}
947
948TEST_F(ZeroHertzLayerQualityConvergenceTest,
949 UnconvergedRepeatRateMaintainsRestrictionOnReconfigureToHigherMaxFps) {
950 PassFrame();
951 ScheduleDelayed(1.5 * kMinFrameDelay, [&] {
952 adapter_->UpdateVideoSourceRestrictions(kRestrictedMaxFps);
953 });
954 ScheduleDelayed(2.5 * kMinFrameDelay, [&] {
955 adapter_->OnConstraintsChanged(VideoTrackSourceConstraints{
956 /*min_fps=*/0, /*max_fps=*/2 * TimeDelta::Seconds(1) / kMinFrameDelay});
957 });
958 ScheduleDelayed(3 * kMinFrameDelay, [&] { PassFrame(); });
959 ScheduleDelayed(8 * kMinFrameDelay, [&] {
960 adapter_->OnConstraintsChanged(VideoTrackSourceConstraints{
961 /*min_fps=*/0,
962 /*max_fps=*/0.2 * TimeDelta::Seconds(1) / kMinFrameDelay});
963 });
964 ScheduleDelayed(9 * kMinFrameDelay, [&] { PassFrame(); });
965 ExpectFrameEntriesAtDelaysFromNow({
966 1 * kMinFrameDelay, // Original frame emitted at non-restricted rate.
967
968 // 1.5 * kMinFrameDelay: restricts max fps to 5 fps which should result
969 // in a new non-idle repeat delay of 2 * kMinFrameDelay.
970 2 * kMinFrameDelay, // Unconverged repeat at non-restricted rate.
971
972 // 2.5 * kMinFrameDelay: new constraint asks for max rate of 20 fps.
973 // The 0Hz adapter is reconstructed for 20 fps but inherits the current
974 // restriction for rate of non-converged frames of 5 fps.
975
976 // A new frame is passed at 3 * kMinFrameDelay. The previous repeat
977 // cadence was stopped by the change in constraints.
978 3.5 * kMinFrameDelay, // Original frame emitted at non-restricted 20 fps.
979 // The delay is 0.5 * kMinFrameDelay.
980 5.5 * kMinFrameDelay, // Unconverged repeat at restricted rate.
981 // The delay is 2 * kMinFrameDelay when restricted.
982 7.5 * kMinFrameDelay, // ...
983
984 // 8 * kMinFrameDelay: new constraint asks for max rate of 2 fps.
985 // The 0Hz adapter is reconstructed for 2 fps and will therefore not obey
986 // the current restriction for rate of non-converged frames of 5 fps
987 // since the new max rate is lower.
988
989 // A new frame is passed at 9 * kMinFrameDelay. The previous repeat
990 // cadence was stopped by the change in constraints.
991 14 * kMinFrameDelay, // Original frame emitted at non-restricted 2 fps.
992 // The delay is 5 * kMinFrameDelay.
993 19 * kMinFrameDelay, // Unconverged repeat at non-restricted rate.
994 24 * kMinFrameDelay, // ...
995 });
996}
997
Markus Handellb4e96d42021-11-05 11:00:55998class FrameCadenceAdapterMetricsTest : public ::testing::Test {
999 public:
Markus Handell28c71802021-11-08 09:11:551000 FrameCadenceAdapterMetricsTest() : time_controller_(Timestamp::Millis(1)) {
1001 metrics::Reset();
1002 }
1003 void DepleteTaskQueues() { time_controller_.AdvanceTime(TimeDelta::Zero()); }
1004
Markus Handell9a478b52021-11-18 15:07:011005 protected:
Markus Handell28c71802021-11-08 09:11:551006 GlobalSimulatedTimeController time_controller_;
Markus Handellb4e96d42021-11-05 11:00:551007};
1008
Markus Handell9d04a782022-05-12 16:38:571009TEST_F(FrameCadenceAdapterMetricsTest, RecordsTimeUntilFirstFrame) {
1010 MockCallback callback;
1011 test::ScopedKeyValueConfig no_field_trials;
1012 auto adapter = CreateAdapter(no_field_trials, time_controller_.GetClock());
1013 adapter->Initialize(&callback);
1014 adapter->SetZeroHertzModeEnabled(
1015 FrameCadenceAdapterInterface::ZeroHertzModeParams{});
1016 adapter->OnConstraintsChanged(VideoTrackSourceConstraints{0, 5.0});
1017 time_controller_.AdvanceTime(TimeDelta::Millis(666));
1018 adapter->OnFrame(CreateFrame());
1019 DepleteTaskQueues();
1020 EXPECT_THAT(
1021 metrics::Samples("WebRTC.Screenshare.ZeroHz.TimeUntilFirstFrameMs"),
1022 ElementsAre(Pair(666, 1)));
1023}
1024
Per Ke975b442024-03-27 10:28:441025TEST_F(FrameCadenceAdapterMetricsTest,
1026 RecordsFrameTimestampMonotonicallyIncreasing) {
1027 MockCallback callback;
1028 test::ScopedKeyValueConfig no_field_trials;
1029 std::unique_ptr<FrameCadenceAdapterInterface> adapter =
1030 CreateAdapter(no_field_trials, time_controller_.GetClock());
1031 adapter->Initialize(&callback);
1032 time_controller_.AdvanceTime(TimeDelta::Millis(666));
1033 adapter->OnFrame(CreateFrameWithTimestamps(&time_controller_));
1034 adapter->OnFrame(CreateFrameWithTimestamps(&time_controller_));
1035 time_controller_.AdvanceTime(TimeDelta::Zero());
1036 adapter = nullptr;
1037 DepleteTaskQueues();
1038 EXPECT_THAT(metrics::Samples(
1039 "WebRTC.Video.InputFrameTimestampMonotonicallyIncreasing"),
1040 ElementsAre(Pair(false, 1)));
1041}
1042
Markus Handell90a7e2c2021-12-29 22:32:301043TEST(FrameCadenceAdapterRealTimeTest, TimestampsDoNotDrift) {
1044 // This regression test must be performed in realtime because of limitations
1045 // in GlobalSimulatedTimeController.
1046 //
1047 // We sleep for a long while in OnFrame when a repeat was scheduled which
1048 // should reflect in accordingly increased ntp_time_ms() and timestamp_us() in
1049 // the repeated frames.
1050 auto factory = CreateDefaultTaskQueueFactory();
1051 auto queue =
1052 factory->CreateTaskQueue("test", TaskQueueFactory::Priority::NORMAL);
Markus Handell90a7e2c2021-12-29 22:32:301053 MockCallback callback;
1054 Clock* clock = Clock::GetRealTimeClock();
1055 std::unique_ptr<FrameCadenceAdapterInterface> adapter;
1056 int frame_counter = 0;
1057 int64_t original_ntp_time_ms;
1058 int64_t original_timestamp_us;
1059 rtc::Event event;
Markus Handella57229b2024-04-16 08:40:451060 test::ScopedKeyValueConfig no_field_trials;
Danil Chapovalov95eeaa72022-07-06 08:14:291061 queue->PostTask([&] {
Markus Handella57229b2024-04-16 08:40:451062 adapter = CreateAdapter(no_field_trials, clock);
Markus Handell90a7e2c2021-12-29 22:32:301063 adapter->Initialize(&callback);
1064 adapter->SetZeroHertzModeEnabled(
1065 FrameCadenceAdapterInterface::ZeroHertzModeParams{});
1066 adapter->OnConstraintsChanged(VideoTrackSourceConstraints{0, 30});
1067 auto frame = CreateFrame();
1068 original_ntp_time_ms = clock->CurrentNtpInMilliseconds();
1069 frame.set_ntp_time_ms(original_ntp_time_ms);
1070 original_timestamp_us = clock->CurrentTime().us();
1071 frame.set_timestamp_us(original_timestamp_us);
1072 constexpr int kSleepMs = rtc::kNumMillisecsPerSec / 2;
1073 EXPECT_CALL(callback, OnFrame)
1074 .WillRepeatedly(
Markus Handell84c016a2023-11-23 12:41:441075 Invoke([&](Timestamp, bool, const VideoFrame& incoming_frame) {
Markus Handell90a7e2c2021-12-29 22:32:301076 ++frame_counter;
1077 // Avoid the first OnFrame and sleep on the second.
1078 if (frame_counter == 2) {
1079 SleepMs(kSleepMs);
1080 } else if (frame_counter == 3) {
1081 EXPECT_GE(incoming_frame.ntp_time_ms(),
1082 original_ntp_time_ms + kSleepMs);
1083 EXPECT_GE(incoming_frame.timestamp_us(),
1084 original_timestamp_us + kSleepMs);
1085 event.Set();
1086 }
1087 }));
1088 adapter->OnFrame(frame);
Danil Chapovalov95eeaa72022-07-06 08:14:291089 });
Markus Handell90a7e2c2021-12-29 22:32:301090 event.Wait(rtc::Event::kForever);
1091 rtc::Event finalized;
Danil Chapovalov95eeaa72022-07-06 08:14:291092 queue->PostTask([&] {
Markus Handell90a7e2c2021-12-29 22:32:301093 adapter = nullptr;
1094 finalized.Set();
Danil Chapovalov95eeaa72022-07-06 08:14:291095 });
Markus Handell90a7e2c2021-12-29 22:32:301096 finalized.Wait(rtc::Event::kForever);
1097}
1098
Markus Handellf2827c42023-09-02 07:41:101099// TODO(bugs.webrtc.org/15462) Disable ScheduledRepeatAllowsForSlowEncode for
1100// TaskQueueLibevent.
1101#if defined(WEBRTC_ENABLE_LIBEVENT)
1102#define MAYBE_ScheduledRepeatAllowsForSlowEncode \
1103 DISABLED_ScheduledRepeatAllowsForSlowEncode
1104#else
1105#define MAYBE_ScheduledRepeatAllowsForSlowEncode \
1106 ScheduledRepeatAllowsForSlowEncode
1107#endif
1108
1109TEST(FrameCadenceAdapterRealTimeTest,
1110 MAYBE_ScheduledRepeatAllowsForSlowEncode) {
1111 // This regression test must be performed in realtime because of limitations
1112 // in GlobalSimulatedTimeController.
1113 //
1114 // We sleep for a long while (but less than max fps) in the first repeated
1115 // OnFrame (frame 2). This should not lead to a belated second repeated
1116 // OnFrame (frame 3).
1117 auto factory = CreateDefaultTaskQueueFactory();
1118 auto queue =
1119 factory->CreateTaskQueue("test", TaskQueueFactory::Priority::NORMAL);
Markus Handellf2827c42023-09-02 07:41:101120 MockCallback callback;
1121 Clock* clock = Clock::GetRealTimeClock();
1122 std::unique_ptr<FrameCadenceAdapterInterface> adapter;
1123 int frame_counter = 0;
1124 rtc::Event event;
1125 absl::optional<Timestamp> start_time;
Markus Handella57229b2024-04-16 08:40:451126 test::ScopedKeyValueConfig no_field_trials;
Markus Handellf2827c42023-09-02 07:41:101127 queue->PostTask([&] {
Markus Handella57229b2024-04-16 08:40:451128 adapter = CreateAdapter(no_field_trials, clock);
Markus Handellf2827c42023-09-02 07:41:101129 adapter->Initialize(&callback);
1130 adapter->SetZeroHertzModeEnabled(
1131 FrameCadenceAdapterInterface::ZeroHertzModeParams{});
1132 adapter->OnConstraintsChanged(VideoTrackSourceConstraints{0, 2});
1133 auto frame = CreateFrame();
1134 constexpr int kSleepMs = 400;
1135 constexpr TimeDelta kAllowedBelate = TimeDelta::Millis(150);
1136 EXPECT_CALL(callback, OnFrame)
1137 .WillRepeatedly(InvokeWithoutArgs([&, kAllowedBelate] {
1138 ++frame_counter;
1139 // Avoid the first OnFrame and sleep on the second.
1140 if (frame_counter == 2) {
1141 start_time = clock->CurrentTime();
1142 SleepMs(kSleepMs);
1143 } else if (frame_counter == 3) {
1144 TimeDelta diff =
1145 clock->CurrentTime() - (*start_time + TimeDelta::Millis(500));
1146 RTC_LOG(LS_ERROR)
1147 << "Difference in when frame should vs is appearing: " << diff;
1148 EXPECT_LT(diff, kAllowedBelate);
1149 event.Set();
1150 }
1151 }));
1152 adapter->OnFrame(frame);
1153 });
1154 event.Wait(rtc::Event::kForever);
1155 rtc::Event finalized;
1156 queue->PostTask([&] {
1157 adapter = nullptr;
1158 finalized.Set();
1159 });
1160 finalized.Wait(rtc::Event::kForever);
1161}
1162
henrikab7ec0572024-01-09 09:48:521163class ZeroHertzQueueOverloadTest : public ::testing::Test {
1164 public:
1165 static constexpr int kMaxFps = 10;
1166
1167 ZeroHertzQueueOverloadTest() {
1168 Initialize();
1169 metrics::Reset();
1170 }
1171
1172 void Initialize() {
1173 adapter_->Initialize(&callback_);
1174 adapter_->SetZeroHertzModeEnabled(
1175 FrameCadenceAdapterInterface::ZeroHertzModeParams{
1176 /*num_simulcast_layers=*/1});
1177 adapter_->OnConstraintsChanged(
1178 VideoTrackSourceConstraints{/*min_fps=*/0, kMaxFps});
1179 time_controller_.AdvanceTime(TimeDelta::Zero());
1180 }
1181
1182 void ScheduleDelayed(TimeDelta delay, absl::AnyInvocable<void() &&> task) {
1183 TaskQueueBase::Current()->PostDelayedTask(std::move(task), delay);
1184 }
1185
1186 void PassFrame() { adapter_->OnFrame(CreateFrame()); }
1187
1188 void AdvanceTime(TimeDelta duration) {
1189 time_controller_.AdvanceTime(duration);
1190 }
1191
1192 void SkipForwardBy(TimeDelta duration) {
1193 time_controller_.SkipForwardBy(duration);
1194 }
1195
1196 Timestamp CurrentTime() { return time_controller_.GetClock()->CurrentTime(); }
1197
1198 protected:
1199 test::ScopedKeyValueConfig field_trials_;
1200 NiceMock<MockCallback> callback_;
1201 GlobalSimulatedTimeController time_controller_{Timestamp::Zero()};
1202 std::unique_ptr<FrameCadenceAdapterInterface> adapter_{
1203 CreateAdapter(field_trials_, time_controller_.GetClock())};
1204};
1205
1206TEST_F(ZeroHertzQueueOverloadTest,
1207 ForwardedFramesDuringTooLongEncodeTimeAreFlaggedWithQueueOverload) {
1208 InSequence s;
1209 PassFrame();
1210 EXPECT_CALL(callback_, OnFrame(_, false, _)).WillOnce(InvokeWithoutArgs([&] {
1211 PassFrame();
1212 PassFrame();
1213 PassFrame();
1214 SkipForwardBy(TimeDelta::Millis(301));
1215 }));
1216 EXPECT_CALL(callback_, OnFrame(_, true, _)).Times(3);
1217 AdvanceTime(TimeDelta::Millis(100));
1218 EXPECT_THAT(metrics::Samples("WebRTC.Screenshare.ZeroHz.QueueOverload"),
1219 ElementsAre(Pair(false, 1), Pair(true, 3)));
1220}
1221
1222TEST_F(ZeroHertzQueueOverloadTest,
1223 ForwardedFramesAfterOverloadBurstAreNotFlaggedWithQueueOverload) {
1224 InSequence s;
1225 PassFrame();
1226 EXPECT_CALL(callback_, OnFrame(_, false, _)).WillOnce(InvokeWithoutArgs([&] {
1227 PassFrame();
1228 PassFrame();
1229 PassFrame();
1230 SkipForwardBy(TimeDelta::Millis(301));
1231 }));
1232 EXPECT_CALL(callback_, OnFrame(_, true, _)).Times(3);
1233 AdvanceTime(TimeDelta::Millis(100));
1234 EXPECT_CALL(callback_, OnFrame(_, false, _)).Times(2);
1235 PassFrame();
1236 PassFrame();
1237 AdvanceTime(TimeDelta::Millis(100));
1238 EXPECT_THAT(metrics::Samples("WebRTC.Screenshare.ZeroHz.QueueOverload"),
1239 ElementsAre(Pair(false, 3), Pair(true, 3)));
1240}
1241
1242TEST_F(ZeroHertzQueueOverloadTest,
1243 ForwardedFramesDuringNormalEncodeTimeAreNotFlaggedWithQueueOverload) {
1244 InSequence s;
1245 PassFrame();
1246 EXPECT_CALL(callback_, OnFrame(_, false, _)).WillOnce(InvokeWithoutArgs([&] {
1247 PassFrame();
1248 PassFrame();
1249 PassFrame();
1250 // Long but not too long encode time.
1251 SkipForwardBy(TimeDelta::Millis(99));
1252 }));
1253 EXPECT_CALL(callback_, OnFrame(_, false, _)).Times(3);
1254 AdvanceTime(TimeDelta::Millis(199));
1255 EXPECT_THAT(metrics::Samples("WebRTC.Screenshare.ZeroHz.QueueOverload"),
1256 ElementsAre(Pair(false, 4)));
1257}
1258
1259TEST_F(
1260 ZeroHertzQueueOverloadTest,
1261 AvoidSettingQueueOverloadAndSendRepeatWhenNoNewPacketsWhileTooLongEncode) {
1262 // Receive one frame only and let OnFrame take such a long time that an
1263 // overload normally is warranted. But the fact that no new frames arrive
1264 // while being blocked should trigger a non-idle repeat to ensure that the
1265 // video stream does not freeze and queue overload should be false.
1266 PassFrame();
1267 EXPECT_CALL(callback_, OnFrame(_, false, _))
1268 .WillOnce(
1269 InvokeWithoutArgs([&] { SkipForwardBy(TimeDelta::Millis(101)); }))
1270 .WillOnce(InvokeWithoutArgs([&] {
1271 // Non-idle repeat.
1272 EXPECT_EQ(CurrentTime(), Timestamp::Zero() + TimeDelta::Millis(201));
1273 }));
1274 AdvanceTime(TimeDelta::Millis(100));
1275 EXPECT_THAT(metrics::Samples("WebRTC.Screenshare.ZeroHz.QueueOverload"),
1276 ElementsAre(Pair(false, 2)));
1277}
1278
1279TEST_F(ZeroHertzQueueOverloadTest,
1280 EnterFastRepeatAfterQueueOverloadWhenReceivedOnlyOneFrameDuringEncode) {
1281 InSequence s;
1282 // - Forward one frame frame during high load which triggers queue overload.
1283 // - Receive only one new frame while being blocked and verify that the
1284 // cancelled repeat was for the first frame and not the second.
1285 // - Fast repeat mode should happen after second frame.
1286 PassFrame();
1287 EXPECT_CALL(callback_, OnFrame(_, false, _)).WillOnce(InvokeWithoutArgs([&] {
1288 PassFrame();
1289 SkipForwardBy(TimeDelta::Millis(101));
1290 }));
1291 EXPECT_CALL(callback_, OnFrame(_, true, _));
1292 AdvanceTime(TimeDelta::Millis(100));
1293
1294 // Fast repeats should take place from here on.
1295 EXPECT_CALL(callback_, OnFrame(_, false, _)).Times(5);
1296 AdvanceTime(TimeDelta::Millis(500));
1297 EXPECT_THAT(metrics::Samples("WebRTC.Screenshare.ZeroHz.QueueOverload"),
1298 ElementsAre(Pair(false, 6), Pair(true, 1)));
1299}
1300
1301TEST_F(ZeroHertzQueueOverloadTest,
1302 QueueOverloadIsDisabledForZeroHerzWhenKillSwitchIsEnabled) {
1303 webrtc::test::ScopedKeyValueConfig field_trials(
1304 field_trials_, "WebRTC-ZeroHertzQueueOverload/Disabled/");
1305 adapter_.reset();
1306 adapter_ = CreateAdapter(field_trials, time_controller_.GetClock());
1307 Initialize();
1308
1309 // Same as ForwardedFramesDuringTooLongEncodeTimeAreFlaggedWithQueueOverload
1310 // but this time the queue overload mechanism is disabled.
1311 InSequence s;
1312 PassFrame();
1313 EXPECT_CALL(callback_, OnFrame(_, false, _)).WillOnce(InvokeWithoutArgs([&] {
1314 PassFrame();
1315 PassFrame();
1316 PassFrame();
1317 SkipForwardBy(TimeDelta::Millis(301));
1318 }));
1319 EXPECT_CALL(callback_, OnFrame(_, false, _)).Times(3);
1320 AdvanceTime(TimeDelta::Millis(100));
1321 EXPECT_EQ(metrics::NumSamples("WebRTC.Screenshare.ZeroHz.QueueOverload"), 0);
1322}
1323
Markus Handellb4e96d42021-11-05 11:00:551324} // namespace
1325} // namespace webrtc