Skip to content
This repository was archived by the owner on Oct 25, 2024. It is now read-only.

Commit b15b291

Browse files
author
Erik Språng
committed
M88 merge: Reland "Adds experimental libvpx VP9 speed settings."
This is a reland of 6e71674 Patch set 1 is the original. Later patch sets fix a parsing bug, and adds a new flag which enables or disabled the ability to set separate per spatial layer speed (use_per_layer_speed). 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: > "use_per_layer_speed,min_pixel_count:0|129600,base_layer_speed:5|7,high_layer_speed:8|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 <[email protected]> > Reviewed-by: Sergey Silkin <[email protected]> > Commit-Queue: Erik Språng <[email protected]> > Cr-Commit-Position: refs/heads/master@{#32749} (cherry picked from commit 3931591) Bug: webrtc:11551, chromium:1157536 Change-Id: Ie7c703eb122197235d8ce77cb72db7a347382468 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/196345 Reviewed-by: Michael Horowitz <[email protected]> Reviewed-by: Sergey Silkin <[email protected]> Commit-Queue: Erik Språng <[email protected]> Cr-Original-Commit-Position: refs/heads/master@{#32780} Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/196901 Reviewed-by: Mirko Bonadei <[email protected]> Cr-Commit-Position: refs/branch-heads/4324@{#3} Cr-Branched-From: daab689-refs/heads/master@{#32599}
1 parent 54bd848 commit b15b291

File tree

3 files changed

+173
-58
lines changed

3 files changed

+173
-58
lines changed

