From ead570c963d99f639a90bc9e267997cddef1db38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Spr=C3=A5ng?= Date: Thu, 3 Dec 2020 16:05:49 +0000 Subject: [PATCH] Revert "Adds experimental libvpx VP9 speed settings." MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 6e7167456b5eba36c7985d6a74f1d191958d4e0f. Reason for revert: Unexpected perf change Original change's description: > Adds experimental libvpx VP9 speed settings. > > Using the field trial WebRTC-VP9-PerformanceFlags, this CL allows you to > configure the libvpx VP9 encoder with a list of flags to affect the > quality vs speed tradeoff. This CL adds support for: > > * Speed (effort), for the temporal base layer frames > * Speed for higher (non-base) layer frames > * De-blocking (as part of the loopfilter) enabled for: > 0 = all frames > 1 = all but frames from the highest temporal layer > 2 = no frames > > Each entry in the list has a threshold in min number of pixels needed > for settings in the entry to apply. > > Example: Two spatial layers (180p, 360p) with three temporal > layers are configured. Field trial "WebRTC-VP9-PerformanceFlags" set to: > "min_pixel_count:0|129600,base_layer_speed:5|8,high_layer_speed:7|8,deblock_mode:1|2" > This translates to: > S0: > - TL0: Speed 5, deblocked > - TL1: Speed 8, deblocked > - TL2: Speed 8, not deblocked > S1: > - TL0: Speed 7, not deblocked > - TL1: Speed 8, not deblocked > - TL2: Speed 8, not deblocked > > Bug: webrtc:11551 > Change-Id: Ieef6816d3e0831ff53348ecc4a90260e2ef10422 > Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/188461 > Reviewed-by: Michael Horowitz > Reviewed-by: Sergey Silkin > Commit-Queue: Erik Språng > Cr-Commit-Position: refs/heads/master@{#32749} TBR=sprang@webrtc.org,ssilkin@webrtc.org,mhoro@webrtc.org Change-Id: If910963441ac1a0e002aac7066791c7cc7764a1a No-Presubmit: true No-Tree-Checks: true No-Try: true Bug: webrtc:11551 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/196344 Reviewed-by: Erik Språng Commit-Queue: Erik Språng Cr-Commit-Position: refs/heads/master@{#32762} --- modules/video_coding/codecs/vp9/vp9_impl.cc | 167 ++++++-------------- modules/video_coding/codecs/vp9/vp9_impl.h | 28 +--- 2 files changed, 58 insertions(+), 137 deletions(-) diff --git a/modules/video_coding/codecs/vp9/vp9_impl.cc b/modules/video_coding/codecs/vp9/vp9_impl.cc index acf5e21e66..c2b1f501fb 100644 --- a/modules/video_coding/codecs/vp9/vp9_impl.cc +++ b/modules/video_coding/codecs/vp9/vp9_impl.cc @@ -32,7 +32,6 @@ #include "modules/video_coding/svc/scalable_video_controller_no_layering.h" #include "modules/video_coding/utility/vp9_uncompressed_header_parser.h" #include "rtc_base/checks.h" -#include "rtc_base/experiments/field_trial_list.h" #include "rtc_base/experiments/field_trial_parser.h" #include "rtc_base/experiments/rate_control_settings.h" #include "rtc_base/keep_ref_until_done.h" @@ -66,6 +65,20 @@ const int kMaxAllowedPidDiff = 30; constexpr int kLowVp9QpThreshold = 149; constexpr int kHighVp9QpThreshold = 205; +// Only positive speeds, range for real-time coding currently is: 5 - 8. +// Lower means slower/better quality, higher means fastest/lower quality. +int GetCpuSpeed(int width, int height) { +#if defined(WEBRTC_ARCH_ARM) || defined(WEBRTC_ARCH_ARM64) || defined(ANDROID) + return 8; +#else + // For smaller resolutions, use lower speed setting (get some coding gain at + // the cost of increased encoding complexity). + if (width * height <= 352 * 288) + return 5; + else + return 7; +#endif +} // Helper class for extracting VP9 colorspace. ColorSpace ExtractVP9ColorSpace(vpx_color_space_t space_t, vpx_color_range_t range_t, @@ -268,6 +281,7 @@ VP9EncoderImpl::VP9EncoderImpl(const cricket::VideoCodec& codec, ParseSdpForVP9Profile(codec.params).value_or(VP9Profile::kProfile0)), inited_(false), timestamp_(0), + cpu_speed_(3), rc_max_intra_target_(0), encoder_(nullptr), config_(nullptr), @@ -304,7 +318,7 @@ VP9EncoderImpl::VP9EncoderImpl(const cricket::VideoCodec& codec, external_ref_ctrl_( !absl::StartsWith(trials.Lookup("WebRTC-Vp9ExternalRefCtrl"), "Disabled")), - performance_flags_(ParsePerformanceFlagsFromTrials(trials)), + per_layer_speed_(ParsePerLayerSpeed(trials)), num_steady_state_frames_(0), config_changed_(true) { codec_ = {}; @@ -441,6 +455,8 @@ bool VP9EncoderImpl::SetSvcRates( first_active_layer_ = 0; bool seen_active_layer = false; bool expect_no_more_active_layers = false; + int highest_active_width = 0; + int highest_active_height = 0; for (int i = 0; i < num_spatial_layers_; ++i) { if (config_->ss_target_bitrate[i] > 0) { RTC_DCHECK(!expect_no_more_active_layers) << "Only middle layer is " @@ -450,6 +466,12 @@ bool VP9EncoderImpl::SetSvcRates( } num_active_spatial_layers_ = i + 1; seen_active_layer = true; + highest_active_width = + (svc_params_.scaling_factor_num[i] * config_->g_w) / + svc_params_.scaling_factor_den[i]; + highest_active_height = + (svc_params_.scaling_factor_num[i] * config_->g_h) / + svc_params_.scaling_factor_den[i]; } else { expect_no_more_active_layers = seen_active_layer; } @@ -477,6 +499,7 @@ bool VP9EncoderImpl::SetSvcRates( svc_controller_->OnRatesUpdated(allocation); } current_bitrate_allocation_ = bitrate_allocation; + cpu_speed_ = GetCpuSpeed(highest_active_width, highest_active_height); config_changed_ = true; return true; } @@ -642,6 +665,8 @@ int VP9EncoderImpl::InitEncode(const VideoCodec* inst, config_->g_threads = NumberOfThreads(config_->g_w, config_->g_h, settings.number_of_cores); + cpu_speed_ = GetCpuSpeed(config_->g_w, config_->g_h); + is_flexible_mode_ = inst->VP9().flexibleMode; inter_layer_pred_ = inst->VP9().interLayerPred; @@ -802,16 +827,22 @@ int VP9EncoderImpl::InitAndSetControlSettings(const VideoCodec* inst) { return WEBRTC_VIDEO_CODEC_UNINITIALIZED; } - UpdatePerformanceFlags(); - RTC_DCHECK_EQ(performance_flags_by_spatial_index_.size(), - static_cast(num_spatial_layers_)); - for (int si = 0; si < std::min(num_spatial_layers_, 1); ++si) { - svc_params_.speed_per_layer[si] = - performance_flags_by_spatial_index_[si].base_layer_speed; - svc_params_.loopfilter_ctrl[si] = - performance_flags_by_spatial_index_[si].deblock_mode; + if (per_layer_speed_.enabled) { + for (int i = 0; i < num_spatial_layers_; ++i) { + if (codec_.spatialLayers[i].active) { + continue; + } + + if (per_layer_speed_.layers[i] != -1) { + svc_params_.speed_per_layer[i] = per_layer_speed_.layers[i]; + } else { + svc_params_.speed_per_layer[i] = GetCpuSpeed( + codec_.spatialLayers[i].width, codec_.spatialLayers[i].height); + } + } } + vpx_codec_control(encoder_, VP8E_SET_CPUUSED, cpu_speed_); vpx_codec_control(encoder_, VP8E_SET_MAX_INTRA_BITRATE_PCT, rc_max_intra_target_); vpx_codec_control(encoder_, VP9E_SET_AQ_MODE, @@ -823,9 +854,6 @@ int VP9EncoderImpl::InitAndSetControlSettings(const VideoCodec* inst) { if (is_svc_) { vpx_codec_control(encoder_, VP9E_SET_SVC, 1); vpx_codec_control(encoder_, VP9E_SET_SVC_PARAMETERS, &svc_params_); - } else { - vpx_codec_control(encoder_, VP8E_SET_CPUUSED, - performance_flags_by_spatial_index_[0].base_layer_speed); } if (num_spatial_layers_ > 1) { @@ -1040,24 +1068,6 @@ int VP9EncoderImpl::Encode(const VideoFrame& input_image, } } - if (is_svc_) { - // Update speed settings that might depend on temporal index. - bool speed_updated = false; - for (int sl_idx = 0; sl_idx < num_spatial_layers_; ++sl_idx) { - const int target_speed = - layer_id.temporal_layer_id_per_spatial[sl_idx] == 0 - ? performance_flags_by_spatial_index_[sl_idx].base_layer_speed - : performance_flags_by_spatial_index_[sl_idx].high_layer_speed; - if (svc_params_.speed_per_layer[sl_idx] != target_speed) { - svc_params_.speed_per_layer[sl_idx] = target_speed; - speed_updated = true; - } - } - if (speed_updated) { - vpx_codec_control(encoder_, VP9E_SET_SVC_PARAMETERS, &svc_params_); - } - } - vpx_codec_control(encoder_, VP9E_SET_SVC_LAYER_ID, &layer_id); if (num_spatial_layers_ > 1) { @@ -1070,6 +1080,7 @@ int VP9EncoderImpl::Encode(const VideoFrame& input_image, if (vpx_codec_enc_config_set(encoder_, config_)) { return WEBRTC_VIDEO_CODEC_ERROR; } + vpx_codec_control(encoder_, VP8E_SET_CPUUSED, cpu_speed_); config_changed_ = false; } @@ -1815,92 +1826,18 @@ VP9EncoderImpl::ParseQualityScalerConfig(const WebRtcKeyValueConfig& trials) { return config; } -void VP9EncoderImpl::UpdatePerformanceFlags() { - const auto find_speed = [&](int min_pixel_count) { - auto it = std::lower_bound( - performance_flags_.begin(), performance_flags_.end(), min_pixel_count, - [](const PerformanceFlags& lhs, int min_pixel_count) { - return lhs.min_pixel_count < min_pixel_count; - }); - return it == performance_flags_.begin() ? *it : *std::prev(it); - }; - - performance_flags_by_spatial_index_.clear(); - if (is_svc_) { - for (int si = 0; si < num_spatial_layers_; ++si) { - performance_flags_by_spatial_index_.push_back(find_speed( - codec_.spatialLayers[si].width * codec_.spatialLayers[si].height)); - } - } else { - performance_flags_by_spatial_index_.push_back( - find_speed(codec_.width * codec_.height)); - } -} - // static -std::vector -VP9EncoderImpl::ParsePerformanceFlagsFromTrials( +VP9EncoderImpl::SpeedSettings VP9EncoderImpl::ParsePerLayerSpeed( const WebRtcKeyValueConfig& trials) { - FieldTrialStructList trials_list( - {FieldTrialStructMember( - "min_pixel_count", - [](PerformanceFlags* c) { return &c->min_pixel_count; }), - FieldTrialStructMember( - "high_layer_speed", - [](PerformanceFlags* c) { return &c->high_layer_speed; }), - FieldTrialStructMember( - "base_layer_speed", - [](PerformanceFlags* c) { return &c->base_layer_speed; }), - FieldTrialStructMember( - "deblock_mode", - [](PerformanceFlags* c) { return &c->deblock_mode; })}, - {}); - - ParseFieldTrial({&trials_list}, trials.Lookup("WebRTC-VP9-PerformanceFlags")); - std::vector configs; - constexpr int kMinSpeed = 1; - constexpr int kMaxSpeed = 9; - for (auto& f : trials_list.Get()) { - if (f.base_layer_speed < kMinSpeed || f.base_layer_speed > kMaxSpeed || - f.high_layer_speed < kMinSpeed || f.high_layer_speed > kMaxSpeed || - f.deblock_mode < 0 || f.deblock_mode > 2) { - RTC_LOG(LS_WARNING) << "Ignoring invalid performance flags: " - << "min_pixel_count = " << f.min_pixel_count - << ", high_layer_speed = " << f.high_layer_speed - << ", base_layer_speed = " << f.base_layer_speed - << ", deblock_mode = " << f.deblock_mode; - continue; - } - configs.push_back(f); - } - - if (configs.empty()) { - return GetDefaultPerformanceFlags(); - } - - std::sort(configs.begin(), configs.end(), - [](const PerformanceFlags& lhs, const PerformanceFlags& rhs) { - return lhs.min_pixel_count < rhs.min_pixel_count; - }); - return configs; -} - -// static -std::vector -VP9EncoderImpl::GetDefaultPerformanceFlags() { - std::vector default_config; -#if defined(WEBRTC_ARCH_ARM) || defined(WEBRTC_ARCH_ARM64) || defined(ANDROID) - // Speed 8 on all layers for all resolutions. - default_config.push_back({0, 8, 8, 0}); -#else - // For smaller resolutions, use lower speed setting (get some coding gain at - // the cost of increased encoding complexity). - default_config.push_back({0, 5, 5, 0}); - - // Use speed 7 for QCIF and above. - default_config.push_back({352 * 288, 7, 7, 0}); -#endif - return default_config; + FieldTrialFlag enabled("enabled"); + FieldTrialParameter speeds[kMaxSpatialLayers]{ + {"s0", -1}, {"s1", -1}, {"s2", -1}, {"s3", -1}, {"s4", -1}}; + ParseFieldTrial( + {&enabled, &speeds[0], &speeds[1], &speeds[2], &speeds[3], &speeds[4]}, + trials.Lookup("WebRTC-VP9-PerLayerSpeed")); + return SpeedSettings{enabled.Get(), + {speeds[0].Get(), speeds[1].Get(), speeds[2].Get(), + speeds[3].Get(), speeds[4].Get()}}; } void VP9EncoderImpl::MaybeRewrapRawWithFormat(const vpx_img_fmt fmt) { diff --git a/modules/video_coding/codecs/vp9/vp9_impl.h b/modules/video_coding/codecs/vp9/vp9_impl.h index 0ed5e629f1..14c3ca8ccc 100644 --- a/modules/video_coding/codecs/vp9/vp9_impl.h +++ b/modules/video_coding/codecs/vp9/vp9_impl.h @@ -112,6 +112,7 @@ class VP9EncoderImpl : public VP9Encoder { const VP9Profile profile_; bool inited_; int64_t timestamp_; + int cpu_speed_; uint32_t rc_max_intra_target_; vpx_codec_ctx_t* encoder_; vpx_codec_enc_cfg_t* config_; @@ -193,28 +194,11 @@ class VP9EncoderImpl : public VP9Encoder { const WebRtcKeyValueConfig& trials); const bool external_ref_ctrl_; - // Flags that can affect speed vs quality tradeoff, and are configureable per - // resolution ranges. - struct PerformanceFlags { - // Min number of pixels needed for this config to be valid. - int min_pixel_count = 0; - - int base_layer_speed = -1; // Speed setting for TL0. - int high_layer_speed = -1; // Speed setting for TL1-TL3. - // 0 = deblock all temporal layers (TL) - // 1 = disable deblock for top-most TL - // 2 = disable deblock for all TLs - int deblock_mode = 0; - }; - // Performance flags, ordered by |min_pixel_count|. - const std::vector performance_flags_; - // Caching of of |speed_configs_|, where index i maps to the resolution as - // specified in |codec_.spatialLayer[i]|. - std::vector performance_flags_by_spatial_index_; - void UpdatePerformanceFlags(); - static std::vector ParsePerformanceFlagsFromTrials( - const WebRtcKeyValueConfig& trials); - static std::vector GetDefaultPerformanceFlags(); + const struct SpeedSettings { + bool enabled; + int layers[kMaxSpatialLayers]; + } per_layer_speed_; + static SpeedSettings ParsePerLayerSpeed(const WebRtcKeyValueConfig& trials); int num_steady_state_frames_; // Only set config when this flag is set.