1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker * Copyright 2020 The WebRTC Project Authors. All rights reserved.
3*d9f75844SAndroid Build Coastguard Worker *
4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker */
10*d9f75844SAndroid Build Coastguard Worker
11*d9f75844SAndroid Build Coastguard Worker #include "video/adaptation/pixel_limit_resource.h"
12*d9f75844SAndroid Build Coastguard Worker
13*d9f75844SAndroid Build Coastguard Worker #include "api/sequence_checker.h"
14*d9f75844SAndroid Build Coastguard Worker #include "api/units/time_delta.h"
15*d9f75844SAndroid Build Coastguard Worker #include "call/adaptation/video_stream_adapter.h"
16*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
17*d9f75844SAndroid Build Coastguard Worker
18*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
19*d9f75844SAndroid Build Coastguard Worker
20*d9f75844SAndroid Build Coastguard Worker namespace {
21*d9f75844SAndroid Build Coastguard Worker
22*d9f75844SAndroid Build Coastguard Worker constexpr TimeDelta kResourceUsageCheckIntervalMs = TimeDelta::Seconds(5);
23*d9f75844SAndroid Build Coastguard Worker
24*d9f75844SAndroid Build Coastguard Worker } // namespace
25*d9f75844SAndroid Build Coastguard Worker
26*d9f75844SAndroid Build Coastguard Worker // static
Create(TaskQueueBase * task_queue,VideoStreamInputStateProvider * input_state_provider)27*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<PixelLimitResource> PixelLimitResource::Create(
28*d9f75844SAndroid Build Coastguard Worker TaskQueueBase* task_queue,
29*d9f75844SAndroid Build Coastguard Worker VideoStreamInputStateProvider* input_state_provider) {
30*d9f75844SAndroid Build Coastguard Worker return rtc::make_ref_counted<PixelLimitResource>(task_queue,
31*d9f75844SAndroid Build Coastguard Worker input_state_provider);
32*d9f75844SAndroid Build Coastguard Worker }
33*d9f75844SAndroid Build Coastguard Worker
PixelLimitResource(TaskQueueBase * task_queue,VideoStreamInputStateProvider * input_state_provider)34*d9f75844SAndroid Build Coastguard Worker PixelLimitResource::PixelLimitResource(
35*d9f75844SAndroid Build Coastguard Worker TaskQueueBase* task_queue,
36*d9f75844SAndroid Build Coastguard Worker VideoStreamInputStateProvider* input_state_provider)
37*d9f75844SAndroid Build Coastguard Worker : task_queue_(task_queue),
38*d9f75844SAndroid Build Coastguard Worker input_state_provider_(input_state_provider),
39*d9f75844SAndroid Build Coastguard Worker max_pixels_(absl::nullopt) {
40*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(task_queue_);
41*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(input_state_provider_);
42*d9f75844SAndroid Build Coastguard Worker }
43*d9f75844SAndroid Build Coastguard Worker
~PixelLimitResource()44*d9f75844SAndroid Build Coastguard Worker PixelLimitResource::~PixelLimitResource() {
45*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(!listener_);
46*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(!repeating_task_.Running());
47*d9f75844SAndroid Build Coastguard Worker }
48*d9f75844SAndroid Build Coastguard Worker
SetMaxPixels(int max_pixels)49*d9f75844SAndroid Build Coastguard Worker void PixelLimitResource::SetMaxPixels(int max_pixels) {
50*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(task_queue_);
51*d9f75844SAndroid Build Coastguard Worker max_pixels_ = max_pixels;
52*d9f75844SAndroid Build Coastguard Worker }
53*d9f75844SAndroid Build Coastguard Worker
SetResourceListener(ResourceListener * listener)54*d9f75844SAndroid Build Coastguard Worker void PixelLimitResource::SetResourceListener(ResourceListener* listener) {
55*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(task_queue_);
56*d9f75844SAndroid Build Coastguard Worker listener_ = listener;
57*d9f75844SAndroid Build Coastguard Worker if (listener_) {
58*d9f75844SAndroid Build Coastguard Worker repeating_task_.Stop();
59*d9f75844SAndroid Build Coastguard Worker repeating_task_ = RepeatingTaskHandle::Start(task_queue_, [&] {
60*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(task_queue_);
61*d9f75844SAndroid Build Coastguard Worker if (!listener_) {
62*d9f75844SAndroid Build Coastguard Worker // We don't have a listener so resource adaptation must not be running,
63*d9f75844SAndroid Build Coastguard Worker // try again later.
64*d9f75844SAndroid Build Coastguard Worker return kResourceUsageCheckIntervalMs;
65*d9f75844SAndroid Build Coastguard Worker }
66*d9f75844SAndroid Build Coastguard Worker if (!max_pixels_.has_value()) {
67*d9f75844SAndroid Build Coastguard Worker // No pixel limit configured yet, try again later.
68*d9f75844SAndroid Build Coastguard Worker return kResourceUsageCheckIntervalMs;
69*d9f75844SAndroid Build Coastguard Worker }
70*d9f75844SAndroid Build Coastguard Worker absl::optional<int> frame_size_pixels =
71*d9f75844SAndroid Build Coastguard Worker input_state_provider_->InputState().frame_size_pixels();
72*d9f75844SAndroid Build Coastguard Worker if (!frame_size_pixels.has_value()) {
73*d9f75844SAndroid Build Coastguard Worker // We haven't observed a frame yet so we don't know if it's going to be
74*d9f75844SAndroid Build Coastguard Worker // too big or too small, try again later.
75*d9f75844SAndroid Build Coastguard Worker return kResourceUsageCheckIntervalMs;
76*d9f75844SAndroid Build Coastguard Worker }
77*d9f75844SAndroid Build Coastguard Worker int current_pixels = frame_size_pixels.value();
78*d9f75844SAndroid Build Coastguard Worker int target_pixel_upper_bounds = max_pixels_.value();
79*d9f75844SAndroid Build Coastguard Worker // To avoid toggling, we allow any resolutions between
80*d9f75844SAndroid Build Coastguard Worker // `target_pixel_upper_bounds` and video_stream_adapter.h's
81*d9f75844SAndroid Build Coastguard Worker // GetLowerResolutionThan(). This is the pixels we end up if we adapt down
82*d9f75844SAndroid Build Coastguard Worker // from `target_pixel_upper_bounds`.
83*d9f75844SAndroid Build Coastguard Worker int target_pixels_lower_bounds =
84*d9f75844SAndroid Build Coastguard Worker GetLowerResolutionThan(target_pixel_upper_bounds);
85*d9f75844SAndroid Build Coastguard Worker if (current_pixels > target_pixel_upper_bounds) {
86*d9f75844SAndroid Build Coastguard Worker listener_->OnResourceUsageStateMeasured(
87*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<Resource>(this), ResourceUsageState::kOveruse);
88*d9f75844SAndroid Build Coastguard Worker } else if (current_pixels < target_pixels_lower_bounds) {
89*d9f75844SAndroid Build Coastguard Worker listener_->OnResourceUsageStateMeasured(
90*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<Resource>(this), ResourceUsageState::kUnderuse);
91*d9f75844SAndroid Build Coastguard Worker }
92*d9f75844SAndroid Build Coastguard Worker return kResourceUsageCheckIntervalMs;
93*d9f75844SAndroid Build Coastguard Worker });
94*d9f75844SAndroid Build Coastguard Worker } else {
95*d9f75844SAndroid Build Coastguard Worker repeating_task_.Stop();
96*d9f75844SAndroid Build Coastguard Worker }
97*d9f75844SAndroid Build Coastguard Worker // The task must be running if we have a listener.
98*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(repeating_task_.Running() || !listener_);
99*d9f75844SAndroid Build Coastguard Worker }
100*d9f75844SAndroid Build Coastguard Worker
101*d9f75844SAndroid Build Coastguard Worker } // namespace webrtc
102