video_stream_adapter_unittest.cc (46177B)
1 /* 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 11 #include "call/adaptation/video_stream_adapter.h" 12 13 #include <cstddef> 14 #include <optional> 15 #include <string> 16 17 #include "absl/strings/str_cat.h" 18 #include "api/adaptation/resource.h" 19 #include "api/rtp_parameters.h" 20 #include "api/scoped_refptr.h" 21 #include "api/video/video_adaptation_counters.h" 22 #include "api/video_codecs/video_encoder.h" 23 #include "call/adaptation/adaptation_constraint.h" 24 #include "call/adaptation/test/fake_frame_rate_provider.h" 25 #include "call/adaptation/test/fake_resource.h" 26 #include "call/adaptation/test/fake_video_stream_input_state_provider.h" 27 #include "call/adaptation/video_source_restrictions.h" 28 #include "call/adaptation/video_stream_input_state.h" 29 #include "rtc_base/checks.h" 30 #include "test/create_test_field_trials.h" 31 #include "test/gmock.h" 32 #include "test/gtest.h" 33 34 namespace webrtc { 35 36 using ::testing::_; 37 using ::testing::Return; 38 39 namespace { 40 41 constexpr int kBalancedHighResolutionPixels = 1280 * 720; 42 constexpr int kBalancedHighFrameRateFps = 30; 43 44 constexpr int kBalancedMediumResolutionPixels = 640 * 480; 45 constexpr int kBalancedMediumFrameRateFps = 20; 46 47 constexpr int kBalancedLowResolutionPixels = 320 * 240; 48 constexpr int kBalancedLowFrameRateFps = 10; 49 50 std::string BalancedFieldTrialConfig() { 51 return "WebRTC-Video-BalancedDegradationSettings/pixels:" + 52 absl::StrCat(kBalancedLowResolutionPixels) + "|" + 53 absl::StrCat(kBalancedMediumResolutionPixels) + "|" + 54 absl::StrCat(kBalancedHighResolutionPixels) + 55 ",fps:" + absl::StrCat(kBalancedLowFrameRateFps) + "|" + 56 absl::StrCat(kBalancedMediumFrameRateFps) + "|" + 57 absl::StrCat(kBalancedHighFrameRateFps) + "/"; 58 } 59 60 // Responsible for adjusting the inputs to VideoStreamAdapter (SetInput), such 61 // as pixels and frame rate, according to the most recent source restrictions. 62 // This helps tests that apply adaptations multiple times: if the input is not 63 // adjusted between adaptations, the subsequent adaptations fail with 64 // kAwaitingPreviousAdaptation. 65 class FakeVideoStream { 66 public: 67 FakeVideoStream(VideoStreamAdapter* adapter, 68 FakeVideoStreamInputStateProvider* provider, 69 int input_pixels, 70 int input_fps, 71 int min_pixels_per_frame) 72 : adapter_(adapter), 73 provider_(provider), 74 input_pixels_(input_pixels), 75 input_fps_(input_fps), 76 min_pixels_per_frame_(min_pixels_per_frame) { 77 provider_->SetInputState(input_pixels_, input_fps_, min_pixels_per_frame_); 78 } 79 80 int input_pixels() const { return input_pixels_; } 81 int input_fps() const { return input_fps_; } 82 83 // Performs ApplyAdaptation() followed by SetInput() with input pixels and 84 // frame rate adjusted according to the resulting restrictions. 85 void ApplyAdaptation(Adaptation adaptation) { 86 adapter_->ApplyAdaptation(adaptation, nullptr); 87 // Update input pixels and fps according to the resulting restrictions. 88 auto restrictions = adapter_->source_restrictions(); 89 if (restrictions.target_pixels_per_frame().has_value()) { 90 RTC_DCHECK(!restrictions.max_pixels_per_frame().has_value() || 91 restrictions.max_pixels_per_frame().value() >= 92 restrictions.target_pixels_per_frame().value()); 93 input_pixels_ = restrictions.target_pixels_per_frame().value(); 94 } else if (restrictions.max_pixels_per_frame().has_value()) { 95 input_pixels_ = restrictions.max_pixels_per_frame().value(); 96 } 97 if (restrictions.max_frame_rate().has_value()) { 98 input_fps_ = restrictions.max_frame_rate().value(); 99 } 100 provider_->SetInputState(input_pixels_, input_fps_, min_pixels_per_frame_); 101 } 102 103 private: 104 VideoStreamAdapter* adapter_; 105 FakeVideoStreamInputStateProvider* provider_; 106 int input_pixels_; 107 int input_fps_; 108 int min_pixels_per_frame_; 109 }; 110 111 class FakeVideoStreamAdapterListner : public VideoSourceRestrictionsListener { 112 public: 113 void OnVideoSourceRestrictionsUpdated( 114 VideoSourceRestrictions /* restrictions */, 115 const VideoAdaptationCounters& /* adaptation_counters */, 116 scoped_refptr<Resource> /* reason */, 117 const VideoSourceRestrictions& unfiltered_restrictions) override { 118 calls_++; 119 last_restrictions_ = unfiltered_restrictions; 120 } 121 122 int calls() const { return calls_; } 123 124 VideoSourceRestrictions last_restrictions() const { 125 return last_restrictions_; 126 } 127 128 private: 129 int calls_ = 0; 130 VideoSourceRestrictions last_restrictions_; 131 }; 132 133 class MockAdaptationConstraint : public AdaptationConstraint { 134 public: 135 MOCK_METHOD(bool, 136 IsAdaptationUpAllowed, 137 (const VideoStreamInputState& input_state, 138 const VideoSourceRestrictions& restrictions_before, 139 const VideoSourceRestrictions& restrictions_after), 140 (const, override)); 141 142 // MOCK_METHOD(std::string, Name, (), (const, override)); 143 std::string Name() const override { return "MockAdaptationConstraint"; } 144 }; 145 146 } // namespace 147 148 class VideoStreamAdapterTest : public ::testing::Test { 149 public: 150 VideoStreamAdapterTest() 151 : resource_(FakeResource::Create("FakeResource")), 152 adapter_(&input_state_provider_, 153 &encoder_stats_observer_, 154 CreateTestFieldTrials(BalancedFieldTrialConfig())) {} 155 156 protected: 157 FakeVideoStreamInputStateProvider input_state_provider_; 158 scoped_refptr<Resource> resource_; 159 testing::StrictMock<MockVideoStreamEncoderObserver> encoder_stats_observer_; 160 VideoStreamAdapter adapter_; 161 }; 162 163 TEST_F(VideoStreamAdapterTest, NoRestrictionsByDefault) { 164 EXPECT_EQ(VideoSourceRestrictions(), adapter_.source_restrictions()); 165 EXPECT_EQ(0, adapter_.adaptation_counters().Total()); 166 } 167 168 TEST_F(VideoStreamAdapterTest, MaintainFramerate_DecreasesPixelsToThreeFifths) { 169 const int kInputPixels = 1280 * 720; 170 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); 171 input_state_provider_.SetInputState(kInputPixels, 30, 172 kDefaultMinPixelsPerFrame); 173 Adaptation adaptation = adapter_.GetAdaptationDown(); 174 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); 175 adapter_.ApplyAdaptation(adaptation, nullptr); 176 EXPECT_EQ(static_cast<size_t>((kInputPixels * 3) / 5), 177 adapter_.source_restrictions().max_pixels_per_frame()); 178 EXPECT_EQ(std::nullopt, 179 adapter_.source_restrictions().target_pixels_per_frame()); 180 EXPECT_EQ(std::nullopt, adapter_.source_restrictions().max_frame_rate()); 181 EXPECT_EQ(1, adapter_.adaptation_counters().resolution_adaptations); 182 } 183 184 TEST_F(VideoStreamAdapterTest, 185 MaintainFramerate_DecreasesPixelsToLimitReached) { 186 const int kMinPixelsPerFrame = 640 * 480; 187 188 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); 189 input_state_provider_.SetInputState(kMinPixelsPerFrame + 1, 30, 190 kMinPixelsPerFrame); 191 EXPECT_CALL(encoder_stats_observer_, OnMinPixelLimitReached()); 192 // Even though we are above kMinPixelsPerFrame, because adapting down would 193 // have exceeded the limit, we are said to have reached the limit already. 194 // This differs from the frame rate adaptation logic, which would have clamped 195 // to the limit in the first step and reported kLimitReached in the second 196 // step. 197 Adaptation adaptation = adapter_.GetAdaptationDown(); 198 EXPECT_EQ(Adaptation::Status::kLimitReached, adaptation.status()); 199 } 200 201 TEST_F(VideoStreamAdapterTest, MaintainFramerate_IncreasePixelsToFiveThirds) { 202 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); 203 FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30, 204 kDefaultMinPixelsPerFrame); 205 // Go down twice, ensuring going back up is still a restricted resolution. 206 fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown()); 207 fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown()); 208 EXPECT_EQ(2, adapter_.adaptation_counters().resolution_adaptations); 209 int input_pixels = fake_stream.input_pixels(); 210 // Go up once. The target is 5/3 and the max is 12/5 of the target. 211 const int target = (input_pixels * 5) / 3; 212 fake_stream.ApplyAdaptation(adapter_.GetAdaptationUp()); 213 EXPECT_EQ(static_cast<size_t>((target * 12) / 5), 214 adapter_.source_restrictions().max_pixels_per_frame()); 215 EXPECT_EQ(static_cast<size_t>(target), 216 adapter_.source_restrictions().target_pixels_per_frame()); 217 EXPECT_EQ(std::nullopt, adapter_.source_restrictions().max_frame_rate()); 218 EXPECT_EQ(1, adapter_.adaptation_counters().resolution_adaptations); 219 } 220 221 TEST_F(VideoStreamAdapterTest, MaintainFramerate_IncreasePixelsToUnrestricted) { 222 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); 223 FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30, 224 kDefaultMinPixelsPerFrame); 225 // We are unrestricted by default and should not be able to adapt up. 226 EXPECT_EQ(Adaptation::Status::kLimitReached, 227 adapter_.GetAdaptationUp().status()); 228 // If we go down once and then back up we should not have any restrictions. 229 fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown()); 230 EXPECT_EQ(1, adapter_.adaptation_counters().resolution_adaptations); 231 fake_stream.ApplyAdaptation(adapter_.GetAdaptationUp()); 232 EXPECT_EQ(VideoSourceRestrictions(), adapter_.source_restrictions()); 233 EXPECT_EQ(0, adapter_.adaptation_counters().Total()); 234 } 235 236 TEST_F(VideoStreamAdapterTest, MaintainResolution_DecreasesFpsToTwoThirds) { 237 const int kInputFps = 30; 238 239 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION); 240 input_state_provider_.SetInputState(1280 * 720, kInputFps, 241 kDefaultMinPixelsPerFrame); 242 Adaptation adaptation = adapter_.GetAdaptationDown(); 243 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); 244 adapter_.ApplyAdaptation(adaptation, nullptr); 245 EXPECT_EQ(std::nullopt, 246 adapter_.source_restrictions().max_pixels_per_frame()); 247 EXPECT_EQ(std::nullopt, 248 adapter_.source_restrictions().target_pixels_per_frame()); 249 EXPECT_EQ(static_cast<double>((kInputFps * 2) / 3), 250 adapter_.source_restrictions().max_frame_rate()); 251 EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations); 252 } 253 254 TEST_F(VideoStreamAdapterTest, MaintainResolution_DecreasesFpsToLimitReached) { 255 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION); 256 FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 257 kMinFrameRateFps + 1, kDefaultMinPixelsPerFrame); 258 // If we are not yet at the limit and the next step would exceed it, the step 259 // is clamped such that we end up exactly on the limit. 260 Adaptation adaptation = adapter_.GetAdaptationDown(); 261 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); 262 fake_stream.ApplyAdaptation(adaptation); 263 EXPECT_EQ(static_cast<double>(kMinFrameRateFps), 264 adapter_.source_restrictions().max_frame_rate()); 265 EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations); 266 // Having reached the limit, the next adaptation down is not valid. 267 EXPECT_EQ(Adaptation::Status::kLimitReached, 268 adapter_.GetAdaptationDown().status()); 269 } 270 271 TEST_F(VideoStreamAdapterTest, MaintainResolution_IncreaseFpsToThreeHalves) { 272 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION); 273 FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30, 274 kDefaultMinPixelsPerFrame); 275 // Go down twice, ensuring going back up is still a restricted frame rate. 276 fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown()); 277 fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown()); 278 EXPECT_EQ(2, adapter_.adaptation_counters().fps_adaptations); 279 int input_fps = fake_stream.input_fps(); 280 // Go up once. The target is 3/2 of the input. 281 Adaptation adaptation = adapter_.GetAdaptationUp(); 282 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); 283 fake_stream.ApplyAdaptation(adaptation); 284 EXPECT_EQ(std::nullopt, 285 adapter_.source_restrictions().max_pixels_per_frame()); 286 EXPECT_EQ(std::nullopt, 287 adapter_.source_restrictions().target_pixels_per_frame()); 288 EXPECT_EQ(static_cast<double>((input_fps * 3) / 2), 289 adapter_.source_restrictions().max_frame_rate()); 290 EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations); 291 } 292 293 TEST_F(VideoStreamAdapterTest, MaintainResolution_IncreaseFpsToUnrestricted) { 294 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION); 295 FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30, 296 kDefaultMinPixelsPerFrame); 297 // We are unrestricted by default and should not be able to adapt up. 298 EXPECT_EQ(Adaptation::Status::kLimitReached, 299 adapter_.GetAdaptationUp().status()); 300 // If we go down once and then back up we should not have any restrictions. 301 fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown()); 302 EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations); 303 fake_stream.ApplyAdaptation(adapter_.GetAdaptationUp()); 304 EXPECT_EQ(VideoSourceRestrictions(), adapter_.source_restrictions()); 305 EXPECT_EQ(0, adapter_.adaptation_counters().Total()); 306 } 307 308 TEST_F(VideoStreamAdapterTest, Balanced_DecreaseFrameRate) { 309 adapter_.SetDegradationPreference(DegradationPreference::BALANCED); 310 input_state_provider_.SetInputState(kBalancedMediumResolutionPixels, 311 kBalancedHighFrameRateFps, 312 kDefaultMinPixelsPerFrame); 313 // If our frame rate is higher than the frame rate associated with our 314 // resolution we should try to adapt to the frame rate associated with our 315 // resolution: kBalancedMediumFrameRateFps. 316 Adaptation adaptation = adapter_.GetAdaptationDown(); 317 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); 318 adapter_.ApplyAdaptation(adaptation, nullptr); 319 EXPECT_EQ(std::nullopt, 320 adapter_.source_restrictions().max_pixels_per_frame()); 321 EXPECT_EQ(std::nullopt, 322 adapter_.source_restrictions().target_pixels_per_frame()); 323 EXPECT_EQ(static_cast<double>(kBalancedMediumFrameRateFps), 324 adapter_.source_restrictions().max_frame_rate()); 325 EXPECT_EQ(0, adapter_.adaptation_counters().resolution_adaptations); 326 EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations); 327 } 328 329 TEST_F(VideoStreamAdapterTest, Balanced_DecreaseResolution) { 330 adapter_.SetDegradationPreference(DegradationPreference::BALANCED); 331 FakeVideoStream fake_stream( 332 &adapter_, &input_state_provider_, kBalancedHighResolutionPixels, 333 kBalancedHighFrameRateFps, kDefaultMinPixelsPerFrame); 334 // If we are not below the current resolution's frame rate limit, we should 335 // adapt resolution according to "maintain-framerate" logic (three fifths). 336 // 337 // However, since we are unlimited at the start and input frame rate is not 338 // below kBalancedHighFrameRateFps, we first restrict the frame rate to 339 // kBalancedHighFrameRateFps even though that is our current frame rate. This 340 // does prevent the source from going higher, though, so it's technically not 341 // a NO-OP. 342 { 343 Adaptation adaptation = adapter_.GetAdaptationDown(); 344 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); 345 fake_stream.ApplyAdaptation(adaptation); 346 } 347 EXPECT_EQ(std::nullopt, 348 adapter_.source_restrictions().max_pixels_per_frame()); 349 EXPECT_EQ(std::nullopt, 350 adapter_.source_restrictions().target_pixels_per_frame()); 351 EXPECT_EQ(static_cast<double>(kBalancedHighFrameRateFps), 352 adapter_.source_restrictions().max_frame_rate()); 353 EXPECT_EQ(0, adapter_.adaptation_counters().resolution_adaptations); 354 EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations); 355 // Verify "maintain-framerate" logic the second time we adapt: Frame rate 356 // restrictions remains the same and resolution goes down. 357 { 358 Adaptation adaptation = adapter_.GetAdaptationDown(); 359 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); 360 fake_stream.ApplyAdaptation(adaptation); 361 } 362 constexpr size_t kReducedPixelsFirstStep = 363 static_cast<size_t>((kBalancedHighResolutionPixels * 3) / 5); 364 EXPECT_EQ(kReducedPixelsFirstStep, 365 adapter_.source_restrictions().max_pixels_per_frame()); 366 EXPECT_EQ(std::nullopt, 367 adapter_.source_restrictions().target_pixels_per_frame()); 368 EXPECT_EQ(static_cast<double>(kBalancedHighFrameRateFps), 369 adapter_.source_restrictions().max_frame_rate()); 370 EXPECT_EQ(1, adapter_.adaptation_counters().resolution_adaptations); 371 EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations); 372 // If we adapt again, because the balanced settings' proposed frame rate is 373 // still kBalancedHighFrameRateFps, "maintain-framerate" will trigger again. 374 static_assert(kReducedPixelsFirstStep > kBalancedMediumResolutionPixels, 375 "The reduced resolution is still greater than the next lower " 376 "balanced setting resolution"); 377 constexpr size_t kReducedPixelsSecondStep = (kReducedPixelsFirstStep * 3) / 5; 378 { 379 Adaptation adaptation = adapter_.GetAdaptationDown(); 380 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); 381 fake_stream.ApplyAdaptation(adaptation); 382 } 383 EXPECT_EQ(kReducedPixelsSecondStep, 384 adapter_.source_restrictions().max_pixels_per_frame()); 385 EXPECT_EQ(std::nullopt, 386 adapter_.source_restrictions().target_pixels_per_frame()); 387 EXPECT_EQ(static_cast<double>(kBalancedHighFrameRateFps), 388 adapter_.source_restrictions().max_frame_rate()); 389 EXPECT_EQ(2, adapter_.adaptation_counters().resolution_adaptations); 390 EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations); 391 } 392 393 // Testing when to adapt frame rate and when to adapt resolution is quite 394 // entangled, so this test covers both cases. 395 // 396 // There is an asymmetry: When we adapt down we do it in one order, but when we 397 // adapt up we don't do it in the reverse order. Instead we always try to adapt 398 // frame rate first according to balanced settings' configs and only when the 399 // frame rate is already achieved do we adjust the resolution. 400 TEST_F(VideoStreamAdapterTest, Balanced_IncreaseFrameRateAndResolution) { 401 adapter_.SetDegradationPreference(DegradationPreference::BALANCED); 402 FakeVideoStream fake_stream( 403 &adapter_, &input_state_provider_, kBalancedHighResolutionPixels, 404 kBalancedHighFrameRateFps, kDefaultMinPixelsPerFrame); 405 // The desired starting point of this test is having adapted frame rate twice. 406 // This requires performing a number of adaptations. 407 constexpr size_t kReducedPixelsFirstStep = 408 static_cast<size_t>((kBalancedHighResolutionPixels * 3) / 5); 409 constexpr size_t kReducedPixelsSecondStep = (kReducedPixelsFirstStep * 3) / 5; 410 constexpr size_t kReducedPixelsThirdStep = (kReducedPixelsSecondStep * 3) / 5; 411 static_assert(kReducedPixelsFirstStep > kBalancedMediumResolutionPixels, 412 "The first pixel reduction is greater than the balanced " 413 "settings' medium pixel configuration"); 414 static_assert(kReducedPixelsSecondStep > kBalancedMediumResolutionPixels, 415 "The second pixel reduction is greater than the balanced " 416 "settings' medium pixel configuration"); 417 static_assert(kReducedPixelsThirdStep <= kBalancedMediumResolutionPixels, 418 "The third pixel reduction is NOT greater than the balanced " 419 "settings' medium pixel configuration"); 420 // The first adaptation should affect the frame rate: See 421 // Balanced_DecreaseResolution for explanation why. 422 fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown()); 423 EXPECT_EQ(static_cast<double>(kBalancedHighFrameRateFps), 424 adapter_.source_restrictions().max_frame_rate()); 425 // The next three adaptations affects the resolution, because we have to reach 426 // kBalancedMediumResolutionPixels before a lower frame rate is considered by 427 // BalancedDegradationSettings. The number three is derived from the 428 // static_asserts above. 429 fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown()); 430 EXPECT_EQ(kReducedPixelsFirstStep, 431 adapter_.source_restrictions().max_pixels_per_frame()); 432 fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown()); 433 EXPECT_EQ(kReducedPixelsSecondStep, 434 adapter_.source_restrictions().max_pixels_per_frame()); 435 fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown()); 436 EXPECT_EQ(kReducedPixelsThirdStep, 437 adapter_.source_restrictions().max_pixels_per_frame()); 438 // Thus, the next adaptation will reduce frame rate to 439 // kBalancedMediumFrameRateFps. 440 fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown()); 441 EXPECT_EQ(static_cast<double>(kBalancedMediumFrameRateFps), 442 adapter_.source_restrictions().max_frame_rate()); 443 EXPECT_EQ(3, adapter_.adaptation_counters().resolution_adaptations); 444 EXPECT_EQ(2, adapter_.adaptation_counters().fps_adaptations); 445 // Adapt up! 446 // While our resolution is in the medium-range, the frame rate associated with 447 // the next resolution configuration up ("high") is kBalancedHighFrameRateFps 448 // and "balanced" prefers adapting frame rate if not already applied. 449 { 450 Adaptation adaptation = adapter_.GetAdaptationUp(); 451 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); 452 fake_stream.ApplyAdaptation(adaptation); 453 EXPECT_EQ(static_cast<double>(kBalancedHighFrameRateFps), 454 adapter_.source_restrictions().max_frame_rate()); 455 EXPECT_EQ(3, adapter_.adaptation_counters().resolution_adaptations); 456 EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations); 457 } 458 // Now that we have already achieved the next frame rate up, we act according 459 // to "maintain-framerate". We go back up in resolution. Due to rounding 460 // errors we don't end up back at kReducedPixelsSecondStep. Rather we get to 461 // kReducedPixelsSecondStepUp, which is off by one compared to 462 // kReducedPixelsSecondStep. 463 constexpr size_t kReducedPixelsSecondStepUp = 464 (kReducedPixelsThirdStep * 5) / 3; 465 { 466 Adaptation adaptation = adapter_.GetAdaptationUp(); 467 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); 468 fake_stream.ApplyAdaptation(adaptation); 469 EXPECT_EQ(kReducedPixelsSecondStepUp, 470 adapter_.source_restrictions().target_pixels_per_frame()); 471 EXPECT_EQ(2, adapter_.adaptation_counters().resolution_adaptations); 472 EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations); 473 } 474 // Now that our resolution is back in the high-range, the next frame rate to 475 // try out is "unlimited". 476 { 477 Adaptation adaptation = adapter_.GetAdaptationUp(); 478 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); 479 fake_stream.ApplyAdaptation(adaptation); 480 EXPECT_EQ(std::nullopt, adapter_.source_restrictions().max_frame_rate()); 481 EXPECT_EQ(2, adapter_.adaptation_counters().resolution_adaptations); 482 EXPECT_EQ(0, adapter_.adaptation_counters().fps_adaptations); 483 } 484 // Now only adapting resolution remains. 485 constexpr size_t kReducedPixelsFirstStepUp = 486 (kReducedPixelsSecondStepUp * 5) / 3; 487 { 488 Adaptation adaptation = adapter_.GetAdaptationUp(); 489 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); 490 fake_stream.ApplyAdaptation(adaptation); 491 EXPECT_EQ(kReducedPixelsFirstStepUp, 492 adapter_.source_restrictions().target_pixels_per_frame()); 493 EXPECT_EQ(1, adapter_.adaptation_counters().resolution_adaptations); 494 EXPECT_EQ(0, adapter_.adaptation_counters().fps_adaptations); 495 } 496 // The last step up should make us entirely unrestricted. 497 { 498 Adaptation adaptation = adapter_.GetAdaptationUp(); 499 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); 500 fake_stream.ApplyAdaptation(adaptation); 501 EXPECT_EQ(VideoSourceRestrictions(), adapter_.source_restrictions()); 502 EXPECT_EQ(0, adapter_.adaptation_counters().Total()); 503 } 504 } 505 506 TEST_F(VideoStreamAdapterTest, Balanced_LimitReached) { 507 adapter_.SetDegradationPreference(DegradationPreference::BALANCED); 508 FakeVideoStream fake_stream( 509 &adapter_, &input_state_provider_, kBalancedLowResolutionPixels, 510 kBalancedLowFrameRateFps, kDefaultMinPixelsPerFrame); 511 // Attempting to adapt up while unrestricted should result in kLimitReached. 512 EXPECT_EQ(Adaptation::Status::kLimitReached, 513 adapter_.GetAdaptationUp().status()); 514 // Adapting down once result in restricted frame rate, in this case we reach 515 // the lowest possible frame rate immediately: kBalancedLowFrameRateFps. 516 EXPECT_CALL(encoder_stats_observer_, OnMinPixelLimitReached()).Times(2); 517 fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown()); 518 EXPECT_EQ(static_cast<double>(kBalancedLowFrameRateFps), 519 adapter_.source_restrictions().max_frame_rate()); 520 EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations); 521 // Any further adaptation must follow "maintain-framerate" rules (these are 522 // covered in more depth by the MaintainFramerate tests). This test does not 523 // assert exactly how resolution is adjusted, only that resolution always 524 // decreases and that we eventually reach kLimitReached. 525 size_t previous_resolution = kBalancedLowResolutionPixels; 526 bool did_reach_limit = false; 527 // If we have not reached the limit within 5 adaptations something is wrong... 528 for (int i = 0; i < 5; i++) { 529 Adaptation adaptation = adapter_.GetAdaptationDown(); 530 if (adaptation.status() == Adaptation::Status::kLimitReached) { 531 did_reach_limit = true; 532 break; 533 } 534 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); 535 fake_stream.ApplyAdaptation(adaptation); 536 EXPECT_LT(adapter_.source_restrictions().max_pixels_per_frame().value(), 537 previous_resolution); 538 previous_resolution = 539 adapter_.source_restrictions().max_pixels_per_frame().value(); 540 } 541 EXPECT_TRUE(did_reach_limit); 542 // Frame rate restrictions are the same as before. 543 EXPECT_EQ(static_cast<double>(kBalancedLowFrameRateFps), 544 adapter_.source_restrictions().max_frame_rate()); 545 EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations); 546 } 547 548 // kAwaitingPreviousAdaptation is only supported in "maintain-framerate". 549 TEST_F(VideoStreamAdapterTest, 550 MaintainFramerate_AwaitingPreviousAdaptationDown) { 551 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); 552 input_state_provider_.SetInputState(1280 * 720, 30, 553 kDefaultMinPixelsPerFrame); 554 // Adapt down once, but don't update the input. 555 adapter_.ApplyAdaptation(adapter_.GetAdaptationDown(), nullptr); 556 EXPECT_EQ(1, adapter_.adaptation_counters().resolution_adaptations); 557 { 558 // Having performed the adaptation, but not updated the input based on the 559 // new restrictions, adapting again in the same direction will not work. 560 Adaptation adaptation = adapter_.GetAdaptationDown(); 561 EXPECT_EQ(Adaptation::Status::kAwaitingPreviousAdaptation, 562 adaptation.status()); 563 } 564 } 565 566 // kAwaitingPreviousAdaptation is only supported in "maintain-framerate". 567 TEST_F(VideoStreamAdapterTest, MaintainFramerate_AwaitingPreviousAdaptationUp) { 568 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); 569 FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30, 570 kDefaultMinPixelsPerFrame); 571 // Perform two adaptation down so that adapting up twice is possible. 572 fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown()); 573 fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown()); 574 EXPECT_EQ(2, adapter_.adaptation_counters().resolution_adaptations); 575 // Adapt up once, but don't update the input. 576 adapter_.ApplyAdaptation(adapter_.GetAdaptationUp(), nullptr); 577 EXPECT_EQ(1, adapter_.adaptation_counters().resolution_adaptations); 578 { 579 // Having performed the adaptation, but not updated the input based on the 580 // new restrictions, adapting again in the same direction will not work. 581 Adaptation adaptation = adapter_.GetAdaptationUp(); 582 EXPECT_EQ(Adaptation::Status::kAwaitingPreviousAdaptation, 583 adaptation.status()); 584 } 585 } 586 587 TEST_F(VideoStreamAdapterTest, 588 MaintainResolution_AdaptsUpAfterSwitchingDegradationPreference) { 589 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION); 590 FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30, 591 kDefaultMinPixelsPerFrame); 592 // Adapt down in fps for later. 593 fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown()); 594 EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations); 595 596 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); 597 fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown()); 598 fake_stream.ApplyAdaptation(adapter_.GetAdaptationUp()); 599 EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations); 600 EXPECT_EQ(0, adapter_.adaptation_counters().resolution_adaptations); 601 602 // We should be able to adapt in framerate one last time after the change of 603 // degradation preference. 604 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION); 605 Adaptation adaptation = adapter_.GetAdaptationUp(); 606 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); 607 fake_stream.ApplyAdaptation(adapter_.GetAdaptationUp()); 608 EXPECT_EQ(0, adapter_.adaptation_counters().fps_adaptations); 609 } 610 611 TEST_F(VideoStreamAdapterTest, 612 MaintainFramerate_AdaptsUpAfterSwitchingDegradationPreference) { 613 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); 614 FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30, 615 kDefaultMinPixelsPerFrame); 616 // Adapt down in resolution for later. 617 fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown()); 618 EXPECT_EQ(1, adapter_.adaptation_counters().resolution_adaptations); 619 620 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION); 621 fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown()); 622 fake_stream.ApplyAdaptation(adapter_.GetAdaptationUp()); 623 EXPECT_EQ(1, adapter_.adaptation_counters().resolution_adaptations); 624 EXPECT_EQ(0, adapter_.adaptation_counters().fps_adaptations); 625 626 // We should be able to adapt in framerate one last time after the change of 627 // degradation preference. 628 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); 629 Adaptation adaptation = adapter_.GetAdaptationUp(); 630 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); 631 fake_stream.ApplyAdaptation(adapter_.GetAdaptationUp()); 632 EXPECT_EQ(0, adapter_.adaptation_counters().resolution_adaptations); 633 } 634 635 TEST_F(VideoStreamAdapterTest, 636 PendingResolutionIncreaseAllowsAdaptUpAfterSwitchToMaintainResolution) { 637 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION); 638 FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30, 639 kDefaultMinPixelsPerFrame); 640 // Adapt fps down so we can adapt up later in the test. 641 fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown()); 642 643 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); 644 fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown()); 645 // Apply adaptation up but don't update input. 646 adapter_.ApplyAdaptation(adapter_.GetAdaptationUp(), nullptr); 647 EXPECT_EQ(Adaptation::Status::kAwaitingPreviousAdaptation, 648 adapter_.GetAdaptationUp().status()); 649 650 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION); 651 Adaptation adaptation = adapter_.GetAdaptationUp(); 652 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); 653 } 654 655 TEST_F(VideoStreamAdapterTest, 656 MaintainFramerate_AdaptsDownAfterSwitchingDegradationPreference) { 657 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION); 658 FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30, 659 kDefaultMinPixelsPerFrame); 660 // Adapt down once, should change FPS. 661 fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown()); 662 EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations); 663 664 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); 665 // Adaptation down should apply after the degradation prefs change. 666 Adaptation adaptation = adapter_.GetAdaptationDown(); 667 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); 668 fake_stream.ApplyAdaptation(adaptation); 669 EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations); 670 EXPECT_EQ(1, adapter_.adaptation_counters().resolution_adaptations); 671 } 672 673 TEST_F(VideoStreamAdapterTest, 674 MaintainResolution_AdaptsDownAfterSwitchingDegradationPreference) { 675 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); 676 FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30, 677 kDefaultMinPixelsPerFrame); 678 // Adapt down once, should change FPS. 679 fake_stream.ApplyAdaptation(adapter_.GetAdaptationDown()); 680 EXPECT_EQ(1, adapter_.adaptation_counters().resolution_adaptations); 681 682 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION); 683 Adaptation adaptation = adapter_.GetAdaptationDown(); 684 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); 685 fake_stream.ApplyAdaptation(adaptation); 686 687 EXPECT_EQ(1, adapter_.adaptation_counters().fps_adaptations); 688 EXPECT_EQ(1, adapter_.adaptation_counters().resolution_adaptations); 689 } 690 691 TEST_F( 692 VideoStreamAdapterTest, 693 PendingResolutionDecreaseAllowsAdaptDownAfterSwitchToMaintainResolution) { 694 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); 695 FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30, 696 kDefaultMinPixelsPerFrame); 697 // Apply adaptation but don't update the input. 698 adapter_.ApplyAdaptation(adapter_.GetAdaptationDown(), nullptr); 699 EXPECT_EQ(Adaptation::Status::kAwaitingPreviousAdaptation, 700 adapter_.GetAdaptationDown().status()); 701 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION); 702 Adaptation adaptation = adapter_.GetAdaptationDown(); 703 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); 704 } 705 706 TEST_F(VideoStreamAdapterTest, RestrictionBroadcasted) { 707 FakeVideoStreamAdapterListner listener; 708 adapter_.AddRestrictionsListener(&listener); 709 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); 710 FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30, 711 kDefaultMinPixelsPerFrame); 712 // Not broadcast on invalid ApplyAdaptation. 713 { 714 Adaptation adaptation = adapter_.GetAdaptationUp(); 715 adapter_.ApplyAdaptation(adaptation, nullptr); 716 EXPECT_EQ(0, listener.calls()); 717 } 718 719 // Broadcast on ApplyAdaptation. 720 { 721 Adaptation adaptation = adapter_.GetAdaptationDown(); 722 fake_stream.ApplyAdaptation(adaptation); 723 EXPECT_EQ(1, listener.calls()); 724 EXPECT_EQ(adaptation.restrictions(), listener.last_restrictions()); 725 } 726 727 // Broadcast on ClearRestrictions(). 728 adapter_.ClearRestrictions(); 729 EXPECT_EQ(2, listener.calls()); 730 EXPECT_EQ(VideoSourceRestrictions(), listener.last_restrictions()); 731 } 732 733 TEST_F(VideoStreamAdapterTest, AdaptationHasNextRestrcitions) { 734 // Any non-disabled DegradationPreference will do. 735 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); 736 FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30, 737 kDefaultMinPixelsPerFrame); 738 // When adaptation is not possible. 739 { 740 Adaptation adaptation = adapter_.GetAdaptationUp(); 741 EXPECT_EQ(Adaptation::Status::kLimitReached, adaptation.status()); 742 EXPECT_EQ(adaptation.restrictions(), adapter_.source_restrictions()); 743 EXPECT_EQ(0, adaptation.counters().Total()); 744 } 745 // When we adapt down. 746 { 747 Adaptation adaptation = adapter_.GetAdaptationDown(); 748 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); 749 fake_stream.ApplyAdaptation(adaptation); 750 EXPECT_EQ(adaptation.restrictions(), adapter_.source_restrictions()); 751 EXPECT_EQ(adaptation.counters(), adapter_.adaptation_counters()); 752 } 753 // When we adapt up. 754 { 755 Adaptation adaptation = adapter_.GetAdaptationUp(); 756 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); 757 fake_stream.ApplyAdaptation(adaptation); 758 EXPECT_EQ(adaptation.restrictions(), adapter_.source_restrictions()); 759 EXPECT_EQ(adaptation.counters(), adapter_.adaptation_counters()); 760 } 761 } 762 763 TEST_F(VideoStreamAdapterTest, 764 SetDegradationPreferenceToOrFromBalancedClearsRestrictions) { 765 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); 766 input_state_provider_.SetInputState(1280 * 720, 30, 767 kDefaultMinPixelsPerFrame); 768 adapter_.ApplyAdaptation(adapter_.GetAdaptationDown(), nullptr); 769 EXPECT_NE(VideoSourceRestrictions(), adapter_.source_restrictions()); 770 EXPECT_NE(0, adapter_.adaptation_counters().Total()); 771 // Changing from non-balanced to balanced clears the restrictions. 772 adapter_.SetDegradationPreference(DegradationPreference::BALANCED); 773 EXPECT_EQ(VideoSourceRestrictions(), adapter_.source_restrictions()); 774 EXPECT_EQ(0, adapter_.adaptation_counters().Total()); 775 // Apply adaptation again. 776 adapter_.ApplyAdaptation(adapter_.GetAdaptationDown(), nullptr); 777 EXPECT_NE(VideoSourceRestrictions(), adapter_.source_restrictions()); 778 EXPECT_NE(0, adapter_.adaptation_counters().Total()); 779 // Changing from balanced to non-balanced clears the restrictions. 780 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION); 781 EXPECT_EQ(VideoSourceRestrictions(), adapter_.source_restrictions()); 782 EXPECT_EQ(0, adapter_.adaptation_counters().Total()); 783 } 784 785 TEST_F(VideoStreamAdapterTest, 786 GetAdaptDownResolutionAdaptsResolutionInMaintainFramerate) { 787 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); 788 input_state_provider_.SetInputState(1280 * 720, 30, 789 kDefaultMinPixelsPerFrame); 790 791 auto adaptation = adapter_.GetAdaptDownResolution(); 792 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); 793 EXPECT_EQ(1, adaptation.counters().resolution_adaptations); 794 EXPECT_EQ(0, adaptation.counters().fps_adaptations); 795 } 796 797 TEST_F(VideoStreamAdapterTest, 798 GetAdaptDownResolutionReturnsWithStatusInDisabledAndMaintainResolution) { 799 adapter_.SetDegradationPreference(DegradationPreference::DISABLED); 800 input_state_provider_.SetInputState(1280 * 720, 30, 801 kDefaultMinPixelsPerFrame); 802 EXPECT_EQ(Adaptation::Status::kAdaptationDisabled, 803 adapter_.GetAdaptDownResolution().status()); 804 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION); 805 EXPECT_EQ(Adaptation::Status::kLimitReached, 806 adapter_.GetAdaptDownResolution().status()); 807 } 808 809 TEST_F(VideoStreamAdapterTest, 810 GetAdaptDownResolutionAdaptsFpsAndResolutionInBalanced) { 811 // Note: This test depends on BALANCED implementation, but with current 812 // implementation and input state settings, BALANCED will adapt resolution and 813 // frame rate once. 814 adapter_.SetDegradationPreference(DegradationPreference::BALANCED); 815 input_state_provider_.SetInputState(1280 * 720, 30, 816 kDefaultMinPixelsPerFrame); 817 818 auto adaptation = adapter_.GetAdaptDownResolution(); 819 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); 820 EXPECT_EQ(1, adaptation.counters().resolution_adaptations); 821 EXPECT_EQ(1, adaptation.counters().fps_adaptations); 822 } 823 824 TEST_F( 825 VideoStreamAdapterTest, 826 GetAdaptDownResolutionAdaptsOnlyResolutionIfFpsAlreadyAdapterInBalanced) { 827 // Note: This test depends on BALANCED implementation, but with current 828 // implementation and input state settings, BALANCED will adapt resolution 829 // only. 830 adapter_.SetDegradationPreference(DegradationPreference::BALANCED); 831 input_state_provider_.SetInputState(1280 * 720, 5, kDefaultMinPixelsPerFrame); 832 FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30, 833 kDefaultMinPixelsPerFrame); 834 835 auto first_adaptation = adapter_.GetAdaptationDown(); 836 fake_stream.ApplyAdaptation(first_adaptation); 837 838 auto adaptation = adapter_.GetAdaptDownResolution(); 839 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); 840 EXPECT_EQ(1, adaptation.counters().resolution_adaptations); 841 EXPECT_EQ(first_adaptation.counters().fps_adaptations, 842 adaptation.counters().fps_adaptations); 843 } 844 845 TEST_F(VideoStreamAdapterTest, 846 GetAdaptDownResolutionAdaptsOnlyFpsIfResolutionLowInBalanced) { 847 // Note: This test depends on BALANCED implementation, but with current 848 // implementation and input state settings, BALANCED will adapt resolution 849 // only. 850 adapter_.SetDegradationPreference(DegradationPreference::BALANCED); 851 input_state_provider_.SetInputState(kDefaultMinPixelsPerFrame, 30, 852 kDefaultMinPixelsPerFrame); 853 854 auto adaptation = adapter_.GetAdaptDownResolution(); 855 EXPECT_EQ(Adaptation::Status::kValid, adaptation.status()); 856 EXPECT_EQ(0, adaptation.counters().resolution_adaptations); 857 EXPECT_EQ(1, adaptation.counters().fps_adaptations); 858 } 859 860 TEST_F(VideoStreamAdapterTest, 861 AdaptationDisabledStatusAlwaysWhenDegradationPreferenceDisabled) { 862 adapter_.SetDegradationPreference(DegradationPreference::DISABLED); 863 input_state_provider_.SetInputState(1280 * 720, 30, 864 kDefaultMinPixelsPerFrame); 865 EXPECT_EQ(Adaptation::Status::kAdaptationDisabled, 866 adapter_.GetAdaptationDown().status()); 867 EXPECT_EQ(Adaptation::Status::kAdaptationDisabled, 868 adapter_.GetAdaptationUp().status()); 869 EXPECT_EQ(Adaptation::Status::kAdaptationDisabled, 870 adapter_.GetAdaptDownResolution().status()); 871 } 872 873 TEST_F(VideoStreamAdapterTest, AdaptationConstraintAllowsAdaptationsUp) { 874 testing::StrictMock<MockAdaptationConstraint> adaptation_constraint; 875 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); 876 adapter_.AddAdaptationConstraint(&adaptation_constraint); 877 input_state_provider_.SetInputState(1280 * 720, 30, 878 kDefaultMinPixelsPerFrame); 879 FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30, 880 kDefaultMinPixelsPerFrame); 881 // Adapt down once so we can adapt up later. 882 auto first_adaptation = adapter_.GetAdaptationDown(); 883 fake_stream.ApplyAdaptation(first_adaptation); 884 885 EXPECT_CALL(adaptation_constraint, 886 IsAdaptationUpAllowed(_, first_adaptation.restrictions(), _)) 887 .WillOnce(Return(true)); 888 EXPECT_EQ(Adaptation::Status::kValid, adapter_.GetAdaptationUp().status()); 889 adapter_.RemoveAdaptationConstraint(&adaptation_constraint); 890 } 891 892 TEST_F(VideoStreamAdapterTest, AdaptationConstraintDisallowsAdaptationsUp) { 893 testing::StrictMock<MockAdaptationConstraint> adaptation_constraint; 894 adapter_.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); 895 adapter_.AddAdaptationConstraint(&adaptation_constraint); 896 input_state_provider_.SetInputState(1280 * 720, 30, 897 kDefaultMinPixelsPerFrame); 898 FakeVideoStream fake_stream(&adapter_, &input_state_provider_, 1280 * 720, 30, 899 kDefaultMinPixelsPerFrame); 900 // Adapt down once so we can adapt up later. 901 auto first_adaptation = adapter_.GetAdaptationDown(); 902 fake_stream.ApplyAdaptation(first_adaptation); 903 904 EXPECT_CALL(adaptation_constraint, 905 IsAdaptationUpAllowed(_, first_adaptation.restrictions(), _)) 906 .WillOnce(Return(false)); 907 EXPECT_EQ(Adaptation::Status::kRejectedByConstraint, 908 adapter_.GetAdaptationUp().status()); 909 adapter_.RemoveAdaptationConstraint(&adaptation_constraint); 910 } 911 912 // Death tests. 913 // Disabled on Android because death tests misbehave on Android, see 914 // base/test/gtest_util.h. 915 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) 916 917 TEST(VideoStreamAdapterDeathTest, 918 SetDegradationPreferenceInvalidatesAdaptations) { 919 FakeVideoStreamInputStateProvider input_state_provider; 920 testing::StrictMock<MockVideoStreamEncoderObserver> encoder_stats_observer_; 921 VideoStreamAdapter adapter(&input_state_provider, &encoder_stats_observer_, 922 CreateTestFieldTrials()); 923 adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE); 924 input_state_provider.SetInputState(1280 * 720, 30, kDefaultMinPixelsPerFrame); 925 Adaptation adaptation = adapter.GetAdaptationDown(); 926 adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION); 927 EXPECT_DEATH(adapter.ApplyAdaptation(adaptation, nullptr), ""); 928 } 929 930 TEST(VideoStreamAdapterDeathTest, AdaptDownInvalidatesAdaptations) { 931 FakeVideoStreamInputStateProvider input_state_provider; 932 testing::StrictMock<MockVideoStreamEncoderObserver> encoder_stats_observer_; 933 VideoStreamAdapter adapter(&input_state_provider, &encoder_stats_observer_, 934 CreateTestFieldTrials()); 935 adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION); 936 input_state_provider.SetInputState(1280 * 720, 30, kDefaultMinPixelsPerFrame); 937 Adaptation adaptation = adapter.GetAdaptationDown(); 938 adapter.GetAdaptationDown(); 939 EXPECT_DEATH(adapter.ApplyAdaptation(adaptation, nullptr), ""); 940 } 941 942 #endif // RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) 943 944 } // namespace webrtc