1 /*
2 * Copyright 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 "video/adaptation/pixel_limit_resource.h"
12
13 #include <memory>
14 #include <utility>
15
16 #include "absl/functional/any_invocable.h"
17 #include "api/units/timestamp.h"
18 #include "call/adaptation/test/fake_video_stream_input_state_provider.h"
19 #include "call/adaptation/test/mock_resource_listener.h"
20 #include "call/adaptation/video_stream_adapter.h"
21 #include "rtc_base/task_queue_for_test.h"
22 #include "test/gmock.h"
23 #include "test/gtest.h"
24 #include "test/time_controller/simulated_time_controller.h"
25
26 using testing::_;
27
28 namespace webrtc {
29
30 namespace {
31
32 constexpr TimeDelta kResourceUsageCheckIntervalMs = TimeDelta::Seconds(5);
33
34 } // namespace
35
36 class PixelLimitResourceTest : public ::testing::Test {
37 public:
PixelLimitResourceTest()38 PixelLimitResourceTest()
39 : time_controller_(Timestamp::Micros(1234)),
40 task_queue_(time_controller_.GetTaskQueueFactory()->CreateTaskQueue(
41 "TestQueue",
42 TaskQueueFactory::Priority::NORMAL)),
43 input_state_provider_() {}
44
SetCurrentPixels(int current_pixels)45 void SetCurrentPixels(int current_pixels) {
46 input_state_provider_.SetInputState(current_pixels, 30, current_pixels);
47 }
48
RunTaskOnTaskQueue(absl::AnyInvocable<void ()&&> task)49 void RunTaskOnTaskQueue(absl::AnyInvocable<void() &&> task) {
50 task_queue_->PostTask(std::move(task));
51 time_controller_.AdvanceTime(TimeDelta::Zero());
52 }
53
54 protected:
55 // Posted tasks, including repeated tasks, are executed when simulated time is
56 // advanced by time_controller_.AdvanceTime().
57 GlobalSimulatedTimeController time_controller_;
58 std::unique_ptr<TaskQueueBase, TaskQueueDeleter> task_queue_;
59 FakeVideoStreamInputStateProvider input_state_provider_;
60 };
61
TEST_F(PixelLimitResourceTest,ResourceIsSilentByDefault)62 TEST_F(PixelLimitResourceTest, ResourceIsSilentByDefault) {
63 // Because our mock is strick, the test would fail if
64 // OnResourceUsageStateMeasured() is invoked.
65 testing::StrictMock<MockResourceListener> resource_listener;
66 RunTaskOnTaskQueue([&]() {
67 rtc::scoped_refptr<PixelLimitResource> pixel_limit_resource =
68 PixelLimitResource::Create(task_queue_.get(), &input_state_provider_);
69 pixel_limit_resource->SetResourceListener(&resource_listener);
70 // Set a current pixel count.
71 SetCurrentPixels(1280 * 720);
72 // Advance a significant amount of time.
73 time_controller_.AdvanceTime(kResourceUsageCheckIntervalMs * 10);
74 pixel_limit_resource->SetResourceListener(nullptr);
75 });
76 }
77
TEST_F(PixelLimitResourceTest,OveruseIsReportedWhileCurrentPixelsIsGreaterThanMaxPixels)78 TEST_F(PixelLimitResourceTest,
79 OveruseIsReportedWhileCurrentPixelsIsGreaterThanMaxPixels) {
80 constexpr int kMaxPixels = 640 * 480;
81 testing::StrictMock<MockResourceListener> resource_listener;
82 RunTaskOnTaskQueue([&]() {
83 rtc::scoped_refptr<PixelLimitResource> pixel_limit_resource =
84 PixelLimitResource::Create(task_queue_.get(), &input_state_provider_);
85 pixel_limit_resource->SetResourceListener(&resource_listener);
86 time_controller_.AdvanceTime(TimeDelta::Zero());
87
88 pixel_limit_resource->SetMaxPixels(kMaxPixels);
89 SetCurrentPixels(kMaxPixels + 1);
90 EXPECT_CALL(resource_listener,
91 OnResourceUsageStateMeasured(_, ResourceUsageState::kOveruse))
92 .Times(1);
93 time_controller_.AdvanceTime(kResourceUsageCheckIntervalMs);
94
95 // As long as the current pixels has not updated, the overuse signal is
96 // repeated at a fixed interval.
97 EXPECT_CALL(resource_listener,
98 OnResourceUsageStateMeasured(_, ResourceUsageState::kOveruse))
99 .Times(3);
100 time_controller_.AdvanceTime(kResourceUsageCheckIntervalMs * 3);
101
102 // When the overuse signal has resulted in a lower resolution, the overuse
103 // signals stops.
104 SetCurrentPixels(kMaxPixels);
105 EXPECT_CALL(resource_listener, OnResourceUsageStateMeasured(_, _)).Times(0);
106 time_controller_.AdvanceTime(kResourceUsageCheckIntervalMs * 3);
107
108 pixel_limit_resource->SetResourceListener(nullptr);
109 });
110 }
111
TEST_F(PixelLimitResourceTest,UnderuseIsReportedWhileCurrentPixelsIsLessThanMinPixels)112 TEST_F(PixelLimitResourceTest,
113 UnderuseIsReportedWhileCurrentPixelsIsLessThanMinPixels) {
114 constexpr int kMaxPixels = 640 * 480;
115 const int kMinPixels = GetLowerResolutionThan(kMaxPixels);
116 testing::StrictMock<MockResourceListener> resource_listener;
117 RunTaskOnTaskQueue([&]() {
118 rtc::scoped_refptr<PixelLimitResource> pixel_limit_resource =
119 PixelLimitResource::Create(task_queue_.get(), &input_state_provider_);
120 pixel_limit_resource->SetResourceListener(&resource_listener);
121 time_controller_.AdvanceTime(TimeDelta::Zero());
122
123 pixel_limit_resource->SetMaxPixels(kMaxPixels);
124 SetCurrentPixels(kMinPixels - 1);
125 EXPECT_CALL(resource_listener,
126 OnResourceUsageStateMeasured(_, ResourceUsageState::kUnderuse))
127 .Times(1);
128 time_controller_.AdvanceTime(kResourceUsageCheckIntervalMs);
129
130 // As long as the current pixels has not updated, the underuse signal is
131 // repeated at a fixed interval.
132 EXPECT_CALL(resource_listener,
133 OnResourceUsageStateMeasured(_, ResourceUsageState::kUnderuse))
134 .Times(3);
135 time_controller_.AdvanceTime(kResourceUsageCheckIntervalMs * 3);
136
137 // When the underuse signal has resulted in a higher resolution, the
138 // underuse signals stops.
139 SetCurrentPixels(kMinPixels);
140 EXPECT_CALL(resource_listener, OnResourceUsageStateMeasured(_, _)).Times(0);
141 time_controller_.AdvanceTime(kResourceUsageCheckIntervalMs * 3);
142
143 pixel_limit_resource->SetResourceListener(nullptr);
144 });
145 }
146
147 } // namespace webrtc
148