tor-browser

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

resource_adaptation_processor_unittest.cc (32915B)


      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/resource_adaptation_processor.h"
     12 
     13 #include <cstddef>
     14 #include <memory>
     15 
     16 #include "api/adaptation/resource.h"
     17 #include "api/rtp_parameters.h"
     18 #include "api/scoped_refptr.h"
     19 #include "api/sequence_checker.h"
     20 #include "api/test/rtc_error_matchers.h"
     21 #include "api/units/time_delta.h"
     22 #include "api/video/video_adaptation_counters.h"
     23 #include "call/adaptation/test/fake_frame_rate_provider.h"
     24 #include "call/adaptation/test/fake_resource.h"
     25 #include "call/adaptation/video_source_restrictions.h"
     26 #include "call/adaptation/video_stream_adapter.h"
     27 #include "call/adaptation/video_stream_input_state_provider.h"
     28 #include "rtc_base/event.h"
     29 #include "rtc_base/task_queue_for_test.h"
     30 #include "rtc_base/thread.h"
     31 #include "rtc_base/thread_annotations.h"
     32 #include "test/create_test_field_trials.h"
     33 #include "test/gmock.h"
     34 #include "test/gtest.h"
     35 #include "test/wait_until.h"
     36 
     37 namespace webrtc {
     38 
     39 namespace {
     40 
     41 using ::testing::Eq;
     42 
     43 constexpr int kDefaultFrameRate = 30;
     44 constexpr int kDefaultFrameSize = 1280 * 720;
     45 constexpr TimeDelta kDefaultTimeout = TimeDelta::Seconds(5);
     46 
     47 class VideoSourceRestrictionsListenerForTesting
     48    : public VideoSourceRestrictionsListener {
     49 public:
     50  VideoSourceRestrictionsListenerForTesting()
     51      : restrictions_updated_count_(0),
     52        restrictions_(),
     53        adaptation_counters_(),
     54        reason_(nullptr) {}
     55  ~VideoSourceRestrictionsListenerForTesting() override {}
     56 
     57  size_t restrictions_updated_count() const {
     58    RTC_DCHECK_RUN_ON(&sequence_checker_);
     59    return restrictions_updated_count_;
     60  }
     61  VideoSourceRestrictions restrictions() const {
     62    RTC_DCHECK_RUN_ON(&sequence_checker_);
     63    return restrictions_;
     64  }
     65  VideoAdaptationCounters adaptation_counters() const {
     66    RTC_DCHECK_RUN_ON(&sequence_checker_);
     67    return adaptation_counters_;
     68  }
     69  scoped_refptr<Resource> reason() const {
     70    RTC_DCHECK_RUN_ON(&sequence_checker_);
     71    return reason_;
     72  }
     73 
     74  // VideoSourceRestrictionsListener implementation.
     75  void OnVideoSourceRestrictionsUpdated(
     76      VideoSourceRestrictions restrictions,
     77      const VideoAdaptationCounters& adaptation_counters,
     78      scoped_refptr<Resource> reason,
     79      const VideoSourceRestrictions& /* unfiltered_restrictions */) override {
     80    RTC_DCHECK_RUN_ON(&sequence_checker_);
     81    ++restrictions_updated_count_;
     82    restrictions_ = restrictions;
     83    adaptation_counters_ = adaptation_counters;
     84    reason_ = reason;
     85  }
     86 
     87 private:
     88  SequenceChecker sequence_checker_;
     89  size_t restrictions_updated_count_ RTC_GUARDED_BY(&sequence_checker_);
     90  VideoSourceRestrictions restrictions_ RTC_GUARDED_BY(&sequence_checker_);
     91  VideoAdaptationCounters adaptation_counters_
     92      RTC_GUARDED_BY(&sequence_checker_);
     93  scoped_refptr<Resource> reason_ RTC_GUARDED_BY(&sequence_checker_);
     94 };
     95 
     96 class ResourceAdaptationProcessorTest : public ::testing::Test {
     97 public:
     98  ResourceAdaptationProcessorTest()
     99      : frame_rate_provider_(),
    100        input_state_provider_(&frame_rate_provider_),
    101        resource_(FakeResource::Create("FakeResource")),
    102        other_resource_(FakeResource::Create("OtherFakeResource")),
    103        video_stream_adapter_(
    104            std::make_unique<VideoStreamAdapter>(&input_state_provider_,
    105                                                 &frame_rate_provider_,
    106                                                 CreateTestFieldTrials())),
    107        processor_(std::make_unique<ResourceAdaptationProcessor>(
    108            video_stream_adapter_.get())) {
    109    video_stream_adapter_->AddRestrictionsListener(&restrictions_listener_);
    110    processor_->AddResource(resource_);
    111    processor_->AddResource(other_resource_);
    112  }
    113  ~ResourceAdaptationProcessorTest() override {
    114    if (processor_) {
    115      DestroyProcessor();
    116    }
    117  }
    118 
    119  void SetInputStates(bool has_input, int fps, int frame_size) {
    120    input_state_provider_.OnHasInputChanged(has_input);
    121    frame_rate_provider_.set_fps(fps);
    122    input_state_provider_.OnFrameSizeObserved(frame_size);
    123  }
    124 
    125  void RestrictSource(VideoSourceRestrictions restrictions) {
    126    SetInputStates(
    127        true, restrictions.max_frame_rate().value_or(kDefaultFrameRate),
    128        restrictions.target_pixels_per_frame().has_value()
    129            ? restrictions.target_pixels_per_frame().value()
    130            : restrictions.max_pixels_per_frame().value_or(kDefaultFrameSize));
    131  }
    132 
    133  void DestroyProcessor() {
    134    if (resource_) {
    135      processor_->RemoveResource(resource_);
    136    }
    137    if (other_resource_) {
    138      processor_->RemoveResource(other_resource_);
    139    }
    140    video_stream_adapter_->RemoveRestrictionsListener(&restrictions_listener_);
    141    processor_.reset();
    142  }
    143 
    144  static void WaitUntilTaskQueueIdle() {
    145    ASSERT_TRUE(Thread::Current()->ProcessMessages(0));
    146  }
    147 
    148 protected:
    149  AutoThread main_thread_;
    150  FakeFrameRateProvider frame_rate_provider_;
    151  VideoStreamInputStateProvider input_state_provider_;
    152  scoped_refptr<FakeResource> resource_;
    153  scoped_refptr<FakeResource> other_resource_;
    154  std::unique_ptr<VideoStreamAdapter> video_stream_adapter_;
    155  std::unique_ptr<ResourceAdaptationProcessor> processor_;
    156  VideoSourceRestrictionsListenerForTesting restrictions_listener_;
    157 };
    158 
    159 }  // namespace
    160 
    161 TEST_F(ResourceAdaptationProcessorTest, DisabledByDefault) {
    162  SetInputStates(true, kDefaultFrameRate, kDefaultFrameSize);
    163  // Adaptation does not happen when disabled.
    164  resource_->SetUsageState(ResourceUsageState::kOveruse);
    165  EXPECT_EQ(0u, restrictions_listener_.restrictions_updated_count());
    166 }
    167 
    168 TEST_F(ResourceAdaptationProcessorTest, InsufficientInput) {
    169  video_stream_adapter_->SetDegradationPreference(
    170      DegradationPreference::MAINTAIN_FRAMERATE);
    171  // Adaptation does not happen if input is insufficient.
    172  // When frame size is missing (OnFrameSizeObserved not called yet).
    173  input_state_provider_.OnHasInputChanged(true);
    174  resource_->SetUsageState(ResourceUsageState::kOveruse);
    175  EXPECT_EQ(0u, restrictions_listener_.restrictions_updated_count());
    176  // When "has input" is missing.
    177  SetInputStates(false, kDefaultFrameRate, kDefaultFrameSize);
    178  resource_->SetUsageState(ResourceUsageState::kOveruse);
    179  EXPECT_EQ(0u, restrictions_listener_.restrictions_updated_count());
    180  // Note: frame rate cannot be missing, if unset it is 0.
    181 }
    182 
    183 // These tests verify that restrictions are applied, but not exactly how much
    184 // the source is restricted. This ensures that the VideoStreamAdapter is wired
    185 // up correctly but not exactly how the VideoStreamAdapter generates
    186 // restrictions. For that, see video_stream_adapter_unittest.cc.
    187 TEST_F(ResourceAdaptationProcessorTest,
    188       OveruseTriggersRestrictingResolutionInMaintainFrameRate) {
    189  video_stream_adapter_->SetDegradationPreference(
    190      DegradationPreference::MAINTAIN_FRAMERATE);
    191  SetInputStates(true, kDefaultFrameRate, kDefaultFrameSize);
    192  resource_->SetUsageState(ResourceUsageState::kOveruse);
    193  EXPECT_EQ(1u, restrictions_listener_.restrictions_updated_count());
    194  EXPECT_TRUE(
    195      restrictions_listener_.restrictions().max_pixels_per_frame().has_value());
    196 }
    197 
    198 TEST_F(ResourceAdaptationProcessorTest,
    199       OveruseTriggersRestrictingFrameRateInMaintainResolution) {
    200  video_stream_adapter_->SetDegradationPreference(
    201      DegradationPreference::MAINTAIN_RESOLUTION);
    202  SetInputStates(true, kDefaultFrameRate, kDefaultFrameSize);
    203  resource_->SetUsageState(ResourceUsageState::kOveruse);
    204  EXPECT_EQ(1u, restrictions_listener_.restrictions_updated_count());
    205  EXPECT_TRUE(
    206      restrictions_listener_.restrictions().max_frame_rate().has_value());
    207 }
    208 
    209 TEST_F(ResourceAdaptationProcessorTest,
    210       OveruseTriggersRestrictingFrameRateAndResolutionInBalanced) {
    211  video_stream_adapter_->SetDegradationPreference(
    212      DegradationPreference::BALANCED);
    213  SetInputStates(true, kDefaultFrameRate, kDefaultFrameSize);
    214  // Adapting multiple times eventually resticts both frame rate and
    215  // resolution. Exactly many times we need to adapt depends on
    216  // BalancedDegradationSettings, VideoStreamAdapter and default input
    217  // states. This test requires it to be achieved within 4 adaptations.
    218  for (size_t i = 0; i < 4; ++i) {
    219    resource_->SetUsageState(ResourceUsageState::kOveruse);
    220    EXPECT_EQ(i + 1, restrictions_listener_.restrictions_updated_count());
    221    RestrictSource(restrictions_listener_.restrictions());
    222  }
    223  EXPECT_TRUE(
    224      restrictions_listener_.restrictions().max_pixels_per_frame().has_value());
    225  EXPECT_TRUE(
    226      restrictions_listener_.restrictions().max_frame_rate().has_value());
    227 }
    228 
    229 TEST_F(ResourceAdaptationProcessorTest, AwaitingPreviousAdaptation) {
    230  video_stream_adapter_->SetDegradationPreference(
    231      DegradationPreference::MAINTAIN_FRAMERATE);
    232  SetInputStates(true, kDefaultFrameRate, kDefaultFrameSize);
    233  resource_->SetUsageState(ResourceUsageState::kOveruse);
    234  EXPECT_EQ(1u, restrictions_listener_.restrictions_updated_count());
    235  // If we don't restrict the source then adaptation will not happen again
    236  // due to "awaiting previous adaptation". This prevents "double-adapt".
    237  resource_->SetUsageState(ResourceUsageState::kOveruse);
    238  EXPECT_EQ(1u, restrictions_listener_.restrictions_updated_count());
    239 }
    240 
    241 TEST_F(ResourceAdaptationProcessorTest, CannotAdaptUpWhenUnrestricted) {
    242  video_stream_adapter_->SetDegradationPreference(
    243      DegradationPreference::MAINTAIN_FRAMERATE);
    244  SetInputStates(true, kDefaultFrameRate, kDefaultFrameSize);
    245  resource_->SetUsageState(ResourceUsageState::kUnderuse);
    246  EXPECT_EQ(0u, restrictions_listener_.restrictions_updated_count());
    247 }
    248 
    249 TEST_F(ResourceAdaptationProcessorTest, UnderuseTakesUsBackToUnrestricted) {
    250  video_stream_adapter_->SetDegradationPreference(
    251      DegradationPreference::MAINTAIN_FRAMERATE);
    252  SetInputStates(true, kDefaultFrameRate, kDefaultFrameSize);
    253  resource_->SetUsageState(ResourceUsageState::kOveruse);
    254  EXPECT_EQ(1u, restrictions_listener_.restrictions_updated_count());
    255  RestrictSource(restrictions_listener_.restrictions());
    256  resource_->SetUsageState(ResourceUsageState::kUnderuse);
    257  EXPECT_EQ(2u, restrictions_listener_.restrictions_updated_count());
    258  EXPECT_EQ(VideoSourceRestrictions(), restrictions_listener_.restrictions());
    259 }
    260 
    261 TEST_F(ResourceAdaptationProcessorTest,
    262       ResourcesCanNotAdaptUpIfNeverAdaptedDown) {
    263  video_stream_adapter_->SetDegradationPreference(
    264      DegradationPreference::MAINTAIN_FRAMERATE);
    265  SetInputStates(true, kDefaultFrameRate, kDefaultFrameSize);
    266  resource_->SetUsageState(ResourceUsageState::kOveruse);
    267  EXPECT_EQ(1u, restrictions_listener_.restrictions_updated_count());
    268  RestrictSource(restrictions_listener_.restrictions());
    269 
    270  // Other resource signals under-use
    271  other_resource_->SetUsageState(ResourceUsageState::kUnderuse);
    272  EXPECT_EQ(1u, restrictions_listener_.restrictions_updated_count());
    273 }
    274 
    275 TEST_F(ResourceAdaptationProcessorTest,
    276       ResourcesCanNotAdaptUpIfNotAdaptedDownAfterReset) {
    277  video_stream_adapter_->SetDegradationPreference(
    278      DegradationPreference::MAINTAIN_FRAMERATE);
    279  SetInputStates(true, kDefaultFrameRate, kDefaultFrameSize);
    280  resource_->SetUsageState(ResourceUsageState::kOveruse);
    281  EXPECT_EQ(1u, restrictions_listener_.restrictions_updated_count());
    282 
    283  video_stream_adapter_->ClearRestrictions();
    284  EXPECT_EQ(0, restrictions_listener_.adaptation_counters().Total());
    285  other_resource_->SetUsageState(ResourceUsageState::kOveruse);
    286  EXPECT_EQ(1, restrictions_listener_.adaptation_counters().Total());
    287  RestrictSource(restrictions_listener_.restrictions());
    288 
    289  // resource_ did not overuse after we reset the restrictions, so adapt
    290  // up should be disallowed.
    291  resource_->SetUsageState(ResourceUsageState::kUnderuse);
    292  EXPECT_EQ(1, restrictions_listener_.adaptation_counters().Total());
    293 }
    294 
    295 TEST_F(ResourceAdaptationProcessorTest, OnlyMostLimitedResourceMayAdaptUp) {
    296  video_stream_adapter_->SetDegradationPreference(
    297      DegradationPreference::MAINTAIN_FRAMERATE);
    298  SetInputStates(true, kDefaultFrameRate, kDefaultFrameSize);
    299  resource_->SetUsageState(ResourceUsageState::kOveruse);
    300  EXPECT_EQ(1, restrictions_listener_.adaptation_counters().Total());
    301  RestrictSource(restrictions_listener_.restrictions());
    302  other_resource_->SetUsageState(ResourceUsageState::kOveruse);
    303  EXPECT_EQ(2, restrictions_listener_.adaptation_counters().Total());
    304  RestrictSource(restrictions_listener_.restrictions());
    305 
    306  // `other_resource_` is most limited, resource_ can't adapt up.
    307  resource_->SetUsageState(ResourceUsageState::kUnderuse);
    308  EXPECT_EQ(2, restrictions_listener_.adaptation_counters().Total());
    309  RestrictSource(restrictions_listener_.restrictions());
    310  other_resource_->SetUsageState(ResourceUsageState::kUnderuse);
    311  EXPECT_EQ(1, restrictions_listener_.adaptation_counters().Total());
    312  RestrictSource(restrictions_listener_.restrictions());
    313 
    314  // `resource_` and `other_resource_` are now most limited, so both must
    315  // signal underuse to adapt up.
    316  other_resource_->SetUsageState(ResourceUsageState::kUnderuse);
    317  EXPECT_EQ(1, restrictions_listener_.adaptation_counters().Total());
    318  RestrictSource(restrictions_listener_.restrictions());
    319  resource_->SetUsageState(ResourceUsageState::kUnderuse);
    320  EXPECT_EQ(0, restrictions_listener_.adaptation_counters().Total());
    321  RestrictSource(restrictions_listener_.restrictions());
    322 }
    323 
    324 TEST_F(ResourceAdaptationProcessorTest,
    325       MultipleResourcesCanTriggerMultipleAdaptations) {
    326  video_stream_adapter_->SetDegradationPreference(
    327      DegradationPreference::MAINTAIN_FRAMERATE);
    328  SetInputStates(true, kDefaultFrameRate, kDefaultFrameSize);
    329  resource_->SetUsageState(ResourceUsageState::kOveruse);
    330  EXPECT_EQ(1, restrictions_listener_.adaptation_counters().Total());
    331  RestrictSource(restrictions_listener_.restrictions());
    332  other_resource_->SetUsageState(ResourceUsageState::kOveruse);
    333  EXPECT_EQ(2, restrictions_listener_.adaptation_counters().Total());
    334  RestrictSource(restrictions_listener_.restrictions());
    335  other_resource_->SetUsageState(ResourceUsageState::kOveruse);
    336  EXPECT_EQ(3, restrictions_listener_.adaptation_counters().Total());
    337  RestrictSource(restrictions_listener_.restrictions());
    338 
    339  // resource_ is not most limited so can't adapt from underuse.
    340  resource_->SetUsageState(ResourceUsageState::kUnderuse);
    341  EXPECT_EQ(3, restrictions_listener_.adaptation_counters().Total());
    342  RestrictSource(restrictions_listener_.restrictions());
    343  other_resource_->SetUsageState(ResourceUsageState::kUnderuse);
    344  EXPECT_EQ(2, restrictions_listener_.adaptation_counters().Total());
    345  RestrictSource(restrictions_listener_.restrictions());
    346  // resource_ is still not most limited so can't adapt from underuse.
    347  resource_->SetUsageState(ResourceUsageState::kUnderuse);
    348  EXPECT_EQ(2, restrictions_listener_.adaptation_counters().Total());
    349  RestrictSource(restrictions_listener_.restrictions());
    350 
    351  // However it will be after overuse
    352  resource_->SetUsageState(ResourceUsageState::kOveruse);
    353  EXPECT_EQ(3, restrictions_listener_.adaptation_counters().Total());
    354  RestrictSource(restrictions_listener_.restrictions());
    355 
    356  // Now other_resource_ can't adapt up as it is not most restricted.
    357  other_resource_->SetUsageState(ResourceUsageState::kUnderuse);
    358  EXPECT_EQ(3, restrictions_listener_.adaptation_counters().Total());
    359  RestrictSource(restrictions_listener_.restrictions());
    360 
    361  // resource_ is limited at 3 adaptations and other_resource_ 2.
    362  // With the most limited resource signalling underuse in the following
    363  // order we get back to unrestricted video.
    364  resource_->SetUsageState(ResourceUsageState::kUnderuse);
    365  EXPECT_EQ(2, restrictions_listener_.adaptation_counters().Total());
    366  RestrictSource(restrictions_listener_.restrictions());
    367  // Both resource_ and other_resource_ are most limited.
    368  other_resource_->SetUsageState(ResourceUsageState::kUnderuse);
    369  EXPECT_EQ(2, restrictions_listener_.adaptation_counters().Total());
    370  RestrictSource(restrictions_listener_.restrictions());
    371  resource_->SetUsageState(ResourceUsageState::kUnderuse);
    372  EXPECT_EQ(1, restrictions_listener_.adaptation_counters().Total());
    373  RestrictSource(restrictions_listener_.restrictions());
    374  // Again both are most limited.
    375  resource_->SetUsageState(ResourceUsageState::kUnderuse);
    376  EXPECT_EQ(1, restrictions_listener_.adaptation_counters().Total());
    377  RestrictSource(restrictions_listener_.restrictions());
    378  other_resource_->SetUsageState(ResourceUsageState::kUnderuse);
    379  EXPECT_EQ(0, restrictions_listener_.adaptation_counters().Total());
    380 }
    381 
    382 TEST_F(ResourceAdaptationProcessorTest,
    383       MostLimitedResourceAdaptationWorksAfterChangingDegradataionPreference) {
    384  video_stream_adapter_->SetDegradationPreference(
    385      DegradationPreference::MAINTAIN_FRAMERATE);
    386  SetInputStates(true, kDefaultFrameRate, kDefaultFrameSize);
    387  // Adapt down until we can't anymore.
    388  resource_->SetUsageState(ResourceUsageState::kOveruse);
    389  RestrictSource(restrictions_listener_.restrictions());
    390  resource_->SetUsageState(ResourceUsageState::kOveruse);
    391  RestrictSource(restrictions_listener_.restrictions());
    392  resource_->SetUsageState(ResourceUsageState::kOveruse);
    393  RestrictSource(restrictions_listener_.restrictions());
    394  resource_->SetUsageState(ResourceUsageState::kOveruse);
    395  RestrictSource(restrictions_listener_.restrictions());
    396  resource_->SetUsageState(ResourceUsageState::kOveruse);
    397  RestrictSource(restrictions_listener_.restrictions());
    398  int last_total = restrictions_listener_.adaptation_counters().Total();
    399 
    400  video_stream_adapter_->SetDegradationPreference(
    401      DegradationPreference::MAINTAIN_RESOLUTION);
    402  // resource_ can not adapt up since we have never reduced FPS.
    403  resource_->SetUsageState(ResourceUsageState::kUnderuse);
    404  EXPECT_EQ(last_total, restrictions_listener_.adaptation_counters().Total());
    405 
    406  other_resource_->SetUsageState(ResourceUsageState::kOveruse);
    407  EXPECT_EQ(last_total + 1,
    408            restrictions_listener_.adaptation_counters().Total());
    409  RestrictSource(restrictions_listener_.restrictions());
    410  // other_resource_ is most limited so should be able to adapt up.
    411  other_resource_->SetUsageState(ResourceUsageState::kUnderuse);
    412  EXPECT_EQ(last_total, restrictions_listener_.adaptation_counters().Total());
    413 }
    414 
    415 TEST_F(ResourceAdaptationProcessorTest,
    416       AdaptsDownWhenOtherResourceIsAlwaysUnderused) {
    417  video_stream_adapter_->SetDegradationPreference(
    418      DegradationPreference::MAINTAIN_FRAMERATE);
    419  SetInputStates(true, kDefaultFrameRate, kDefaultFrameSize);
    420  other_resource_->SetUsageState(ResourceUsageState::kUnderuse);
    421  // Does not trigger adapataion because there's no restriction.
    422  EXPECT_EQ(0, restrictions_listener_.adaptation_counters().Total());
    423 
    424  RestrictSource(restrictions_listener_.restrictions());
    425  resource_->SetUsageState(ResourceUsageState::kOveruse);
    426  // Adapts down even if other resource asked for adapting up.
    427  EXPECT_EQ(1, restrictions_listener_.adaptation_counters().Total());
    428 
    429  RestrictSource(restrictions_listener_.restrictions());
    430  other_resource_->SetUsageState(ResourceUsageState::kUnderuse);
    431  // Doesn't adapt up because adaptation is due to another resource.
    432  EXPECT_EQ(1, restrictions_listener_.adaptation_counters().Total());
    433  RestrictSource(restrictions_listener_.restrictions());
    434 }
    435 
    436 TEST_F(ResourceAdaptationProcessorTest,
    437       TriggerOveruseNotOnAdaptationTaskQueue) {
    438  video_stream_adapter_->SetDegradationPreference(
    439      DegradationPreference::MAINTAIN_FRAMERATE);
    440  SetInputStates(true, kDefaultFrameRate, kDefaultFrameSize);
    441 
    442  TaskQueueForTest resource_task_queue("ResourceTaskQueue");
    443  resource_task_queue.PostTask(
    444      [&]() { resource_->SetUsageState(ResourceUsageState::kOveruse); });
    445 
    446  EXPECT_THAT(
    447      WaitUntil(
    448          [&] { return restrictions_listener_.restrictions_updated_count(); },
    449          Eq(1u)),
    450      IsRtcOk());
    451 }
    452 
    453 TEST_F(ResourceAdaptationProcessorTest,
    454       DestroyProcessorWhileResourceListenerDelegateHasTaskInFlight) {
    455  video_stream_adapter_->SetDegradationPreference(
    456      DegradationPreference::MAINTAIN_FRAMERATE);
    457  SetInputStates(true, kDefaultFrameRate, kDefaultFrameSize);
    458 
    459  // Wait for `resource_` to signal oversue first so we know that the delegate
    460  // has passed it on to the processor's task queue.
    461  Event resource_event;
    462  TaskQueueForTest resource_task_queue("ResourceTaskQueue");
    463  resource_task_queue.PostTask([&]() {
    464    resource_->SetUsageState(ResourceUsageState::kOveruse);
    465    resource_event.Set();
    466  });
    467 
    468  EXPECT_TRUE(resource_event.Wait(kDefaultTimeout));
    469  // Now destroy the processor while handling the overuse is in flight.
    470  DestroyProcessor();
    471 
    472  // Because the processor was destroyed by the time the delegate's task ran,
    473  // the overuse signal must not have been handled.
    474  EXPECT_EQ(0u, restrictions_listener_.restrictions_updated_count());
    475 }
    476 
    477 TEST_F(ResourceAdaptationProcessorTest,
    478       ResourceOveruseIgnoredWhenSignalledDuringRemoval) {
    479  video_stream_adapter_->SetDegradationPreference(
    480      DegradationPreference::MAINTAIN_FRAMERATE);
    481  SetInputStates(true, kDefaultFrameRate, kDefaultFrameSize);
    482 
    483  Event overuse_event;
    484  TaskQueueForTest resource_task_queue("ResourceTaskQueue");
    485  // Queues task for `resource_` overuse while `processor_` is still listening.
    486  resource_task_queue.PostTask([&]() {
    487    resource_->SetUsageState(ResourceUsageState::kOveruse);
    488    overuse_event.Set();
    489  });
    490  EXPECT_TRUE(overuse_event.Wait(kDefaultTimeout));
    491  // Once we know the overuse task is queued, remove `resource_` so that
    492  // `processor_` is not listening to it.
    493  processor_->RemoveResource(resource_);
    494 
    495  // Runs the queued task so `processor_` gets signalled kOveruse from
    496  // `resource_` even though `processor_` was not listening.
    497  WaitUntilTaskQueueIdle();
    498 
    499  // No restrictions should change even though `resource_` signaled `kOveruse`.
    500  EXPECT_EQ(0u, restrictions_listener_.restrictions_updated_count());
    501 
    502  // Delete `resource_` for cleanup.
    503  resource_ = nullptr;
    504 }
    505 
    506 TEST_F(ResourceAdaptationProcessorTest,
    507       RemovingOnlyAdaptedResourceResetsAdaptation) {
    508  video_stream_adapter_->SetDegradationPreference(
    509      DegradationPreference::MAINTAIN_FRAMERATE);
    510  SetInputStates(true, kDefaultFrameRate, kDefaultFrameSize);
    511 
    512  resource_->SetUsageState(ResourceUsageState::kOveruse);
    513  EXPECT_EQ(1, restrictions_listener_.adaptation_counters().Total());
    514  RestrictSource(restrictions_listener_.restrictions());
    515 
    516  processor_->RemoveResource(resource_);
    517  EXPECT_EQ(0, restrictions_listener_.adaptation_counters().Total());
    518 
    519  // Delete `resource_` for cleanup.
    520  resource_ = nullptr;
    521 }
    522 
    523 TEST_F(ResourceAdaptationProcessorTest,
    524       RemovingMostLimitedResourceSetsAdaptationToNextLimitedLevel) {
    525  video_stream_adapter_->SetDegradationPreference(
    526      DegradationPreference::BALANCED);
    527  SetInputStates(true, kDefaultFrameRate, kDefaultFrameSize);
    528 
    529  other_resource_->SetUsageState(ResourceUsageState::kOveruse);
    530  RestrictSource(restrictions_listener_.restrictions());
    531  EXPECT_EQ(1, restrictions_listener_.adaptation_counters().Total());
    532  VideoSourceRestrictions next_limited_restrictions =
    533      restrictions_listener_.restrictions();
    534  VideoAdaptationCounters next_limited_counters =
    535      restrictions_listener_.adaptation_counters();
    536 
    537  resource_->SetUsageState(ResourceUsageState::kOveruse);
    538  RestrictSource(restrictions_listener_.restrictions());
    539  EXPECT_EQ(2, restrictions_listener_.adaptation_counters().Total());
    540 
    541  // Removing most limited `resource_` should revert us back to
    542  processor_->RemoveResource(resource_);
    543  EXPECT_EQ(1, restrictions_listener_.adaptation_counters().Total());
    544  EXPECT_EQ(next_limited_restrictions, restrictions_listener_.restrictions());
    545  EXPECT_EQ(next_limited_counters,
    546            restrictions_listener_.adaptation_counters());
    547 
    548  // Delete `resource_` for cleanup.
    549  resource_ = nullptr;
    550 }
    551 
    552 TEST_F(ResourceAdaptationProcessorTest,
    553       RemovingMostLimitedResourceSetsAdaptationIfInputStateUnchanged) {
    554  video_stream_adapter_->SetDegradationPreference(
    555      DegradationPreference::MAINTAIN_FRAMERATE);
    556  SetInputStates(true, kDefaultFrameRate, kDefaultFrameSize);
    557 
    558  other_resource_->SetUsageState(ResourceUsageState::kOveruse);
    559  RestrictSource(restrictions_listener_.restrictions());
    560  EXPECT_EQ(1, restrictions_listener_.adaptation_counters().Total());
    561  VideoSourceRestrictions next_limited_restrictions =
    562      restrictions_listener_.restrictions();
    563  VideoAdaptationCounters next_limited_counters =
    564      restrictions_listener_.adaptation_counters();
    565 
    566  // Overuse twice and underuse once. After the underuse we don't restrict the
    567  // source. Normally this would block future underuses.
    568  resource_->SetUsageState(ResourceUsageState::kOveruse);
    569  RestrictSource(restrictions_listener_.restrictions());
    570  resource_->SetUsageState(ResourceUsageState::kOveruse);
    571  RestrictSource(restrictions_listener_.restrictions());
    572  resource_->SetUsageState(ResourceUsageState::kUnderuse);
    573  EXPECT_EQ(2, restrictions_listener_.adaptation_counters().Total());
    574 
    575  // Removing most limited `resource_` should revert us back to, even though we
    576  // did not call RestrictSource() after `resource_` was overused. Normally
    577  // adaptation for MAINTAIN_FRAMERATE would be blocked here but for removal we
    578  // allow this anyways.
    579  processor_->RemoveResource(resource_);
    580  EXPECT_EQ(1, restrictions_listener_.adaptation_counters().Total());
    581  EXPECT_EQ(next_limited_restrictions, restrictions_listener_.restrictions());
    582  EXPECT_EQ(next_limited_counters,
    583            restrictions_listener_.adaptation_counters());
    584 
    585  // Delete `resource_` for cleanup.
    586  resource_ = nullptr;
    587 }
    588 
    589 TEST_F(ResourceAdaptationProcessorTest,
    590       RemovingResourceNotMostLimitedHasNoEffectOnLimitations) {
    591  video_stream_adapter_->SetDegradationPreference(
    592      DegradationPreference::BALANCED);
    593  SetInputStates(true, kDefaultFrameRate, kDefaultFrameSize);
    594 
    595  other_resource_->SetUsageState(ResourceUsageState::kOveruse);
    596  RestrictSource(restrictions_listener_.restrictions());
    597  EXPECT_EQ(1, restrictions_listener_.adaptation_counters().Total());
    598 
    599  resource_->SetUsageState(ResourceUsageState::kOveruse);
    600  RestrictSource(restrictions_listener_.restrictions());
    601  VideoSourceRestrictions current_restrictions =
    602      restrictions_listener_.restrictions();
    603  VideoAdaptationCounters current_counters =
    604      restrictions_listener_.adaptation_counters();
    605  EXPECT_EQ(2, restrictions_listener_.adaptation_counters().Total());
    606 
    607  // Removing most limited `resource_` should revert us back to
    608  processor_->RemoveResource(other_resource_);
    609  EXPECT_EQ(current_restrictions, restrictions_listener_.restrictions());
    610  EXPECT_EQ(current_counters, restrictions_listener_.adaptation_counters());
    611 
    612  // Delete `other_resource_` for cleanup.
    613  other_resource_ = nullptr;
    614 }
    615 
    616 TEST_F(ResourceAdaptationProcessorTest,
    617       RemovingMostLimitedResourceAfterSwitchingDegradationPreferences) {
    618  video_stream_adapter_->SetDegradationPreference(
    619      DegradationPreference::MAINTAIN_FRAMERATE);
    620  SetInputStates(true, kDefaultFrameRate, kDefaultFrameSize);
    621 
    622  other_resource_->SetUsageState(ResourceUsageState::kOveruse);
    623  RestrictSource(restrictions_listener_.restrictions());
    624  EXPECT_EQ(1, restrictions_listener_.adaptation_counters().Total());
    625  VideoSourceRestrictions next_limited_restrictions =
    626      restrictions_listener_.restrictions();
    627  VideoAdaptationCounters next_limited_counters =
    628      restrictions_listener_.adaptation_counters();
    629 
    630  video_stream_adapter_->SetDegradationPreference(
    631      DegradationPreference::MAINTAIN_RESOLUTION);
    632  resource_->SetUsageState(ResourceUsageState::kOveruse);
    633  RestrictSource(restrictions_listener_.restrictions());
    634  EXPECT_EQ(2, restrictions_listener_.adaptation_counters().Total());
    635 
    636  // Revert to `other_resource_` when removing `resource_` even though the
    637  // degradation preference was different when it was overused.
    638  processor_->RemoveResource(resource_);
    639  EXPECT_EQ(next_limited_counters,
    640            restrictions_listener_.adaptation_counters());
    641 
    642  // After switching back to MAINTAIN_FRAMERATE, the next most limited settings
    643  // are restored.
    644  video_stream_adapter_->SetDegradationPreference(
    645      DegradationPreference::MAINTAIN_FRAMERATE);
    646  EXPECT_EQ(next_limited_restrictions, restrictions_listener_.restrictions());
    647 
    648  // Delete `resource_` for cleanup.
    649  resource_ = nullptr;
    650 }
    651 
    652 TEST_F(ResourceAdaptationProcessorTest,
    653       RemovingMostLimitedResourceSetsNextLimitationsInDisabled) {
    654  video_stream_adapter_->SetDegradationPreference(
    655      DegradationPreference::MAINTAIN_FRAMERATE);
    656  SetInputStates(true, kDefaultFrameRate, kDefaultFrameSize);
    657 
    658  other_resource_->SetUsageState(ResourceUsageState::kOveruse);
    659  RestrictSource(restrictions_listener_.restrictions());
    660  VideoSourceRestrictions next_limited_restrictions =
    661      restrictions_listener_.restrictions();
    662  VideoAdaptationCounters next_limited_counters =
    663      restrictions_listener_.adaptation_counters();
    664  EXPECT_EQ(1, restrictions_listener_.adaptation_counters().Total());
    665  resource_->SetUsageState(ResourceUsageState::kOveruse);
    666  RestrictSource(restrictions_listener_.restrictions());
    667  EXPECT_EQ(2, restrictions_listener_.adaptation_counters().Total());
    668 
    669  video_stream_adapter_->SetDegradationPreference(
    670      DegradationPreference::DISABLED);
    671 
    672  // Revert to `other_resource_` when removing `resource_` even though the
    673  // current degradataion preference is disabled.
    674  processor_->RemoveResource(resource_);
    675 
    676  // After switching back to MAINTAIN_FRAMERATE, the next most limited settings
    677  // are restored.
    678  video_stream_adapter_->SetDegradationPreference(
    679      DegradationPreference::MAINTAIN_FRAMERATE);
    680  EXPECT_EQ(next_limited_restrictions, restrictions_listener_.restrictions());
    681  EXPECT_EQ(next_limited_counters,
    682            restrictions_listener_.adaptation_counters());
    683 
    684  // Delete `resource_` for cleanup.
    685  resource_ = nullptr;
    686 }
    687 
    688 TEST_F(ResourceAdaptationProcessorTest,
    689       RemovedResourceSignalsIgnoredByProcessor) {
    690  video_stream_adapter_->SetDegradationPreference(
    691      DegradationPreference::MAINTAIN_FRAMERATE);
    692  SetInputStates(true, kDefaultFrameRate, kDefaultFrameSize);
    693 
    694  processor_->RemoveResource(resource_);
    695  resource_->SetUsageState(ResourceUsageState::kOveruse);
    696  EXPECT_EQ(0u, restrictions_listener_.restrictions_updated_count());
    697 
    698  // Delete `resource_` for cleanup.
    699  resource_ = nullptr;
    700 }
    701 
    702 TEST_F(ResourceAdaptationProcessorTest,
    703       RemovingResourceWhenMultipleMostLimtedHasNoEffect) {
    704  video_stream_adapter_->SetDegradationPreference(
    705      DegradationPreference::MAINTAIN_FRAMERATE);
    706  SetInputStates(true, kDefaultFrameRate, kDefaultFrameSize);
    707 
    708  other_resource_->SetUsageState(ResourceUsageState::kOveruse);
    709  RestrictSource(restrictions_listener_.restrictions());
    710  EXPECT_EQ(1, restrictions_listener_.adaptation_counters().Total());
    711  // Adapt `resource_` up and then down so that both resource's are most
    712  // limited at 1 adaptation.
    713  resource_->SetUsageState(ResourceUsageState::kOveruse);
    714  RestrictSource(restrictions_listener_.restrictions());
    715  resource_->SetUsageState(ResourceUsageState::kUnderuse);
    716  RestrictSource(restrictions_listener_.restrictions());
    717  EXPECT_EQ(1, restrictions_listener_.adaptation_counters().Total());
    718 
    719  // Removing `resource_` has no effect since both `resource_` and
    720  // `other_resource_` are most limited.
    721  processor_->RemoveResource(resource_);
    722  EXPECT_EQ(1, restrictions_listener_.adaptation_counters().Total());
    723 
    724  // Delete `resource_` for cleanup.
    725  resource_ = nullptr;
    726 }
    727 
    728 TEST_F(ResourceAdaptationProcessorTest,
    729       ResourceOverusedAtLimitReachedWillShareMostLimited) {
    730  video_stream_adapter_->SetDegradationPreference(
    731      DegradationPreference::MAINTAIN_FRAMERATE);
    732  SetInputStates(true, kDefaultFrameRate, kDefaultFrameSize);
    733 
    734  bool has_reached_min_pixels = false;
    735  ON_CALL(frame_rate_provider_, OnMinPixelLimitReached())
    736      .WillByDefault(testing::Assign(&has_reached_min_pixels, true));
    737 
    738  // Adapt 10 times, which should make us hit the limit.
    739  for (int i = 0; i < 10; ++i) {
    740    resource_->SetUsageState(ResourceUsageState::kOveruse);
    741    RestrictSource(restrictions_listener_.restrictions());
    742  }
    743  EXPECT_TRUE(has_reached_min_pixels);
    744  auto last_update_count = restrictions_listener_.restrictions_updated_count();
    745  other_resource_->SetUsageState(ResourceUsageState::kOveruse);
    746  // Now both `resource_` and `other_resource_` are most limited. Underuse of
    747  // `resource_` will not adapt up.
    748  resource_->SetUsageState(ResourceUsageState::kUnderuse);
    749  EXPECT_EQ(last_update_count,
    750            restrictions_listener_.restrictions_updated_count());
    751 }
    752 
    753 }  // namespace webrtc