diff --git a/video/overuse_frame_detector_resource_adaptation_module.cc b/video/overuse_frame_detector_resource_adaptation_module.cc index 05813eb10d..e73f7fa4d1 100644 --- a/video/overuse_frame_detector_resource_adaptation_module.cc +++ b/video/overuse_frame_detector_resource_adaptation_module.cc @@ -359,7 +359,7 @@ OveruseFrameDetectorResourceAdaptationModule:: 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 @@ void OveruseFrameDetectorResourceAdaptationModule::OnEncodeCompleted( encode_duration_us); } -void OveruseFrameDetectorResourceAdaptationModule::SetIsQualityScalerEnabled( - bool is_quality_scaler_enabled) { - is_quality_scaler_enabled_ = is_quality_scaler_enabled; +void OveruseFrameDetectorResourceAdaptationModule::UpdateQualityScalerSettings( + absl::optional qp_thresholds) { + if (qp_thresholds.has_value()) { + quality_scaler_ = + std::make_unique(this, qp_thresholds.value()); + } else { + quality_scaler_ = nullptr; + } } void OveruseFrameDetectorResourceAdaptationModule::AdaptUp(AdaptReason reason) { @@ -824,11 +829,11 @@ OveruseFrameDetectorResourceAdaptationModule::GetActiveCounts( 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 7d266fa35d..2bb05f9963 100644 --- a/video/overuse_frame_detector_resource_adaptation_module.h +++ b/video/overuse_frame_detector_resource_adaptation_module.h @@ -63,6 +63,7 @@ class OveruseFrameDetectorResourceAdaptationModule DegradationPreference degradation_preference() const { return degradation_preference_; } + QualityScaler* quality_scaler() const { return quality_scaler_.get(); } // ResourceAdaptationModuleInterface implementation. void StartResourceAdaptation( @@ -85,12 +86,9 @@ class OveruseFrameDetectorResourceAdaptationModule int64_t capture_time_us, absl::optional 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 qp_thresholds); class AdaptCounter final { public: @@ -209,7 +207,7 @@ class OveruseFrameDetectorResourceAdaptationModule absl::optional last_input_frame_size_; absl::optional target_frame_rate_; absl::optional target_bitrate_bps_; - bool is_quality_scaler_enabled_; + std::unique_ptr quality_scaler_; absl::optional encoder_settings_; VideoStreamEncoderObserver* const encoder_stats_observer_; }; diff --git a/video/video_stream_encoder.cc b/video/video_stream_encoder.cc index 6eaf8c719c..7ec659d837 100644 --- a/video/video_stream_encoder.cc +++ b/video/video_stream_encoder.cc @@ -18,6 +18,7 @@ #include #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 @@ void VideoStreamEncoder::Stop() { 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 @@ void VideoStreamEncoder::ConfigureQualityScaler( 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 @@ void VideoStreamEncoder::ConfigureQualityScaler( 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( - 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 thresholds = resource_adaptation_module_->GetQpThresholds(); if (thresholds) { - quality_scaler_->SetQpThresholds(*thresholds); + quality_scaler->SetQpThresholds(*thresholds); } } @@ -1553,8 +1549,10 @@ void VideoStreamEncoder::OnDroppedFrame(DropReason reason) { 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 @@ void VideoStreamEncoder::OnDroppedFrame(DropReason reason) { 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 @@ void VideoStreamEncoder::OnBitrateUpdated(DataRate target_bitrate, << " 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::DropDueToSize(uint32_t pixel_count) const { } 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 @@ bool VideoStreamEncoder::TryQualityRampup(int64_t now_ms) { // 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 @@ void VideoStreamEncoder::RunPostEncode(const EncodedImage& encoded_image, 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 01d77382a2..97a4a66a05 100644 --- a/video/video_stream_encoder.h +++ b/video/video_stream_encoder.h @@ -226,9 +226,6 @@ class VideoStreamEncoder : public VideoStreamEncoderInterface, const RateControlSettings rate_control_settings_; const QualityScalerSettings quality_scaler_settings_; - std::unique_ptr 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.