Index: webrtc/video/vie_encoder.cc |
diff --git a/webrtc/video/vie_encoder.cc b/webrtc/video/vie_encoder.cc |
index ad1c144d6682f3c532d849f40901eb87fdb1a8d0..c30752b6dfb048e96d40a5f2e2e25853fe4b529e 100644 |
--- a/webrtc/video/vie_encoder.cc |
+++ b/webrtc/video/vie_encoder.cc |
@@ -12,7 +12,6 @@ |
#include <algorithm> |
#include <limits> |
-#include <numeric> |
#include <utility> |
#include "webrtc/base/arraysize.h" |
@@ -43,7 +42,6 @@ |
// on MediaCodec and fallback implementations are in place. |
// See https://bugs.chromium.org/p/webrtc/issues/detail?id=7206 |
const int kMinPixelsPerFrame = 320 * 180; |
-const int kMinFramerateFps = 2; |
// The maximum number of frames to drop at beginning of stream |
// to try and achieve desired bitrate. |
@@ -152,7 +150,7 @@ |
public: |
explicit VideoSourceProxy(ViEEncoder* vie_encoder) |
: vie_encoder_(vie_encoder), |
- degradation_preference_(DegradationPreference::kDegradationDisabled), |
+ degradation_preference_(DegradationPreference::kMaintainResolution), |
source_(nullptr) {} |
void SetSource(rtc::VideoSourceInterface<VideoFrame>* source, |
@@ -163,10 +161,10 @@ |
rtc::VideoSinkWants wants; |
{ |
rtc::CritScope lock(&crit_); |
- degradation_preference_ = degradation_preference; |
old_source = source_; |
source_ = source; |
- wants = GetActiveSinkWants(); |
+ degradation_preference_ = degradation_preference; |
+ wants = current_wants(); |
} |
if (old_source != source && old_source != nullptr) { |
@@ -183,30 +181,10 @@ |
void SetWantsRotationApplied(bool rotation_applied) { |
rtc::CritScope lock(&crit_); |
sink_wants_.rotation_applied = rotation_applied; |
- if (source_) |
- source_->AddOrUpdateSink(vie_encoder_, sink_wants_); |
- } |
- |
- rtc::VideoSinkWants GetActiveSinkWants() EXCLUSIVE_LOCKS_REQUIRED(&crit_) { |
- rtc::VideoSinkWants wants = sink_wants_; |
- // Clear any constraints from the current sink wants that don't apply to |
- // the used degradation_preference. |
- switch (degradation_preference_) { |
- case DegradationPreference::kBalanced: |
- FALLTHROUGH(); |
- case DegradationPreference::kMaintainFramerate: |
- wants.max_framerate_fps = std::numeric_limits<int>::max(); |
- break; |
- case DegradationPreference::kMaintainResolution: |
- wants.max_pixel_count = std::numeric_limits<int>::max(); |
- wants.target_pixel_count.reset(); |
- break; |
- case DegradationPreference::kDegradationDisabled: |
- wants.max_pixel_count = std::numeric_limits<int>::max(); |
- wants.target_pixel_count.reset(); |
- wants.max_framerate_fps = std::numeric_limits<int>::max(); |
- } |
- return wants; |
+ disabled_scaling_sink_wants_.rotation_applied = rotation_applied; |
+ if (source_) { |
+ source_->AddOrUpdateSink(vie_encoder_, current_wants()); |
+ } |
} |
void RequestResolutionLowerThan(int pixel_count) { |
@@ -224,28 +202,10 @@ |
const int pixels_wanted = (pixel_count * 3) / 5; |
if (pixels_wanted < kMinPixelsPerFrame) |
return; |
- sink_wants_.max_pixel_count = pixels_wanted; |
+ sink_wants_.max_pixel_count = rtc::Optional<int>(pixels_wanted); |
sink_wants_.target_pixel_count = rtc::Optional<int>(); |
if (source_) |
- source_->AddOrUpdateSink(vie_encoder_, GetActiveSinkWants()); |
- } |
- |
- void RequestFramerateLowerThan(int framerate_fps) { |
- // Called on the encoder task queue. |
- rtc::CritScope lock(&crit_); |
- if (!IsFramerateScalingEnabledLocked()) { |
- // This can happen since |degradation_preference_| is set on |
- // libjingle's worker thread but the adaptation is done on the encoder |
- // task queue. |
- return; |
- } |
- // The input video frame rate will be scaled down to 2/3 of input fps, |
- // rounding down. |
- const int framerate_wanted = |
- std::max(kMinFramerateFps, (framerate_fps * 2) / 3); |
- sink_wants_.max_framerate_fps = framerate_wanted; |
- if (source_) |
- source_->AddOrUpdateSink(vie_encoder_, GetActiveSinkWants()); |
+ source_->AddOrUpdateSink(vie_encoder_, sink_wants_); |
} |
void RequestHigherResolutionThan(int pixel_count) { |
@@ -256,46 +216,16 @@ |
// task queue. |
return; |
} |
- |
- if (pixel_count == std::numeric_limits<int>::max()) { |
- // Remove any constraints. |
- sink_wants_.target_pixel_count.reset(); |
- sink_wants_.max_pixel_count = std::numeric_limits<int>::max(); |
- } else { |
- // 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 = pixel_count * 4; |
- } |
+ // 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); |
if (source_) |
- source_->AddOrUpdateSink(vie_encoder_, GetActiveSinkWants()); |
- } |
- |
- void RequestHigherFramerateThan(int framerate_fps) { |
- // Called on the encoder task queue. |
- rtc::CritScope lock(&crit_); |
- if (!IsFramerateScalingEnabledLocked()) { |
- // This can happen since |degradation_preference_| is set on |
- // libjingle's worker thread but the adaptation is done on the encoder |
- // task queue. |
- return; |
- } |
- if (framerate_fps == std::numeric_limits<int>::max()) { |
- // Remove any restrains. |
- sink_wants_.max_framerate_fps = std::numeric_limits<int>::max(); |
- } else { |
- // The input video frame rate will be scaled up to the last step, with |
- // rounding. |
- const int framerate_wanted = (framerate_fps * 3) / 2; |
- sink_wants_.max_framerate_fps = framerate_wanted; |
- } |
- if (source_) |
- source_->AddOrUpdateSink(vie_encoder_, GetActiveSinkWants()); |
+ source_->AddOrUpdateSink(vie_encoder_, sink_wants_); |
} |
private: |
@@ -305,16 +235,17 @@ |
DegradationPreference::kMaintainResolution; |
} |
- bool IsFramerateScalingEnabledLocked() const |
+ const rtc::VideoSinkWants& current_wants() const |
EXCLUSIVE_LOCKS_REQUIRED(&crit_) { |
- return degradation_preference_ == |
- DegradationPreference::kMaintainResolution; |
+ return IsResolutionScalingEnabledLocked() ? sink_wants_ |
+ : disabled_scaling_sink_wants_; |
} |
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_); |
@@ -353,7 +284,8 @@ |
has_received_rpsi_(false), |
picture_id_rpsi_(0), |
clock_(Clock::GetRealTimeClock()), |
- degradation_preference_(DegradationPreference::kDegradationDisabled), |
+ scale_counter_(kScaleReasonSize, 0), |
+ degradation_preference_(DegradationPreference::kMaintainResolution), |
last_captured_timestamp_(0), |
delta_ntp_internal_ms_(clock_->CurrentNtpInMilliseconds() - |
clock_->TimeInMilliseconds()), |
@@ -424,11 +356,7 @@ |
source_proxy_->SetSource(source, degradation_preference); |
encoder_queue_.PostTask([this, degradation_preference] { |
RTC_DCHECK_RUN_ON(&encoder_queue_); |
- if (degradation_preference_ != degradation_preference) { |
- // Reset adaptation state, so that we're not tricked into thinking there's |
- // an already pending request of the same type. |
- last_adaptation_request_.reset(); |
- } |
+ |
degradation_preference_ = degradation_preference; |
initial_rampup_ = |
degradation_preference_ != DegradationPreference::kMaintainResolution |
@@ -547,10 +475,9 @@ |
quality_scaler_.reset(nullptr); |
initial_rampup_ = kMaxInitialFramedrop; |
} |
- const std::vector<int>& scale_counters = GetScaleCounters(); |
stats_proxy_->SetResolutionRestrictionStats( |
- degradation_preference_allows_scaling, scale_counters[kCpu] > 0, |
- scale_counters[kQuality]); |
+ degradation_preference_allows_scaling, scale_counter_[kCpu] > 0, |
+ scale_counter_[kQuality]); |
} |
void ViEEncoder::OnFrame(const VideoFrame& video_frame) { |
@@ -813,191 +740,79 @@ |
void ViEEncoder::AdaptDown(AdaptReason reason) { |
RTC_DCHECK_RUN_ON(&encoder_queue_); |
- AdaptationRequest adaptation_request = { |
- last_frame_info_->pixel_count(), |
- stats_proxy_->GetStats().input_frame_rate, |
- AdaptationRequest::Mode::kAdaptDown}; |
- bool downgrade_requested = |
- last_adaptation_request_ && |
- last_adaptation_request_->mode_ == AdaptationRequest::Mode::kAdaptDown; |
- |
- int max_downgrades = 0; |
- switch (degradation_preference_) { |
- case DegradationPreference::kBalanced: |
- FALLTHROUGH(); |
- case DegradationPreference::kMaintainFramerate: |
- max_downgrades = kMaxCpuResolutionDowngrades; |
- if (downgrade_requested && |
- 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: |
- max_downgrades = kMaxCpuFramerateDowngrades; |
- if (adaptation_request.framerate_fps_ <= 0 || |
- (downgrade_requested && |
- adaptation_request.framerate_fps_ < kMinFramerateFps)) { |
- // If no input fps estimate available, can't determine how to scale down |
- // framerate. Otherwise, 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; |
- case DegradationPreference::kDegradationDisabled: |
- return; |
- } |
- |
- last_adaptation_request_.emplace(adaptation_request); |
- const std::vector<int>& scale_counter = GetScaleCounters(); |
+ if (degradation_preference_ != DegradationPreference::kBalanced) |
+ return; |
+ RTC_DCHECK(static_cast<bool>(last_frame_info_)); |
+ int current_pixel_count = last_frame_info_->pixel_count(); |
+ 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_.emplace(AdaptationRequest{ |
+ current_pixel_count, AdaptationRequest::Mode::kAdaptDown}); |
switch (reason) { |
case kQuality: |
- stats_proxy_->OnQualityRestrictedResolutionChanged(scale_counter[reason] + |
- 1); |
+ stats_proxy_->OnQualityRestrictedResolutionChanged( |
+ scale_counter_[reason] + 1); |
break; |
case kCpu: |
- if (scale_counter[reason] >= max_downgrades) |
+ if (scale_counter_[reason] >= kMaxCpuDowngrades) |
return; |
// Update stats accordingly. |
stats_proxy_->OnCpuRestrictedResolutionChanged(true); |
break; |
} |
- |
- IncrementScaleCounter(reason, 1); |
- |
- switch (degradation_preference_) { |
- case DegradationPreference::kBalanced: |
- FALLTHROUGH(); |
- case DegradationPreference::kMaintainFramerate: |
- 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; |
- case DegradationPreference::kDegradationDisabled: |
- RTC_NOTREACHED(); |
- } |
- |
+ ++scale_counter_[reason]; |
+ source_proxy_->RequestResolutionLowerThan(current_pixel_count); |
+ LOG(LS_INFO) << "Scaling down resolution."; |
for (size_t i = 0; i < kScaleReasonSize; ++i) { |
- LOG(LS_INFO) << "Scaled " << GetScaleCounters()[i] |
+ LOG(LS_INFO) << "Scaled " << scale_counter_[i] |
<< " times for reason: " << (i ? "cpu" : "quality"); |
} |
} |
void ViEEncoder::AdaptUp(AdaptReason reason) { |
RTC_DCHECK_RUN_ON(&encoder_queue_); |
- int scale_counter = GetScaleCounters()[reason]; |
- if (scale_counter == 0) |
- return; |
- RTC_DCHECK_GT(scale_counter, 0); |
- AdaptationRequest adaptation_request = { |
- last_frame_info_->pixel_count(), |
- stats_proxy_->GetStats().input_frame_rate, |
- AdaptationRequest::Mode::kAdaptUp}; |
- |
- bool adapt_up_requested = |
- last_adaptation_request_ && |
- last_adaptation_request_->mode_ == AdaptationRequest::Mode::kAdaptUp; |
- switch (degradation_preference_) { |
- case DegradationPreference::kBalanced: |
- FALLTHROUGH(); |
- case DegradationPreference::kMaintainFramerate: |
- if (adapt_up_requested && |
- 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; |
- case DegradationPreference::kDegradationDisabled: |
- return; |
- } |
+ if (scale_counter_[reason] == 0 || |
+ 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(); |
+ 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_.emplace(AdaptationRequest{ |
+ current_pixel_count, AdaptationRequest::Mode::kAdaptUp}); |
switch (reason) { |
case kQuality: |
- stats_proxy_->OnQualityRestrictedResolutionChanged(scale_counter - 1); |
+ stats_proxy_->OnQualityRestrictedResolutionChanged( |
+ scale_counter_[reason] - 1); |
break; |
case kCpu: |
// Update stats accordingly. |
- stats_proxy_->OnCpuRestrictedResolutionChanged(scale_counter > 1); |
+ stats_proxy_->OnCpuRestrictedResolutionChanged(scale_counter_[reason] > |
+ 1); |
break; |
} |
- |
- // Decrease counter of how many times we have scaled down, for this |
- // degradation preference mode and reason. |
- IncrementScaleCounter(reason, -1); |
- |
- // Get a sum of how many times have scaled down, in total, for this |
- // degradation preference mode. If it is 0, remove any restraints. |
- const std::vector<int>& current_scale_counters = GetScaleCounters(); |
- const int scale_sum = std::accumulate(current_scale_counters.begin(), |
- current_scale_counters.end(), 0); |
- switch (degradation_preference_) { |
- case DegradationPreference::kBalanced: |
- FALLTHROUGH(); |
- case DegradationPreference::kMaintainFramerate: |
- if (scale_sum == 0) { |
- LOG(LS_INFO) << "Removing resolution down-scaling setting."; |
- source_proxy_->RequestHigherResolutionThan( |
- std::numeric_limits<int>::max()); |
- } else { |
- source_proxy_->RequestHigherResolutionThan( |
- adaptation_request.input_pixel_count_); |
- LOG(LS_INFO) << "Scaling up resolution."; |
- } |
- break; |
- case DegradationPreference::kMaintainResolution: |
- if (scale_sum == 0) { |
- LOG(LS_INFO) << "Removing framerate down-scaling setting."; |
- source_proxy_->RequestHigherFramerateThan( |
- std::numeric_limits<int>::max()); |
- } else { |
- source_proxy_->RequestHigherFramerateThan( |
- adaptation_request.framerate_fps_); |
- LOG(LS_INFO) << "Scaling up framerate."; |
- } |
- break; |
- case DegradationPreference::kDegradationDisabled: |
- RTC_NOTREACHED(); |
- } |
- |
+ --scale_counter_[reason]; |
+ source_proxy_->RequestHigherResolutionThan(current_pixel_count); |
+ LOG(LS_INFO) << "Scaling up resolution."; |
for (size_t i = 0; i < kScaleReasonSize; ++i) { |
- LOG(LS_INFO) << "Scaled " << current_scale_counters[i] |
+ LOG(LS_INFO) << "Scaled " << scale_counter_[i] |
<< " times for reason: " << (i ? "cpu" : "quality"); |
} |
} |
-const std::vector<int>& ViEEncoder::GetScaleCounters() { |
- auto it = scale_counters_.find(degradation_preference_); |
- if (it == scale_counters_.end()) { |
- scale_counters_[degradation_preference_].resize(kScaleReasonSize); |
- return scale_counters_[degradation_preference_]; |
- } |
- return it->second; |
-} |
- |
-void ViEEncoder::IncrementScaleCounter(int reason, int delta) { |
- // Get the counters and validate. This may also lazily initialize the state. |
- const std::vector<int>& counter = GetScaleCounters(); |
- if (delta < 0) { |
- RTC_DCHECK_GE(counter[reason], delta); |
- } |
- scale_counters_[degradation_preference_][reason] += delta; |
-} |
- |
} // namespace webrtc |