Changes default pacing factor to 1.1x

This changes the default behavior to use pacing factor of 1.1x instead
of 2.5x, it also sets libvpx rate controler as trusted, turns on the
encoder pushback mechanism and sets spatial hysteresis to 1.2.
The unused "dynamic rate" settings in libvpx is removed.

The new settings matches what has been used in chromium since 2019.
If needed, the legacy behavior can be enabled using the field trial
WebRTC-VideoRateControl.

Bug: webrtc:10155
Change-Id: I8186b491aa5bef61e8f568e96c980ca68f0c208f
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/186661
Commit-Queue: Erik Språng <sprang@webrtc.org>
Reviewed-by: Per Kjellander <perkj@webrtc.org>
Reviewed-by: Christoffer Rodbro <crodbro@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32477}
This commit is contained in:
Erik Språng
2020-10-22 17:44:42 +02:00
committed by Commit Bot
parent 213fa85f73
commit 9d69cbeabf
17 changed files with 137 additions and 298 deletions

View File

@ -68,9 +68,6 @@ constexpr uint32_t kVp832ByteAlign = 32u;
constexpr int kRtpTicksPerSecond = 90000;
constexpr int kRtpTicksPerMs = kRtpTicksPerSecond / 1000;
constexpr double kLowRateFactor = 1.0;
constexpr double kHighRateFactor = 2.0;
// VP8 denoiser states.
enum denoiserState : uint32_t {
kDenoiserOff,
@ -82,15 +79,6 @@ enum denoiserState : uint32_t {
kDenoiserOnAdaptive
};
// These settings correspond to the settings in vpx_codec_enc_cfg.
struct Vp8RateSettings {
uint32_t rc_undershoot_pct;
uint32_t rc_overshoot_pct;
uint32_t rc_buf_sz;
uint32_t rc_buf_optimal_sz;
uint32_t rc_dropframe_thresh;
};
// Greatest common divisior
int GCD(int a, int b) {
int c = a % b;
@ -102,56 +90,6 @@ int GCD(int a, int b) {
return b;
}
uint32_t Interpolate(uint32_t low,
uint32_t high,
double bandwidth_headroom_factor) {
RTC_DCHECK_GE(bandwidth_headroom_factor, kLowRateFactor);
RTC_DCHECK_LE(bandwidth_headroom_factor, kHighRateFactor);
// |factor| is between 0.0 and 1.0.
const double factor = bandwidth_headroom_factor - kLowRateFactor;
return static_cast<uint32_t>(((1.0 - factor) * low) + (factor * high) + 0.5);
}
Vp8RateSettings GetRateSettings(double bandwidth_headroom_factor) {
static const Vp8RateSettings low_settings{1000u, 0u, 100u, 30u, 40u};
static const Vp8RateSettings high_settings{100u, 15u, 1000u, 600u, 5u};
if (bandwidth_headroom_factor <= kLowRateFactor) {
return low_settings;
} else if (bandwidth_headroom_factor >= kHighRateFactor) {
return high_settings;
}
Vp8RateSettings settings;
settings.rc_undershoot_pct =
Interpolate(low_settings.rc_undershoot_pct,
high_settings.rc_undershoot_pct, bandwidth_headroom_factor);
settings.rc_overshoot_pct =
Interpolate(low_settings.rc_overshoot_pct, high_settings.rc_overshoot_pct,
bandwidth_headroom_factor);
settings.rc_buf_sz =
Interpolate(low_settings.rc_buf_sz, high_settings.rc_buf_sz,
bandwidth_headroom_factor);
settings.rc_buf_optimal_sz =
Interpolate(low_settings.rc_buf_optimal_sz,
high_settings.rc_buf_optimal_sz, bandwidth_headroom_factor);
settings.rc_dropframe_thresh =
Interpolate(low_settings.rc_dropframe_thresh,
high_settings.rc_dropframe_thresh, bandwidth_headroom_factor);
return settings;
}
void UpdateRateSettings(vpx_codec_enc_cfg_t* config,
const Vp8RateSettings& new_settings) {
config->rc_undershoot_pct = new_settings.rc_undershoot_pct;
config->rc_overshoot_pct = new_settings.rc_overshoot_pct;
config->rc_buf_sz = new_settings.rc_buf_sz;
config->rc_buf_optimal_sz = new_settings.rc_buf_optimal_sz;
config->rc_dropframe_thresh = new_settings.rc_dropframe_thresh;
}
static_assert(Vp8EncoderConfig::TemporalLayerConfig::kMaxPeriodicity ==
VPX_TS_MAX_PERIODICITY,
"Vp8EncoderConfig::kMaxPeriodicity must be kept in sync with the "
@ -407,14 +345,6 @@ void LibvpxVp8Encoder::SetRates(const RateControlParameters& parameters) {
UpdateVpxConfiguration(stream_idx);
if (rate_control_settings_.Vp8DynamicRateSettings()) {
// Tweak rate control settings based on available network headroom.
UpdateRateSettings(
&vpx_configs_[i],
GetRateSettings(parameters.bandwidth_allocation.bps<double>() /
parameters.bitrate.get_sum_bps()));
}
vpx_codec_err_t err =
libvpx_->codec_enc_config_set(&encoders_[i], &vpx_configs_[i]);
if (err != VPX_CODEC_OK) {

View File

@ -190,68 +190,6 @@ TEST_F(TestVp8Impl, SetRates) {
bitrate_allocation, static_cast<double>(codec_settings_.maxFramerate)));
}
TEST_F(TestVp8Impl, DynamicSetRates) {
test::ScopedFieldTrials field_trials(
"WebRTC-VideoRateControl/vp8_dynamic_rate:true/");
auto* const vpx = new NiceMock<MockLibvpxVp8Interface>();
LibvpxVp8Encoder encoder((std::unique_ptr<LibvpxInterface>(vpx)),
VP8Encoder::Settings());
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
encoder.InitEncode(&codec_settings_,
VideoEncoder::Settings(kCapabilities, 1, 1000)));
const uint32_t kBitrateBps = 300000;
VideoEncoder::RateControlParameters rate_settings;
rate_settings.bitrate.SetBitrate(0, 0, kBitrateBps);
rate_settings.framerate_fps =
static_cast<double>(codec_settings_.maxFramerate);
// Set rates with no headroom.
rate_settings.bandwidth_allocation = DataRate::BitsPerSec(kBitrateBps);
EXPECT_CALL(
*vpx,
codec_enc_config_set(
_, AllOf(Field(&vpx_codec_enc_cfg_t::rc_target_bitrate,
kBitrateBps / 1000),
Field(&vpx_codec_enc_cfg_t::rc_undershoot_pct, 1000u),
Field(&vpx_codec_enc_cfg_t::rc_overshoot_pct, 0u),
Field(&vpx_codec_enc_cfg_t::rc_buf_sz, 100u),
Field(&vpx_codec_enc_cfg_t::rc_buf_optimal_sz, 30u),
Field(&vpx_codec_enc_cfg_t::rc_dropframe_thresh, 40u))))
.WillOnce(Return(VPX_CODEC_OK));
encoder.SetRates(rate_settings);
// Set rates with max headroom.
rate_settings.bandwidth_allocation = DataRate::BitsPerSec(kBitrateBps * 2);
EXPECT_CALL(
*vpx, codec_enc_config_set(
_, AllOf(Field(&vpx_codec_enc_cfg_t::rc_target_bitrate,
kBitrateBps / 1000),
Field(&vpx_codec_enc_cfg_t::rc_undershoot_pct, 100u),
Field(&vpx_codec_enc_cfg_t::rc_overshoot_pct, 15u),
Field(&vpx_codec_enc_cfg_t::rc_buf_sz, 1000u),
Field(&vpx_codec_enc_cfg_t::rc_buf_optimal_sz, 600u),
Field(&vpx_codec_enc_cfg_t::rc_dropframe_thresh, 5u))))
.WillOnce(Return(VPX_CODEC_OK));
encoder.SetRates(rate_settings);
// Set rates with headroom half way.
rate_settings.bandwidth_allocation =
DataRate::BitsPerSec((3 * kBitrateBps) / 2);
EXPECT_CALL(
*vpx,
codec_enc_config_set(
_, AllOf(Field(&vpx_codec_enc_cfg_t::rc_target_bitrate,
kBitrateBps / 1000),
Field(&vpx_codec_enc_cfg_t::rc_undershoot_pct, 550u),
Field(&vpx_codec_enc_cfg_t::rc_overshoot_pct, 8u),
Field(&vpx_codec_enc_cfg_t::rc_buf_sz, 550u),
Field(&vpx_codec_enc_cfg_t::rc_buf_optimal_sz, 315u),
Field(&vpx_codec_enc_cfg_t::rc_dropframe_thresh, 23u))))
.WillOnce(Return(VPX_CODEC_OK));
encoder.SetRates(rate_settings);
}
TEST_F(TestVp8Impl, EncodeFrameAndRelease) {
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, encoder_->Release());
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,

View File

@ -56,9 +56,6 @@ uint8_t kUpdBufIdx[4] = {0, 0, 1, 0};
// Maximum allowed PID difference for differnet per-layer frame-rate case.
const int kMaxAllowedPidDiff = 30;
constexpr double kLowRateFactor = 1.0;
constexpr double kHighRateFactor = 2.0;
// TODO(ilink): Tune these thresholds further.
// Selected using ConverenceMotion_1280_720_50.yuv clip.
// No toggling observed on any link capacity from 100-2000kbps.
@ -68,15 +65,6 @@ constexpr double kHighRateFactor = 2.0;
constexpr int kLowVp9QpThreshold = 149;
constexpr int kHighVp9QpThreshold = 205;
// These settings correspond to the settings in vpx_codec_enc_cfg.
struct Vp9RateSettings {
uint32_t rc_undershoot_pct;
uint32_t rc_overshoot_pct;
uint32_t rc_buf_sz;
uint32_t rc_buf_optimal_sz;
uint32_t rc_dropframe_thresh;
};
// 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) {
@ -168,56 +156,6 @@ std::pair<size_t, size_t> GetActiveLayers(
return {0, 0};
}
uint32_t Interpolate(uint32_t low,
uint32_t high,
double bandwidth_headroom_factor) {
RTC_DCHECK_GE(bandwidth_headroom_factor, kLowRateFactor);
RTC_DCHECK_LE(bandwidth_headroom_factor, kHighRateFactor);
// |factor| is between 0.0 and 1.0.
const double factor = bandwidth_headroom_factor - kLowRateFactor;
return static_cast<uint32_t>(((1.0 - factor) * low) + (factor * high) + 0.5);
}
Vp9RateSettings GetRateSettings(double bandwidth_headroom_factor) {
static const Vp9RateSettings low_settings{100u, 0u, 100u, 33u, 40u};
static const Vp9RateSettings high_settings{50u, 50u, 1000u, 700u, 5u};
if (bandwidth_headroom_factor <= kLowRateFactor) {
return low_settings;
} else if (bandwidth_headroom_factor >= kHighRateFactor) {
return high_settings;
}
Vp9RateSettings settings;
settings.rc_undershoot_pct =
Interpolate(low_settings.rc_undershoot_pct,
high_settings.rc_undershoot_pct, bandwidth_headroom_factor);
settings.rc_overshoot_pct =
Interpolate(low_settings.rc_overshoot_pct, high_settings.rc_overshoot_pct,
bandwidth_headroom_factor);
settings.rc_buf_sz =
Interpolate(low_settings.rc_buf_sz, high_settings.rc_buf_sz,
bandwidth_headroom_factor);
settings.rc_buf_optimal_sz =
Interpolate(low_settings.rc_buf_optimal_sz,
high_settings.rc_buf_optimal_sz, bandwidth_headroom_factor);
settings.rc_dropframe_thresh =
Interpolate(low_settings.rc_dropframe_thresh,
high_settings.rc_dropframe_thresh, bandwidth_headroom_factor);
return settings;
}
void UpdateRateSettings(vpx_codec_enc_cfg_t* config,
const Vp9RateSettings& new_settings) {
config->rc_undershoot_pct = new_settings.rc_undershoot_pct;
config->rc_overshoot_pct = new_settings.rc_overshoot_pct;
config->rc_buf_sz = new_settings.rc_buf_sz;
config->rc_buf_optimal_sz = new_settings.rc_buf_optimal_sz;
config->rc_dropframe_thresh = new_settings.rc_dropframe_thresh;
}
std::unique_ptr<ScalableVideoController> CreateVp9ScalabilityStructure(
const VideoCodec& codec) {
int num_spatial_layers = codec.VP9().numberOfSpatialLayers;
@ -364,9 +302,6 @@ VP9EncoderImpl::VP9EncoderImpl(const cricket::VideoCodec& codec,
trusted_rate_controller_(
RateControlSettings::ParseFromKeyValueConfig(&trials)
.LibvpxVp9TrustedRateController()),
dynamic_rate_settings_(
RateControlSettings::ParseFromKeyValueConfig(&trials)
.Vp9DynamicRateSettings()),
layer_buffering_(false),
full_superframe_drop_(true),
first_frame_in_picture_(true),
@ -586,13 +521,6 @@ void VP9EncoderImpl::SetRates(const RateControlParameters& parameters) {
codec_.maxFramerate = static_cast<uint32_t>(parameters.framerate_fps + 0.5);
if (dynamic_rate_settings_) {
// Tweak rate control settings based on available network headroom.
UpdateRateSettings(
config_, GetRateSettings(parameters.bandwidth_allocation.bps<double>() /
parameters.bitrate.get_sum_bps()));
}
bool res = SetSvcRates(parameters.bitrate);
RTC_DCHECK(res) << "Failed to set new bitrate allocation";
config_changed_ = true;

View File

@ -132,7 +132,6 @@ class VP9EncoderImpl : public VP9Encoder {
InterLayerPredMode inter_layer_pred_;
bool external_ref_control_;
const bool trusted_rate_controller_;
const bool dynamic_rate_settings_;
bool layer_buffering_;
const bool full_superframe_drop_;
vpx_svc_frame_drop_t svc_drop_frame_;