DEPS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ deps = {
210210
'src/third_party/perfetto':
211211
'https://android.googlesource.com/platform/external/perfetto.git@81e9301838fcce3f967c51b92628ea4f7caa4c20',
212212
'src/third_party/libvpx/source/libvpx':
213-
'https://chromium.googlesource.com/webm/libvpx.git@94384b5c685ad3baac8989f19ee587eb72093a7f',
213+
'https://chromium.googlesource.com/webm/libvpx.git@12059d9566fff24ef12e4154438b046abd3a8da7',
214214
'src/third_party/libyuv':
215215
'https://chromium.googlesource.com/libyuv/libyuv.git@f014dbd87ab06258569ad10a4cb6f84a8a7f7dd2',
216216
'src/third_party/lss': {

modules/video_coding/codecs/vp9/vp9_impl.cc

Lines changed: 138 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "modules/video_coding/svc/scalable_video_controller_no_layering.h"
3333
#include "modules/video_coding/utility/vp9_uncompressed_header_parser.h"
3434
#include "rtc_base/checks.h"
35+
#include "rtc_base/experiments/field_trial_list.h"
3536
#include "rtc_base/experiments/field_trial_parser.h"
3637
#include "rtc_base/experiments/rate_control_settings.h"
3738
#include "rtc_base/keep_ref_until_done.h"
@@ -65,20 +66,6 @@ const int kMaxAllowedPidDiff = 30;
6566
constexpr int kLowVp9QpThreshold = 149;
6667
constexpr int kHighVp9QpThreshold = 205;
6768

68-
// Only positive speeds, range for real-time coding currently is: 5 - 8.
69-
// Lower means slower/better quality, higher means fastest/lower quality.
70-
int GetCpuSpeed(int width, int height) {
71-
#if defined(WEBRTC_ARCH_ARM) || defined(WEBRTC_ARCH_ARM64) || defined(ANDROID)
72-
return 8;
73-
#else
74-
// For smaller resolutions, use lower speed setting (get some coding gain at
75-
// the cost of increased encoding complexity).
76-
if (width * height <= 352 * 288)
77-
return 5;
78-
else
79-
return 7;
80-
#endif
81-
}
8269
// Helper class for extracting VP9 colorspace.
8370
ColorSpace ExtractVP9ColorSpace(vpx_color_space_t space_t,
8471
vpx_color_range_t range_t,
@@ -281,7 +268,6 @@ VP9EncoderImpl::VP9EncoderImpl(const cricket::VideoCodec& codec,
281268
ParseSdpForVP9Profile(codec.params).value_or(VP9Profile::kProfile0)),
282269
inited_(false),
283270
timestamp_(0),
284-
cpu_speed_(3),
285271
rc_max_intra_target_(0),
286272
encoder_(nullptr),
287273
config_(nullptr),
@@ -318,7 +304,7 @@ VP9EncoderImpl::VP9EncoderImpl(const cricket::VideoCodec& codec,
318304
external_ref_ctrl_(
319305
!absl::StartsWith(trials.Lookup("WebRTC-Vp9ExternalRefCtrl"),
320306
"Disabled")),
321-
per_layer_speed_(ParsePerLayerSpeed(trials)),
307+
performance_flags_(ParsePerformanceFlagsFromTrials(trials)),
322308
num_steady_state_frames_(0),
323309
config_changed_(true) {
324310
codec_ = {};
@@ -455,8 +441,6 @@ bool VP9EncoderImpl::SetSvcRates(
455441
first_active_layer_ = 0;
456442
bool seen_active_layer = false;
457443
bool expect_no_more_active_layers = false;
458-
int highest_active_width = 0;
459-
int highest_active_height = 0;
460444
for (int i = 0; i < num_spatial_layers_; ++i) {
461445
if (config_->ss_target_bitrate[i] > 0) {
462446
RTC_DCHECK(!expect_no_more_active_layers) << "Only middle layer is "
@@ -466,12 +450,6 @@ bool VP9EncoderImpl::SetSvcRates(
466450
}
467451
num_active_spatial_layers_ = i + 1;
468452
seen_active_layer = true;
469-
highest_active_width =
470-
(svc_params_.scaling_factor_num[i] * config_->g_w) /
471-
svc_params_.scaling_factor_den[i];
472-
highest_active_height =
473-
(svc_params_.scaling_factor_num[i] * config_->g_h) /
474-
svc_params_.scaling_factor_den[i];
475453
} else {
476454
expect_no_more_active_layers = seen_active_layer;
477455
}
@@ -499,7 +477,6 @@ bool VP9EncoderImpl::SetSvcRates(
499477
svc_controller_->OnRatesUpdated(allocation);
500478
}
501479
current_bitrate_allocation_ = bitrate_allocation;
502-
cpu_speed_ = GetCpuSpeed(highest_active_width, highest_active_height);
503480
config_changed_ = true;
504481
return true;
505482
}
@@ -570,6 +547,7 @@ int VP9EncoderImpl::InitEncode(const VideoCodec* inst,
570547
if (&codec_ != inst) {
571548
codec_ = *inst;
572549
}
550+
memset(&svc_params_, 0, sizeof(vpx_svc_extra_cfg_t));
573551

574552
force_key_frame_ = true;
575553
pics_since_key_ = 0;
@@ -665,8 +643,6 @@ int VP9EncoderImpl::InitEncode(const VideoCodec* inst,
665643
config_->g_threads =
666644
NumberOfThreads(config_->g_w, config_->g_h, settings.number_of_cores);
667645

668-
cpu_speed_ = GetCpuSpeed(config_->g_w, config_->g_h);
669-
670646
is_flexible_mode_ = inst->VP9().flexibleMode;
671647

672648
inter_layer_pred_ = inst->VP9().interLayerPred;
@@ -827,22 +803,18 @@ int VP9EncoderImpl::InitAndSetControlSettings(const VideoCodec* inst) {
827803
return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
828804
}
829805

830-
if (per_layer_speed_.enabled) {
831-
for (int i = 0; i < num_spatial_layers_; ++i) {
832-
if (codec_.spatialLayers[i].active) {
833-
continue;
834-
}
835-
836-
if (per_layer_speed_.layers[i] != -1) {
837-
svc_params_.speed_per_layer[i] = per_layer_speed_.layers[i];
838-
} else {
839-
svc_params_.speed_per_layer[i] = GetCpuSpeed(
840-
codec_.spatialLayers[i].width, codec_.spatialLayers[i].height);
841-
}
806+
UpdatePerformanceFlags();
807+
RTC_DCHECK_EQ(performance_flags_by_spatial_index_.size(),
808+
static_cast<size_t>(num_spatial_layers_));
809+
if (performance_flags_.use_per_layer_speed) {
810+
for (int si = 0; si < num_spatial_layers_; ++si) {
811+
svc_params_.speed_per_layer[si] =
812+
performance_flags_by_spatial_index_[si].base_layer_speed;
813+
svc_params_.loopfilter_ctrl[si] =
814+
performance_flags_by_spatial_index_[si].deblock_mode;
842815
}
843816
}
844817

845-
vpx_codec_control(encoder_, VP8E_SET_CPUUSED, cpu_speed_);
846818
vpx_codec_control(encoder_, VP8E_SET_MAX_INTRA_BITRATE_PCT,
847819
rc_max_intra_target_);
848820
vpx_codec_control(encoder_, VP9E_SET_AQ_MODE,
@@ -855,6 +827,11 @@ int VP9EncoderImpl::InitAndSetControlSettings(const VideoCodec* inst) {
855827
vpx_codec_control(encoder_, VP9E_SET_SVC, 1);
856828
vpx_codec_control(encoder_, VP9E_SET_SVC_PARAMETERS, &svc_params_);
857829
}
830+
if (!performance_flags_.use_per_layer_speed) {
831+
vpx_codec_control(
832+
encoder_, VP8E_SET_CPUUSED,
833+
performance_flags_by_spatial_index_.rbegin()->base_layer_speed);
834+
}
858835

859836
if (num_spatial_layers_ > 1) {
860837
switch (inter_layer_pred_) {
@@ -1068,6 +1045,24 @@ int VP9EncoderImpl::Encode(const VideoFrame& input_image,
10681045
}
10691046
}
10701047

1048+
if (is_svc_ && performance_flags_.use_per_layer_speed) {
1049+
// Update speed settings that might depend on temporal index.
1050+
bool speed_updated = false;
1051+
for (int sl_idx = 0; sl_idx < num_spatial_layers_; ++sl_idx) {
1052+
const int target_speed =
1053+
layer_id.temporal_layer_id_per_spatial[sl_idx] == 0
1054+
? performance_flags_by_spatial_index_[sl_idx].base_layer_speed
1055+
: performance_flags_by_spatial_index_[sl_idx].high_layer_speed;
1056+
if (svc_params_.speed_per_layer[sl_idx] != target_speed) {
1057+
svc_params_.speed_per_layer[sl_idx] = target_speed;
1058+
speed_updated = true;
1059+
}
1060+
}
1061+
if (speed_updated) {
1062+
vpx_codec_control(encoder_, VP9E_SET_SVC_PARAMETERS, &svc_params_);
1063+
}
1064+
}
1065+
10711066
vpx_codec_control(encoder_, VP9E_SET_SVC_LAYER_ID, &layer_id);
10721067

10731068
if (num_spatial_layers_ > 1) {
@@ -1080,7 +1075,25 @@ int VP9EncoderImpl::Encode(const VideoFrame& input_image,
10801075
if (vpx_codec_enc_config_set(encoder_, config_)) {
10811076
return WEBRTC_VIDEO_CODEC_ERROR;
10821077
}
1083-
vpx_codec_control(encoder_, VP8E_SET_CPUUSED, cpu_speed_);
1078+
1079+
if (!performance_flags_.use_per_layer_speed) {
1080+
// Not setting individual speeds per layer, find the highest active
1081+
// resolution instead and base the speed on that.
1082+
for (int i = num_spatial_layers_ - 1; i >= 0; --i) {
1083+
if (config_->ss_target_bitrate[i] > 0) {
1084+
int width = (svc_params_.scaling_factor_num[i] * config_->g_w) /
1085+
svc_params_.scaling_factor_den[i];
1086+
int height = (svc_params_.scaling_factor_num[i] * config_->g_h) /
1087+
svc_params_.scaling_factor_den[i];
1088+
int speed =
1089+
std::prev(performance_flags_.settings_by_resolution.lower_bound(
1090+
width * height))
1091+
->second.base_layer_speed;
1092+
vpx_codec_control(encoder_, VP8E_SET_CPUUSED, speed);
1093+
break;
1094+
}
1095+
}
1096+
}
10841097
config_changed_ = false;
10851098
}
10861099

@@ -1826,18 +1839,92 @@ VP9EncoderImpl::ParseQualityScalerConfig(const WebRtcKeyValueConfig& trials) {
18261839
return config;
18271840
}
18281841

1842+
void VP9EncoderImpl::UpdatePerformanceFlags() {
1843+
const auto find_speed = [&](int min_pixel_count) {
1844+
RTC_DCHECK(!performance_flags_.settings_by_resolution.empty());
1845+
auto it =
1846+
performance_flags_.settings_by_resolution.upper_bound(min_pixel_count);
1847+
return std::prev(it)->second;
1848+
};
1849+
1850+
performance_flags_by_spatial_index_.clear();
1851+
if (is_svc_) {
1852+
for (int si = 0; si < num_spatial_layers_; ++si) {
1853+
performance_flags_by_spatial_index_.push_back(find_speed(
1854+
codec_.spatialLayers[si].width * codec_.spatialLayers[si].height));
1855+
}
1856+
} else {
1857+
performance_flags_by_spatial_index_.push_back(
1858+
find_speed(codec_.width * codec_.height));
1859+
}
1860+
}
1861+
18291862
// static
1830-
VP9EncoderImpl::SpeedSettings VP9EncoderImpl::ParsePerLayerSpeed(
1863+
VP9EncoderImpl::PerformanceFlags
1864+
VP9EncoderImpl::ParsePerformanceFlagsFromTrials(
18311865
const WebRtcKeyValueConfig& trials) {
1832-
FieldTrialFlag enabled("enabled");
1833-
FieldTrialParameter<int> speeds[kMaxSpatialLayers]{
1834-
{"s0", -1}, {"s1", -1}, {"s2", -1}, {"s3", -1}, {"s4", -1}};
1835-
ParseFieldTrial(
1836-
{&enabled, &speeds[0], &speeds[1], &speeds[2], &speeds[3], &speeds[4]},
1837-
trials.Lookup("WebRTC-VP9-PerLayerSpeed"));
1838-
return SpeedSettings{enabled.Get(),
1839-
{speeds[0].Get(), speeds[1].Get(), speeds[2].Get(),
1840-
speeds[3].Get(), speeds[4].Get()}};
1866+
struct Params : public PerformanceFlags::ParameterSet {
1867+
int min_pixel_count = 0;
1868+
};
1869+
1870+
FieldTrialStructList<Params> trials_list(
1871+
{FieldTrialStructMember("min_pixel_count",
1872+
[](Params* p) { return &p->min_pixel_count; }),
1873+
FieldTrialStructMember("high_layer_speed",
1874+
[](Params* p) { return &p->high_layer_speed; }),
1875+
FieldTrialStructMember("base_layer_speed",
1876+
[](Params* p) { return &p->base_layer_speed; }),
1877+
FieldTrialStructMember("deblock_mode",
1878+
[](Params* p) { return &p->deblock_mode; })},
1879+
{});
1880+
1881+
FieldTrialFlag per_layer_speed("use_per_layer_speed");
1882+
1883+
ParseFieldTrial({&trials_list, &per_layer_speed},
1884+
trials.Lookup("WebRTC-VP9-PerformanceFlags"));
1885+
1886+
PerformanceFlags flags;
1887+
flags.use_per_layer_speed = per_layer_speed.Get();
1888+
1889+
constexpr int kMinSpeed = 1;
1890+
constexpr int kMaxSpeed = 9;
1891+
for (auto& f : trials_list.Get()) {
1892+
if (f.base_layer_speed < kMinSpeed || f.base_layer_speed > kMaxSpeed ||
1893+
f.high_layer_speed < kMinSpeed || f.high_layer_speed > kMaxSpeed ||
1894+
f.deblock_mode < 0 || f.deblock_mode > 2) {
1895+
RTC_LOG(LS_WARNING) << "Ignoring invalid performance flags: "
1896+
<< "min_pixel_count = " << f.min_pixel_count
1897+
<< ", high_layer_speed = " << f.high_layer_speed
1898+
<< ", base_layer_speed = " << f.base_layer_speed
1899+
<< ", deblock_mode = " << f.deblock_mode;
1900+
continue;
1901+
}
1902+
flags.settings_by_resolution[f.min_pixel_count] = f;
1903+
}
1904+
1905+
if (flags.settings_by_resolution.empty()) {
1906+
return GetDefaultPerformanceFlags();
1907+
}
1908+
1909+
return flags;
1910+
}
1911+
1912+
// static
1913+
VP9EncoderImpl::PerformanceFlags VP9EncoderImpl::GetDefaultPerformanceFlags() {
1914+
PerformanceFlags flags;
1915+
flags.use_per_layer_speed = false;
1916+
#if defined(WEBRTC_ARCH_ARM) || defined(WEBRTC_ARCH_ARM64) || defined(ANDROID)
1917+
// Speed 8 on all layers for all resolutions.
1918+
flags.settings_by_resolution[0] = {8, 8, 0};
1919+
#else
1920+
// For smaller resolutions, use lower speed setting (get some coding gain at
1921+
// the cost of increased encoding complexity).
1922+
flags.settings_by_resolution[0] = {5, 5, 0};
1923+
1924+
// Use speed 7 for QCIF and above.
1925+
flags.settings_by_resolution[352 * 288] = {7, 7, 0};
1926+
#endif
1927+
return flags;
18411928
}
18421929

18431930
void VP9EncoderImpl::MaybeRewrapRawWithFormat(const vpx_img_fmt fmt) {

modules/video_coding/codecs/vp9/vp9_impl.h

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,6 @@ class VP9EncoderImpl : public VP9Encoder {
112112
const VP9Profile profile_;
113113
bool inited_;
114114
int64_t timestamp_;
115-
int cpu_speed_;
116115
uint32_t rc_max_intra_target_;
117116
vpx_codec_ctx_t* encoder_;
118117
vpx_codec_enc_cfg_t* config_;
@@ -194,11 +193,40 @@ class VP9EncoderImpl : public VP9Encoder {
194193
const WebRtcKeyValueConfig& trials);
195194
const bool external_ref_ctrl_;
196195

197-
const struct SpeedSettings {
198-
bool enabled;
199-
int layers[kMaxSpatialLayers];
200-
} per_layer_speed_;
201-
static SpeedSettings ParsePerLayerSpeed(const WebRtcKeyValueConfig& trials);
196+
// Flags that can affect speed vs quality tradeoff, and are configureable per
197+
// resolution ranges.
198+
struct PerformanceFlags {
199+
// If false, a lookup will be made in |settings_by_resolution| base on the
200+
// highest currently active resolution, and the overall speed then set to
201+
// to the |base_layer_speed| matching that entry.
202+
// If true, each active resolution will have it's speed and deblock_mode set
203+
// based on it resolution, and the high layer speed configured for non
204+
// base temporal layer frames.
205+
bool use_per_layer_speed = false;
206+
207+
struct ParameterSet {
208+
int base_layer_speed = -1; // Speed setting for TL0.
209+
int high_layer_speed = -1; // Speed setting for TL1-TL3.
210+
// 0 = deblock all temporal layers (TL)
211+
// 1 = disable deblock for top-most TL
212+
// 2 = disable deblock for all TLs
213+
int deblock_mode = 0;
214+
};
215+
// Map from min pixel count to settings for that resolution and above.
216+
// E.g. if you want some settings A if below wvga (640x360) and some other
217+
// setting B at wvga and above, you'd use map {{0, A}, {230400, B}}.
218+
std::map<int, ParameterSet> settings_by_resolution;
219+
};
220+
// Performance flags, ordered by |min_pixel_count|.
221+
const PerformanceFlags performance_flags_;
222+
// Caching of of |speed_configs_|, where index i maps to the resolution as
223+
// specified in |codec_.spatialLayer[i]|.
224+
std::vector<PerformanceFlags::ParameterSet>
225+
performance_flags_by_spatial_index_;
226+
void UpdatePerformanceFlags();
227+
static PerformanceFlags ParsePerformanceFlagsFromTrials(
228+
const WebRtcKeyValueConfig& trials);
229+
static PerformanceFlags GetDefaultPerformanceFlags();
202230

203231
int num_steady_state_frames_;
204232
// Only set config when this flag is set.

0 commit comments

Comments
 (0)