Index: webrtc/video/vie_encoder.cc |
diff --git a/webrtc/video/vie_encoder.cc b/webrtc/video/vie_encoder.cc |
index 1458af266f68efb6692756205f2296b6cd217e20..995af4dd099613864a814e625f6b0515ab62d27f 100644 |
--- a/webrtc/video/vie_encoder.cc |
+++ b/webrtc/video/vie_encoder.cc |
@@ -163,9 +163,21 @@ class ViEEncoder::VideoSourceProxy { |
{ |
rtc::CritScope lock(&crit_); |
old_source = source_; |
- source_ = source; |
+ wants = sink_wants_; |
+ // If changing degradation preference, clear any constraints from the |
+ // current sink wants that will no longer apply. |
+ if (degradation_preference_ != degradation_preference) { |
+ switch (degradation_preference) { |
+ case DegradationPreference::kBalanced: |
+ wants.framerate_fps_.reset(); |
+ break; |
+ case DegradationPreference::kMaintainResolution: |
+ wants.pixel_count.reset(); |
+ break; |
+ } |
+ } |
degradation_preference_ = degradation_preference; |
- wants = current_wants(); |
+ source_ = source; |
} |
if (old_source != source && old_source != nullptr) { |
@@ -182,9 +194,8 @@ class ViEEncoder::VideoSourceProxy { |
void SetWantsRotationApplied(bool rotation_applied) { |
rtc::CritScope lock(&crit_); |
sink_wants_.rotation_applied = rotation_applied; |
- disabled_scaling_sink_wants_.rotation_applied = rotation_applied; |
if (source_) { |
- source_->AddOrUpdateSink(vie_encoder_, current_wants()); |
+ source_->AddOrUpdateSink(vie_encoder_, sink_wants_); |
} |
} |
@@ -203,12 +214,16 @@ class ViEEncoder::VideoSourceProxy { |
const int pixels_wanted = (pixel_count * 3) / 5; |
if (pixels_wanted < kMinPixelsPerFrame) |
return; |
- sink_wants_.max_pixel_count = rtc::Optional<int>(pixels_wanted); |
- sink_wants_.target_pixel_count = rtc::Optional<int>(); |
+ sink_wants_.pixel_count.emplace(rtc::VideoSinkWants::Range( |
+ kMinPixelsPerFrame, pixels_wanted, pixel_count - 1)); |
if (source_) |
source_->AddOrUpdateSink(vie_encoder_, sink_wants_); |
} |
+ void RequestFramerateLowerThan(int framerate_fps) { |
+ // TODO(sprang): Update SinkWants. |
+ } |
+ |
void RequestHigherResolutionThan(int pixel_count) { |
rtc::CritScope lock(&crit_); |
if (!IsResolutionScalingEnabledLocked()) { |
@@ -217,18 +232,21 @@ class ViEEncoder::VideoSourceProxy { |
// task queue. |
return; |
} |
- // On step down we request at most 3/5 the pixel count of the previous |
- // resolution, so in order to take "one step up" we request a resolution as |
- // close as possible to 5/3 of the current resolution. The actual pixel |
- // count selected depends on the capabilities of the source. In order to not |
- // take a too large step up, we cap the requested pixel count to be at most |
- // four time the current number of pixels. |
- sink_wants_.target_pixel_count = rtc::Optional<int>((pixel_count * 5) / 3); |
- sink_wants_.max_pixel_count = rtc::Optional<int>(pixel_count * 4); |
+ |
+ // The input video frame size will have a resolution with "one step up" |
+ // pixels than |max_pixel_count_step_up| where "one step up" depends on |
+ // how the source can scale the input frame size. We still cap the step up |
+ // to be at most twice the number of pixels. |
+ sink_wants_.pixel_count.emplace(rtc::VideoSinkWants::Range( |
+ pixel_count + 1, (pixel_count * 5) / 3, pixel_count * 4)); |
if (source_) |
source_->AddOrUpdateSink(vie_encoder_, sink_wants_); |
} |
+ void RequestHigherFramerateThan(int framerate_fps) { |
+ // TODO(sprang): Update SinkWants. |
+ } |
+ |
private: |
bool IsResolutionScalingEnabledLocked() const |
EXCLUSIVE_LOCKS_REQUIRED(&crit_) { |
@@ -236,17 +254,16 @@ class ViEEncoder::VideoSourceProxy { |
DegradationPreference::kMaintainResolution; |
} |
- const rtc::VideoSinkWants& current_wants() const |
+ bool IsFramerateScalingEnabledLocked() const |
EXCLUSIVE_LOCKS_REQUIRED(&crit_) { |
- return IsResolutionScalingEnabledLocked() ? sink_wants_ |
- : disabled_scaling_sink_wants_; |
+ return degradation_preference_ == |
+ DegradationPreference::kMaintainResolution; |
} |
rtc::CriticalSection crit_; |
rtc::SequencedTaskChecker main_checker_; |
ViEEncoder* const vie_encoder_; |
rtc::VideoSinkWants sink_wants_ GUARDED_BY(&crit_); |
- rtc::VideoSinkWants disabled_scaling_sink_wants_ GUARDED_BY(&crit_); |
DegradationPreference degradation_preference_ GUARDED_BY(&crit_); |
rtc::VideoSourceInterface<VideoFrame>* source_ GUARDED_BY(&crit_); |
@@ -741,19 +758,37 @@ void ViEEncoder::OnBitrateUpdated(uint32_t bitrate_bps, |
void ViEEncoder::AdaptDown(AdaptReason reason) { |
RTC_DCHECK_RUN_ON(&encoder_queue_); |
- if (degradation_preference_ != DegradationPreference::kBalanced) |
- return; |
- RTC_DCHECK(static_cast<bool>(last_frame_info_)); |
- int current_pixel_count = last_frame_info_->pixel_count(); |
+ AdaptationRequest adaptation_request = { |
+ last_frame_info_->pixel_count(), |
+ stats_proxy_->GetStats().input_frame_rate, |
+ AdaptationRequest::Mode::kAdaptDown}; |
+ |
if (last_adaptation_request_ && |
- last_adaptation_request_->mode_ == AdaptationRequest::Mode::kAdaptDown && |
- current_pixel_count >= last_adaptation_request_->input_pixel_count_) { |
- // Don't request lower resolution if the current resolution is not lower |
- // than the last time we asked for the resolution to be lowered. |
- return; |
+ last_adaptation_request_->mode_ == AdaptationRequest::Mode::kAdaptDown) { |
+ switch (degradation_preference_) { |
+ case DegradationPreference::kBalanced: |
+ if (adaptation_request.input_pixel_count_ >= |
+ last_adaptation_request_->input_pixel_count_) { |
+ // Don't request lower resolution if the current resolution is not |
+ // lower |
+ // than the last time we asked for the resolution to be lowered. |
+ return; |
+ } |
+ break; |
+ case DegradationPreference::kMaintainResolution: |
+ if (adaptation_request.framerate_fps_ <= 1) { |
+ // Don't request lower framerate if we don't have a valid frame rate. |
+ // Since framerate, unlike resolution, is a measure we have to |
+ // estimate, and can fluctuate naturally over time, don't make the |
+ // same kind of limitations as for resolution, but trust the overuse |
+ // detector to not trigger too often. |
+ return; |
+ } |
+ break; |
+ } |
} |
- last_adaptation_request_.emplace(AdaptationRequest{ |
- current_pixel_count, AdaptationRequest::Mode::kAdaptDown}); |
+ |
+ last_adaptation_request_.emplace(adaptation_request); |
switch (reason) { |
case kQuality: |
@@ -768,8 +803,20 @@ void ViEEncoder::AdaptDown(AdaptReason reason) { |
break; |
} |
++scale_counter_[reason]; |
- source_proxy_->RequestResolutionLowerThan(current_pixel_count); |
- LOG(LS_INFO) << "Scaling down resolution."; |
+ |
+ switch (degradation_preference_) { |
+ case DegradationPreference::kBalanced: |
+ source_proxy_->RequestResolutionLowerThan( |
+ adaptation_request.input_pixel_count_); |
+ LOG(LS_INFO) << "Scaling down resolution."; |
+ break; |
+ case DegradationPreference::kMaintainResolution: |
+ source_proxy_->RequestFramerateLowerThan( |
+ adaptation_request.framerate_fps_); |
+ LOG(LS_INFO) << "Scaling down framerate."; |
+ break; |
+ } |
+ |
for (size_t i = 0; i < kScaleReasonSize; ++i) { |
LOG(LS_INFO) << "Scaled " << scale_counter_[i] |
<< " times for reason: " << (i ? "cpu" : "quality"); |
@@ -782,19 +829,31 @@ void ViEEncoder::AdaptUp(AdaptReason reason) { |
degradation_preference_ != DegradationPreference::kBalanced) { |
return; |
} |
- // Only scale if resolution is higher than last time we requested higher |
- // resolution. |
- RTC_DCHECK(static_cast<bool>(last_frame_info_)); |
- int current_pixel_count = last_frame_info_->pixel_count(); |
+ |
+ AdaptationRequest adaptation_request = { |
+ last_frame_info_->pixel_count(), |
+ stats_proxy_->GetStats().input_frame_rate, |
+ AdaptationRequest::Mode::kAdaptUp}; |
+ |
if (last_adaptation_request_ && |
- last_adaptation_request_->mode_ == AdaptationRequest::Mode::kAdaptUp && |
- current_pixel_count <= last_adaptation_request_->input_pixel_count_) { |
- // Don't request higher resolution if the current resolution is not higher |
- // than the last time we asked for the resolution to be higher. |
- return; |
+ last_adaptation_request_->mode_ == AdaptationRequest::Mode::kAdaptUp) { |
+ switch (degradation_preference_) { |
+ case DegradationPreference::kBalanced: |
+ if (adaptation_request.input_pixel_count_ <= |
+ last_adaptation_request_->input_pixel_count_) { |
+ // Don't request higher resolution if the current resolution is not |
+ // higher than the last time we asked for the resolution to be higher. |
+ return; |
+ } |
+ break; |
+ case DegradationPreference::kMaintainResolution: |
+ // TODO(sprang): Don't request higher framerate if we are already at |
+ // max requested fps? |
+ break; |
+ } |
} |
- last_adaptation_request_.emplace(AdaptationRequest{ |
- current_pixel_count, AdaptationRequest::Mode::kAdaptUp}); |
+ |
+ last_adaptation_request_.emplace(adaptation_request); |
switch (reason) { |
case kQuality: |
@@ -808,8 +867,20 @@ void ViEEncoder::AdaptUp(AdaptReason reason) { |
break; |
} |
--scale_counter_[reason]; |
- source_proxy_->RequestHigherResolutionThan(current_pixel_count); |
- LOG(LS_INFO) << "Scaling up resolution."; |
+ |
+ switch (degradation_preference_) { |
+ case DegradationPreference::kBalanced: |
+ source_proxy_->RequestHigherResolutionThan( |
+ adaptation_request.input_pixel_count_); |
+ LOG(LS_INFO) << "Scaling up resolution."; |
+ break; |
+ case DegradationPreference::kMaintainResolution: |
+ source_proxy_->RequestHigherFramerateThan( |
+ adaptation_request.framerate_fps_); |
+ LOG(LS_INFO) << "Scaling up framerate."; |
+ break; |
+ } |
+ |
for (size_t i = 0; i < kScaleReasonSize; ++i) { |
LOG(LS_INFO) << "Scaled " << scale_counter_[i] |
<< " times for reason: " << (i ? "cpu" : "quality"); |