blob: 28eb19b1aa68746528b98586067cb4e6c23aa9a6 [file] [log] [blame]
/*
* 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 <memory>
#include <utility>
#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<void() &&> 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<TaskQueueBase, TaskQueueDeleter> 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<MockResourceListener> resource_listener;
RunTaskOnTaskQueue([&]() {
rtc::scoped_refptr<PixelLimitResource> 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<MockResourceListener> resource_listener;
RunTaskOnTaskQueue([&]() {
rtc::scoped_refptr<PixelLimitResource> 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<MockResourceListener> resource_listener;
RunTaskOnTaskQueue([&]() {
rtc::scoped_refptr<PixelLimitResource> 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