Move quality scaler into adaptation module
This allows for further refactoring, eventually moving
all of quality scaler out of video stream encoder.
Bug: webrtc:11222
Change-Id: Id121608da56f57549a616ccc5f141bb598668b40
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/167728
Commit-Queue: Evan Shrubsole <eshr@google.com>
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#30417}
diff --git a/video/overuse_frame_detector_resource_adaptation_module.cc b/video/overuse_frame_detector_resource_adaptation_module.cc
index 05813eb..e73f7fa 100644
--- a/video/overuse_frame_detector_resource_adaptation_module.cc
+++ b/video/overuse_frame_detector_resource_adaptation_module.cc
@@ -359,7 +359,7 @@
last_input_frame_size_(absl::nullopt),
target_frame_rate_(absl::nullopt),
target_bitrate_bps_(absl::nullopt),
- is_quality_scaler_enabled_(false),
+ quality_scaler_(nullptr),
encoder_settings_(absl::nullopt),
encoder_stats_observer_(encoder_stats_observer) {
RTC_DCHECK(adaptation_listener_);
@@ -480,9 +480,14 @@
encode_duration_us);
}
-void OveruseFrameDetectorResourceAdaptationModule::SetIsQualityScalerEnabled(
- bool is_quality_scaler_enabled) {
- is_quality_scaler_enabled_ = is_quality_scaler_enabled;
+void OveruseFrameDetectorResourceAdaptationModule::UpdateQualityScalerSettings(
+ absl::optional<VideoEncoder::QpThresholds> qp_thresholds) {
+ if (qp_thresholds.has_value()) {
+ quality_scaler_ =
+ std::make_unique<QualityScaler>(this, qp_thresholds.value());
+ } else {
+ quality_scaler_ = nullptr;
+ }
}
void OveruseFrameDetectorResourceAdaptationModule::AdaptUp(AdaptReason reason) {
@@ -824,11 +829,11 @@
break;
case kQuality:
if (!IsFramerateScalingEnabled(degradation_preference_) ||
- !is_quality_scaler_enabled_) {
+ !quality_scaler_) {
counts.num_framerate_reductions = absl::nullopt;
}
if (!IsResolutionScalingEnabled(degradation_preference_) ||
- !is_quality_scaler_enabled_) {
+ !quality_scaler_) {
counts.num_resolution_reductions = absl::nullopt;
}
break;
diff --git a/video/overuse_frame_detector_resource_adaptation_module.h b/video/overuse_frame_detector_resource_adaptation_module.h
index 7d266fa..2bb05f9 100644
--- a/video/overuse_frame_detector_resource_adaptation_module.h
+++ b/video/overuse_frame_detector_resource_adaptation_module.h
@@ -63,6 +63,7 @@
DegradationPreference degradation_preference() const {
return degradation_preference_;
}
+ QualityScaler* quality_scaler() const { return quality_scaler_.get(); }
// ResourceAdaptationModuleInterface implementation.
void StartResourceAdaptation(
@@ -85,12 +86,9 @@
int64_t capture_time_us,
absl::optional<int> encode_duration_us) override;
- // Inform the detector whether or not the quality scaler is enabled. This
- // helps GetActiveCounts() return absl::nullopt when appropriate.
- // TODO(hbos): This feels really hacky, can we report the right values without
- // this boolean? It would be really easy to report the wrong thing if this
- // method is called incorrectly.
- void SetIsQualityScalerEnabled(bool is_quality_scaler_enabled);
+ // Use nullopt to disable quality scaling.
+ void UpdateQualityScalerSettings(
+ absl::optional<VideoEncoder::QpThresholds> qp_thresholds);
class AdaptCounter final {
public:
@@ -209,7 +207,7 @@
absl::optional<int> last_input_frame_size_;
absl::optional<double> target_frame_rate_;
absl::optional<uint32_t> target_bitrate_bps_;
- bool is_quality_scaler_enabled_;
+ std::unique_ptr<QualityScaler> quality_scaler_;
absl::optional<EncoderSettings> encoder_settings_;
VideoStreamEncoderObserver* const encoder_stats_observer_;
};
diff --git a/video/video_stream_encoder.cc b/video/video_stream_encoder.cc
index 6eaf8c7..7ec659d 100644
--- a/video/video_stream_encoder.cc
+++ b/video/video_stream_encoder.cc
@@ -18,6 +18,7 @@
#include <utility>
#include "absl/algorithm/container.h"
+#include "absl/types/optional.h"
#include "api/video/encoded_image.h"
#include "api/video/i420_buffer.h"
#include "api/video/video_bitrate_allocator_factory.h"
@@ -341,8 +342,7 @@
rate_allocator_ = nullptr;
bitrate_observer_ = nullptr;
ReleaseEncoder();
- quality_scaler_ = nullptr;
- resource_adaptation_module_->SetIsQualityScalerEnabled(false);
+ resource_adaptation_module_->UpdateQualityScalerSettings(absl::nullopt);
shutdown_event_.Set();
});
@@ -786,7 +786,7 @@
scaling_settings.thresholds;
if (quality_scaling_allowed) {
- if (quality_scaler_ == nullptr) {
+ if (resource_adaptation_module_->quality_scaler() == nullptr) {
// Quality scaler has not already been configured.
// Use experimental thresholds if available.
@@ -795,28 +795,24 @@
experimental_thresholds = QualityScalingExperiment::GetQpThresholds(
encoder_config_.codec_type);
}
- // Since the interface is non-public, std::make_unique can't do this
- // upcast.
- AdaptationObserverInterface* observer = resource_adaptation_module_.get();
- quality_scaler_ = std::make_unique<QualityScaler>(
- observer, experimental_thresholds ? *experimental_thresholds
- : *(scaling_settings.thresholds));
- resource_adaptation_module_->SetIsQualityScalerEnabled(true);
+ resource_adaptation_module_->UpdateQualityScalerSettings(
+ experimental_thresholds ? *experimental_thresholds
+ : *(scaling_settings.thresholds));
initial_framedrop_ = 0;
}
} else {
- quality_scaler_.reset(nullptr);
- resource_adaptation_module_->SetIsQualityScalerEnabled(false);
+ resource_adaptation_module_->UpdateQualityScalerSettings(absl::nullopt);
initial_framedrop_ = kMaxInitialFramedrop;
}
+ QualityScaler* quality_scaler = resource_adaptation_module_->quality_scaler();
if (resource_adaptation_module_->degradation_preference() ==
DegradationPreference::BALANCED &&
- quality_scaler_ && last_frame_info_) {
+ quality_scaler && last_frame_info_) {
absl::optional<VideoEncoder::QpThresholds> thresholds =
resource_adaptation_module_->GetQpThresholds();
if (thresholds) {
- quality_scaler_->SetQpThresholds(*thresholds);
+ quality_scaler->SetQpThresholds(*thresholds);
}
}
@@ -1553,8 +1549,10 @@
VideoStreamEncoderObserver::DropReason::kMediaOptimization);
encoder_queue_.PostTask([this] {
RTC_DCHECK_RUN_ON(&encoder_queue_);
- if (quality_scaler_)
- quality_scaler_->ReportDroppedFrameByMediaOpt();
+ QualityScaler* quality_scaler =
+ resource_adaptation_module_->quality_scaler();
+ if (quality_scaler)
+ quality_scaler->ReportDroppedFrameByMediaOpt();
});
break;
case DropReason::kDroppedByEncoder:
@@ -1562,8 +1560,10 @@
VideoStreamEncoderObserver::DropReason::kEncoder);
encoder_queue_.PostTask([this] {
RTC_DCHECK_RUN_ON(&encoder_queue_);
- if (quality_scaler_)
- quality_scaler_->ReportDroppedFrameByEncoder();
+ QualityScaler* quality_scaler =
+ resource_adaptation_module_->quality_scaler();
+ if (quality_scaler)
+ quality_scaler->ReportDroppedFrameByEncoder();
});
break;
}
@@ -1607,7 +1607,8 @@
<< " rtt " << round_trip_time_ms;
if (set_start_bitrate_bps_ > 0 && !has_seen_first_bwe_drop_ &&
- quality_scaler_ && quality_scaler_settings_.InitialBitrateIntervalMs() &&
+ resource_adaptation_module_->quality_scaler() &&
+ quality_scaler_settings_.InitialBitrateIntervalMs() &&
quality_scaler_settings_.InitialBitrateFactor()) {
int64_t diff_ms = clock_->TimeInMilliseconds() - set_start_bitrate_time_ms_;
if (diff_ms < quality_scaler_settings_.InitialBitrateIntervalMs().value() &&
@@ -1680,7 +1681,8 @@
}
bool VideoStreamEncoder::TryQualityRampup(int64_t now_ms) {
- if (!quality_scaler_)
+ QualityScaler* quality_scaler = resource_adaptation_module_->quality_scaler();
+ if (!quality_scaler)
return false;
uint32_t bw_kbps = last_encoder_rate_settings_
@@ -1692,7 +1694,7 @@
// Verify that encoder is at max bitrate and the QP is low.
if (encoder_target_bitrate_bps_.value_or(0) ==
send_codec_.maxBitrate * 1000 &&
- quality_scaler_->QpFastFilterLow()) {
+ quality_scaler->QpFastFilterLow()) {
return true;
}
}
@@ -1764,8 +1766,9 @@
encoded_image.Timestamp(), time_sent_us,
encoded_image.capture_time_ms_ * rtc::kNumMicrosecsPerMillisec,
encode_duration_us);
- if (quality_scaler_ && encoded_image.qp_ >= 0)
- quality_scaler_->ReportQp(encoded_image.qp_, time_sent_us);
+ QualityScaler* quality_scaler = resource_adaptation_module_->quality_scaler();
+ if (quality_scaler && encoded_image.qp_ >= 0)
+ quality_scaler->ReportQp(encoded_image.qp_, time_sent_us);
if (bitrate_adjuster_) {
bitrate_adjuster_->OnEncodedFrame(encoded_image, temporal_index);
}
diff --git a/video/video_stream_encoder.h b/video/video_stream_encoder.h
index 01d7738..97a4a66 100644
--- a/video/video_stream_encoder.h
+++ b/video/video_stream_encoder.h
@@ -226,9 +226,6 @@
const RateControlSettings rate_control_settings_;
const QualityScalerSettings quality_scaler_settings_;
- std::unique_ptr<QualityScaler> quality_scaler_ RTC_GUARDED_BY(&encoder_queue_)
- RTC_PT_GUARDED_BY(&encoder_queue_);
-
VideoStreamEncoderObserver* const encoder_stats_observer_;
// |thread_checker_| checks that public methods that are related to lifetime
// of VideoStreamEncoder are called on the same thread.