xref: /aosp_15_r20/external/webrtc/video/adaptation/pixel_limit_resource.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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