Henrik Boström | 87eece9 | 2020-04-17 18:36:19 +0200 | [diff] [blame] | 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 | #ifndef CALL_ADAPTATION_RESOURCE_ADAPTATION_PROCESSOR_H_ |
| 12 | #define CALL_ADAPTATION_RESOURCE_ADAPTATION_PROCESSOR_H_ |
| 13 | |
Evan Shrubsole | 0dcb470 | 2020-05-07 13:45:14 +0200 | [diff] [blame] | 14 | #include <map> |
Henrik Boström | 87eece9 | 2020-04-17 18:36:19 +0200 | [diff] [blame] | 15 | #include <memory> |
Henrik Boström | f0eef12 | 2020-05-28 16:22:42 +0200 | [diff] [blame] | 16 | #include <string> |
Evan Shrubsole | 6446903 | 2020-06-11 10:45:29 +0200 | [diff] [blame] | 17 | #include <utility> |
Henrik Boström | 87eece9 | 2020-04-17 18:36:19 +0200 | [diff] [blame] | 18 | #include <vector> |
| 19 | |
| 20 | #include "absl/types/optional.h" |
Henrik Boström | e2e8c17 | 2020-06-03 09:24:06 +0200 | [diff] [blame] | 21 | #include "api/adaptation/resource.h" |
Henrik Boström | 87eece9 | 2020-04-17 18:36:19 +0200 | [diff] [blame] | 22 | #include "api/rtp_parameters.h" |
Henrik Boström | c55516d | 2020-05-11 16:29:22 +0200 | [diff] [blame] | 23 | #include "api/scoped_refptr.h" |
Henrik Boström | 39ab1b5 | 2020-06-03 09:21:34 +0200 | [diff] [blame] | 24 | #include "api/task_queue/task_queue_base.h" |
Henrik Boström | 87eece9 | 2020-04-17 18:36:19 +0200 | [diff] [blame] | 25 | #include "api/video/video_frame.h" |
| 26 | #include "api/video/video_stream_encoder_observer.h" |
Henrik Boström | 0f0aa9c | 2020-06-02 13:02:36 +0200 | [diff] [blame] | 27 | #include "call/adaptation/adaptation_constraint.h" |
| 28 | #include "call/adaptation/adaptation_listener.h" |
Henrik Boström | 87eece9 | 2020-04-17 18:36:19 +0200 | [diff] [blame] | 29 | #include "call/adaptation/resource_adaptation_processor_interface.h" |
| 30 | #include "call/adaptation/video_source_restrictions.h" |
| 31 | #include "call/adaptation/video_stream_adapter.h" |
| 32 | #include "call/adaptation/video_stream_input_state.h" |
| 33 | #include "call/adaptation/video_stream_input_state_provider.h" |
| 34 | |
| 35 | namespace webrtc { |
| 36 | |
Henrik Boström | c55516d | 2020-05-11 16:29:22 +0200 | [diff] [blame] | 37 | // The Resource Adaptation Processor is responsible for reacting to resource |
| 38 | // usage measurements (e.g. overusing or underusing CPU). When a resource is |
| 39 | // overused the Processor is responsible for performing mitigations in order to |
| 40 | // consume less resources. |
| 41 | // |
| 42 | // Today we have one Processor per VideoStreamEncoder and the Processor is only |
| 43 | // capable of restricting resolution or frame rate of the encoded stream. In the |
| 44 | // future we should have a single Processor responsible for all encoded streams, |
| 45 | // and it should be capable of reconfiguring other things than just |
| 46 | // VideoSourceRestrictions (e.g. reduce render frame rate). |
| 47 | // See Resource-Adaptation hotlist: |
| 48 | // https://bugs.chromium.org/u/590058293/hotlists/Resource-Adaptation |
| 49 | // |
| 50 | // The ResourceAdaptationProcessor is single-threaded. It may be constructed on |
| 51 | // any thread but MUST subsequently be used and destroyed on a single sequence, |
| 52 | // i.e. the "resource adaptation task queue". |
Henrik Boström | 87eece9 | 2020-04-17 18:36:19 +0200 | [diff] [blame] | 53 | class ResourceAdaptationProcessor : public ResourceAdaptationProcessorInterface, |
Evan Shrubsole | ec0af26 | 2020-07-01 11:47:46 +0200 | [diff] [blame^] | 54 | public VideoSourceRestrictionsListener, |
Henrik Boström | 87eece9 | 2020-04-17 18:36:19 +0200 | [diff] [blame] | 55 | public ResourceListener { |
| 56 | public: |
| 57 | ResourceAdaptationProcessor( |
| 58 | VideoStreamInputStateProvider* input_state_provider, |
Evan Shrubsole | ec0af26 | 2020-07-01 11:47:46 +0200 | [diff] [blame^] | 59 | VideoStreamEncoderObserver* encoder_stats_observer, |
| 60 | VideoStreamAdapter* video_stream_adapter); |
Henrik Boström | 87eece9 | 2020-04-17 18:36:19 +0200 | [diff] [blame] | 61 | ~ResourceAdaptationProcessor() override; |
| 62 | |
Henrik Boström | 39ab1b5 | 2020-06-03 09:21:34 +0200 | [diff] [blame] | 63 | void SetResourceAdaptationQueue( |
| 64 | TaskQueueBase* resource_adaptation_queue) override; |
Henrik Boström | c55516d | 2020-05-11 16:29:22 +0200 | [diff] [blame] | 65 | |
Henrik Boström | 87eece9 | 2020-04-17 18:36:19 +0200 | [diff] [blame] | 66 | // ResourceAdaptationProcessorInterface implementation. |
| 67 | DegradationPreference degradation_preference() const override; |
| 68 | DegradationPreference effective_degradation_preference() const override; |
| 69 | |
Evan Shrubsole | ec0af26 | 2020-07-01 11:47:46 +0200 | [diff] [blame^] | 70 | void AddResourceLimitationsListener( |
| 71 | ResourceLimitationsListener* limitations_listener) override; |
| 72 | void RemoveResourceLimitationsListener( |
| 73 | ResourceLimitationsListener* limitations_listener) override; |
Henrik Boström | c55516d | 2020-05-11 16:29:22 +0200 | [diff] [blame] | 74 | void AddResource(rtc::scoped_refptr<Resource> resource) override; |
Henrik Boström | f4a9991 | 2020-06-11 12:07:14 +0200 | [diff] [blame] | 75 | std::vector<rtc::scoped_refptr<Resource>> GetResources() const override; |
Henrik Boström | c55516d | 2020-05-11 16:29:22 +0200 | [diff] [blame] | 76 | void RemoveResource(rtc::scoped_refptr<Resource> resource) override; |
Henrik Boström | 0f0aa9c | 2020-06-02 13:02:36 +0200 | [diff] [blame] | 77 | void AddAdaptationConstraint( |
| 78 | AdaptationConstraint* adaptation_constraint) override; |
| 79 | void RemoveAdaptationConstraint( |
| 80 | AdaptationConstraint* adaptation_constraint) override; |
| 81 | void AddAdaptationListener(AdaptationListener* adaptation_listener) override; |
| 82 | void RemoveAdaptationListener( |
| 83 | AdaptationListener* adaptation_listener) override; |
Henrik Boström | 87eece9 | 2020-04-17 18:36:19 +0200 | [diff] [blame] | 84 | |
| 85 | void SetDegradationPreference( |
| 86 | DegradationPreference degradation_preference) override; |
| 87 | void SetIsScreenshare(bool is_screenshare) override; |
Henrik Boström | 87eece9 | 2020-04-17 18:36:19 +0200 | [diff] [blame] | 88 | |
| 89 | // ResourceListener implementation. |
| 90 | // Triggers OnResourceUnderuse() or OnResourceOveruse(). |
Henrik Boström | 39ab1b5 | 2020-06-03 09:21:34 +0200 | [diff] [blame] | 91 | void OnResourceUsageStateMeasured(rtc::scoped_refptr<Resource> resource, |
| 92 | ResourceUsageState usage_state) override; |
Henrik Boström | 87eece9 | 2020-04-17 18:36:19 +0200 | [diff] [blame] | 93 | |
Evan Shrubsole | ec0af26 | 2020-07-01 11:47:46 +0200 | [diff] [blame^] | 94 | // VideoSourceRestrictionsListener implementation. |
| 95 | void OnVideoSourceRestrictionsUpdated( |
| 96 | VideoSourceRestrictions restrictions, |
| 97 | const VideoAdaptationCounters& adaptation_counters, |
| 98 | rtc::scoped_refptr<Resource> reason, |
| 99 | const VideoSourceRestrictions& unfiltered_restrictions) override; |
| 100 | |
Henrik Boström | 3745d3f | 2020-04-30 10:13:29 +0200 | [diff] [blame] | 101 | // May trigger 1-2 adaptations. It is meant to reduce resolution but this is |
| 102 | // not guaranteed. It may adapt frame rate, which does not address the issue. |
| 103 | // TODO(hbos): Can we get rid of this? |
Henrik Boström | 87eece9 | 2020-04-17 18:36:19 +0200 | [diff] [blame] | 104 | void TriggerAdaptationDueToFrameDroppedDueToSize( |
Henrik Boström | c55516d | 2020-05-11 16:29:22 +0200 | [diff] [blame] | 105 | rtc::scoped_refptr<Resource> reason_resource) override; |
Henrik Boström | 87eece9 | 2020-04-17 18:36:19 +0200 | [diff] [blame] | 106 | |
| 107 | private: |
| 108 | bool HasSufficientInputForAdaptation( |
| 109 | const VideoStreamInputState& input_state) const; |
| 110 | |
Henrik Boström | 39ab1b5 | 2020-06-03 09:21:34 +0200 | [diff] [blame] | 111 | // If resource usage measurements happens off the adaptation task queue, this |
| 112 | // class takes care of posting the measurement for the processor to handle it |
| 113 | // on the adaptation task queue. |
| 114 | class ResourceListenerDelegate : public rtc::RefCountInterface, |
| 115 | public ResourceListener { |
| 116 | public: |
| 117 | explicit ResourceListenerDelegate(ResourceAdaptationProcessor* processor); |
| 118 | |
| 119 | void SetResourceAdaptationQueue(TaskQueueBase* resource_adaptation_queue); |
| 120 | void OnProcessorDestroyed(); |
| 121 | |
| 122 | // ResourceListener implementation. |
| 123 | void OnResourceUsageStateMeasured(rtc::scoped_refptr<Resource> resource, |
| 124 | ResourceUsageState usage_state) override; |
| 125 | |
| 126 | private: |
| 127 | TaskQueueBase* resource_adaptation_queue_; |
| 128 | ResourceAdaptationProcessor* processor_ |
| 129 | RTC_GUARDED_BY(resource_adaptation_queue_); |
| 130 | }; |
| 131 | |
Henrik Boström | f0eef12 | 2020-05-28 16:22:42 +0200 | [diff] [blame] | 132 | enum class MitigationResult { |
| 133 | kDisabled, |
| 134 | kInsufficientInput, |
Evan Shrubsole | 6446903 | 2020-06-11 10:45:29 +0200 | [diff] [blame] | 135 | kNotMostLimitedResource, |
| 136 | kSharedMostLimitedResource, |
Henrik Boström | f0eef12 | 2020-05-28 16:22:42 +0200 | [diff] [blame] | 137 | kRejectedByAdapter, |
Henrik Boström | 0f0aa9c | 2020-06-02 13:02:36 +0200 | [diff] [blame] | 138 | kRejectedByConstraint, |
Henrik Boström | f0eef12 | 2020-05-28 16:22:42 +0200 | [diff] [blame] | 139 | kAdaptationApplied, |
| 140 | }; |
| 141 | |
| 142 | struct MitigationResultAndLogMessage { |
| 143 | MitigationResultAndLogMessage(); |
| 144 | MitigationResultAndLogMessage(MitigationResult result, std::string message); |
| 145 | MitigationResult result; |
| 146 | std::string message; |
| 147 | }; |
| 148 | |
Henrik Boström | 87eece9 | 2020-04-17 18:36:19 +0200 | [diff] [blame] | 149 | // Performs the adaptation by getting the next target, applying it and |
| 150 | // informing listeners of the new VideoSourceRestriction and adaptation |
| 151 | // counters. |
Henrik Boström | f0eef12 | 2020-05-28 16:22:42 +0200 | [diff] [blame] | 152 | MitigationResultAndLogMessage OnResourceUnderuse( |
| 153 | rtc::scoped_refptr<Resource> reason_resource); |
| 154 | MitigationResultAndLogMessage OnResourceOveruse( |
| 155 | rtc::scoped_refptr<Resource> reason_resource); |
Henrik Boström | 87eece9 | 2020-04-17 18:36:19 +0200 | [diff] [blame] | 156 | |
| 157 | // Needs to be invoked any time |degradation_preference_| or |is_screenshare_| |
| 158 | // changes to ensure |effective_degradation_preference_| is up-to-date. |
| 159 | void MaybeUpdateEffectiveDegradationPreference(); |
Evan Shrubsole | 6446903 | 2020-06-11 10:45:29 +0200 | [diff] [blame] | 160 | |
| 161 | void UpdateResourceLimitations( |
| 162 | rtc::scoped_refptr<Resource> reason_resource, |
| 163 | const VideoStreamAdapter::RestrictionsWithCounters& |
| 164 | peek_next_restrictions) RTC_RUN_ON(resource_adaptation_queue_); |
| 165 | |
| 166 | // Searches |adaptation_limits_by_resources_| for each resource with the |
| 167 | // highest total adaptation counts. Adaptation up may only occur if the |
| 168 | // resource performing the adaptation is the only most limited resource. This |
| 169 | // function returns the list of all most limited resources as well as the |
| 170 | // corresponding adaptation of that resource. |
Evan Shrubsole | ce971b0 | 2020-06-12 16:00:03 +0200 | [diff] [blame] | 171 | std::pair<std::vector<rtc::scoped_refptr<Resource>>, |
| 172 | VideoStreamAdapter::RestrictionsWithCounters> |
Evan Shrubsole | 6446903 | 2020-06-11 10:45:29 +0200 | [diff] [blame] | 173 | FindMostLimitedResources() const RTC_RUN_ON(resource_adaptation_queue_); |
Henrik Boström | 87eece9 | 2020-04-17 18:36:19 +0200 | [diff] [blame] | 174 | |
Evan Shrubsole | ce971b0 | 2020-06-12 16:00:03 +0200 | [diff] [blame] | 175 | void MaybeUpdateResourceLimitationsOnResourceRemoval( |
| 176 | VideoStreamAdapter::RestrictionsWithCounters removed_limitations) |
| 177 | RTC_RUN_ON(resource_adaptation_queue_); |
| 178 | |
Henrik Boström | 39ab1b5 | 2020-06-03 09:21:34 +0200 | [diff] [blame] | 179 | TaskQueueBase* resource_adaptation_queue_; |
| 180 | rtc::scoped_refptr<ResourceListenerDelegate> resource_listener_delegate_; |
Henrik Boström | 87eece9 | 2020-04-17 18:36:19 +0200 | [diff] [blame] | 181 | // Input and output. |
Henrik Boström | c55516d | 2020-05-11 16:29:22 +0200 | [diff] [blame] | 182 | VideoStreamInputStateProvider* const input_state_provider_ |
Henrik Boström | 39ab1b5 | 2020-06-03 09:21:34 +0200 | [diff] [blame] | 183 | RTC_GUARDED_BY(resource_adaptation_queue_); |
Henrik Boström | c55516d | 2020-05-11 16:29:22 +0200 | [diff] [blame] | 184 | VideoStreamEncoderObserver* const encoder_stats_observer_ |
Henrik Boström | 39ab1b5 | 2020-06-03 09:21:34 +0200 | [diff] [blame] | 185 | RTC_GUARDED_BY(resource_adaptation_queue_); |
Evan Shrubsole | ec0af26 | 2020-07-01 11:47:46 +0200 | [diff] [blame^] | 186 | std::vector<ResourceLimitationsListener*> resource_limitations_listeners_ |
Henrik Boström | 39ab1b5 | 2020-06-03 09:21:34 +0200 | [diff] [blame] | 187 | RTC_GUARDED_BY(resource_adaptation_queue_); |
Henrik Boström | c55516d | 2020-05-11 16:29:22 +0200 | [diff] [blame] | 188 | std::vector<rtc::scoped_refptr<Resource>> resources_ |
Henrik Boström | 39ab1b5 | 2020-06-03 09:21:34 +0200 | [diff] [blame] | 189 | RTC_GUARDED_BY(resource_adaptation_queue_); |
Henrik Boström | 0f0aa9c | 2020-06-02 13:02:36 +0200 | [diff] [blame] | 190 | std::vector<AdaptationConstraint*> adaptation_constraints_ |
Henrik Boström | 39ab1b5 | 2020-06-03 09:21:34 +0200 | [diff] [blame] | 191 | RTC_GUARDED_BY(resource_adaptation_queue_); |
Henrik Boström | 0f0aa9c | 2020-06-02 13:02:36 +0200 | [diff] [blame] | 192 | std::vector<AdaptationListener*> adaptation_listeners_ |
Henrik Boström | 39ab1b5 | 2020-06-03 09:21:34 +0200 | [diff] [blame] | 193 | RTC_GUARDED_BY(resource_adaptation_queue_); |
Henrik Boström | c55516d | 2020-05-11 16:29:22 +0200 | [diff] [blame] | 194 | // Purely used for statistics, does not ensure mapped resources stay alive. |
Evan Shrubsole | ce971b0 | 2020-06-12 16:00:03 +0200 | [diff] [blame] | 195 | std::map<rtc::scoped_refptr<Resource>, |
| 196 | VideoStreamAdapter::RestrictionsWithCounters> |
Evan Shrubsole | 6446903 | 2020-06-11 10:45:29 +0200 | [diff] [blame] | 197 | adaptation_limits_by_resources_ |
| 198 | RTC_GUARDED_BY(resource_adaptation_queue_); |
Henrik Boström | 87eece9 | 2020-04-17 18:36:19 +0200 | [diff] [blame] | 199 | // Adaptation strategy settings. |
Henrik Boström | c55516d | 2020-05-11 16:29:22 +0200 | [diff] [blame] | 200 | DegradationPreference degradation_preference_ |
Henrik Boström | 39ab1b5 | 2020-06-03 09:21:34 +0200 | [diff] [blame] | 201 | RTC_GUARDED_BY(resource_adaptation_queue_); |
Henrik Boström | c55516d | 2020-05-11 16:29:22 +0200 | [diff] [blame] | 202 | DegradationPreference effective_degradation_preference_ |
Henrik Boström | 39ab1b5 | 2020-06-03 09:21:34 +0200 | [diff] [blame] | 203 | RTC_GUARDED_BY(resource_adaptation_queue_); |
| 204 | bool is_screenshare_ RTC_GUARDED_BY(resource_adaptation_queue_); |
Henrik Boström | 87eece9 | 2020-04-17 18:36:19 +0200 | [diff] [blame] | 205 | // Responsible for generating and applying possible adaptations. |
Evan Shrubsole | ec0af26 | 2020-07-01 11:47:46 +0200 | [diff] [blame^] | 206 | VideoStreamAdapter* const stream_adapter_ |
Henrik Boström | 39ab1b5 | 2020-06-03 09:21:34 +0200 | [diff] [blame] | 207 | RTC_GUARDED_BY(resource_adaptation_queue_); |
Henrik Boström | c55516d | 2020-05-11 16:29:22 +0200 | [diff] [blame] | 208 | VideoSourceRestrictions last_reported_source_restrictions_ |
Henrik Boström | 39ab1b5 | 2020-06-03 09:21:34 +0200 | [diff] [blame] | 209 | RTC_GUARDED_BY(resource_adaptation_queue_); |
Henrik Boström | f0eef12 | 2020-05-28 16:22:42 +0200 | [diff] [blame] | 210 | // Keeps track of previous mitigation results per resource since the last |
| 211 | // successful adaptation. Used to avoid RTC_LOG spam. |
| 212 | std::map<Resource*, MitigationResult> previous_mitigation_results_ |
Henrik Boström | 39ab1b5 | 2020-06-03 09:21:34 +0200 | [diff] [blame] | 213 | RTC_GUARDED_BY(resource_adaptation_queue_); |
Henrik Boström | 91aa732 | 2020-04-28 12:24:33 +0200 | [diff] [blame] | 214 | // Prevents recursion. |
| 215 | // |
| 216 | // This is used to prevent triggering resource adaptation in the process of |
| 217 | // already handling resouce adaptation, since that could cause the same states |
| 218 | // to be modified in unexpected ways. Example: |
| 219 | // |
| 220 | // Resource::OnResourceUsageStateMeasured() -> |
| 221 | // ResourceAdaptationProcessor::OnResourceOveruse() -> |
| 222 | // Resource::OnAdaptationApplied() -> |
| 223 | // Resource::OnResourceUsageStateMeasured() -> |
| 224 | // ResourceAdaptationProcessor::OnResourceOveruse() // Boom, not allowed. |
Henrik Boström | 39ab1b5 | 2020-06-03 09:21:34 +0200 | [diff] [blame] | 225 | bool processing_in_progress_ RTC_GUARDED_BY(resource_adaptation_queue_); |
Henrik Boström | 87eece9 | 2020-04-17 18:36:19 +0200 | [diff] [blame] | 226 | }; |
| 227 | |
| 228 | } // namespace webrtc |
| 229 | |
| 230 | #endif // CALL_ADAPTATION_RESOURCE_ADAPTATION_PROCESSOR_H_ |