Index: webrtc/video/vie_encoder.cc |
diff --git a/webrtc/video/vie_encoder.cc b/webrtc/video/vie_encoder.cc |
index eaf693af169392883496a2f7fff370029248b433..b149db73bf009e767773d24793e834eb4155cf7c 100644 |
--- a/webrtc/video/vie_encoder.cc |
+++ b/webrtc/video/vie_encoder.cc |
@@ -42,6 +42,10 @@ const int kMinPixelsPerFrame = 320 * 180; |
const int kMinPixelsPerFrame = 120 * 90; |
#endif |
+// The maximum number of frames to drop at beginning of stream |
+// to try and achieve desired bitrate. |
+const int kMaxInitialFramedrop = 4; |
+ |
// TODO(pbos): Lower these thresholds (to closer to 100%) when we handle |
// pipelining encoders better (multiple input frames before something comes |
// out). This should effectively turn off CPU adaptations for systems that |
@@ -55,6 +59,17 @@ CpuOveruseOptions GetCpuOveruseOptions(bool full_overuse_time) { |
return options; |
} |
+uint32_t MaximumFrameSizeForBitrate(uint32_t kbps) { |
+ if (kbps > 0) { |
+ if (kbps < 300 /* qvga */) { |
+ return 320 * 240; |
+ } else if (kbps < 500 /* vga */) { |
+ return 640 * 480; |
+ } |
+ } |
+ return std::numeric_limits<uint32_t>::max(); |
+} |
+ |
} // namespace |
class ViEEncoder::ConfigureEncoderTask : public rtc::QueuedTask { |
@@ -244,6 +259,7 @@ ViEEncoder::ViEEncoder(uint32_t number_of_cores, |
EncodedFrameObserver* encoder_timing) |
: shutdown_event_(true /* manual_reset */, false), |
number_of_cores_(number_of_cores), |
+ initial_rampup_(0), |
source_proxy_(new VideoSourceProxy(this)), |
sink_(nullptr), |
settings_(settings), |
@@ -341,8 +357,8 @@ void ViEEncoder::SetSource( |
RTC_DCHECK_RUN_ON(&encoder_queue_); |
scaling_enabled_ = (degradation_preference != |
VideoSendStream::DegradationPreference::kMaintainResolution); |
- stats_proxy_->SetResolutionRestrictionStats( |
- scaling_enabled_, scale_counter_[kCpu] > 0, scale_counter_[kQuality]); |
+ initial_rampup_ = scaling_enabled_ ? 0 : kMaxInitialFramedrop; |
+ ConfigureQualityScaler(); |
}); |
} |
@@ -437,8 +453,14 @@ void ViEEncoder::ReconfigureEncoder() { |
sink_->OnEncoderConfigurationChanged( |
std::move(streams), encoder_config_.min_transmit_bitrate_bps); |
+ ConfigureQualityScaler(); |
+} |
+ |
+void ViEEncoder::ConfigureQualityScaler() { |
+ RTC_DCHECK_RUN_ON(&encoder_queue_); |
const auto scaling_settings = settings_.encoder->GetScalingSettings(); |
if (scaling_enabled_ && scaling_settings.enabled) { |
+ // Drop frames and scale down until desired quality is achieved. |
if (scaling_settings.thresholds) { |
quality_scaler_.reset( |
new QualityScaler(this, *(scaling_settings.thresholds))); |
@@ -447,9 +469,9 @@ void ViEEncoder::ReconfigureEncoder() { |
} |
} else { |
quality_scaler_.reset(nullptr); |
- stats_proxy_->SetResolutionRestrictionStats( |
- false, scale_counter_[kCpu] > 0, scale_counter_[kQuality]); |
} |
+ stats_proxy_->SetResolutionRestrictionStats( |
+ scaling_enabled_, scale_counter_[kCpu] > 0, scale_counter_[kQuality]); |
} |
void ViEEncoder::OnFrame(const VideoFrame& video_frame) { |
@@ -545,6 +567,16 @@ void ViEEncoder::EncodeVideoFrame(const VideoFrame& video_frame, |
<< ", texture=" << last_frame_info_->is_texture; |
} |
+ if (initial_rampup_ < kMaxInitialFramedrop && |
+ video_frame.size() > |
+ MaximumFrameSizeForBitrate(encoder_start_bitrate_bps_ / 1000)) { |
+ LOG(LS_INFO) << "Dropping frame. Too large for target bitrate."; |
+ ScaleDown(kQuality); |
+ ++initial_rampup_; |
+ return; |
+ } |
+ initial_rampup_ = kMaxInitialFramedrop; |
+ |
int64_t now_ms = clock_->TimeInMilliseconds(); |
if (pending_encoder_reconfiguration_) { |
ReconfigureEncoder(); |