diff --git a/webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.cc b/webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.cc index cb35fdc462..bbb3f0985c 100644 --- a/webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.cc +++ b/webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.cc @@ -466,7 +466,7 @@ bool SimulcastEncoderAdapter::SupportsNativeHandle() const { VideoEncoder::ScalingSettings SimulcastEncoderAdapter::GetScalingSettings() const { // Turn off quality scaling for simulcast. - if (NumberOfStreams(codec_) != 1) + if (!Initialized() || NumberOfStreams(codec_) != 1) return VideoEncoder::ScalingSettings(false); return streaminfos_[0].encoder->GetScalingSettings(); } diff --git a/webrtc/video/send_statistics_proxy.cc b/webrtc/video/send_statistics_proxy.cc index 82d7f0dc75..6c249f70a9 100644 --- a/webrtc/video/send_statistics_proxy.cc +++ b/webrtc/video/send_statistics_proxy.cc @@ -506,17 +506,13 @@ void SendStatisticsProxy::OnSendEncodedImage( uma_container_->key_frame_counter_.Add(encoded_image._frameType == kVideoFrameKey); stats_.bw_limited_resolution = - stats_.bw_limited_resolution || - encoded_image.adapt_reason_.bw_resolutions_disabled > 0; + encoded_image.adapt_reason_.bw_resolutions_disabled > 0 || + quality_downscales_ > 0; - if (encoded_image.adapt_reason_.quality_resolution_downscales != -1) { - bool downscaled = - encoded_image.adapt_reason_.quality_resolution_downscales > 0; - uma_container_->quality_limited_frame_counter_.Add(downscaled); - if (downscaled) { - uma_container_->quality_downscales_counter_.Add( - encoded_image.adapt_reason_.quality_resolution_downscales); - } + if (quality_downscales_ != -1) { + uma_container_->quality_limited_frame_counter_.Add(quality_downscales_ > 0); + if (quality_downscales_ > 0) + uma_container_->quality_downscales_counter_.Add(quality_downscales_); } if (encoded_image.adapt_reason_.bw_resolutions_disabled != -1) { bool bw_limited = encoded_image.adapt_reason_.bw_resolutions_disabled > 0; @@ -587,11 +583,20 @@ void SendStatisticsProxy::OnIncomingFrame(int width, int height) { uma_container_->cpu_limited_frame_counter_.Add(stats_.cpu_limited_resolution); } -void SendStatisticsProxy::SetResolutionRestrictionStats(bool bandwidth, - bool cpu) { +void SendStatisticsProxy::SetResolutionRestrictionStats( + bool scaling_enabled, + bool cpu_restricted, + int num_quality_downscales) { rtc::CritScope lock(&crit_); - stats_.bw_limited_resolution = bandwidth; - stats_.cpu_limited_resolution = cpu; + if (scaling_enabled) { + quality_downscales_ = num_quality_downscales; + stats_.bw_limited_resolution = quality_downscales_ > 0; + stats_.cpu_limited_resolution = cpu_restricted; + } else { + stats_.bw_limited_resolution = false; + stats_.cpu_limited_resolution = false; + quality_downscales_ = -1; + } } void SendStatisticsProxy::OnCpuRestrictedResolutionChanged( @@ -602,10 +607,10 @@ void SendStatisticsProxy::OnCpuRestrictedResolutionChanged( } void SendStatisticsProxy::OnQualityRestrictedResolutionChanged( - bool restricted) { + int num_quality_downscales) { rtc::CritScope lock(&crit_); - uma_container_->quality_downscales_counter_.Add(restricted); - stats_.bw_limited_resolution = restricted; + quality_downscales_ = num_quality_downscales; + stats_.bw_limited_resolution = quality_downscales_ > 0; } void SendStatisticsProxy::RtcpPacketTypesCounterUpdated( diff --git a/webrtc/video/send_statistics_proxy.h b/webrtc/video/send_statistics_proxy.h index 934dab2f93..ec8bb6d28c 100644 --- a/webrtc/video/send_statistics_proxy.h +++ b/webrtc/video/send_statistics_proxy.h @@ -58,8 +58,10 @@ class SendStatisticsProxy : public CpuOveruseMetricsObserver, void OnIncomingFrame(int width, int height); void OnCpuRestrictedResolutionChanged(bool cpu_restricted_resolution); - void OnQualityRestrictedResolutionChanged(bool restricted); - void SetResolutionRestrictionStats(bool bandwidth, bool cpu); + void OnQualityRestrictedResolutionChanged(int num_quality_downscales); + void SetResolutionRestrictionStats(bool scaling_enabled, + bool cpu_restricted, + int num_quality_downscales); void OnEncoderStatsUpdate(uint32_t framerate, uint32_t bitrate); void OnSuspendChange(bool is_suspended); @@ -154,6 +156,7 @@ class SendStatisticsProxy : public CpuOveruseMetricsObserver, uint32_t last_sent_frame_timestamp_ GUARDED_BY(crit_); std::map update_times_ GUARDED_BY(crit_); rtc::ExpFilter encode_time_ GUARDED_BY(crit_); + int quality_downscales_ GUARDED_BY(crit_) = 0; // Contains stats used for UMA histograms. These stats will be reset if // content type changes between real-time video and screenshare, since these diff --git a/webrtc/video/send_statistics_proxy_unittest.cc b/webrtc/video/send_statistics_proxy_unittest.cc index 4cee1046dd..acb8a306ca 100644 --- a/webrtc/video/send_statistics_proxy_unittest.cc +++ b/webrtc/video/send_statistics_proxy_unittest.cc @@ -31,6 +31,12 @@ const int kWidth = 640; const int kHeight = 480; const int kQpIdx0 = 21; const int kQpIdx1 = 39; +const CodecSpecificInfo kDefaultCodecInfo = []() { + CodecSpecificInfo codec_info; + codec_info.codecType = kVideoCodecVP8; + codec_info.codecSpecific.VP8.simulcastIdx = 0; + return codec_info; +}(); } // namespace class SendStatisticsProxyTest : public ::testing::Test { @@ -659,10 +665,10 @@ TEST_F(SendStatisticsProxyTest, TEST_F(SendStatisticsProxyTest, QualityLimitedHistogramsNotUpdatedWhenDisabled) { EncodedImage encoded_image; - // encoded_image.adapt_reason_.quality_resolution_downscales disabled by - // default: -1 + statistics_proxy_->SetResolutionRestrictionStats(false /* scaling_enabled */, + 0, 0); for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) - statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr); + statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo); // Histograms are updated when the statistics_proxy_ is deleted. statistics_proxy_.reset(); @@ -674,11 +680,9 @@ TEST_F(SendStatisticsProxyTest, TEST_F(SendStatisticsProxyTest, QualityLimitedHistogramsUpdatedWhenEnabled_NoResolutionDownscale) { - const int kDownscales = 0; EncodedImage encoded_image; - encoded_image.adapt_reason_.quality_resolution_downscales = kDownscales; for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) - statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr); + statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo); // Histograms are updated when the statistics_proxy_ is deleted. statistics_proxy_.reset(); @@ -695,10 +699,9 @@ TEST_F(SendStatisticsProxyTest, QualityLimitedHistogramsUpdatedWhenEnabled_TwoResolutionDownscales) { const int kDownscales = 2; EncodedImage encoded_image; - encoded_image.adapt_reason_.quality_resolution_downscales = kDownscales; + statistics_proxy_->OnQualityRestrictedResolutionChanged(kDownscales); for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) - statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr); - + statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo); // Histograms are updated when the statistics_proxy_ is deleted. statistics_proxy_.reset(); EXPECT_EQ( @@ -720,12 +723,18 @@ TEST_F(SendStatisticsProxyTest, GetStatsReportsBandwidthLimitedResolution) { EncodedImage encoded_image; statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr); EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution); - // Resolution not scaled. + + // Simulcast disabled resolutions + encoded_image.adapt_reason_.bw_resolutions_disabled = 1; + statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr); + EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution); + encoded_image.adapt_reason_.bw_resolutions_disabled = 0; statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr); EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution); - // Resolution scaled due to bandwidth. - encoded_image.adapt_reason_.bw_resolutions_disabled = 1; + + // Resolution scaled due to quality. + statistics_proxy_->OnQualityRestrictedResolutionChanged(1); statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr); EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution); } diff --git a/webrtc/video/vie_encoder.cc b/webrtc/video/vie_encoder.cc index cc33a79b3d..f78633d532 100644 --- a/webrtc/video/vie_encoder.cc +++ b/webrtc/video/vie_encoder.cc @@ -15,6 +15,7 @@ #include #include "webrtc/modules/video_coding/include/video_codec_initializer.h" +#include "webrtc/base/arraysize.h" #include "webrtc/base/checks.h" #include "webrtc/base/logging.h" #include "webrtc/base/trace_event.h" @@ -268,6 +269,7 @@ ViEEncoder::ViEEncoder(uint32_t number_of_cores, has_received_rpsi_(false), picture_id_rpsi_(0), clock_(Clock::GetRealTimeClock()), + scale_counter_(kScaleReasonSize, 0), last_frame_width_(0), last_frame_height_(0), last_captured_timestamp_(0), @@ -339,12 +341,10 @@ void ViEEncoder::SetSource( source_proxy_->SetSource(source, degradation_preference); encoder_queue_.PostTask([this, degradation_preference] { RTC_DCHECK_RUN_ON(&encoder_queue_); - scaling_enabled_ = - (degradation_preference != + scaling_enabled_ = (degradation_preference != VideoSendStream::DegradationPreference::kMaintainResolution); stats_proxy_->SetResolutionRestrictionStats( - scaling_enabled_ && scale_counter_[kQuality] > 0, - scaling_enabled_ && scale_counter_[kCpu] > 0); + scaling_enabled_, scale_counter_[kCpu] > 0, scale_counter_[kQuality]); }); } @@ -440,7 +440,7 @@ void ViEEncoder::ReconfigureEncoder() { std::move(streams), encoder_config_.min_transmit_bitrate_bps); const auto scaling_settings = settings_.encoder->GetScalingSettings(); - if (scaling_settings.enabled && scaling_enabled_) { + if (scaling_enabled_ && scaling_settings.enabled) { if (scaling_settings.thresholds) { quality_scaler_.reset( new QualityScaler(this, *(scaling_settings.thresholds))); @@ -449,6 +449,8 @@ void ViEEncoder::ReconfigureEncoder() { } } else { quality_scaler_.reset(nullptr); + stats_proxy_->SetResolutionRestrictionStats( + false, scale_counter_[kCpu] > 0, scale_counter_[kQuality]); } } @@ -596,9 +598,8 @@ EncodedImageCallback::Result ViEEncoder::OnEncodedImage( // Encoded is called on whatever thread the real encoder implementation run // on. In the case of hardware encoders, there might be several encoders // running in parallel on different threads. - if (stats_proxy_) { + if (stats_proxy_) stats_proxy_->OnSendEncodedImage(encoded_image, codec_specific_info); - } EncodedImageCallback::Result result = sink_->OnEncodedImage(encoded_image, codec_specific_info, fragmentation); @@ -707,7 +708,8 @@ void ViEEncoder::ScaleDown(ScaleReason reason) { return; switch (reason) { case kQuality: - stats_proxy_->OnQualityRestrictedResolutionChanged(true); + stats_proxy_->OnQualityRestrictedResolutionChanged( + scale_counter_[reason] + 1); break; case kCpu: if (scale_counter_[reason] >= kMaxCpuDowngrades) @@ -739,7 +741,7 @@ void ViEEncoder::ScaleUp(ScaleReason reason) { switch (reason) { case kQuality: stats_proxy_->OnQualityRestrictedResolutionChanged( - scale_counter_[reason] > 1); + scale_counter_[reason] - 1); break; case kCpu: // Update stats accordingly. diff --git a/webrtc/video/vie_encoder.h b/webrtc/video/vie_encoder.h index ca7bd9334d..c086644e14 100644 --- a/webrtc/video/vie_encoder.h +++ b/webrtc/video/vie_encoder.h @@ -211,7 +211,7 @@ class ViEEncoder : public rtc::VideoSinkInterface, Clock* const clock_; // Counters used for deciding if the video resolution is currently // restricted, and if so, why. - int scale_counter_[kScaleReasonSize] ACCESS_ON(&encoder_queue_) = {0}; + std::vector scale_counter_ ACCESS_ON(&encoder_queue_); // Set depending on degradation preferences bool scaling_enabled_ ACCESS_ON(&encoder_queue_) = false; diff --git a/webrtc/video_frame.h b/webrtc/video_frame.h index 5fd62a6bbb..bec43f80cc 100644 --- a/webrtc/video_frame.h +++ b/webrtc/video_frame.h @@ -136,14 +136,10 @@ class EncodedImage { EncodedImage(uint8_t* buffer, size_t length, size_t size) : _buffer(buffer), _length(length), _size(size) {} + // TODO(kthelgason): get rid of this struct as it only has a single member + // remaining. struct AdaptReason { - AdaptReason() - : quality_resolution_downscales(-1), - bw_resolutions_disabled(-1) {} - - int quality_resolution_downscales; // Number of times this frame is down - // scaled in resolution due to quality. - // Or -1 if information is not provided. + AdaptReason() : bw_resolutions_disabled(-1) {} int bw_resolutions_disabled; // Number of resolutions that are not sent // due to bandwidth for this frame. // Or -1 if information is not provided.