| Index: webrtc/video/vie_encoder.cc
|
| diff --git a/webrtc/video/vie_encoder.cc b/webrtc/video/vie_encoder.cc
|
| index c2598f48a9079a9a103ab1f5cf66216997132ffc..5722d06c1e651a4961896e49e774e83e9ed5218d 100644
|
| --- a/webrtc/video/vie_encoder.cc
|
| +++ b/webrtc/video/vie_encoder.cc
|
| @@ -257,9 +257,6 @@ ViEEncoder::ViEEncoder(uint32_t number_of_cores,
|
| has_received_rpsi_(false),
|
| picture_id_rpsi_(0),
|
| clock_(Clock::GetRealTimeClock()),
|
| - degradation_preference_(
|
| - VideoSendStream::DegradationPreference::kBalanced),
|
| - cpu_restricted_counter_(0),
|
| last_frame_width_(0),
|
| last_frame_height_(0),
|
| last_captured_timestamp_(0),
|
| @@ -292,6 +289,7 @@ void ViEEncoder::Stop() {
|
| rate_allocator_.reset();
|
| video_sender_.RegisterExternalEncoder(nullptr, settings_.payload_type,
|
| false);
|
| + quality_scaler_ = nullptr;
|
| shutdown_event_.Set();
|
| });
|
|
|
| @@ -318,17 +316,12 @@ void ViEEncoder::SetSource(
|
| source_proxy_->SetSource(source, degradation_preference);
|
| encoder_queue_.PostTask([this, degradation_preference] {
|
| RTC_DCHECK_RUN_ON(&encoder_queue_);
|
| - degradation_preference_ = degradation_preference;
|
| - // Set the stats for if we are currently CPU restricted. We are CPU
|
| - // restricted depending on degradation preference and
|
| - // if the overusedetector has currently detected overuse which is counted in
|
| - // |cpu_restricted_counter_|
|
| - // We do this on the encoder task queue to avoid a race with the stats set
|
| - // in ViEEncoder::NormalUsage and ViEEncoder::OveruseDetected.
|
| - stats_proxy_->SetCpuRestrictedResolution(
|
| - degradation_preference_ !=
|
| - VideoSendStream::DegradationPreference::kMaintainResolution &&
|
| - cpu_restricted_counter_ != 0);
|
| + scaling_enabled_ =
|
| + (degradation_preference !=
|
| + VideoSendStream::DegradationPreference::kMaintainResolution);
|
| + stats_proxy_->SetResolutionRestrictionStats(
|
| + scaling_enabled_ && scale_counter_[kQuality] > 0,
|
| + scaling_enabled_ && scale_counter_[kCpu] > 0);
|
| });
|
| }
|
|
|
| @@ -420,6 +413,18 @@ void ViEEncoder::ReconfigureEncoder() {
|
|
|
| sink_->OnEncoderConfigurationChanged(
|
| std::move(streams), encoder_config_.min_transmit_bitrate_bps);
|
| +
|
| + const auto scaling_settings = settings_.encoder->GetScalingSettings();
|
| + if (scaling_settings.enabled && scaling_enabled_) {
|
| + if (scaling_settings.thresholds) {
|
| + quality_scaler_.reset(
|
| + new QualityScaler(this, *(scaling_settings.thresholds)));
|
| + } else {
|
| + quality_scaler_.reset(new QualityScaler(this, codec_type_));
|
| + }
|
| + } else {
|
| + quality_scaler_.reset(nullptr);
|
| + }
|
| }
|
|
|
| void ViEEncoder::OnFrame(const VideoFrame& video_frame) {
|
| @@ -497,6 +502,7 @@ void ViEEncoder::TraceFrameDropEnd() {
|
| void ViEEncoder::EncodeVideoFrame(const VideoFrame& video_frame,
|
| int64_t time_when_posted_in_ms) {
|
| RTC_DCHECK_RUN_ON(&encoder_queue_);
|
| +
|
| if (pre_encode_callback_)
|
| pre_encode_callback_->OnFrame(video_frame);
|
|
|
| @@ -574,15 +580,25 @@ EncodedImageCallback::Result ViEEncoder::OnEncodedImage(
|
|
|
| int64_t time_sent = clock_->TimeInMilliseconds();
|
| uint32_t timestamp = encoded_image._timeStamp;
|
| -
|
| - encoder_queue_.PostTask([this, timestamp, time_sent] {
|
| + const int qp = encoded_image.qp_;
|
| + encoder_queue_.PostTask([this, timestamp, time_sent, qp] {
|
| RTC_DCHECK_RUN_ON(&encoder_queue_);
|
| overuse_detector_.FrameSent(timestamp, time_sent);
|
| + if (quality_scaler_)
|
| + quality_scaler_->ReportQP(qp);
|
| });
|
|
|
| return result;
|
| }
|
|
|
| +void ViEEncoder::OnDroppedFrame() {
|
| + encoder_queue_.PostTask([this] {
|
| + RTC_DCHECK_RUN_ON(&encoder_queue_);
|
| + if (quality_scaler_)
|
| + quality_scaler_->ReportDroppedFrame();
|
| + });
|
| +}
|
| +
|
| void ViEEncoder::SendStatistics(uint32_t bit_rate, uint32_t frame_rate) {
|
| RTC_DCHECK(module_process_thread_checker_.CalledOnValidThread());
|
| if (stats_proxy_)
|
| @@ -654,47 +670,67 @@ void ViEEncoder::OnBitrateUpdated(uint32_t bitrate_bps,
|
| }
|
| }
|
|
|
| -void ViEEncoder::OveruseDetected() {
|
| +void ViEEncoder::ScaleDown(ScaleReason reason) {
|
| RTC_DCHECK_RUN_ON(&encoder_queue_);
|
| - if (degradation_preference_ ==
|
| - VideoSendStream::DegradationPreference::kMaintainResolution ||
|
| - cpu_restricted_counter_ >= kMaxCpuDowngrades) {
|
| + if (!scaling_enabled_)
|
| return;
|
| - }
|
| - LOG(LS_INFO) << "CPU overuse detected. Requesting lower resolution.";
|
| // Request lower resolution if the current resolution is lower than last time
|
| // we asked for the resolution to be lowered.
|
| - // Update stats accordingly.
|
| int current_pixel_count = last_frame_height_ * last_frame_width_;
|
| - if (!max_pixel_count_ || current_pixel_count < *max_pixel_count_) {
|
| - max_pixel_count_ = rtc::Optional<int>(current_pixel_count);
|
| - max_pixel_count_step_up_ = rtc::Optional<int>();
|
| - stats_proxy_->OnCpuRestrictedResolutionChanged(true);
|
| - ++cpu_restricted_counter_;
|
| - source_proxy_->RequestResolutionLowerThan(current_pixel_count);
|
| + if (max_pixel_count_ && current_pixel_count >= *max_pixel_count_)
|
| + return;
|
| + switch (reason) {
|
| + case kQuality:
|
| + if (scale_counter_[reason] >= kMaxQualityDowngrades)
|
| + return;
|
| + stats_proxy_->OnQualityRestrictedResolutionChanged(true);
|
| + break;
|
| + case kCpu:
|
| + if (scale_counter_[reason] >= kMaxCpuDowngrades)
|
| + return;
|
| + // Update stats accordingly.
|
| + stats_proxy_->OnCpuRestrictedResolutionChanged(true);
|
| + break;
|
| + }
|
| + max_pixel_count_ = rtc::Optional<int>(current_pixel_count);
|
| + max_pixel_count_step_up_ = rtc::Optional<int>();
|
| + ++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 " << scale_counter_[i]
|
| + << " times for reason: " << (i ? "quality" : "cpu");
|
| }
|
| }
|
|
|
| -void ViEEncoder::NormalUsage() {
|
| +void ViEEncoder::ScaleUp(ScaleReason reason) {
|
| RTC_DCHECK_RUN_ON(&encoder_queue_);
|
| - if (degradation_preference_ ==
|
| - VideoSendStream::DegradationPreference::kMaintainResolution ||
|
| - cpu_restricted_counter_ == 0) {
|
| + if (scale_counter_[reason] == 0 || !scaling_enabled_)
|
| return;
|
| - }
|
| -
|
| - LOG(LS_INFO) << "CPU underuse detected. Requesting higher resolution.";
|
| + // Only scale if resolution is higher than last time
|
| + // we requested higher resolution.
|
| int current_pixel_count = last_frame_height_ * last_frame_width_;
|
| - // Request higher resolution if we are CPU restricted and the the current
|
| - // resolution is higher than last time we requested higher resolution.
|
| - // Update stats accordingly.
|
| - if (!max_pixel_count_step_up_ ||
|
| - current_pixel_count > *max_pixel_count_step_up_) {
|
| - max_pixel_count_ = rtc::Optional<int>();
|
| - max_pixel_count_step_up_ = rtc::Optional<int>(current_pixel_count);
|
| - --cpu_restricted_counter_;
|
| - stats_proxy_->OnCpuRestrictedResolutionChanged(cpu_restricted_counter_ > 0);
|
| - source_proxy_->RequestHigherResolutionThan(current_pixel_count);
|
| + if (current_pixel_count <= max_pixel_count_step_up_.value_or(0))
|
| + return;
|
| + switch (reason) {
|
| + case kQuality:
|
| + stats_proxy_->OnQualityRestrictedResolutionChanged(
|
| + scale_counter_[reason] > 1);
|
| + break;
|
| + case kCpu:
|
| + // Update stats accordingly.
|
| + stats_proxy_->OnCpuRestrictedResolutionChanged(scale_counter_[reason] >
|
| + 1);
|
| + break;
|
| + }
|
| + max_pixel_count_ = rtc::Optional<int>();
|
| + max_pixel_count_step_up_ = rtc::Optional<int>(current_pixel_count);
|
| + --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 " << scale_counter_[i]
|
| + << " times for reason: " << (i ? "quality" : "cpu");
|
| }
|
| }
|
|
|
|
|