tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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