blob: e80bd6f1f65f509879e02cecd660374e39b0251d [file] [log] [blame]
Henrik Boströmb08882b2020-01-07 10:11:17 +01001/*
2 * Copyright 2019 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 VIDEO_OVERUSE_FRAME_DETECTOR_RESOURCE_ADAPTATION_MODULE_H_
12#define VIDEO_OVERUSE_FRAME_DETECTOR_RESOURCE_ADAPTATION_MODULE_H_
13
14#include <map>
15#include <memory>
16#include <string>
17#include <utility>
18#include <vector>
19
20#include "absl/types/optional.h"
21#include "api/rtp_parameters.h"
22#include "api/video/video_frame.h"
Henrik Boströmb08882b2020-01-07 10:11:17 +010023#include "api/video/video_source_interface.h"
24#include "api/video/video_stream_encoder_observer.h"
Henrik Boström4bab2fc2020-01-21 11:18:06 +010025#include "api/video_codecs/video_codec.h"
Henrik Boströmb08882b2020-01-07 10:11:17 +010026#include "api/video_codecs/video_encoder.h"
27#include "api/video_codecs/video_encoder_config.h"
Henrik Boström48258ac2020-02-06 12:49:57 +010028#include "call/adaptation/resource.h"
Henrik Boström382cc6d2020-01-07 10:15:04 +010029#include "call/adaptation/resource_adaptation_module_interface.h"
Henrik Boströmb08882b2020-01-07 10:11:17 +010030#include "rtc_base/experiments/balanced_degradation_settings.h"
Evan Shrubsolee331a122020-02-05 13:30:33 +010031#include "rtc_base/experiments/quality_rampup_experiment.h"
Evan Shrubsole7c3a1fc2020-02-04 16:26:38 +010032#include "rtc_base/experiments/quality_scaler_settings.h"
Evan Shrubsole33be9df2020-03-05 18:39:32 +010033#include "rtc_base/strings/string_builder.h"
Evan Shrubsole7c3a1fc2020-02-04 16:26:38 +010034#include "system_wrappers/include/clock.h"
Henrik Boströmefbec9a2020-03-06 10:41:25 +010035#include "video/adaptation/adaptation_counters.h"
36#include "video/adaptation/video_stream_adapter.h"
Henrik Boström06534852020-02-06 14:27:00 +010037#include "video/encode_usage_resource.h"
Henrik Boströmb08882b2020-01-07 10:11:17 +010038#include "video/overuse_frame_detector.h"
Henrik Boström06534852020-02-06 14:27:00 +010039#include "video/quality_scaler_resource.h"
Henrik Boströmb08882b2020-01-07 10:11:17 +010040
41namespace webrtc {
42
Henrik Boström382cc6d2020-01-07 10:15:04 +010043class VideoStreamEncoder;
44
Henrik Boströmb08882b2020-01-07 10:11:17 +010045// This class is used by the VideoStreamEncoder and is responsible for adapting
46// resolution up or down based on encode usage percent. It keeps track of video
47// source settings, adaptation counters and may get influenced by
48// VideoStreamEncoder's quality scaler through AdaptUp() and AdaptDown() calls.
Henrik Boström07b17df2020-01-15 11:42:12 +010049//
50// This class is single-threaded. The caller is responsible for ensuring safe
51// usage.
Henrik Boströmb08882b2020-01-07 10:11:17 +010052// TODO(hbos): Add unittests specific to this class, it is currently only tested
53// indirectly in video_stream_encoder_unittest.cc and other tests exercising
54// VideoStreamEncoder.
Henrik Boströmefbec9a2020-03-06 10:41:25 +010055// TODO(https://crbug.com/webrtc/11222): Rename this class to something more
56// appropriate and move it to the video/adaptation/ subdirectory.
Henrik Boströmb08882b2020-01-07 10:11:17 +010057class OveruseFrameDetectorResourceAdaptationModule
Henrik Boström48258ac2020-02-06 12:49:57 +010058 : public ResourceAdaptationModuleInterface,
59 public ResourceListener {
Henrik Boströmb08882b2020-01-07 10:11:17 +010060 public:
Henrik Boström07b17df2020-01-15 11:42:12 +010061 // The module can be constructed on any sequence, but must be initialized and
62 // used on a single sequence, e.g. the encoder queue.
Henrik Boströmb08882b2020-01-07 10:11:17 +010063 OveruseFrameDetectorResourceAdaptationModule(
Evan Shrubsole7c3a1fc2020-02-04 16:26:38 +010064 Clock* clock,
Henrik Boströmad515a22020-01-27 13:38:05 +010065 bool experiment_cpu_load_estimator,
Henrik Boströmb08882b2020-01-07 10:11:17 +010066 std::unique_ptr<OveruseFrameDetector> overuse_detector,
Henrik Boströmd2382002020-01-10 15:44:01 +010067 VideoStreamEncoderObserver* encoder_stats_observer,
68 ResourceAdaptationModuleListener* adaptation_listener);
Henrik Boströmb08882b2020-01-07 10:11:17 +010069 ~OveruseFrameDetectorResourceAdaptationModule() override;
70
Henrik Boströmb08882b2020-01-07 10:11:17 +010071 DegradationPreference degradation_preference() const {
Henrik Boströmb08882b2020-01-07 10:11:17 +010072 return degradation_preference_;
73 }
74
Henrik Boström382cc6d2020-01-07 10:15:04 +010075 // ResourceAdaptationModuleInterface implementation.
Henrik Boströma3d42522020-01-16 13:55:29 +010076 void StartResourceAdaptation(
Henrik Boströmd2382002020-01-10 15:44:01 +010077 ResourceAdaptationModuleListener* adaptation_listener) override;
Henrik Boströma3d42522020-01-16 13:55:29 +010078 void StopResourceAdaptation() override;
Evan Shrubsoleaa6fbc12020-02-25 16:26:01 +010079 // Uses a default AdaptReason of kCpu.
80 void AddResource(Resource* resource) override;
81 void AddResource(Resource* resource,
82 AdaptationObserverInterface::AdaptReason reason);
Henrik Boströma3d42522020-01-16 13:55:29 +010083 void SetHasInputVideo(bool has_input_video) override;
84 void SetDegradationPreference(
85 DegradationPreference degradation_preference) override;
Henrik Boström4bab2fc2020-01-21 11:18:06 +010086 void SetEncoderSettings(EncoderSettings encoder_settings) override;
Evan Shrubsole7c3a1fc2020-02-04 16:26:38 +010087 void SetStartBitrate(DataRate start_bitrate) override;
88 void SetTargetBitrate(DataRate target_bitrate) override;
Evan Shrubsolee331a122020-02-05 13:30:33 +010089 void SetEncoderRates(
90 const VideoEncoder::RateControlParameters& encoder_rates) override;
Henrik Boström382cc6d2020-01-07 10:15:04 +010091
Henrik Boströmd4578ae2020-01-22 16:16:04 +010092 void OnFrame(const VideoFrame& frame) override;
93 void OnFrameDroppedDueToSize() override;
Mirko Bonadei2e161c42020-02-20 08:45:01 +000094 void OnMaybeEncodeFrame() override;
Henrik Boströmd4578ae2020-01-22 16:16:04 +010095 void OnEncodeStarted(const VideoFrame& cropped_frame,
96 int64_t time_when_first_seen_us) override;
Evan Shrubsolebfe3ef82020-01-30 14:29:35 +010097 void OnEncodeCompleted(const EncodedImage& encoded_image,
Henrik Boströmd4578ae2020-01-22 16:16:04 +010098 int64_t time_sent_in_us,
Henrik Boströmd4578ae2020-01-22 16:16:04 +010099 absl::optional<int> encode_duration_us) override;
Evan Shrubsolec809e8b2020-01-31 15:36:35 +0100100 void OnFrameDropped(EncodedImageCallback::DropReason reason) override;
Evan Shrubsolee331a122020-02-05 13:30:33 +0100101
Henrik Boström7875c992020-02-06 10:35:00 +0100102 // TODO(hbos): Is dropping initial frames really just a special case of "don't
103 // encode frames right now"? Can this be part of VideoSourceRestrictions,
104 // which handles the output of the rest of the encoder settings? This is
105 // something we'll need to support for "disable video due to overuse", not
106 // initial frames.
Evan Shrubsolef2be3ef2020-02-03 10:43:31 +0100107 bool DropInitialFrames() const;
Henrik Boströmb08882b2020-01-07 10:11:17 +0100108
Evan Shrubsolec81798b2020-02-03 15:46:08 +0100109 // TODO(eshr): This can be made private if we configure on
110 // SetDegredationPreference and SetEncoderSettings.
111 // (https://crbug.com/webrtc/11338)
112 void ConfigureQualityScaler(const VideoEncoder::EncoderInfo& encoder_info);
Henrik Boströmb08882b2020-01-07 10:11:17 +0100113
Henrik Boström48258ac2020-02-06 12:49:57 +0100114 // ResourceUsageListener implementation.
115 ResourceListenerResponse OnResourceUsageStateMeasured(
116 const Resource& resource) override;
117
Evan Shrubsole33be9df2020-03-05 18:39:32 +0100118 // For reasons of adaptation and statistics, we not only count the total
119 // number of adaptations, but we also count the number of adaptations per
120 // reason.
121 // This method takes the new total number of adaptations and allocates that to
122 // the "active" count - number of adaptations for the current reason.
123 // The "other" count is the number of adaptations for the other reason.
124 // This must be called for each adaptation step made.
125 static void OnAdaptationCountChanged(
126 const AdaptationCounters& adaptation_count,
127 AdaptationCounters* active_count,
128 AdaptationCounters* other_active);
129
Henrik Boströmb08882b2020-01-07 10:11:17 +0100130 private:
Henrik Boström8cfecac2020-02-07 11:29:14 +0100131 class InitialFrameDropper;
Henrik Boströmb08882b2020-01-07 10:11:17 +0100132
Evan Shrubsoleaa6fbc12020-02-25 16:26:01 +0100133 enum class State { kStopped, kStarted };
134
Henrik Boström60383832020-02-28 09:03:53 +0100135 // Returns a target that we are guaranteed to be able to adapt to, or null if
136 // adaptation is not desired or not possible.
Henrik Boströmb0f2e0c2020-03-06 13:32:03 +0100137 absl::optional<VideoStreamAdapter::AdaptationTarget> GetAdaptUpTarget(
Henrik Boström60383832020-02-28 09:03:53 +0100138 int input_pixels,
139 int input_fps,
140 AdaptationObserverInterface::AdaptReason reason) const;
Henrik Boströmb0f2e0c2020-03-06 13:32:03 +0100141 absl::optional<VideoStreamAdapter::AdaptationTarget> GetAdaptDownTarget(
Henrik Boström60383832020-02-28 09:03:53 +0100142 int input_pixels,
143 int input_fps,
Evan Shrubsole33be9df2020-03-05 18:39:32 +0100144 int min_pixels_per_frame) const;
Henrik Boström60383832020-02-28 09:03:53 +0100145 // Applies the |target| to |source_restrictor_|.
Henrik Boströmb0f2e0c2020-03-06 13:32:03 +0100146 void ApplyAdaptationTarget(const VideoStreamAdapter::AdaptationTarget& target,
147 int input_pixels,
148 int input_fps,
149 int min_pixels_per_frame);
Henrik Boström60383832020-02-28 09:03:53 +0100150
151 // Performs the adaptation by getting the next target, applying it and
152 // informing listeners of the new VideoSourceRestriction and adapt counters.
Henrik Boström48258ac2020-02-06 12:49:57 +0100153 void OnResourceUnderuse(AdaptationObserverInterface::AdaptReason reason);
154 ResourceListenerResponse OnResourceOveruse(
155 AdaptationObserverInterface::AdaptReason reason);
156
Henrik Boströmad515a22020-01-27 13:38:05 +0100157 CpuOveruseOptions GetCpuOveruseOptions() const;
Henrik Boströmd4578ae2020-01-22 16:16:04 +0100158 int LastInputFrameSizeOrDefault() const;
Henrik Boström60383832020-02-28 09:03:53 +0100159 int MinPixelsPerFrame() const;
Evan Shrubsolec81798b2020-02-03 15:46:08 +0100160 VideoStreamEncoderObserver::AdaptationSteps GetActiveCounts(
Henrik Boström7875c992020-02-06 10:35:00 +0100161 AdaptationObserverInterface::AdaptReason reason);
Henrik Boströmb0f2e0c2020-03-06 13:32:03 +0100162 VideoStreamAdapter::VideoInputMode GetVideoInputMode() const;
Henrik Boström4bab2fc2020-01-21 11:18:06 +0100163
Henrik Boström8234b922020-01-13 17:26:50 +0100164 // Makes |video_source_restrictions_| up-to-date and informs the
165 // |adaptation_listener_| if restrictions are changed, allowing the listener
166 // to reconfigure the source accordingly.
Henrik Boström07b17df2020-01-15 11:42:12 +0100167 void MaybeUpdateVideoSourceRestrictions();
Henrik Boström7875c992020-02-06 10:35:00 +0100168 // Calculates an up-to-date value of the target frame rate and informs the
169 // |encode_usage_resource_| of the new value.
Henrik Boströmfae6f0e2020-01-20 11:16:50 +0100170 void MaybeUpdateTargetFrameRate();
Henrik Boström8234b922020-01-13 17:26:50 +0100171
Evan Shrubsolec81798b2020-02-03 15:46:08 +0100172 // Use nullopt to disable quality scaling.
173 void UpdateQualityScalerSettings(
174 absl::optional<VideoEncoder::QpThresholds> qp_thresholds);
175
Henrik Boström7875c992020-02-06 10:35:00 +0100176 void UpdateAdaptationStats(AdaptationObserverInterface::AdaptReason reason);
Henrik Boströmb08882b2020-01-07 10:11:17 +0100177
Evan Shrubsolee331a122020-02-05 13:30:33 +0100178 // Checks to see if we should execute the quality rampup experiment. The
179 // experiment resets all video restrictions at the start of the call in the
180 // case the bandwidth estimate is high enough.
181 // TODO(https://crbug.com/webrtc/11222) Move experiment details into an inner
182 // class.
183 void MaybePerformQualityRampupExperiment();
184 void ResetVideoSourceRestrictions();
185
Evan Shrubsole33be9df2020-03-05 18:39:32 +0100186 std::string ActiveCountsToString() const;
187
Henrik Boström8234b922020-01-13 17:26:50 +0100188 ResourceAdaptationModuleListener* const adaptation_listener_;
Evan Shrubsole7c3a1fc2020-02-04 16:26:38 +0100189 Clock* clock_;
Evan Shrubsoleaa6fbc12020-02-25 16:26:01 +0100190 State state_;
Henrik Boströmad515a22020-01-27 13:38:05 +0100191 const bool experiment_cpu_load_estimator_;
Henrik Boström8234b922020-01-13 17:26:50 +0100192 // The restrictions that |adaptation_listener_| is informed of.
Henrik Boström07b17df2020-01-15 11:42:12 +0100193 VideoSourceRestrictions video_source_restrictions_;
Henrik Boströma3d42522020-01-16 13:55:29 +0100194 bool has_input_video_;
Henrik Boströmb0f2e0c2020-03-06 13:32:03 +0100195 // TODO(https://crbug.com/webrtc/11393): DegradationPreference has mostly
196 // moved to VideoStreamAdapter. Move it entirely and delete it from this
197 // class. If the responsibility of generating next steps for adaptations is
198 // owned by the adapter, this class has no buisness relying on implementation
199 // details of the adapter.
Henrik Boström07b17df2020-01-15 11:42:12 +0100200 DegradationPreference degradation_preference_;
Henrik Boströmce0ea492020-01-13 11:27:18 +0100201 // Keeps track of source restrictions that this adaptation module outputs.
Henrik Boströmefbec9a2020-03-06 10:41:25 +0100202 const std::unique_ptr<VideoStreamAdapter> stream_adapter_;
Henrik Boström7875c992020-02-06 10:35:00 +0100203 const std::unique_ptr<EncodeUsageResource> encode_usage_resource_;
204 const std::unique_ptr<QualityScalerResource> quality_scaler_resource_;
Henrik Boström8cfecac2020-02-07 11:29:14 +0100205 const std::unique_ptr<InitialFrameDropper> initial_frame_dropper_;
Henrik Boström7875c992020-02-06 10:35:00 +0100206 const bool quality_scaling_experiment_enabled_;
Henrik Boströmd4578ae2020-01-22 16:16:04 +0100207 absl::optional<int> last_input_frame_size_;
Henrik Boströmfae6f0e2020-01-20 11:16:50 +0100208 absl::optional<double> target_frame_rate_;
Evan Shrubsole7c3a1fc2020-02-04 16:26:38 +0100209 // This is the last non-zero target bitrate for the encoder.
210 absl::optional<uint32_t> encoder_target_bitrate_bps_;
Evan Shrubsolee331a122020-02-05 13:30:33 +0100211 absl::optional<VideoEncoder::RateControlParameters> encoder_rates_;
Evan Shrubsolee331a122020-02-05 13:30:33 +0100212 bool quality_rampup_done_;
213 QualityRampupExperiment quality_rampup_experiment_;
Henrik Boström4bab2fc2020-01-21 11:18:06 +0100214 absl::optional<EncoderSettings> encoder_settings_;
Henrik Boström07b17df2020-01-15 11:42:12 +0100215 VideoStreamEncoderObserver* const encoder_stats_observer_;
Evan Shrubsoleaa6fbc12020-02-25 16:26:01 +0100216
217 // Ties a resource to a reason for statistical reporting. This AdaptReason is
218 // also used by this module to make decisions about how to adapt up/down.
219 struct ResourceAndReason {
220 ResourceAndReason(Resource* resource,
221 AdaptationObserverInterface::AdaptReason reason)
222 : resource(resource), reason(reason) {}
223 virtual ~ResourceAndReason() = default;
224
225 Resource* const resource;
226 const AdaptationObserverInterface::AdaptReason reason;
227 };
228 std::vector<ResourceAndReason> resources_;
Evan Shrubsole33be9df2020-03-05 18:39:32 +0100229 // One AdaptationCounter for each reason, tracking the number of times we have
230 // adapted for each reason. The sum of active_counts_ MUST always equal the
231 // total adaptation provided by the VideoSourceRestrictions.
232 // TODO(https://crbug.com/webrtc/11392): Move all active count logic to
233 // encoder_stats_observer_; Counters used for deciding if the video resolution
234 // or framerate is currently restricted, and if so, why, on a per degradation
235 // preference basis.
236 std::array<AdaptationCounters, AdaptationObserverInterface::kScaleReasonSize>
237 active_counts_;
Henrik Boströmb08882b2020-01-07 10:11:17 +0100238};
239
240} // namespace webrtc
241
242#endif // VIDEO_OVERUSE_FRAME_DETECTOR_RESOURCE_ADAPTATION_MODULE_H_