diff --git a/modules/video_coding/BUILD.gn b/modules/video_coding/BUILD.gn index bf8a4d620c..c02f0a8fdf 100644 --- a/modules/video_coding/BUILD.gn +++ b/modules/video_coding/BUILD.gn @@ -556,6 +556,8 @@ rtc_library("webrtc_vp9") { ":webrtc_vp9_helpers", "../../api:fec_controller_api", "../../api:scoped_refptr", + "../../api/transport:field_trial_based_config", + "../../api/transport:webrtc_key_value_config", "../../api/video:video_frame", "../../api/video:video_frame_i010", "../../api/video:video_rtp_headers", @@ -565,13 +567,17 @@ rtc_library("webrtc_vp9") { "../../media:rtc_vp9_profile", "../../rtc_base", "../../rtc_base:checks", + "../../rtc_base/experiments:field_trial_parser", "../../rtc_base/experiments:rate_control_settings", "../../rtc_base/synchronization:mutex", "../../system_wrappers:field_trial", "../rtp_rtcp:rtp_rtcp_format", "//third_party/libyuv", ] - absl_deps = [ "//third_party/abseil-cpp/absl/memory" ] + absl_deps = [ + "//third_party/abseil-cpp/absl/memory", + "//third_party/abseil-cpp/absl/strings:strings", + ] if (rtc_build_libvpx) { deps += [ rtc_libvpx_dir ] } diff --git a/modules/video_coding/codecs/vp9/vp9_impl.cc b/modules/video_coding/codecs/vp9/vp9_impl.cc index 07ccab347a..bf41e167c9 100644 --- a/modules/video_coding/codecs/vp9/vp9_impl.cc +++ b/modules/video_coding/codecs/vp9/vp9_impl.cc @@ -19,6 +19,8 @@ #include #include "absl/memory/memory.h" +#include "absl/strings/match.h" +#include "api/transport/field_trial_based_config.h" #include "api/video/color_space.h" #include "api/video/i010_buffer.h" #include "common_video/include/video_frame_buffer.h" @@ -27,12 +29,12 @@ #include "modules/video_coding/codecs/vp9/svc_rate_allocator.h" #include "modules/video_coding/utility/vp9_uncompressed_header_parser.h" #include "rtc_base/checks.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" #include "rtc_base/logging.h" #include "rtc_base/time_utils.h" #include "rtc_base/trace_event.h" -#include "system_wrappers/include/field_trial.h" #include "third_party/libyuv/include/libyuv/convert.h" #include "vpx/vp8cx.h" #include "vpx/vp8dx.h" @@ -221,6 +223,10 @@ void VP9EncoderImpl::EncoderOutputCodedPacketCallback(vpx_codec_cx_pkt* pkt, } VP9EncoderImpl::VP9EncoderImpl(const cricket::VideoCodec& codec) + : VP9EncoderImpl(codec, FieldTrialBasedConfig()) {} + +VP9EncoderImpl::VP9EncoderImpl(const cricket::VideoCodec& codec, + const WebRtcKeyValueConfig& trials) : encoded_image_(), encoded_complete_callback_(nullptr), profile_( @@ -239,27 +245,32 @@ VP9EncoderImpl::VP9EncoderImpl(const cricket::VideoCodec& codec) num_spatial_layers_(0), num_active_spatial_layers_(0), first_active_layer_(0), - layer_deactivation_requires_key_frame_( - field_trial::IsEnabled("WebRTC-Vp9IssueKeyFrameOnLayerDeactivation")), + layer_deactivation_requires_key_frame_(absl::StartsWith( + trials.Lookup("WebRTC-Vp9IssueKeyFrameOnLayerDeactivation"), + "Enabled")), is_svc_(false), inter_layer_pred_(InterLayerPredMode::kOn), external_ref_control_(false), // Set in InitEncode because of tests. - trusted_rate_controller_(RateControlSettings::ParseFromFieldTrials() - .LibvpxVp9TrustedRateController()), + trusted_rate_controller_( + RateControlSettings::ParseFromKeyValueConfig(&trials) + .LibvpxVp9TrustedRateController()), dynamic_rate_settings_( - RateControlSettings::ParseFromFieldTrials().Vp9DynamicRateSettings()), + RateControlSettings::ParseFromKeyValueConfig(&trials) + .Vp9DynamicRateSettings()), layer_buffering_(false), full_superframe_drop_(true), first_frame_in_picture_(true), ss_info_needed_(false), force_all_active_layers_(false), is_flexible_mode_(false), - variable_framerate_experiment_(ParseVariableFramerateConfig( - "WebRTC-VP9VariableFramerateScreenshare")), + variable_framerate_experiment_(ParseVariableFramerateConfig(trials)), variable_framerate_controller_( variable_framerate_experiment_.framerate_limit), - quality_scaler_experiment_( - ParseQualityScalerConfig("WebRTC-VP9QualityScaler")), + quality_scaler_experiment_(ParseQualityScalerConfig(trials)), + external_ref_ctrl_( + !absl::StartsWith(trials.Lookup("WebRTC-Vp9ExternalRefCtrl"), + "Disabled")), + per_layer_speed_(ParsePerLayerSpeed(trials)), num_steady_state_frames_(0), config_changed_(true) { codec_ = {}; @@ -270,8 +281,7 @@ VP9EncoderImpl::~VP9EncoderImpl() { Release(); } -void VP9EncoderImpl::SetFecControllerOverride( - FecControllerOverride* fec_controller_override) { +void VP9EncoderImpl::SetFecControllerOverride(FecControllerOverride*) { // Ignored. } @@ -615,11 +625,10 @@ int VP9EncoderImpl::InitEncode(const VideoCodec* inst, // External reference control is required for different frame rate on spatial // layers because libvpx generates rtp incompatible references in this case. - external_ref_control_ = - !field_trial::IsDisabled("WebRTC-Vp9ExternalRefCtrl") || - (num_spatial_layers_ > 1 && - codec_.mode == VideoCodecMode::kScreensharing) || - inter_layer_pred_ == InterLayerPredMode::kOn; + external_ref_control_ = external_ref_ctrl_ || + (num_spatial_layers_ > 1 && + codec_.mode == VideoCodecMode::kScreensharing) || + inter_layer_pred_ == InterLayerPredMode::kOn; if (num_temporal_layers_ == 1) { gof_.SetGofInfoVP9(kTemporalStructureMode1); @@ -756,6 +765,22 @@ int VP9EncoderImpl::InitAndSetControlSettings(const VideoCodec* inst) { RTC_LOG(LS_ERROR) << "Init error: " << vpx_codec_err_to_string(rv); return WEBRTC_VIDEO_CODEC_UNINITIALIZED; } + + 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_); @@ -1652,7 +1677,8 @@ size_t VP9EncoderImpl::SteadyStateSize(int sid, int tid) { // static VP9EncoderImpl::VariableFramerateExperiment -VP9EncoderImpl::ParseVariableFramerateConfig(std::string group_name) { +VP9EncoderImpl::ParseVariableFramerateConfig( + const WebRtcKeyValueConfig& trials) { FieldTrialFlag enabled = FieldTrialFlag("Enabled"); FieldTrialParameter framerate_limit("min_fps", 5.0); FieldTrialParameter qp("min_qp", 32); @@ -1661,7 +1687,7 @@ VP9EncoderImpl::ParseVariableFramerateConfig(std::string group_name) { "frames_before_steady_state", 5); ParseFieldTrial({&enabled, &framerate_limit, &qp, &undershoot_percentage, &frames_before_steady_state}, - field_trial::FindFullName(group_name)); + trials.Lookup("WebRTC-VP9VariableFramerateScreenshare")); VariableFramerateExperiment config; config.enabled = enabled.Get(); config.framerate_limit = framerate_limit.Get(); @@ -1674,12 +1700,12 @@ VP9EncoderImpl::ParseVariableFramerateConfig(std::string group_name) { // static VP9EncoderImpl::QualityScalerExperiment -VP9EncoderImpl::ParseQualityScalerConfig(std::string group_name) { +VP9EncoderImpl::ParseQualityScalerConfig(const WebRtcKeyValueConfig& trials) { FieldTrialFlag disabled = FieldTrialFlag("Disabled"); FieldTrialParameter low_qp("low_qp", kLowVp9QpThreshold); FieldTrialParameter high_qp("hihg_qp", kHighVp9QpThreshold); ParseFieldTrial({&disabled, &low_qp, &high_qp}, - field_trial::FindFullName(group_name)); + trials.Lookup("WebRTC-VP9QualityScaler")); QualityScalerExperiment config; config.enabled = !disabled.Get(); RTC_LOG(LS_INFO) << "Webrtc quality scaler for vp9 is " @@ -1690,6 +1716,20 @@ VP9EncoderImpl::ParseQualityScalerConfig(std::string group_name) { return config; } +// static +VP9EncoderImpl::SpeedSettings VP9EncoderImpl::ParsePerLayerSpeed( + const WebRtcKeyValueConfig& trials) { + 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) { if (!raw_) { raw_ = vpx_img_wrap(nullptr, fmt, codec_.width, codec_.height, 1, nullptr); @@ -1702,14 +1742,16 @@ void VP9EncoderImpl::MaybeRewrapRawWithFormat(const vpx_img_fmt fmt) { // else no-op since the image is already in the right format. } -VP9DecoderImpl::VP9DecoderImpl() +VP9DecoderImpl::VP9DecoderImpl() : VP9DecoderImpl(FieldTrialBasedConfig()) {} +VP9DecoderImpl::VP9DecoderImpl(const WebRtcKeyValueConfig& trials) : decode_complete_callback_(nullptr), inited_(false), decoder_(nullptr), key_frame_required_(true), - preferred_output_format_(field_trial::IsEnabled("WebRTC-NV12Decode") - ? VideoFrameBuffer::Type::kNV12 - : VideoFrameBuffer::Type::kI420) {} + preferred_output_format_( + absl::StartsWith(trials.Lookup("WebRTC-NV12Decode"), "Enabled") + ? VideoFrameBuffer::Type::kNV12 + : VideoFrameBuffer::Type::kI420) {} VP9DecoderImpl::~VP9DecoderImpl() { inited_ = true; // in order to do the actual release diff --git a/modules/video_coding/codecs/vp9/vp9_impl.h b/modules/video_coding/codecs/vp9/vp9_impl.h index 1ebb1c1f33..6e23dc6d79 100644 --- a/modules/video_coding/codecs/vp9/vp9_impl.h +++ b/modules/video_coding/codecs/vp9/vp9_impl.h @@ -20,6 +20,7 @@ #include #include "api/fec_controller_override.h" +#include "api/transport/webrtc_key_value_config.h" #include "api/video_codecs/video_encoder.h" #include "common_video/include/video_frame_buffer_pool.h" #include "media/base/vp9_profile.h" @@ -35,6 +36,8 @@ namespace webrtc { class VP9EncoderImpl : public VP9Encoder { public: explicit VP9EncoderImpl(const cricket::VideoCodec& codec); + VP9EncoderImpl(const cricket::VideoCodec& codec, + const WebRtcKeyValueConfig& trials); ~VP9EncoderImpl() override; @@ -176,7 +179,7 @@ class VP9EncoderImpl : public VP9Encoder { int frames_before_steady_state; } variable_framerate_experiment_; static VariableFramerateExperiment ParseVariableFramerateConfig( - std::string group_name); + const WebRtcKeyValueConfig& trials); FramerateController variable_framerate_controller_; const struct QualityScalerExperiment { @@ -185,7 +188,14 @@ class VP9EncoderImpl : public VP9Encoder { bool enabled; } quality_scaler_experiment_; static QualityScalerExperiment ParseQualityScalerConfig( - std::string group_name); + const WebRtcKeyValueConfig& trials); + const bool external_ref_ctrl_; + + 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. @@ -195,6 +205,7 @@ class VP9EncoderImpl : public VP9Encoder { class VP9DecoderImpl : public VP9Decoder { public: VP9DecoderImpl(); + explicit VP9DecoderImpl(const WebRtcKeyValueConfig& trials); virtual ~VP9DecoderImpl();