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

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

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

Powered by Google App Engine
This is Rietveld 408576698