/* * Copyright 2020 The WebRTC Project Authors. All rights reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "video/adaptation/pixel_limit_resource.h" #include #include #include "absl/functional/any_invocable.h" #include "api/units/timestamp.h" #include "call/adaptation/test/fake_video_stream_input_state_provider.h" #include "call/adaptation/test/mock_resource_listener.h" #include "call/adaptation/video_stream_adapter.h" #include "rtc_base/task_queue_for_test.h" #include "test/gmock.h" #include "test/gtest.h" #include "test/time_controller/simulated_time_controller.h" using testing::_; namespace webrtc { namespace { constexpr TimeDelta kResourceUsageCheckIntervalMs = TimeDelta::Seconds(5); } // namespace class PixelLimitResourceTest : public ::testing::Test { public: PixelLimitResourceTest() : time_controller_(Timestamp::Micros(1234)), task_queue_(time_controller_.GetTaskQueueFactory()->CreateTaskQueue( "TestQueue", TaskQueueFactory::Priority::NORMAL)), input_state_provider_() {} void SetCurrentPixels(int current_pixels) { input_state_provider_.SetInputState(current_pixels, 30, current_pixels); } void RunTaskOnTaskQueue(absl::AnyInvocable task) { task_queue_->PostTask(std::move(task)); time_controller_.AdvanceTime(TimeDelta::Zero()); } protected: // Posted tasks, including repeated tasks, are executed when simulated time is // advanced by time_controller_.AdvanceTime(). GlobalSimulatedTimeController time_controller_; std::unique_ptr task_queue_; FakeVideoStreamInputStateProvider input_state_provider_; }; TEST_F(PixelLimitResourceTest, ResourceIsSilentByDefault) { // Because our mock is strick, the test would fail if // OnResourceUsageStateMeasured() is invoked. testing::StrictMock resource_listener; RunTaskOnTaskQueue([&]() { rtc::scoped_refptr pixel_limit_resource = PixelLimitResource::Create(task_queue_.get(), &input_state_provider_); pixel_limit_resource->SetResourceListener(&resource_listener); // Set a current pixel count. SetCurrentPixels(1280 * 720); // Advance a significant amount of time. time_controller_.AdvanceTime(kResourceUsageCheckIntervalMs * 10); pixel_limit_resource->SetResourceListener(nullptr); }); } TEST_F(PixelLimitResourceTest, OveruseIsReportedWhileCurrentPixelsIsGreaterThanMaxPixels) { constexpr int kMaxPixels = 640 * 480; testing::StrictMock resource_listener; RunTaskOnTaskQueue([&]() { rtc::scoped_refptr pixel_limit_resource = PixelLimitResource::Create(task_queue_.get(), &input_state_provider_); pixel_limit_resource->SetResourceListener(&resource_listener); time_controller_.AdvanceTime(TimeDelta::Zero()); pixel_limit_resource->SetMaxPixels(kMaxPixels); SetCurrentPixels(kMaxPixels + 1); EXPECT_CALL(resource_listener, OnResourceUsageStateMeasured(_, ResourceUsageState::kOveruse)) .Times(1); time_controller_.AdvanceTime(kResourceUsageCheckIntervalMs); // As long as the current pixels has not updated, the overuse signal is // repeated at a fixed interval. EXPECT_CALL(resource_listener, OnResourceUsageStateMeasured(_, ResourceUsageState::kOveruse)) .Times(3); time_controller_.AdvanceTime(kResourceUsageCheckIntervalMs * 3); // When the overuse signal has resulted in a lower resolution, the overuse // signals stops. SetCurrentPixels(kMaxPixels); EXPECT_CALL(resource_listener, OnResourceUsageStateMeasured(_, _)).Times(0); time_controller_.AdvanceTime(kResourceUsageCheckIntervalMs * 3); pixel_limit_resource->SetResourceListener(nullptr); }); } TEST_F(PixelLimitResourceTest, UnderuseIsReportedWhileCurrentPixelsIsLessThanMinPixels) { constexpr int kMaxPixels = 640 * 480; const int kMinPixels = GetLowerResolutionThan(kMaxPixels); testing::StrictMock resource_listener; RunTaskOnTaskQueue([&]() { rtc::scoped_refptr pixel_limit_resource = PixelLimitResource::Create(task_queue_.get(), &input_state_provider_); pixel_limit_resource->SetResourceListener(&resource_listener); time_controller_.AdvanceTime(TimeDelta::Zero()); pixel_limit_resource->SetMaxPixels(kMaxPixels); SetCurrentPixels(kMinPixels - 1); EXPECT_CALL(resource_listener, OnResourceUsageStateMeasured(_, ResourceUsageState::kUnderuse)) .Times(1); time_controller_.AdvanceTime(kResourceUsageCheckIntervalMs); // As long as the current pixels has not updated, the underuse signal is // repeated at a fixed interval. EXPECT_CALL(resource_listener, OnResourceUsageStateMeasured(_, ResourceUsageState::kUnderuse)) .Times(3); time_controller_.AdvanceTime(kResourceUsageCheckIntervalMs * 3); // When the underuse signal has resulted in a higher resolution, the // underuse signals stops. SetCurrentPixels(kMinPixels); EXPECT_CALL(resource_listener, OnResourceUsageStateMeasured(_, _)).Times(0); time_controller_.AdvanceTime(kResourceUsageCheckIntervalMs * 3); pixel_limit_resource->SetResourceListener(nullptr); }); } } // namespace webrtc