Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(18)

Side by Side Diff: webrtc/video/vie_encoder.cc

Issue 2716643002: Add framerate to VideoSinkWants and ability to signal on overuse (Closed)
Patch Set: Comments Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
(...skipping 24 matching lines...) Expand all
35 using DegradationPreference = VideoSendStream::DegradationPreference; 35 using DegradationPreference = VideoSendStream::DegradationPreference;
36 36
37 // Time interval for logging frame counts. 37 // Time interval for logging frame counts.
38 const int64_t kFrameLogIntervalMs = 60000; 38 const int64_t kFrameLogIntervalMs = 60000;
39 39
40 // We will never ask for a resolution lower than this. 40 // We will never ask for a resolution lower than this.
41 // TODO(kthelgason): Lower this limit when better testing 41 // TODO(kthelgason): Lower this limit when better testing
42 // on MediaCodec and fallback implementations are in place. 42 // on MediaCodec and fallback implementations are in place.
43 // See https://bugs.chromium.org/p/webrtc/issues/detail?id=7206 43 // See https://bugs.chromium.org/p/webrtc/issues/detail?id=7206
44 const int kMinPixelsPerFrame = 320 * 180; 44 const int kMinPixelsPerFrame = 320 * 180;
45 const int kMinFramerateFps = 2;
45 46
46 // The maximum number of frames to drop at beginning of stream 47 // The maximum number of frames to drop at beginning of stream
47 // to try and achieve desired bitrate. 48 // to try and achieve desired bitrate.
48 const int kMaxInitialFramedrop = 4; 49 const int kMaxInitialFramedrop = 4;
49 50
50 // TODO(pbos): Lower these thresholds (to closer to 100%) when we handle 51 // TODO(pbos): Lower these thresholds (to closer to 100%) when we handle
51 // pipelining encoders better (multiple input frames before something comes 52 // pipelining encoders better (multiple input frames before something comes
52 // out). This should effectively turn off CPU adaptations for systems that 53 // out). This should effectively turn off CPU adaptations for systems that
53 // remotely cope with the load right now. 54 // remotely cope with the load right now.
54 CpuOveruseOptions GetCpuOveruseOptions(bool full_overuse_time) { 55 CpuOveruseOptions GetCpuOveruseOptions(bool full_overuse_time) {
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
143 }; 144 };
144 145
145 // VideoSourceProxy is responsible ensuring thread safety between calls to 146 // VideoSourceProxy is responsible ensuring thread safety between calls to
146 // ViEEncoder::SetSource that will happen on libjingle's worker thread when a 147 // ViEEncoder::SetSource that will happen on libjingle's worker thread when a
147 // video capturer is connected to the encoder and the encoder task queue 148 // video capturer is connected to the encoder and the encoder task queue
148 // (encoder_queue_) where the encoder reports its VideoSinkWants. 149 // (encoder_queue_) where the encoder reports its VideoSinkWants.
149 class ViEEncoder::VideoSourceProxy { 150 class ViEEncoder::VideoSourceProxy {
150 public: 151 public:
151 explicit VideoSourceProxy(ViEEncoder* vie_encoder) 152 explicit VideoSourceProxy(ViEEncoder* vie_encoder)
152 : vie_encoder_(vie_encoder), 153 : vie_encoder_(vie_encoder),
153 degradation_preference_(DegradationPreference::kMaintainResolution), 154 degradation_preference_(DegradationPreference::kDegradationDisabled),
154 source_(nullptr) {} 155 source_(nullptr) {}
155 156
156 void SetSource(rtc::VideoSourceInterface<VideoFrame>* source, 157 void SetSource(rtc::VideoSourceInterface<VideoFrame>* source,
157 const DegradationPreference& degradation_preference) { 158 const DegradationPreference& degradation_preference) {
158 // Called on libjingle's worker thread. 159 // Called on libjingle's worker thread.
159 RTC_DCHECK_CALLED_SEQUENTIALLY(&main_checker_); 160 RTC_DCHECK_CALLED_SEQUENTIALLY(&main_checker_);
160 rtc::VideoSourceInterface<VideoFrame>* old_source = nullptr; 161 rtc::VideoSourceInterface<VideoFrame>* old_source = nullptr;
161 rtc::VideoSinkWants wants; 162 rtc::VideoSinkWants wants;
162 { 163 {
163 rtc::CritScope lock(&crit_); 164 rtc::CritScope lock(&crit_);
165 degradation_preference_ = degradation_preference;
164 old_source = source_; 166 old_source = source_;
165 source_ = source; 167 source_ = source;
166 degradation_preference_ = degradation_preference; 168 wants = GetActiveSinkWants();
167 wants = current_wants();
168 } 169 }
169 170
170 if (old_source != source && old_source != nullptr) { 171 if (old_source != source && old_source != nullptr) {
171 old_source->RemoveSink(vie_encoder_); 172 old_source->RemoveSink(vie_encoder_);
172 } 173 }
173 174
174 if (!source) { 175 if (!source) {
175 return; 176 return;
176 } 177 }
177 178
178 source->AddOrUpdateSink(vie_encoder_, wants); 179 source->AddOrUpdateSink(vie_encoder_, wants);
179 } 180 }
180 181
181 void SetWantsRotationApplied(bool rotation_applied) { 182 void SetWantsRotationApplied(bool rotation_applied) {
182 rtc::CritScope lock(&crit_); 183 rtc::CritScope lock(&crit_);
183 sink_wants_.rotation_applied = rotation_applied; 184 sink_wants_.rotation_applied = rotation_applied;
184 disabled_scaling_sink_wants_.rotation_applied = rotation_applied; 185 if (source_)
185 if (source_) { 186 source_->AddOrUpdateSink(vie_encoder_, sink_wants_);
186 source_->AddOrUpdateSink(vie_encoder_, current_wants()); 187 }
188
189 rtc::VideoSinkWants GetActiveSinkWants() EXCLUSIVE_LOCKS_REQUIRED(&crit_) {
190 rtc::VideoSinkWants wants = sink_wants_;
191 // Clear any constraints from the current sink wants that don't apply to
192 // the used degradation_preference.
193 switch (degradation_preference_) {
194 case DegradationPreference::kBalanced:
195 FALLTHROUGH();
196 case DegradationPreference::kMaintainFramerate:
197 wants.max_framerate_fps = std::numeric_limits<int>::max();
198 break;
199 case DegradationPreference::kMaintainResolution:
200 wants.max_pixel_count = std::numeric_limits<int>::max();
201 wants.target_pixel_count.reset();
202 break;
203 case DegradationPreference::kDegradationDisabled:
204 wants.max_pixel_count = std::numeric_limits<int>::max();
205 wants.target_pixel_count.reset();
206 wants.max_framerate_fps = std::numeric_limits<int>::max();
187 } 207 }
208 return wants;
188 } 209 }
189 210
190 void RequestResolutionLowerThan(int pixel_count) { 211 void RequestResolutionLowerThan(int pixel_count) {
191 // Called on the encoder task queue. 212 // Called on the encoder task queue.
192 rtc::CritScope lock(&crit_); 213 rtc::CritScope lock(&crit_);
193 if (!IsResolutionScalingEnabledLocked()) { 214 if (!IsResolutionScalingEnabledLocked()) {
194 // This can happen since |degradation_preference_| is set on 215 // This can happen since |degradation_preference_| is set on
195 // libjingle's worker thread but the adaptation is done on the encoder 216 // libjingle's worker thread but the adaptation is done on the encoder
196 // task queue. 217 // task queue.
197 return; 218 return;
198 } 219 }
199 // The input video frame size will have a resolution with less than or 220 // The input video frame size will have a resolution with less than or
200 // equal to |max_pixel_count| depending on how the source can scale the 221 // equal to |max_pixel_count| depending on how the source can scale the
201 // input frame size. 222 // input frame size.
202 const int pixels_wanted = (pixel_count * 3) / 5; 223 const int pixels_wanted = (pixel_count * 3) / 5;
203 if (pixels_wanted < kMinPixelsPerFrame) 224 if (pixels_wanted < kMinPixelsPerFrame)
204 return; 225 return;
205 sink_wants_.max_pixel_count = rtc::Optional<int>(pixels_wanted); 226 sink_wants_.max_pixel_count = pixels_wanted;
206 sink_wants_.target_pixel_count = rtc::Optional<int>(); 227 sink_wants_.target_pixel_count = rtc::Optional<int>();
207 if (source_) 228 if (source_)
208 source_->AddOrUpdateSink(vie_encoder_, sink_wants_); 229 source_->AddOrUpdateSink(vie_encoder_, GetActiveSinkWants());
230 }
231
232 void RequestFramerateLowerThan(int framerate_fps) {
233 // Called on the encoder task queue.
234 rtc::CritScope lock(&crit_);
235 if (!IsFramerateScalingEnabledLocked()) {
236 // This can happen since |degradation_preference_| is set on
237 // libjingle's worker thread but the adaptation is done on the encoder
238 // task queue.
239 return;
240 }
241 // The input video frame rate will be scaled down to 2/3 of input fps,
242 // rounding down.
243 const int framerate_wanted =
244 std::max(kMinFramerateFps, (framerate_fps * 2) / 3);
245 sink_wants_.max_framerate_fps = framerate_wanted;
246 if (source_)
247 source_->AddOrUpdateSink(vie_encoder_, GetActiveSinkWants());
209 } 248 }
210 249
211 void RequestHigherResolutionThan(int pixel_count) { 250 void RequestHigherResolutionThan(int pixel_count) {
212 rtc::CritScope lock(&crit_); 251 rtc::CritScope lock(&crit_);
213 if (!IsResolutionScalingEnabledLocked()) { 252 if (!IsResolutionScalingEnabledLocked()) {
214 // This can happen since |degradation_preference_| is set on 253 // This can happen since |degradation_preference_| is set on
215 // libjingle's worker thread but the adaptation is done on the encoder 254 // libjingle's worker thread but the adaptation is done on the encoder
216 // task queue. 255 // task queue.
217 return; 256 return;
218 } 257 }
219 // On step down we request at most 3/5 the pixel count of the previous 258
220 // resolution, so in order to take "one step up" we request a resolution as 259 if (pixel_count == std::numeric_limits<int>::max()) {
221 // close as possible to 5/3 of the current resolution. The actual pixel 260 // Remove any constraints.
222 // count selected depends on the capabilities of the source. In order to not 261 sink_wants_.target_pixel_count.reset();
223 // take a too large step up, we cap the requested pixel count to be at most 262 sink_wants_.max_pixel_count = std::numeric_limits<int>::max();
224 // four time the current number of pixels. 263 } else {
225 sink_wants_.target_pixel_count = rtc::Optional<int>((pixel_count * 5) / 3); 264 // On step down we request at most 3/5 the pixel count of the previous
226 sink_wants_.max_pixel_count = rtc::Optional<int>(pixel_count * 4); 265 // resolution, so in order to take "one step up" we request a resolution
266 // as close as possible to 5/3 of the current resolution. The actual pixel
267 // count selected depends on the capabilities of the source. In order to
268 // not take a too large step up, we cap the requested pixel count to be at
269 // most four time the current number of pixels.
270 sink_wants_.target_pixel_count =
271 rtc::Optional<int>((pixel_count * 5) / 3);
272 sink_wants_.max_pixel_count = pixel_count * 4;
273 }
227 if (source_) 274 if (source_)
228 source_->AddOrUpdateSink(vie_encoder_, sink_wants_); 275 source_->AddOrUpdateSink(vie_encoder_, GetActiveSinkWants());
276 }
277
278 void RequestHigherFramerateThan(int framerate_fps) {
279 // Called on the encoder task queue.
280 rtc::CritScope lock(&crit_);
281 if (!IsFramerateScalingEnabledLocked()) {
282 // This can happen since |degradation_preference_| is set on
283 // libjingle's worker thread but the adaptation is done on the encoder
284 // task queue.
285 return;
286 }
287 if (framerate_fps == std::numeric_limits<int>::max()) {
288 // Remove any restrains.
289 sink_wants_.max_framerate_fps = std::numeric_limits<int>::max();
290 } else {
291 // The input video frame rate will be scaled up to the last step, with
292 // rounding.
293 const int framerate_wanted = (framerate_fps * 3) / 2;
294 sink_wants_.max_framerate_fps = framerate_wanted;
295 }
296 if (source_)
297 source_->AddOrUpdateSink(vie_encoder_, GetActiveSinkWants());
229 } 298 }
230 299
231 private: 300 private:
232 bool IsResolutionScalingEnabledLocked() const 301 bool IsResolutionScalingEnabledLocked() const
233 EXCLUSIVE_LOCKS_REQUIRED(&crit_) { 302 EXCLUSIVE_LOCKS_REQUIRED(&crit_) {
234 return degradation_preference_ != 303 return degradation_preference_ !=
235 DegradationPreference::kMaintainResolution; 304 DegradationPreference::kMaintainResolution;
236 } 305 }
237 306
238 const rtc::VideoSinkWants& current_wants() const 307 bool IsFramerateScalingEnabledLocked() const
239 EXCLUSIVE_LOCKS_REQUIRED(&crit_) { 308 EXCLUSIVE_LOCKS_REQUIRED(&crit_) {
240 return IsResolutionScalingEnabledLocked() ? sink_wants_ 309 return degradation_preference_ ==
241 : disabled_scaling_sink_wants_; 310 DegradationPreference::kMaintainResolution;
242 } 311 }
243 312
244 rtc::CriticalSection crit_; 313 rtc::CriticalSection crit_;
245 rtc::SequencedTaskChecker main_checker_; 314 rtc::SequencedTaskChecker main_checker_;
246 ViEEncoder* const vie_encoder_; 315 ViEEncoder* const vie_encoder_;
247 rtc::VideoSinkWants sink_wants_ GUARDED_BY(&crit_); 316 rtc::VideoSinkWants sink_wants_ GUARDED_BY(&crit_);
248 rtc::VideoSinkWants disabled_scaling_sink_wants_ GUARDED_BY(&crit_);
249 DegradationPreference degradation_preference_ GUARDED_BY(&crit_); 317 DegradationPreference degradation_preference_ GUARDED_BY(&crit_);
250 rtc::VideoSourceInterface<VideoFrame>* source_ GUARDED_BY(&crit_); 318 rtc::VideoSourceInterface<VideoFrame>* source_ GUARDED_BY(&crit_);
251 319
252 RTC_DISALLOW_COPY_AND_ASSIGN(VideoSourceProxy); 320 RTC_DISALLOW_COPY_AND_ASSIGN(VideoSourceProxy);
253 }; 321 };
254 322
255 ViEEncoder::ViEEncoder(uint32_t number_of_cores, 323 ViEEncoder::ViEEncoder(uint32_t number_of_cores,
256 SendStatisticsProxy* stats_proxy, 324 SendStatisticsProxy* stats_proxy,
257 const VideoSendStream::Config::EncoderSettings& settings, 325 const VideoSendStream::Config::EncoderSettings& settings,
258 rtc::VideoSinkInterface<VideoFrame>* pre_encode_callback, 326 rtc::VideoSinkInterface<VideoFrame>* pre_encode_callback,
(...skipping 18 matching lines...) Expand all
277 encoder_start_bitrate_bps_(0), 345 encoder_start_bitrate_bps_(0),
278 max_data_payload_length_(0), 346 max_data_payload_length_(0),
279 nack_enabled_(false), 347 nack_enabled_(false),
280 last_observed_bitrate_bps_(0), 348 last_observed_bitrate_bps_(0),
281 encoder_paused_and_dropped_frame_(false), 349 encoder_paused_and_dropped_frame_(false),
282 has_received_sli_(false), 350 has_received_sli_(false),
283 picture_id_sli_(0), 351 picture_id_sli_(0),
284 has_received_rpsi_(false), 352 has_received_rpsi_(false),
285 picture_id_rpsi_(0), 353 picture_id_rpsi_(0),
286 clock_(Clock::GetRealTimeClock()), 354 clock_(Clock::GetRealTimeClock()),
287 scale_counter_(kScaleReasonSize, 0), 355 degradation_preference_(DegradationPreference::kDegradationDisabled),
288 degradation_preference_(DegradationPreference::kMaintainResolution),
289 last_captured_timestamp_(0), 356 last_captured_timestamp_(0),
290 delta_ntp_internal_ms_(clock_->CurrentNtpInMilliseconds() - 357 delta_ntp_internal_ms_(clock_->CurrentNtpInMilliseconds() -
291 clock_->TimeInMilliseconds()), 358 clock_->TimeInMilliseconds()),
292 last_frame_log_ms_(clock_->TimeInMilliseconds()), 359 last_frame_log_ms_(clock_->TimeInMilliseconds()),
293 captured_frame_count_(0), 360 captured_frame_count_(0),
294 dropped_frame_count_(0), 361 dropped_frame_count_(0),
295 bitrate_observer_(nullptr), 362 bitrate_observer_(nullptr),
296 encoder_queue_("EncoderQueue") { 363 encoder_queue_("EncoderQueue") {
297 RTC_DCHECK(stats_proxy); 364 RTC_DCHECK(stats_proxy);
298 encoder_queue_.PostTask([this] { 365 encoder_queue_.PostTask([this] {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
349 }); 416 });
350 } 417 }
351 418
352 void ViEEncoder::SetSource( 419 void ViEEncoder::SetSource(
353 rtc::VideoSourceInterface<VideoFrame>* source, 420 rtc::VideoSourceInterface<VideoFrame>* source,
354 const VideoSendStream::DegradationPreference& degradation_preference) { 421 const VideoSendStream::DegradationPreference& degradation_preference) {
355 RTC_DCHECK_RUN_ON(&thread_checker_); 422 RTC_DCHECK_RUN_ON(&thread_checker_);
356 source_proxy_->SetSource(source, degradation_preference); 423 source_proxy_->SetSource(source, degradation_preference);
357 encoder_queue_.PostTask([this, degradation_preference] { 424 encoder_queue_.PostTask([this, degradation_preference] {
358 RTC_DCHECK_RUN_ON(&encoder_queue_); 425 RTC_DCHECK_RUN_ON(&encoder_queue_);
359 426 if (degradation_preference_ != degradation_preference) {
427 // Reset adaptation state, so that we're not tricked into thinking there's
428 // an already pending request of the same type.
429 last_adaptation_request_.reset();
430 }
360 degradation_preference_ = degradation_preference; 431 degradation_preference_ = degradation_preference;
361 initial_rampup_ = 432 initial_rampup_ =
362 degradation_preference_ != DegradationPreference::kMaintainResolution 433 degradation_preference_ != DegradationPreference::kMaintainResolution
363 ? 0 434 ? 0
364 : kMaxInitialFramedrop; 435 : kMaxInitialFramedrop;
365 ConfigureQualityScaler(); 436 ConfigureQualityScaler();
366 }); 437 });
367 } 438 }
368 439
369 void ViEEncoder::SetSink(EncoderSink* sink, bool rotation_applied) { 440 void ViEEncoder::SetSink(EncoderSink* sink, bool rotation_applied) {
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
468 if (scaling_settings.thresholds) { 539 if (scaling_settings.thresholds) {
469 quality_scaler_.reset( 540 quality_scaler_.reset(
470 new QualityScaler(this, *(scaling_settings.thresholds))); 541 new QualityScaler(this, *(scaling_settings.thresholds)));
471 } else { 542 } else {
472 quality_scaler_.reset(new QualityScaler(this, codec_type_)); 543 quality_scaler_.reset(new QualityScaler(this, codec_type_));
473 } 544 }
474 } else { 545 } else {
475 quality_scaler_.reset(nullptr); 546 quality_scaler_.reset(nullptr);
476 initial_rampup_ = kMaxInitialFramedrop; 547 initial_rampup_ = kMaxInitialFramedrop;
477 } 548 }
549 const std::vector<int>& scale_counters = GetScaleCounters();
478 stats_proxy_->SetResolutionRestrictionStats( 550 stats_proxy_->SetResolutionRestrictionStats(
479 degradation_preference_allows_scaling, scale_counter_[kCpu] > 0, 551 degradation_preference_allows_scaling, scale_counters[kCpu] > 0,
480 scale_counter_[kQuality]); 552 scale_counters[kQuality]);
481 } 553 }
482 554
483 void ViEEncoder::OnFrame(const VideoFrame& video_frame) { 555 void ViEEncoder::OnFrame(const VideoFrame& video_frame) {
484 RTC_DCHECK_RUNS_SERIALIZED(&incoming_frame_race_checker_); 556 RTC_DCHECK_RUNS_SERIALIZED(&incoming_frame_race_checker_);
485 VideoFrame incoming_frame = video_frame; 557 VideoFrame incoming_frame = video_frame;
486 558
487 // Local time in webrtc time base. 559 // Local time in webrtc time base.
488 int64_t current_time_us = clock_->TimeInMicroseconds(); 560 int64_t current_time_us = clock_->TimeInMicroseconds();
489 int64_t current_time_ms = current_time_us / rtc::kNumMicrosecsPerMillisec; 561 int64_t current_time_ms = current_time_us / rtc::kNumMicrosecsPerMillisec;
490 // TODO(nisse): This always overrides the incoming timestamp. Don't 562 // TODO(nisse): This always overrides the incoming timestamp. Don't
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after
733 805
734 if (video_suspension_changed) { 806 if (video_suspension_changed) {
735 LOG(LS_INFO) << "Video suspend state changed to: " 807 LOG(LS_INFO) << "Video suspend state changed to: "
736 << (video_is_suspended ? "suspended" : "not suspended"); 808 << (video_is_suspended ? "suspended" : "not suspended");
737 stats_proxy_->OnSuspendChange(video_is_suspended); 809 stats_proxy_->OnSuspendChange(video_is_suspended);
738 } 810 }
739 } 811 }
740 812
741 void ViEEncoder::AdaptDown(AdaptReason reason) { 813 void ViEEncoder::AdaptDown(AdaptReason reason) {
742 RTC_DCHECK_RUN_ON(&encoder_queue_); 814 RTC_DCHECK_RUN_ON(&encoder_queue_);
743 if (degradation_preference_ != DegradationPreference::kBalanced) 815 AdaptationRequest adaptation_request = {
744 return; 816 last_frame_info_->pixel_count(),
745 RTC_DCHECK(static_cast<bool>(last_frame_info_)); 817 stats_proxy_->GetStats().input_frame_rate,
746 int current_pixel_count = last_frame_info_->pixel_count(); 818 AdaptationRequest::Mode::kAdaptDown};
747 if (last_adaptation_request_ && 819 bool downgrade_requested =
748 last_adaptation_request_->mode_ == AdaptationRequest::Mode::kAdaptDown && 820 last_adaptation_request_ &&
749 current_pixel_count >= last_adaptation_request_->input_pixel_count_) { 821 last_adaptation_request_->mode_ == AdaptationRequest::Mode::kAdaptDown;
750 // Don't request lower resolution if the current resolution is not lower 822
751 // than the last time we asked for the resolution to be lowered. 823 int max_downgrades = 0;
752 return; 824 switch (degradation_preference_) {
825 case DegradationPreference::kBalanced:
826 FALLTHROUGH();
827 case DegradationPreference::kMaintainFramerate:
828 max_downgrades = kMaxCpuResolutionDowngrades;
829 if (downgrade_requested &&
830 adaptation_request.input_pixel_count_ >=
831 last_adaptation_request_->input_pixel_count_) {
832 // Don't request lower resolution if the current resolution is not
833 // lower than the last time we asked for the resolution to be lowered.
834 return;
835 }
836 break;
837 case DegradationPreference::kMaintainResolution:
838 max_downgrades = kMaxCpuFramerateDowngrades;
839 if (adaptation_request.framerate_fps_ <= 0 ||
840 (downgrade_requested &&
841 adaptation_request.framerate_fps_ < kMinFramerateFps)) {
842 // If no input fps estimate available, can't determine how to scale down
843 // framerate. Otherwise, don't request lower framerate if we don't have
844 // a valid frame rate. Since framerate, unlike resolution, is a measure
845 // we have to estimate, and can fluctuate naturally over time, don't
846 // make the same kind of limitations as for resolution, but trust the
847 // overuse detector to not trigger too often.
848 return;
849 }
850 break;
851 case DegradationPreference::kDegradationDisabled:
852 return;
753 } 853 }
754 last_adaptation_request_.emplace(AdaptationRequest{ 854
755 current_pixel_count, AdaptationRequest::Mode::kAdaptDown}); 855 last_adaptation_request_.emplace(adaptation_request);
856 const std::vector<int>& scale_counter = GetScaleCounters();
756 857
757 switch (reason) { 858 switch (reason) {
758 case kQuality: 859 case kQuality:
759 stats_proxy_->OnQualityRestrictedResolutionChanged( 860 stats_proxy_->OnQualityRestrictedResolutionChanged(scale_counter[reason] +
760 scale_counter_[reason] + 1); 861 1);
761 break; 862 break;
762 case kCpu: 863 case kCpu:
763 if (scale_counter_[reason] >= kMaxCpuDowngrades) 864 if (scale_counter[reason] >= max_downgrades)
764 return; 865 return;
765 // Update stats accordingly. 866 // Update stats accordingly.
766 stats_proxy_->OnCpuRestrictedResolutionChanged(true); 867 stats_proxy_->OnCpuRestrictedResolutionChanged(true);
767 break; 868 break;
768 } 869 }
769 ++scale_counter_[reason]; 870
770 source_proxy_->RequestResolutionLowerThan(current_pixel_count); 871 IncrementScaleCounter(reason, 1);
771 LOG(LS_INFO) << "Scaling down resolution."; 872
873 switch (degradation_preference_) {
874 case DegradationPreference::kBalanced:
875 FALLTHROUGH();
876 case DegradationPreference::kMaintainFramerate:
877 source_proxy_->RequestResolutionLowerThan(
878 adaptation_request.input_pixel_count_);
879 LOG(LS_INFO) << "Scaling down resolution.";
880 break;
881 case DegradationPreference::kMaintainResolution:
882 source_proxy_->RequestFramerateLowerThan(
883 adaptation_request.framerate_fps_);
884 LOG(LS_INFO) << "Scaling down framerate.";
885 break;
886 case DegradationPreference::kDegradationDisabled:
887 RTC_NOTREACHED();
888 }
889
772 for (size_t i = 0; i < kScaleReasonSize; ++i) { 890 for (size_t i = 0; i < kScaleReasonSize; ++i) {
773 LOG(LS_INFO) << "Scaled " << scale_counter_[i] 891 LOG(LS_INFO) << "Scaled " << GetScaleCounters()[i]
774 << " times for reason: " << (i ? "cpu" : "quality"); 892 << " times for reason: " << (i ? "cpu" : "quality");
775 } 893 }
776 } 894 }
777 895
778 void ViEEncoder::AdaptUp(AdaptReason reason) { 896 void ViEEncoder::AdaptUp(AdaptReason reason) {
779 RTC_DCHECK_RUN_ON(&encoder_queue_); 897 RTC_DCHECK_RUN_ON(&encoder_queue_);
780 if (scale_counter_[reason] == 0 || 898 int scale_counter = GetScaleCounters()[reason];
781 degradation_preference_ != DegradationPreference::kBalanced) { 899 if (scale_counter == 0)
782 return; 900 return;
901 RTC_DCHECK_GT(scale_counter, 0);
902 AdaptationRequest adaptation_request = {
903 last_frame_info_->pixel_count(),
904 stats_proxy_->GetStats().input_frame_rate,
905 AdaptationRequest::Mode::kAdaptUp};
906
907 bool adapt_up_requested =
908 last_adaptation_request_ &&
909 last_adaptation_request_->mode_ == AdaptationRequest::Mode::kAdaptUp;
910 switch (degradation_preference_) {
911 case DegradationPreference::kBalanced:
912 FALLTHROUGH();
913 case DegradationPreference::kMaintainFramerate:
914 if (adapt_up_requested &&
915 adaptation_request.input_pixel_count_ <=
916 last_adaptation_request_->input_pixel_count_) {
917 // Don't request higher resolution if the current resolution is not
918 // higher than the last time we asked for the resolution to be higher.
919 return;
920 }
921 break;
922 case DegradationPreference::kMaintainResolution:
923 // TODO(sprang): Don't request higher framerate if we are already at
924 // max requested fps?
925 break;
926 case DegradationPreference::kDegradationDisabled:
927 return;
783 } 928 }
784 // Only scale if resolution is higher than last time we requested higher
785 // resolution.
786 RTC_DCHECK(static_cast<bool>(last_frame_info_));
787 int current_pixel_count = last_frame_info_->pixel_count();
788 if (last_adaptation_request_ &&
789 last_adaptation_request_->mode_ == AdaptationRequest::Mode::kAdaptUp &&
790 current_pixel_count <= last_adaptation_request_->input_pixel_count_) {
791 // Don't request higher resolution if the current resolution is not higher
792 // than the last time we asked for the resolution to be higher.
793 return;
794 }
795 last_adaptation_request_.emplace(AdaptationRequest{
796 current_pixel_count, AdaptationRequest::Mode::kAdaptUp});
797 929
798 switch (reason) { 930 switch (reason) {
799 case kQuality: 931 case kQuality:
800 stats_proxy_->OnQualityRestrictedResolutionChanged( 932 stats_proxy_->OnQualityRestrictedResolutionChanged(scale_counter - 1);
801 scale_counter_[reason] - 1);
802 break; 933 break;
803 case kCpu: 934 case kCpu:
804 // Update stats accordingly. 935 // Update stats accordingly.
805 stats_proxy_->OnCpuRestrictedResolutionChanged(scale_counter_[reason] > 936 stats_proxy_->OnCpuRestrictedResolutionChanged(scale_counter > 1);
806 1);
807 break; 937 break;
808 } 938 }
809 --scale_counter_[reason]; 939
810 source_proxy_->RequestHigherResolutionThan(current_pixel_count); 940 // Decrease counter of how many times we have scaled down, for this
811 LOG(LS_INFO) << "Scaling up resolution."; 941 // degradation preference mode and reason.
942 IncrementScaleCounter(reason, -1);
943
944 // Get a sum of how many times have scaled down, in total, for this
945 // degradation preference mode. If it is 0, remove any restraints.
946 const std::vector<int>& current_scale_counters = GetScaleCounters();
947 const int scale_sum = std::accumulate(current_scale_counters.begin(),
948 current_scale_counters.end(), 0);
949 switch (degradation_preference_) {
950 case DegradationPreference::kBalanced:
951 FALLTHROUGH();
952 case DegradationPreference::kMaintainFramerate:
953 if (scale_sum == 0) {
954 LOG(LS_INFO) << "Removing resolution down-scaling setting.";
955 source_proxy_->RequestHigherResolutionThan(
956 std::numeric_limits<int>::max());
957 } else {
958 source_proxy_->RequestHigherResolutionThan(
959 adaptation_request.input_pixel_count_);
960 LOG(LS_INFO) << "Scaling up resolution.";
961 }
962 break;
963 case DegradationPreference::kMaintainResolution:
964 if (scale_sum == 0) {
965 LOG(LS_INFO) << "Removing framerate down-scaling setting.";
966 source_proxy_->RequestHigherFramerateThan(
967 std::numeric_limits<int>::max());
968 } else {
969 source_proxy_->RequestHigherFramerateThan(
970 adaptation_request.framerate_fps_);
971 LOG(LS_INFO) << "Scaling up framerate.";
972 }
973 break;
974 case DegradationPreference::kDegradationDisabled:
975 RTC_NOTREACHED();
976 }
977
812 for (size_t i = 0; i < kScaleReasonSize; ++i) { 978 for (size_t i = 0; i < kScaleReasonSize; ++i) {
813 LOG(LS_INFO) << "Scaled " << scale_counter_[i] 979 LOG(LS_INFO) << "Scaled " << current_scale_counters[i]
814 << " times for reason: " << (i ? "cpu" : "quality"); 980 << " times for reason: " << (i ? "cpu" : "quality");
815 } 981 }
816 } 982 }
817 983
984 const std::vector<int>& ViEEncoder::GetScaleCounters() {
985 auto it = scale_counters_.find(degradation_preference_);
986 if (it == scale_counters_.end()) {
987 scale_counters_[degradation_preference_].resize(kScaleReasonSize);
988 return scale_counters_[degradation_preference_];
989 }
990 return it->second;
991 }
992
993 void ViEEncoder::IncrementScaleCounter(int reason, int delta) {
994 // Get the counters and validate. This may also lazily initialize the state.
995 const std::vector<int>& counter = GetScaleCounters();
996 if (delta < 0) {
997 RTC_DCHECK_GE(counter[reason], delta);
998 }
999 scale_counters_[degradation_preference_][reason] += delta;
1000 }
1001
818 } // namespace webrtc 1002 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698