Adds field trial to set per-layer speed for libvpx vp9.

The trial name WebRTC-VP9-PerLayerSpeed is used to
a) set encoding speed per spatial layer, based on resolution
b) allow explicitly overriding speed per layer, for testing

Additionally, this CL updates the vp9 wrapper in preparation for
injectable trials.

Bug: webrtc:11551, webrtc:11926
Change-Id: I2bb3a664feaef60483ffc241b71070284d3e0172
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/186400
Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
Commit-Queue: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32294}
This commit is contained in:
Erik Språng
2020-10-01 19:13:13 +02:00
committed by Commit Bot
parent 85ddb23235
commit e3c436b16a
3 changed files with 87 additions and 28 deletions

View File

@ -19,6 +19,8 @@
#include <vector>
#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<double> framerate_limit("min_fps", 5.0);
FieldTrialParameter<int> 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<int> low_qp("low_qp", kLowVp9QpThreshold);
FieldTrialParameter<int> 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<int> 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