blob: 8f291942544379b06549e033fab8c09750496496 [file] [log] [blame]
Henrik Boström4c076052020-03-18 10:09:59 +01001/*
2 * Copyright (c) 2020 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
Henrik Boström1d766542020-04-17 14:40:39 +020011#include "call/adaptation/video_stream_adapter.h"
Henrik Boström4c076052020-03-18 10:09:59 +010012
13#include <string>
14#include <utility>
15
16#include "absl/types/optional.h"
Evan Shrubsole73ecede2020-07-09 13:51:39 +020017#include "api/scoped_refptr.h"
Evan Shrubsolece0a11d2020-04-16 11:36:55 +020018#include "api/video/video_adaptation_reason.h"
Henrik Boström4c076052020-03-18 10:09:59 +010019#include "api/video_codecs/video_codec.h"
20#include "api/video_codecs/video_encoder.h"
21#include "api/video_codecs/video_encoder_config.h"
Evan Shrubsole73ecede2020-07-09 13:51:39 +020022#include "call/adaptation/adaptation_constraint.h"
Henrik Boström4c076052020-03-18 10:09:59 +010023#include "call/adaptation/encoder_settings.h"
Evan Shrubsoled73d4212020-08-17 11:10:45 +020024#include "call/adaptation/test/fake_frame_rate_provider.h"
Evan Shrubsole73ecede2020-07-09 13:51:39 +020025#include "call/adaptation/test/fake_resource.h"
Henrik Boströmad706092020-12-04 09:37:47 +010026#include "call/adaptation/test/fake_video_stream_input_state_provider.h"
Henrik Boström4c076052020-03-18 10:09:59 +010027#include "call/adaptation/video_source_restrictions.h"
Evan Shrubsole34b1a422020-07-02 14:42:09 +020028#include "call/adaptation/video_stream_input_state.h"
Henrik Boström4c076052020-03-18 10:09:59 +010029#include "rtc_base/string_encode.h"
Henrik Boström4c076052020-03-18 10:09:59 +010030#include "test/gmock.h"
31#include "test/gtest.h"
Jonas Orelandc7f691a2022-03-09 15:12:07 +010032#include "test/scoped_key_value_config.h"
Henrik Boström4c076052020-03-18 10:09:59 +010033#include "test/testsupport/rtc_expect_death.h"
34
35namespace webrtc {
36
Evan Shrubsoledc4d4222020-07-09 11:47:10 +020037using ::testing::_;
38using ::testing::DoAll;
Evan Shrubsole73ecede2020-07-09 13:51:39 +020039using ::testing::Return;
Evan Shrubsoledc4d4222020-07-09 11:47:10 +020040using ::testing::SaveArg;
41
Henrik Boström4c076052020-03-18 10:09:59 +010042namespace {
43
Henrik Boström4c076052020-03-18 10:09:59 +010044const int kBalancedHighResolutionPixels = 1280 * 720;
45const int kBalancedHighFrameRateFps = 30;
46
47const int kBalancedMediumResolutionPixels = 640 * 480;
48const int kBalancedMediumFrameRateFps = 20;
49
50const int kBalancedLowResolutionPixels = 320 * 240;
51const int kBalancedLowFrameRateFps = 10;
52
53std::string BalancedFieldTrialConfig() {
54 return "WebRTC-Video-BalancedDegradationSettings/pixels:" +
55 rtc::ToString(kBalancedLowResolutionPixels) + "|" +
56 rtc::ToString(kBalancedMediumResolutionPixels) + "|" +
57 rtc::ToString(kBalancedHighResolutionPixels) +
58 ",fps:" + rtc::ToString(kBalancedLowFrameRateFps) + "|" +
59 rtc::ToString(kBalancedMediumFrameRateFps) + "|" +
60 rtc::ToString(kBalancedHighFrameRateFps) + "/";
61}
62
63// Responsible for adjusting the inputs to VideoStreamAdapter (SetInput), such
64// as pixels and frame rate, according to the most recent source restrictions.
65// This helps tests that apply adaptations multiple times: if the input is not
66// adjusted between adaptations, the subsequent adaptations fail with
67// kAwaitingPreviousAdaptation.
68class FakeVideoStream {
69 public:
70 FakeVideoStream(VideoStreamAdapter* adapter,
Evan Shrubsole34b1a422020-07-02 14:42:09 +020071 FakeVideoStreamInputStateProvider* provider,
Henrik Boström4c076052020-03-18 10:09:59 +010072 int input_pixels,
73 int input_fps,
Henrik Boströmb613e3a2020-04-17 13:48:21 +020074 int min_pixels_per_frame)
Henrik Boström4c076052020-03-18 10:09:59 +010075 : adapter_(adapter),
Evan Shrubsole34b1a422020-07-02 14:42:09 +020076 provider_(provider),
Henrik Boström4c076052020-03-18 10:09:59 +010077 input_pixels_(input_pixels),
78 input_fps_(input_fps),
Henrik Boströmb613e3a2020-04-17 13:48:21 +020079 min_pixels_per_frame_(min_pixels_per_frame) {
Evan Shrubsole34b1a422020-07-02 14:42:09 +020080 provider_->SetInputState(input_pixels_, input_fps_, min_pixels_per_frame_);
Henrik Boström4c076052020-03-18 10:09:59 +010081 }
82
83 int input_pixels() const { return input_pixels_; }
84 int input_fps() const { return input_fps_; }
85
86 // Performs ApplyAdaptation() followed by SetInput() with input pixels and
87 // frame rate adjusted according to the resulting restrictions.
88 void ApplyAdaptation(Adaptation adaptation) {
Evan Shrubsoleec0af262020-07-01 11:47:46 +020089 adapter_->ApplyAdaptation(adaptation, nullptr);
Henrik Boström4c076052020-03-18 10:09:59 +010090 // Update input pixels and fps according to the resulting restrictions.
91 auto restrictions = adapter_->source_restrictions();
92 if (restrictions.target_pixels_per_frame().has_value()) {
93 RTC_DCHECK(!restrictions.max_pixels_per_frame().has_value() ||
94 restrictions.max_pixels_per_frame().value() >=
95 restrictions.target_pixels_per_frame().value());
96 input_pixels_ = restrictions.target_pixels_per_frame().value();
97 } else if (restrictions.max_pixels_per_frame().has_value()) {
98 input_pixels_ = restrictions.max_pixels_per_frame().value();
99 }
100 if (restrictions.max_frame_rate().has_value()) {
101 input_fps_ = restrictions.max_frame_rate().value();
102 }
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200103 provider_->SetInputState(input_pixels_, input_fps_, min_pixels_per_frame_);
Henrik Boström4c076052020-03-18 10:09:59 +0100104 }
105
106 private:
107 VideoStreamAdapter* adapter_;
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200108 FakeVideoStreamInputStateProvider* provider_;
Henrik Boström4c076052020-03-18 10:09:59 +0100109 int input_pixels_;
110 int input_fps_;
Henrik Boströmb613e3a2020-04-17 13:48:21 +0200111 int min_pixels_per_frame_;
Henrik Boström4c076052020-03-18 10:09:59 +0100112};
113
Evan Shrubsoleec0af262020-07-01 11:47:46 +0200114class FakeVideoStreamAdapterListner : public VideoSourceRestrictionsListener {
115 public:
116 void OnVideoSourceRestrictionsUpdated(
117 VideoSourceRestrictions restrictions,
118 const VideoAdaptationCounters& adaptation_counters,
119 rtc::scoped_refptr<Resource> reason,
Evan Shrubsoled73d4212020-08-17 11:10:45 +0200120 const VideoSourceRestrictions& unfiltered_restrictions) override {
Evan Shrubsoleec0af262020-07-01 11:47:46 +0200121 calls_++;
122 last_restrictions_ = unfiltered_restrictions;
123 }
124
125 int calls() const { return calls_; }
126
127 VideoSourceRestrictions last_restrictions() const {
128 return last_restrictions_;
129 }
130
131 private:
132 int calls_ = 0;
133 VideoSourceRestrictions last_restrictions_;
134};
135
Evan Shrubsole73ecede2020-07-09 13:51:39 +0200136class MockAdaptationConstraint : public AdaptationConstraint {
137 public:
138 MOCK_METHOD(bool,
139 IsAdaptationUpAllowed,
140 (const VideoStreamInputState& input_state,
141 const VideoSourceRestrictions& restrictions_before,
Evan Shrubsoleb93ad752020-08-13 11:35:24 +0200142 const VideoSourceRestrictions& restrictions_after),
Evan Shrubsole73ecede2020-07-09 13:51:39 +0200143 (const, override));
144
145 // MOCK_METHOD(std::string, Name, (), (const, override));
146 std::string Name() const override { return "MockAdaptationConstraint"; }
147};
148
Henrik Boström4c076052020-03-18 10:09:59 +0100149} // namespace
150
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200151class VideoStreamAdapterTest : public ::testing::Test {
152 public:
153 VideoStreamAdapterTest()
154 : field_trials_(BalancedFieldTrialConfig()),
Evan Shrubsole73ecede2020-07-09 13:51:39 +0200155 resource_(FakeResource::Create("FakeResource")),
Jonas Orelandc7f691a2022-03-09 15:12:07 +0100156 adapter_(&input_state_provider_,
157 &encoder_stats_observer_,
158 field_trials_) {}
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200159
160 protected:
Jonas Orelandc7f691a2022-03-09 15:12:07 +0100161 webrtc::test::ScopedKeyValueConfig field_trials_;
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200162 FakeVideoStreamInputStateProvider input_state_provider_;
Evan Shrubsole73ecede2020-07-09 13:51:39 +0200163 rtc::scoped_refptr<Resource> resource_;
Evan Shrubsoled73d4212020-08-17 11:10:45 +0200164 testing::StrictMock<MockVideoStreamEncoderObserver> encoder_stats_observer_;
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200165 VideoStreamAdapter adapter_;
166};
167
168TEST_F(VideoStreamAdapterTest, NoRestrictionsByDefault) {
169 EXPECT_EQ(VideoSourceRestrictions(), adapter_.source_restrictions());
170 EXPECT_EQ(0, adapter_.adaptation_counters().Total());
Henrik Boström4c076052020-03-18 10:09:59 +0100171}
172
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200173TEST_F(VideoStreamAdapterTest, MaintainFramerate_DecreasesPixelsToThreeFifths) {
Henrik Boström4c076052020-03-18 10:09:59 +0100174 const int kInputPixels = 1280 * 720;
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200175 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE);
176 input_state_provider_.SetInputState(kInputPixels, 30,
177 kDefaultMinPixelsPerFrame);
178 Adaptation adaptation = adapter_.GetAdaptationDown();
Henrik Boström4c076052020-03-18 10:09:59 +0100179 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200180 adapter_.ApplyAdaptation(adaptation, nullptr);
Henrik Boström4c076052020-03-18 10:09:59 +0100181 EXPECT_EQ(static_cast<size_t>((kInputPixels * 3) / 5),
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200182 adapter_.source_restrictions().max_pixels_per_frame());
Henrik Boström4c076052020-03-18 10:09:59 +0100183 EXPECT_EQ(absl::nullopt,
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200184 adapter_.source_restrictions().target_pixels_per_frame());
185 EXPECT_EQ(absl::nullopt, adapter_.source_restrictions().max_frame_rate());
186 EXPECT_EQ(1, adapter_.adaptation_counters().resolution_adaptations);
Henrik Boström4c076052020-03-18 10:09:59 +0100187}
188
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200189TEST_F(VideoStreamAdapterTest,
190 MaintainFramerate_DecreasesPixelsToLimitReached) {
Henrik Boström4c076052020-03-18 10:09:59 +0100191 const int kMinPixelsPerFrame = 640 * 480;
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200192
193 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE);
194 input_state_provider_.SetInputState(kMinPixelsPerFrame + 1, 30,
195 kMinPixelsPerFrame);
Evan Shrubsoled73d4212020-08-17 11:10:45 +0200196 EXPECT_CALL(encoder_stats_observer_, OnMinPixelLimitReached());
Henrik Boström4c076052020-03-18 10:09:59 +0100197 // Even though we are above kMinPixelsPerFrame, because adapting down would
198 // have exceeded the limit, we are said to have reached the limit already.
199 // This differs from the frame rate adaptation logic, which would have clamped
200 // to the limit in the first step and reported kLimitReached in the second
201 // step.
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200202 Adaptation adaptation = adapter_.GetAdaptationDown();
Henrik Boström4c076052020-03-18 10:09:59 +0100203 EXPECT_EQ(Adaptation::Status::kLimitReached, adaptation.status());
Henrik Boström4c076052020-03-18 10:09:59 +0100204}
205
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200206TEST_F(VideoStreamAdapterTest, MaintainFramerate_IncreasePixelsToFiveThirds) {
207 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE);
208 FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30,
Henrik Boströmb613e3a2020-04-17 13:48:21 +0200209 kDefaultMinPixelsPerFrame);
Henrik Boström4c076052020-03-18 10:09:59 +0100210 // Go down twice, ensuring going back up is still a restricted resolution.
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200211 fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown());
212 fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown());
213 EXPECT_EQ(2, adapter_.adaptation_counters().resolution_adaptations);
Henrik Boström4c076052020-03-18 10:09:59 +0100214 int input_pixels = fake_stream.input_pixels();
215 // Go up once. The target is 5/3 and the max is 12/5 of the target.
216 const int target = (input_pixels * 5) / 3;
Evan Shrubsoleb93ad752020-08-13 11:35:24 +0200217 fake_stream.ApplyAdaptation(adapter_.GetAdaptationUp());
Henrik Boström4c076052020-03-18 10:09:59 +0100218 EXPECT_EQ(static_cast<size_t>((target * 12) / 5),
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200219 adapter_.source_restrictions().max_pixels_per_frame());
Henrik Boström4c076052020-03-18 10:09:59 +0100220 EXPECT_EQ(static_cast<size_t>(target),
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200221 adapter_.source_restrictions().target_pixels_per_frame());
222 EXPECT_EQ(absl::nullopt, adapter_.source_restrictions().max_frame_rate());
223 EXPECT_EQ(1, adapter_.adaptation_counters().resolution_adaptations);
Henrik Boström4c076052020-03-18 10:09:59 +0100224}
225
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200226TEST_F(VideoStreamAdapterTest, MaintainFramerate_IncreasePixelsToUnrestricted) {
227 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE);
228 FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30,
Henrik Boströmb613e3a2020-04-17 13:48:21 +0200229 kDefaultMinPixelsPerFrame);
Henrik Boström4c076052020-03-18 10:09:59 +0100230 // We are unrestricted by default and should not be able to adapt up.
231 EXPECT_EQ(Adaptation::Status::kLimitReached,
Evan Shrubsoleb93ad752020-08-13 11:35:24 +0200232 adapter_.GetAdaptationUp().status());
Henrik Boström4c076052020-03-18 10:09:59 +0100233 // If we go down once and then back up we should not have any restrictions.
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200234 fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown());
235 EXPECT_EQ(1, adapter_.adaptation_counters().resolution_adaptations);
Evan Shrubsoleb93ad752020-08-13 11:35:24 +0200236 fake_stream.ApplyAdaptation(adapter_.GetAdaptationUp());
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200237 EXPECT_EQ(VideoSourceRestrictions(), adapter_.source_restrictions());
238 EXPECT_EQ(0, adapter_.adaptation_counters().Total());
Henrik Boström4c076052020-03-18 10:09:59 +0100239}
240
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200241TEST_F(VideoStreamAdapterTest, MaintainResolution_DecreasesFpsToTwoThirds) {
Henrik Boström4c076052020-03-18 10:09:59 +0100242 const int kInputFps = 30;
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200243
244 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION);
245 input_state_provider_.SetInputState(1280 * 720, kInputFps,
246 kDefaultMinPixelsPerFrame);
247 Adaptation adaptation = adapter_.GetAdaptationDown();
Henrik Boström4c076052020-03-18 10:09:59 +0100248 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200249 adapter_.ApplyAdaptation(adaptation, nullptr);
Henrik Boström4c076052020-03-18 10:09:59 +0100250 EXPECT_EQ(absl::nullopt,
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200251 adapter_.source_restrictions().max_pixels_per_frame());
Henrik Boström4c076052020-03-18 10:09:59 +0100252 EXPECT_EQ(absl::nullopt,
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200253 adapter_.source_restrictions().target_pixels_per_frame());
Henrik Boström4c076052020-03-18 10:09:59 +0100254 EXPECT_EQ(static_cast<double>((kInputFps * 2) / 3),
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200255 adapter_.source_restrictions().max_frame_rate());
256 EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations);
Henrik Boström4c076052020-03-18 10:09:59 +0100257}
258
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200259TEST_F(VideoStreamAdapterTest, MaintainResolution_DecreasesFpsToLimitReached) {
260 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION);
261 FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720,
262 kMinFrameRateFps + 1, kDefaultMinPixelsPerFrame);
Henrik Boström4c076052020-03-18 10:09:59 +0100263 // If we are not yet at the limit and the next step would exceed it, the step
264 // is clamped such that we end up exactly on the limit.
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200265 Adaptation adaptation = adapter_.GetAdaptationDown();
Henrik Boström4c076052020-03-18 10:09:59 +0100266 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
267 fake_stream.ApplyAdaptation(adaptation);
268 EXPECT_EQ(static_cast<double>(kMinFrameRateFps),
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200269 adapter_.source_restrictions().max_frame_rate());
270 EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations);
Henrik Boström4c076052020-03-18 10:09:59 +0100271 // Having reached the limit, the next adaptation down is not valid.
272 EXPECT_EQ(Adaptation::Status::kLimitReached,
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200273 adapter_.GetAdaptationDown().status());
Henrik Boström4c076052020-03-18 10:09:59 +0100274}
275
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200276TEST_F(VideoStreamAdapterTest, MaintainResolution_IncreaseFpsToThreeHalves) {
277 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION);
278 FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30,
Henrik Boströmb613e3a2020-04-17 13:48:21 +0200279 kDefaultMinPixelsPerFrame);
Henrik Boström4c076052020-03-18 10:09:59 +0100280 // Go down twice, ensuring going back up is still a restricted frame rate.
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200281 fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown());
282 fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown());
283 EXPECT_EQ(2, adapter_.adaptation_counters().fps_adaptations);
Henrik Boström4c076052020-03-18 10:09:59 +0100284 int input_fps = fake_stream.input_fps();
285 // Go up once. The target is 3/2 of the input.
Evan Shrubsoleb93ad752020-08-13 11:35:24 +0200286 Adaptation adaptation = adapter_.GetAdaptationUp();
Henrik Boström4c076052020-03-18 10:09:59 +0100287 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
288 fake_stream.ApplyAdaptation(adaptation);
289 EXPECT_EQ(absl::nullopt,
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200290 adapter_.source_restrictions().max_pixels_per_frame());
Henrik Boström4c076052020-03-18 10:09:59 +0100291 EXPECT_EQ(absl::nullopt,
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200292 adapter_.source_restrictions().target_pixels_per_frame());
Henrik Boström4c076052020-03-18 10:09:59 +0100293 EXPECT_EQ(static_cast<double>((input_fps * 3) / 2),
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200294 adapter_.source_restrictions().max_frame_rate());
295 EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations);
Henrik Boström4c076052020-03-18 10:09:59 +0100296}
297
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200298TEST_F(VideoStreamAdapterTest, MaintainResolution_IncreaseFpsToUnrestricted) {
299 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION);
300 FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30,
Henrik Boströmb613e3a2020-04-17 13:48:21 +0200301 kDefaultMinPixelsPerFrame);
Henrik Boström4c076052020-03-18 10:09:59 +0100302 // We are unrestricted by default and should not be able to adapt up.
303 EXPECT_EQ(Adaptation::Status::kLimitReached,
Evan Shrubsoleb93ad752020-08-13 11:35:24 +0200304 adapter_.GetAdaptationUp().status());
Henrik Boström4c076052020-03-18 10:09:59 +0100305 // If we go down once and then back up we should not have any restrictions.
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200306 fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown());
307 EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations);
Evan Shrubsoleb93ad752020-08-13 11:35:24 +0200308 fake_stream.ApplyAdaptation(adapter_.GetAdaptationUp());
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200309 EXPECT_EQ(VideoSourceRestrictions(), adapter_.source_restrictions());
310 EXPECT_EQ(0, adapter_.adaptation_counters().Total());
Henrik Boström4c076052020-03-18 10:09:59 +0100311}
312
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200313TEST_F(VideoStreamAdapterTest, Balanced_DecreaseFrameRate) {
314 adapter_.SetDegradationPreference(DegradationPreference::BALANCED);
315 input_state_provider_.SetInputState(kBalancedMediumResolutionPixels,
316 kBalancedHighFrameRateFps,
317 kDefaultMinPixelsPerFrame);
Henrik Boström4c076052020-03-18 10:09:59 +0100318 // If our frame rate is higher than the frame rate associated with our
319 // resolution we should try to adapt to the frame rate associated with our
320 // resolution: kBalancedMediumFrameRateFps.
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200321 Adaptation adaptation = adapter_.GetAdaptationDown();
Henrik Boström4c076052020-03-18 10:09:59 +0100322 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200323 adapter_.ApplyAdaptation(adaptation, nullptr);
Henrik Boström4c076052020-03-18 10:09:59 +0100324 EXPECT_EQ(absl::nullopt,
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200325 adapter_.source_restrictions().max_pixels_per_frame());
Henrik Boström4c076052020-03-18 10:09:59 +0100326 EXPECT_EQ(absl::nullopt,
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200327 adapter_.source_restrictions().target_pixels_per_frame());
Henrik Boström4c076052020-03-18 10:09:59 +0100328 EXPECT_EQ(static_cast<double>(kBalancedMediumFrameRateFps),
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200329 adapter_.source_restrictions().max_frame_rate());
330 EXPECT_EQ(0, adapter_.adaptation_counters().resolution_adaptations);
331 EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations);
Henrik Boström4c076052020-03-18 10:09:59 +0100332}
333
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200334TEST_F(VideoStreamAdapterTest, Balanced_DecreaseResolution) {
335 adapter_.SetDegradationPreference(DegradationPreference::BALANCED);
336 FakeVideoStream fake_stream(
337 &adapter_, &input_state_provider_, kBalancedHighResolutionPixels,
338 kBalancedHighFrameRateFps, kDefaultMinPixelsPerFrame);
Henrik Boström4c076052020-03-18 10:09:59 +0100339 // If we are not below the current resolution's frame rate limit, we should
340 // adapt resolution according to "maintain-framerate" logic (three fifths).
341 //
342 // However, since we are unlimited at the start and input frame rate is not
343 // below kBalancedHighFrameRateFps, we first restrict the frame rate to
344 // kBalancedHighFrameRateFps even though that is our current frame rate. This
345 // does prevent the source from going higher, though, so it's technically not
346 // a NO-OP.
347 {
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200348 Adaptation adaptation = adapter_.GetAdaptationDown();
Henrik Boström4c076052020-03-18 10:09:59 +0100349 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
350 fake_stream.ApplyAdaptation(adaptation);
351 }
352 EXPECT_EQ(absl::nullopt,
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200353 adapter_.source_restrictions().max_pixels_per_frame());
Henrik Boström4c076052020-03-18 10:09:59 +0100354 EXPECT_EQ(absl::nullopt,
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200355 adapter_.source_restrictions().target_pixels_per_frame());
Henrik Boström4c076052020-03-18 10:09:59 +0100356 EXPECT_EQ(static_cast<double>(kBalancedHighFrameRateFps),
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200357 adapter_.source_restrictions().max_frame_rate());
358 EXPECT_EQ(0, adapter_.adaptation_counters().resolution_adaptations);
359 EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations);
Henrik Boström4c076052020-03-18 10:09:59 +0100360 // Verify "maintain-framerate" logic the second time we adapt: Frame rate
361 // restrictions remains the same and resolution goes down.
362 {
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200363 Adaptation adaptation = adapter_.GetAdaptationDown();
Henrik Boström4c076052020-03-18 10:09:59 +0100364 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
365 fake_stream.ApplyAdaptation(adaptation);
366 }
367 constexpr size_t kReducedPixelsFirstStep =
368 static_cast<size_t>((kBalancedHighResolutionPixels * 3) / 5);
369 EXPECT_EQ(kReducedPixelsFirstStep,
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200370 adapter_.source_restrictions().max_pixels_per_frame());
Henrik Boström4c076052020-03-18 10:09:59 +0100371 EXPECT_EQ(absl::nullopt,
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200372 adapter_.source_restrictions().target_pixels_per_frame());
Henrik Boström4c076052020-03-18 10:09:59 +0100373 EXPECT_EQ(static_cast<double>(kBalancedHighFrameRateFps),
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200374 adapter_.source_restrictions().max_frame_rate());
375 EXPECT_EQ(1, adapter_.adaptation_counters().resolution_adaptations);
376 EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations);
Henrik Boström4c076052020-03-18 10:09:59 +0100377 // If we adapt again, because the balanced settings' proposed frame rate is
378 // still kBalancedHighFrameRateFps, "maintain-framerate" will trigger again.
379 static_assert(kReducedPixelsFirstStep > kBalancedMediumResolutionPixels,
380 "The reduced resolution is still greater than the next lower "
381 "balanced setting resolution");
382 constexpr size_t kReducedPixelsSecondStep = (kReducedPixelsFirstStep * 3) / 5;
383 {
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200384 Adaptation adaptation = adapter_.GetAdaptationDown();
Henrik Boström4c076052020-03-18 10:09:59 +0100385 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
386 fake_stream.ApplyAdaptation(adaptation);
387 }
388 EXPECT_EQ(kReducedPixelsSecondStep,
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200389 adapter_.source_restrictions().max_pixels_per_frame());
Henrik Boström4c076052020-03-18 10:09:59 +0100390 EXPECT_EQ(absl::nullopt,
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200391 adapter_.source_restrictions().target_pixels_per_frame());
Henrik Boström4c076052020-03-18 10:09:59 +0100392 EXPECT_EQ(static_cast<double>(kBalancedHighFrameRateFps),
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200393 adapter_.source_restrictions().max_frame_rate());
394 EXPECT_EQ(2, adapter_.adaptation_counters().resolution_adaptations);
395 EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations);
Henrik Boström4c076052020-03-18 10:09:59 +0100396}
397
398// Testing when to adapt frame rate and when to adapt resolution is quite
399// entangled, so this test covers both cases.
400//
401// There is an asymmetry: When we adapt down we do it in one order, but when we
402// adapt up we don't do it in the reverse order. Instead we always try to adapt
403// frame rate first according to balanced settings' configs and only when the
404// frame rate is already achieved do we adjust the resolution.
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200405TEST_F(VideoStreamAdapterTest, Balanced_IncreaseFrameRateAndResolution) {
406 adapter_.SetDegradationPreference(DegradationPreference::BALANCED);
407 FakeVideoStream fake_stream(
408 &adapter_, &input_state_provider_, kBalancedHighResolutionPixels,
409 kBalancedHighFrameRateFps, kDefaultMinPixelsPerFrame);
Henrik Boström4c076052020-03-18 10:09:59 +0100410 // The desired starting point of this test is having adapted frame rate twice.
411 // This requires performing a number of adaptations.
412 constexpr size_t kReducedPixelsFirstStep =
413 static_cast<size_t>((kBalancedHighResolutionPixels * 3) / 5);
414 constexpr size_t kReducedPixelsSecondStep = (kReducedPixelsFirstStep * 3) / 5;
415 constexpr size_t kReducedPixelsThirdStep = (kReducedPixelsSecondStep * 3) / 5;
416 static_assert(kReducedPixelsFirstStep > kBalancedMediumResolutionPixels,
417 "The first pixel reduction is greater than the balanced "
418 "settings' medium pixel configuration");
419 static_assert(kReducedPixelsSecondStep > kBalancedMediumResolutionPixels,
420 "The second pixel reduction is greater than the balanced "
421 "settings' medium pixel configuration");
422 static_assert(kReducedPixelsThirdStep <= kBalancedMediumResolutionPixels,
423 "The third pixel reduction is NOT greater than the balanced "
424 "settings' medium pixel configuration");
425 // The first adaptation should affect the frame rate: See
426 // Balanced_DecreaseResolution for explanation why.
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200427 fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown());
Henrik Boström4c076052020-03-18 10:09:59 +0100428 EXPECT_EQ(static_cast<double>(kBalancedHighFrameRateFps),
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200429 adapter_.source_restrictions().max_frame_rate());
Henrik Boström4c076052020-03-18 10:09:59 +0100430 // The next three adaptations affects the resolution, because we have to reach
431 // kBalancedMediumResolutionPixels before a lower frame rate is considered by
432 // BalancedDegradationSettings. The number three is derived from the
433 // static_asserts above.
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200434 fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown());
Henrik Boström4c076052020-03-18 10:09:59 +0100435 EXPECT_EQ(kReducedPixelsFirstStep,
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200436 adapter_.source_restrictions().max_pixels_per_frame());
437 fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown());
Henrik Boström4c076052020-03-18 10:09:59 +0100438 EXPECT_EQ(kReducedPixelsSecondStep,
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200439 adapter_.source_restrictions().max_pixels_per_frame());
440 fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown());
Henrik Boström4c076052020-03-18 10:09:59 +0100441 EXPECT_EQ(kReducedPixelsThirdStep,
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200442 adapter_.source_restrictions().max_pixels_per_frame());
Henrik Boström4c076052020-03-18 10:09:59 +0100443 // Thus, the next adaptation will reduce frame rate to
444 // kBalancedMediumFrameRateFps.
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200445 fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown());
Henrik Boström4c076052020-03-18 10:09:59 +0100446 EXPECT_EQ(static_cast<double>(kBalancedMediumFrameRateFps),
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200447 adapter_.source_restrictions().max_frame_rate());
448 EXPECT_EQ(3, adapter_.adaptation_counters().resolution_adaptations);
449 EXPECT_EQ(2, adapter_.adaptation_counters().fps_adaptations);
Henrik Boström4c076052020-03-18 10:09:59 +0100450 // Adapt up!
451 // While our resolution is in the medium-range, the frame rate associated with
452 // the next resolution configuration up ("high") is kBalancedHighFrameRateFps
453 // and "balanced" prefers adapting frame rate if not already applied.
454 {
Evan Shrubsoleb93ad752020-08-13 11:35:24 +0200455 Adaptation adaptation = adapter_.GetAdaptationUp();
Henrik Boström4c076052020-03-18 10:09:59 +0100456 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
457 fake_stream.ApplyAdaptation(adaptation);
458 EXPECT_EQ(static_cast<double>(kBalancedHighFrameRateFps),
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200459 adapter_.source_restrictions().max_frame_rate());
460 EXPECT_EQ(3, adapter_.adaptation_counters().resolution_adaptations);
461 EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations);
Henrik Boström4c076052020-03-18 10:09:59 +0100462 }
463 // Now that we have already achieved the next frame rate up, we act according
464 // to "maintain-framerate". We go back up in resolution. Due to rounding
465 // errors we don't end up back at kReducedPixelsSecondStep. Rather we get to
466 // kReducedPixelsSecondStepUp, which is off by one compared to
467 // kReducedPixelsSecondStep.
468 constexpr size_t kReducedPixelsSecondStepUp =
469 (kReducedPixelsThirdStep * 5) / 3;
470 {
Evan Shrubsoleb93ad752020-08-13 11:35:24 +0200471 Adaptation adaptation = adapter_.GetAdaptationUp();
Henrik Boström4c076052020-03-18 10:09:59 +0100472 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
473 fake_stream.ApplyAdaptation(adaptation);
474 EXPECT_EQ(kReducedPixelsSecondStepUp,
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200475 adapter_.source_restrictions().target_pixels_per_frame());
476 EXPECT_EQ(2, adapter_.adaptation_counters().resolution_adaptations);
477 EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations);
Henrik Boström4c076052020-03-18 10:09:59 +0100478 }
479 // Now that our resolution is back in the high-range, the next frame rate to
480 // try out is "unlimited".
481 {
Evan Shrubsoleb93ad752020-08-13 11:35:24 +0200482 Adaptation adaptation = adapter_.GetAdaptationUp();
Henrik Boström4c076052020-03-18 10:09:59 +0100483 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
484 fake_stream.ApplyAdaptation(adaptation);
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200485 EXPECT_EQ(absl::nullopt, adapter_.source_restrictions().max_frame_rate());
486 EXPECT_EQ(2, adapter_.adaptation_counters().resolution_adaptations);
487 EXPECT_EQ(0, adapter_.adaptation_counters().fps_adaptations);
Henrik Boström4c076052020-03-18 10:09:59 +0100488 }
489 // Now only adapting resolution remains.
490 constexpr size_t kReducedPixelsFirstStepUp =
491 (kReducedPixelsSecondStepUp * 5) / 3;
492 {
Evan Shrubsoleb93ad752020-08-13 11:35:24 +0200493 Adaptation adaptation = adapter_.GetAdaptationUp();
Henrik Boström4c076052020-03-18 10:09:59 +0100494 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
495 fake_stream.ApplyAdaptation(adaptation);
496 EXPECT_EQ(kReducedPixelsFirstStepUp,
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200497 adapter_.source_restrictions().target_pixels_per_frame());
498 EXPECT_EQ(1, adapter_.adaptation_counters().resolution_adaptations);
499 EXPECT_EQ(0, adapter_.adaptation_counters().fps_adaptations);
Henrik Boström4c076052020-03-18 10:09:59 +0100500 }
501 // The last step up should make us entirely unrestricted.
502 {
Evan Shrubsoleb93ad752020-08-13 11:35:24 +0200503 Adaptation adaptation = adapter_.GetAdaptationUp();
Henrik Boström4c076052020-03-18 10:09:59 +0100504 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
505 fake_stream.ApplyAdaptation(adaptation);
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200506 EXPECT_EQ(VideoSourceRestrictions(), adapter_.source_restrictions());
507 EXPECT_EQ(0, adapter_.adaptation_counters().Total());
Henrik Boström4c076052020-03-18 10:09:59 +0100508 }
509}
510
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200511TEST_F(VideoStreamAdapterTest, Balanced_LimitReached) {
512 adapter_.SetDegradationPreference(DegradationPreference::BALANCED);
513 FakeVideoStream fake_stream(
514 &adapter_, &input_state_provider_, kBalancedLowResolutionPixels,
515 kBalancedLowFrameRateFps, kDefaultMinPixelsPerFrame);
Henrik Boström4c076052020-03-18 10:09:59 +0100516 // Attempting to adapt up while unrestricted should result in kLimitReached.
517 EXPECT_EQ(Adaptation::Status::kLimitReached,
Evan Shrubsoleb93ad752020-08-13 11:35:24 +0200518 adapter_.GetAdaptationUp().status());
Henrik Boström4c076052020-03-18 10:09:59 +0100519 // Adapting down once result in restricted frame rate, in this case we reach
520 // the lowest possible frame rate immediately: kBalancedLowFrameRateFps.
Evan Shrubsoled73d4212020-08-17 11:10:45 +0200521 EXPECT_CALL(encoder_stats_observer_, OnMinPixelLimitReached()).Times(2);
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200522 fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown());
Henrik Boström4c076052020-03-18 10:09:59 +0100523 EXPECT_EQ(static_cast<double>(kBalancedLowFrameRateFps),
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200524 adapter_.source_restrictions().max_frame_rate());
525 EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations);
Henrik Boström4c076052020-03-18 10:09:59 +0100526 // Any further adaptation must follow "maintain-framerate" rules (these are
527 // covered in more depth by the MaintainFramerate tests). This test does not
528 // assert exactly how resolution is adjusted, only that resolution always
529 // decreases and that we eventually reach kLimitReached.
530 size_t previous_resolution = kBalancedLowResolutionPixels;
531 bool did_reach_limit = false;
532 // If we have not reached the limit within 5 adaptations something is wrong...
533 for (int i = 0; i < 5; i++) {
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200534 Adaptation adaptation = adapter_.GetAdaptationDown();
Henrik Boström4c076052020-03-18 10:09:59 +0100535 if (adaptation.status() == Adaptation::Status::kLimitReached) {
536 did_reach_limit = true;
537 break;
538 }
539 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
540 fake_stream.ApplyAdaptation(adaptation);
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200541 EXPECT_LT(adapter_.source_restrictions().max_pixels_per_frame().value(),
Henrik Boström4c076052020-03-18 10:09:59 +0100542 previous_resolution);
543 previous_resolution =
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200544 adapter_.source_restrictions().max_pixels_per_frame().value();
Henrik Boström4c076052020-03-18 10:09:59 +0100545 }
546 EXPECT_TRUE(did_reach_limit);
547 // Frame rate restrictions are the same as before.
548 EXPECT_EQ(static_cast<double>(kBalancedLowFrameRateFps),
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200549 adapter_.source_restrictions().max_frame_rate());
550 EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations);
Henrik Boström4c076052020-03-18 10:09:59 +0100551}
552
Henrik Boström4c076052020-03-18 10:09:59 +0100553// kAwaitingPreviousAdaptation is only supported in "maintain-framerate".
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200554TEST_F(VideoStreamAdapterTest,
555 MaintainFramerate_AwaitingPreviousAdaptationDown) {
556 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE);
557 input_state_provider_.SetInputState(1280 * 720, 30,
558 kDefaultMinPixelsPerFrame);
Henrik Boström4c076052020-03-18 10:09:59 +0100559 // Adapt down once, but don't update the input.
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200560 adapter_.ApplyAdaptation(adapter_.GetAdaptationDown(), nullptr);
561 EXPECT_EQ(1, adapter_.adaptation_counters().resolution_adaptations);
Henrik Boström4c076052020-03-18 10:09:59 +0100562 {
563 // Having performed the adaptation, but not updated the input based on the
564 // new restrictions, adapting again in the same direction will not work.
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200565 Adaptation adaptation = adapter_.GetAdaptationDown();
Henrik Boström4c076052020-03-18 10:09:59 +0100566 EXPECT_EQ(Adaptation::Status::kAwaitingPreviousAdaptation,
567 adaptation.status());
568 }
569}
570
571// kAwaitingPreviousAdaptation is only supported in "maintain-framerate".
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200572TEST_F(VideoStreamAdapterTest, MaintainFramerate_AwaitingPreviousAdaptationUp) {
573 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE);
574 FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30,
Henrik Boströmb613e3a2020-04-17 13:48:21 +0200575 kDefaultMinPixelsPerFrame);
Henrik Boström4c076052020-03-18 10:09:59 +0100576 // Perform two adaptation down so that adapting up twice is possible.
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200577 fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown());
578 fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown());
579 EXPECT_EQ(2, adapter_.adaptation_counters().resolution_adaptations);
Henrik Boström4c076052020-03-18 10:09:59 +0100580 // Adapt up once, but don't update the input.
Evan Shrubsoleb93ad752020-08-13 11:35:24 +0200581 adapter_.ApplyAdaptation(adapter_.GetAdaptationUp(), nullptr);
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200582 EXPECT_EQ(1, adapter_.adaptation_counters().resolution_adaptations);
Henrik Boström4c076052020-03-18 10:09:59 +0100583 {
584 // Having performed the adaptation, but not updated the input based on the
585 // new restrictions, adapting again in the same direction will not work.
Evan Shrubsoleb93ad752020-08-13 11:35:24 +0200586 Adaptation adaptation = adapter_.GetAdaptationUp();
Henrik Boström4c076052020-03-18 10:09:59 +0100587 EXPECT_EQ(Adaptation::Status::kAwaitingPreviousAdaptation,
588 adaptation.status());
589 }
590}
591
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200592TEST_F(VideoStreamAdapterTest,
593 MaintainResolution_AdaptsUpAfterSwitchingDegradationPreference) {
594 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION);
595 FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30,
Evan Shrubsole84afe462020-05-13 11:47:01 +0200596 kDefaultMinPixelsPerFrame);
597 // Adapt down in fps for later.
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200598 fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown());
599 EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations);
Evan Shrubsole84afe462020-05-13 11:47:01 +0200600
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200601 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE);
602 fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown());
Evan Shrubsoleb93ad752020-08-13 11:35:24 +0200603 fake_stream.ApplyAdaptation(adapter_.GetAdaptationUp());
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200604 EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations);
605 EXPECT_EQ(0, adapter_.adaptation_counters().resolution_adaptations);
Evan Shrubsole84afe462020-05-13 11:47:01 +0200606
607 // We should be able to adapt in framerate one last time after the change of
608 // degradation preference.
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200609 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION);
Evan Shrubsoleb93ad752020-08-13 11:35:24 +0200610 Adaptation adaptation = adapter_.GetAdaptationUp();
Evan Shrubsole84afe462020-05-13 11:47:01 +0200611 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
Evan Shrubsoleb93ad752020-08-13 11:35:24 +0200612 fake_stream.ApplyAdaptation(adapter_.GetAdaptationUp());
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200613 EXPECT_EQ(0, adapter_.adaptation_counters().fps_adaptations);
Evan Shrubsole84afe462020-05-13 11:47:01 +0200614}
615
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200616TEST_F(VideoStreamAdapterTest,
617 MaintainFramerate_AdaptsUpAfterSwitchingDegradationPreference) {
618 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE);
619 FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30,
Evan Shrubsole84afe462020-05-13 11:47:01 +0200620 kDefaultMinPixelsPerFrame);
621 // Adapt down in resolution for later.
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200622 fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown());
623 EXPECT_EQ(1, adapter_.adaptation_counters().resolution_adaptations);
Evan Shrubsole84afe462020-05-13 11:47:01 +0200624
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200625 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION);
626 fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown());
Evan Shrubsoleb93ad752020-08-13 11:35:24 +0200627 fake_stream.ApplyAdaptation(adapter_.GetAdaptationUp());
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200628 EXPECT_EQ(1, adapter_.adaptation_counters().resolution_adaptations);
629 EXPECT_EQ(0, adapter_.adaptation_counters().fps_adaptations);
Evan Shrubsole84afe462020-05-13 11:47:01 +0200630
631 // We should be able to adapt in framerate one last time after the change of
632 // degradation preference.
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200633 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE);
Evan Shrubsoleb93ad752020-08-13 11:35:24 +0200634 Adaptation adaptation = adapter_.GetAdaptationUp();
Evan Shrubsole84afe462020-05-13 11:47:01 +0200635 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
Evan Shrubsoleb93ad752020-08-13 11:35:24 +0200636 fake_stream.ApplyAdaptation(adapter_.GetAdaptationUp());
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200637 EXPECT_EQ(0, adapter_.adaptation_counters().resolution_adaptations);
Evan Shrubsole84afe462020-05-13 11:47:01 +0200638}
639
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200640TEST_F(VideoStreamAdapterTest,
641 PendingResolutionIncreaseAllowsAdaptUpAfterSwitchToMaintainResolution) {
642 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION);
643 FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30,
Evan Shrubsole84afe462020-05-13 11:47:01 +0200644 kDefaultMinPixelsPerFrame);
645 // Adapt fps down so we can adapt up later in the test.
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200646 fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown());
Evan Shrubsole84afe462020-05-13 11:47:01 +0200647
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200648 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE);
649 fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown());
Evan Shrubsole84afe462020-05-13 11:47:01 +0200650 // Apply adaptation up but don't update input.
Evan Shrubsoleb93ad752020-08-13 11:35:24 +0200651 adapter_.ApplyAdaptation(adapter_.GetAdaptationUp(), nullptr);
Evan Shrubsole84afe462020-05-13 11:47:01 +0200652 EXPECT_EQ(Adaptation::Status::kAwaitingPreviousAdaptation,
Evan Shrubsoleb93ad752020-08-13 11:35:24 +0200653 adapter_.GetAdaptationUp().status());
Evan Shrubsole84afe462020-05-13 11:47:01 +0200654
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200655 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION);
Evan Shrubsoleb93ad752020-08-13 11:35:24 +0200656 Adaptation adaptation = adapter_.GetAdaptationUp();
Evan Shrubsole84afe462020-05-13 11:47:01 +0200657 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
658}
659
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200660TEST_F(VideoStreamAdapterTest,
661 MaintainFramerate_AdaptsDownAfterSwitchingDegradationPreference) {
662 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION);
663 FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30,
Evan Shrubsole84afe462020-05-13 11:47:01 +0200664 kDefaultMinPixelsPerFrame);
665 // Adapt down once, should change FPS.
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200666 fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown());
667 EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations);
Evan Shrubsole84afe462020-05-13 11:47:01 +0200668
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200669 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE);
Evan Shrubsole84afe462020-05-13 11:47:01 +0200670 // Adaptation down should apply after the degradation prefs change.
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200671 Adaptation adaptation = adapter_.GetAdaptationDown();
Evan Shrubsole84afe462020-05-13 11:47:01 +0200672 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
673 fake_stream.ApplyAdaptation(adaptation);
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200674 EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations);
675 EXPECT_EQ(1, adapter_.adaptation_counters().resolution_adaptations);
Evan Shrubsole84afe462020-05-13 11:47:01 +0200676}
677
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200678TEST_F(VideoStreamAdapterTest,
679 MaintainResolution_AdaptsDownAfterSwitchingDegradationPreference) {
680 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE);
681 FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30,
Evan Shrubsole84afe462020-05-13 11:47:01 +0200682 kDefaultMinPixelsPerFrame);
683 // Adapt down once, should change FPS.
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200684 fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown());
685 EXPECT_EQ(1, adapter_.adaptation_counters().resolution_adaptations);
Evan Shrubsole84afe462020-05-13 11:47:01 +0200686
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200687 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION);
688 Adaptation adaptation = adapter_.GetAdaptationDown();
Evan Shrubsole84afe462020-05-13 11:47:01 +0200689 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
690 fake_stream.ApplyAdaptation(adaptation);
691
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200692 EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations);
693 EXPECT_EQ(1, adapter_.adaptation_counters().resolution_adaptations);
Evan Shrubsole84afe462020-05-13 11:47:01 +0200694}
695
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200696TEST_F(
697 VideoStreamAdapterTest,
698 PendingResolutionDecreaseAllowsAdaptDownAfterSwitchToMaintainResolution) {
699 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE);
700 FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30,
Evan Shrubsole84afe462020-05-13 11:47:01 +0200701 kDefaultMinPixelsPerFrame);
702 // Apply adaptation but don't update the input.
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200703 adapter_.ApplyAdaptation(adapter_.GetAdaptationDown(), nullptr);
Evan Shrubsole84afe462020-05-13 11:47:01 +0200704 EXPECT_EQ(Adaptation::Status::kAwaitingPreviousAdaptation,
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200705 adapter_.GetAdaptationDown().status());
706 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION);
707 Adaptation adaptation = adapter_.GetAdaptationDown();
Evan Shrubsole84afe462020-05-13 11:47:01 +0200708 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
709}
710
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200711TEST_F(VideoStreamAdapterTest, RestrictionBroadcasted) {
Evan Shrubsoleec0af262020-07-01 11:47:46 +0200712 FakeVideoStreamAdapterListner listener;
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200713 adapter_.AddRestrictionsListener(&listener);
714 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE);
715 FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30,
Evan Shrubsoleec0af262020-07-01 11:47:46 +0200716 kDefaultMinPixelsPerFrame);
717 // Not broadcast on invalid ApplyAdaptation.
718 {
Evan Shrubsoleb93ad752020-08-13 11:35:24 +0200719 Adaptation adaptation = adapter_.GetAdaptationUp();
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200720 adapter_.ApplyAdaptation(adaptation, nullptr);
Evan Shrubsoleec0af262020-07-01 11:47:46 +0200721 EXPECT_EQ(0, listener.calls());
722 }
723
724 // Broadcast on ApplyAdaptation.
725 {
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200726 Adaptation adaptation = adapter_.GetAdaptationDown();
Evan Shrubsoleec0af262020-07-01 11:47:46 +0200727 fake_stream.ApplyAdaptation(adaptation);
728 EXPECT_EQ(1, listener.calls());
Evan Shrubsoled7d2f272020-07-03 15:16:43 +0200729 EXPECT_EQ(adaptation.restrictions(), listener.last_restrictions());
Evan Shrubsoleec0af262020-07-01 11:47:46 +0200730 }
731
732 // Broadcast on ClearRestrictions().
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200733 adapter_.ClearRestrictions();
Evan Shrubsoleec0af262020-07-01 11:47:46 +0200734 EXPECT_EQ(2, listener.calls());
735 EXPECT_EQ(VideoSourceRestrictions(), listener.last_restrictions());
736}
737
Evan Shrubsoled7d2f272020-07-03 15:16:43 +0200738TEST_F(VideoStreamAdapterTest, AdaptationHasNextRestrcitions) {
Henrik Boström4c076052020-03-18 10:09:59 +0100739 // Any non-disabled DegradationPreference will do.
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200740 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE);
741 FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30,
Henrik Boströmb613e3a2020-04-17 13:48:21 +0200742 kDefaultMinPixelsPerFrame);
Henrik Boström4c076052020-03-18 10:09:59 +0100743 // When adaptation is not possible.
744 {
Evan Shrubsoleb93ad752020-08-13 11:35:24 +0200745 Adaptation adaptation = adapter_.GetAdaptationUp();
Henrik Boström4c076052020-03-18 10:09:59 +0100746 EXPECT_EQ(Adaptation::Status::kLimitReached, adaptation.status());
Evan Shrubsoled7d2f272020-07-03 15:16:43 +0200747 EXPECT_EQ(adaptation.restrictions(), adapter_.source_restrictions());
748 EXPECT_EQ(0, adaptation.counters().Total());
Henrik Boström4c076052020-03-18 10:09:59 +0100749 }
750 // When we adapt down.
751 {
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200752 Adaptation adaptation = adapter_.GetAdaptationDown();
Henrik Boström4c076052020-03-18 10:09:59 +0100753 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
Henrik Boström4c076052020-03-18 10:09:59 +0100754 fake_stream.ApplyAdaptation(adaptation);
Evan Shrubsoled7d2f272020-07-03 15:16:43 +0200755 EXPECT_EQ(adaptation.restrictions(), adapter_.source_restrictions());
756 EXPECT_EQ(adaptation.counters(), adapter_.adaptation_counters());
Henrik Boström4c076052020-03-18 10:09:59 +0100757 }
758 // When we adapt up.
759 {
Evan Shrubsoleb93ad752020-08-13 11:35:24 +0200760 Adaptation adaptation = adapter_.GetAdaptationUp();
Henrik Boström4c076052020-03-18 10:09:59 +0100761 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
Henrik Boström4c076052020-03-18 10:09:59 +0100762 fake_stream.ApplyAdaptation(adaptation);
Evan Shrubsoled7d2f272020-07-03 15:16:43 +0200763 EXPECT_EQ(adaptation.restrictions(), adapter_.source_restrictions());
764 EXPECT_EQ(adaptation.counters(), adapter_.adaptation_counters());
Henrik Boström4c076052020-03-18 10:09:59 +0100765 }
766}
767
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200768TEST_F(VideoStreamAdapterTest,
769 SetDegradationPreferenceToOrFromBalancedClearsRestrictions) {
770 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE);
771 input_state_provider_.SetInputState(1280 * 720, 30,
772 kDefaultMinPixelsPerFrame);
773 adapter_.ApplyAdaptation(adapter_.GetAdaptationDown(), nullptr);
774 EXPECT_NE(VideoSourceRestrictions(), adapter_.source_restrictions());
775 EXPECT_NE(0, adapter_.adaptation_counters().Total());
Henrik Boström4c076052020-03-18 10:09:59 +0100776 // Changing from non-balanced to balanced clears the restrictions.
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200777 adapter_.SetDegradationPreference(DegradationPreference::BALANCED);
778 EXPECT_EQ(VideoSourceRestrictions(), adapter_.source_restrictions());
779 EXPECT_EQ(0, adapter_.adaptation_counters().Total());
Henrik Boström4c076052020-03-18 10:09:59 +0100780 // Apply adaptation again.
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200781 adapter_.ApplyAdaptation(adapter_.GetAdaptationDown(), nullptr);
782 EXPECT_NE(VideoSourceRestrictions(), adapter_.source_restrictions());
783 EXPECT_NE(0, adapter_.adaptation_counters().Total());
Henrik Boström4c076052020-03-18 10:09:59 +0100784 // Changing from balanced to non-balanced clears the restrictions.
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200785 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION);
786 EXPECT_EQ(VideoSourceRestrictions(), adapter_.source_restrictions());
787 EXPECT_EQ(0, adapter_.adaptation_counters().Total());
Henrik Boström4c076052020-03-18 10:09:59 +0100788}
789
Evan Shrubsoleafd1dcb2020-07-06 11:16:51 +0200790TEST_F(VideoStreamAdapterTest,
791 GetAdaptDownResolutionAdaptsResolutionInMaintainFramerate) {
792 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE);
793 input_state_provider_.SetInputState(1280 * 720, 30,
794 kDefaultMinPixelsPerFrame);
795
796 auto adaptation = adapter_.GetAdaptDownResolution();
797 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
798 EXPECT_EQ(1, adaptation.counters().resolution_adaptations);
799 EXPECT_EQ(0, adaptation.counters().fps_adaptations);
800}
801
Evan Shrubsole3444a492020-07-07 09:04:34 +0200802TEST_F(VideoStreamAdapterTest,
803 GetAdaptDownResolutionReturnsWithStatusInDisabledAndMaintainResolution) {
Evan Shrubsoleafd1dcb2020-07-06 11:16:51 +0200804 adapter_.SetDegradationPreference(DegradationPreference::DISABLED);
805 input_state_provider_.SetInputState(1280 * 720, 30,
806 kDefaultMinPixelsPerFrame);
Evan Shrubsole3444a492020-07-07 09:04:34 +0200807 EXPECT_EQ(Adaptation::Status::kAdaptationDisabled,
Evan Shrubsoleafd1dcb2020-07-06 11:16:51 +0200808 adapter_.GetAdaptDownResolution().status());
Evan Shrubsole3444a492020-07-07 09:04:34 +0200809 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION);
Evan Shrubsoleafd1dcb2020-07-06 11:16:51 +0200810 EXPECT_EQ(Adaptation::Status::kLimitReached,
811 adapter_.GetAdaptDownResolution().status());
812}
813
814TEST_F(VideoStreamAdapterTest,
815 GetAdaptDownResolutionAdaptsFpsAndResolutionInBalanced) {
816 // Note: This test depends on BALANCED implementation, but with current
817 // implementation and input state settings, BALANCED will adapt resolution and
818 // frame rate once.
819 adapter_.SetDegradationPreference(DegradationPreference::BALANCED);
820 input_state_provider_.SetInputState(1280 * 720, 30,
821 kDefaultMinPixelsPerFrame);
822
823 auto adaptation = adapter_.GetAdaptDownResolution();
824 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
825 EXPECT_EQ(1, adaptation.counters().resolution_adaptations);
826 EXPECT_EQ(1, adaptation.counters().fps_adaptations);
827}
828
829TEST_F(
830 VideoStreamAdapterTest,
831 GetAdaptDownResolutionAdaptsOnlyResolutionIfFpsAlreadyAdapterInBalanced) {
832 // Note: This test depends on BALANCED implementation, but with current
833 // implementation and input state settings, BALANCED will adapt resolution
834 // only.
835 adapter_.SetDegradationPreference(DegradationPreference::BALANCED);
836 input_state_provider_.SetInputState(1280 * 720, 5, kDefaultMinPixelsPerFrame);
837 FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30,
838 kDefaultMinPixelsPerFrame);
839
840 auto first_adaptation = adapter_.GetAdaptationDown();
841 fake_stream.ApplyAdaptation(first_adaptation);
842
843 auto adaptation = adapter_.GetAdaptDownResolution();
844 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
845 EXPECT_EQ(1, adaptation.counters().resolution_adaptations);
846 EXPECT_EQ(first_adaptation.counters().fps_adaptations,
847 adaptation.counters().fps_adaptations);
848}
849
850TEST_F(VideoStreamAdapterTest,
851 GetAdaptDownResolutionAdaptsOnlyFpsIfResolutionLowInBalanced) {
852 // Note: This test depends on BALANCED implementation, but with current
853 // implementation and input state settings, BALANCED will adapt resolution
854 // only.
855 adapter_.SetDegradationPreference(DegradationPreference::BALANCED);
856 input_state_provider_.SetInputState(kDefaultMinPixelsPerFrame, 30,
857 kDefaultMinPixelsPerFrame);
858
859 auto adaptation = adapter_.GetAdaptDownResolution();
860 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
861 EXPECT_EQ(0, adaptation.counters().resolution_adaptations);
862 EXPECT_EQ(1, adaptation.counters().fps_adaptations);
863}
864
Evan Shrubsole3444a492020-07-07 09:04:34 +0200865TEST_F(VideoStreamAdapterTest,
866 AdaptationDisabledStatusAlwaysWhenDegradationPreferenceDisabled) {
867 adapter_.SetDegradationPreference(DegradationPreference::DISABLED);
868 input_state_provider_.SetInputState(1280 * 720, 30,
869 kDefaultMinPixelsPerFrame);
870 EXPECT_EQ(Adaptation::Status::kAdaptationDisabled,
871 adapter_.GetAdaptationDown().status());
872 EXPECT_EQ(Adaptation::Status::kAdaptationDisabled,
Evan Shrubsoleb93ad752020-08-13 11:35:24 +0200873 adapter_.GetAdaptationUp().status());
Evan Shrubsole3444a492020-07-07 09:04:34 +0200874 EXPECT_EQ(Adaptation::Status::kAdaptationDisabled,
875 adapter_.GetAdaptDownResolution().status());
876}
877
Evan Shrubsole73ecede2020-07-09 13:51:39 +0200878TEST_F(VideoStreamAdapterTest, AdaptationConstraintAllowsAdaptationsUp) {
879 testing::StrictMock<MockAdaptationConstraint> adaptation_constraint;
880 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE);
881 adapter_.AddAdaptationConstraint(&adaptation_constraint);
882 input_state_provider_.SetInputState(1280 * 720, 30,
883 kDefaultMinPixelsPerFrame);
884 FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30,
885 kDefaultMinPixelsPerFrame);
886 // Adapt down once so we can adapt up later.
887 auto first_adaptation = adapter_.GetAdaptationDown();
888 fake_stream.ApplyAdaptation(first_adaptation);
889
Evan Shrubsoleb93ad752020-08-13 11:35:24 +0200890 EXPECT_CALL(adaptation_constraint,
891 IsAdaptationUpAllowed(_, first_adaptation.restrictions(), _))
Evan Shrubsole73ecede2020-07-09 13:51:39 +0200892 .WillOnce(Return(true));
Evan Shrubsoleb93ad752020-08-13 11:35:24 +0200893 EXPECT_EQ(Adaptation::Status::kValid, adapter_.GetAdaptationUp().status());
Evan Shrubsole73ecede2020-07-09 13:51:39 +0200894 adapter_.RemoveAdaptationConstraint(&adaptation_constraint);
895}
896
897TEST_F(VideoStreamAdapterTest, AdaptationConstraintDisallowsAdaptationsUp) {
898 testing::StrictMock<MockAdaptationConstraint> adaptation_constraint;
899 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE);
900 adapter_.AddAdaptationConstraint(&adaptation_constraint);
901 input_state_provider_.SetInputState(1280 * 720, 30,
902 kDefaultMinPixelsPerFrame);
903 FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30,
904 kDefaultMinPixelsPerFrame);
905 // Adapt down once so we can adapt up later.
906 auto first_adaptation = adapter_.GetAdaptationDown();
907 fake_stream.ApplyAdaptation(first_adaptation);
908
Evan Shrubsoleb93ad752020-08-13 11:35:24 +0200909 EXPECT_CALL(adaptation_constraint,
910 IsAdaptationUpAllowed(_, first_adaptation.restrictions(), _))
Evan Shrubsole73ecede2020-07-09 13:51:39 +0200911 .WillOnce(Return(false));
912 EXPECT_EQ(Adaptation::Status::kRejectedByConstraint,
Evan Shrubsoleb93ad752020-08-13 11:35:24 +0200913 adapter_.GetAdaptationUp().status());
Evan Shrubsole73ecede2020-07-09 13:51:39 +0200914 adapter_.RemoveAdaptationConstraint(&adaptation_constraint);
915}
916
Henrik Boström4c076052020-03-18 10:09:59 +0100917// Death tests.
918// Disabled on Android because death tests misbehave on Android, see
919// base/test/gtest_util.h.
920#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
921
922TEST(VideoStreamAdapterDeathTest,
923 SetDegradationPreferenceInvalidatesAdaptations) {
Jonas Orelandc7f691a2022-03-09 15:12:07 +0100924 webrtc::test::ScopedKeyValueConfig field_trials;
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200925 FakeVideoStreamInputStateProvider input_state_provider;
Evan Shrubsoled73d4212020-08-17 11:10:45 +0200926 testing::StrictMock<MockVideoStreamEncoderObserver> encoder_stats_observer_;
Jonas Orelandc7f691a2022-03-09 15:12:07 +0100927 VideoStreamAdapter adapter(&input_state_provider, &encoder_stats_observer_,
928 field_trials);
Henrik Boström4c076052020-03-18 10:09:59 +0100929 adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE);
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200930 input_state_provider.SetInputState(1280 * 720, 30, kDefaultMinPixelsPerFrame);
Henrik Boström4c076052020-03-18 10:09:59 +0100931 Adaptation adaptation = adapter.GetAdaptationDown();
932 adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION);
Evan Shrubsoleec0af262020-07-01 11:47:46 +0200933 EXPECT_DEATH(adapter.ApplyAdaptation(adaptation, nullptr), "");
Henrik Boström4c076052020-03-18 10:09:59 +0100934}
935
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200936TEST(VideoStreamAdapterDeathTest, AdaptDownInvalidatesAdaptations) {
Jonas Orelandc7f691a2022-03-09 15:12:07 +0100937 webrtc::test::ScopedKeyValueConfig field_trials;
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200938 FakeVideoStreamInputStateProvider input_state_provider;
Evan Shrubsoled73d4212020-08-17 11:10:45 +0200939 testing::StrictMock<MockVideoStreamEncoderObserver> encoder_stats_observer_;
Jonas Orelandc7f691a2022-03-09 15:12:07 +0100940 VideoStreamAdapter adapter(&input_state_provider, &encoder_stats_observer_,
941 field_trials);
Henrik Boström4c076052020-03-18 10:09:59 +0100942 adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION);
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200943 input_state_provider.SetInputState(1280 * 720, 30, kDefaultMinPixelsPerFrame);
Henrik Boström4c076052020-03-18 10:09:59 +0100944 Adaptation adaptation = adapter.GetAdaptationDown();
Evan Shrubsole34b1a422020-07-02 14:42:09 +0200945 adapter.GetAdaptationDown();
Evan Shrubsoled7d2f272020-07-03 15:16:43 +0200946 EXPECT_DEATH(adapter.ApplyAdaptation(adaptation, nullptr), "");
Henrik Boström4c076052020-03-18 10:09:59 +0100947}
948
949#endif // RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
950
951} // namespace webrtc