Make balanced degradation settings configurable through field trial.

Bug: none
Change-Id: Iad6dfdfdae13149bb8abe4b884e288e50aa7b73d
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/135102
Reviewed-by: Stefan Holmer <stefan@webrtc.org>
Commit-Queue: Åsa Persson <asapersson@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27892}
This commit is contained in:
Åsa Persson 2019-05-06 12:22:49 +02:00 committed by Commit Bot
parent bf47f340ee
commit f3d828eb8e
8 changed files with 268 additions and 26 deletions

View File

@ -99,6 +99,18 @@ rtc_static_library("normalize_simulcast_size_experiment") {
]
}
rtc_static_library("balanced_degradation_settings") {
sources = [
"balanced_degradation_settings.cc",
"balanced_degradation_settings.h",
]
deps = [
":field_trial_parser",
"../:rtc_base_approved",
"../../system_wrappers:field_trial",
]
}
rtc_static_library("cpu_speed_experiment") {
sources = [
"cpu_speed_experiment.cc",
@ -169,6 +181,7 @@ if (rtc_include_tests) {
testonly = true
sources = [
"balanced_degradation_settings_unittest.cc",
"cpu_speed_experiment_unittest.cc",
"field_trial_list_unittest.cc",
"field_trial_parser_unittest.cc",
@ -181,6 +194,7 @@ if (rtc_include_tests) {
"rtt_mult_experiment_unittest.cc",
]
deps = [
":balanced_degradation_settings",
":cpu_speed_experiment",
":field_trial_parser",
":keyframe_interval_settings_experiment",

View File

@ -0,0 +1,99 @@
/*
* Copyright 2019 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "rtc_base/experiments/balanced_degradation_settings.h"
#include <limits>
#include "rtc_base/experiments/field_trial_list.h"
#include "rtc_base/experiments/field_trial_parser.h"
#include "rtc_base/logging.h"
#include "system_wrappers/include/field_trial.h"
namespace webrtc {
namespace {
constexpr char kFieldTrial[] = "WebRTC-Video-BalancedDegradationSettings";
constexpr int kMinFps = 1;
constexpr int kMaxFps = 100;
std::vector<BalancedDegradationSettings::Config> DefaultConfigs() {
return {{320 * 240, 7}, {480 * 270, 10}, {640 * 480, 15}};
}
bool IsValid(const std::vector<BalancedDegradationSettings::Config>& configs) {
if (configs.size() <= 1) {
RTC_LOG(LS_WARNING) << "Unsupported size, value ignored.";
return false;
}
for (const auto& config : configs) {
if (config.fps < kMinFps || config.fps > kMaxFps) {
RTC_LOG(LS_WARNING) << "Unsupported fps setting, value ignored.";
return false;
}
}
for (size_t i = 1; i < configs.size(); ++i) {
if (configs[i].pixels < configs[i - 1].pixels ||
configs[i].fps < configs[i - 1].fps) {
RTC_LOG(LS_WARNING) << "Invalid parameter value provided.";
return false;
}
}
return true;
}
std::vector<BalancedDegradationSettings::Config> GetValidOrDefault(
const std::vector<BalancedDegradationSettings::Config>& configs) {
if (IsValid(configs)) {
return configs;
}
return DefaultConfigs();
}
} // namespace
BalancedDegradationSettings::Config::Config() = default;
BalancedDegradationSettings::Config::Config(int pixels, int fps)
: pixels(pixels), fps(fps) {}
BalancedDegradationSettings::BalancedDegradationSettings() {
FieldTrialStructList<Config> configs(
{FieldTrialStructMember("pixels", [](Config* c) { return &c->pixels; }),
FieldTrialStructMember("fps", [](Config* c) { return &c->fps; })},
{});
ParseFieldTrial({&configs}, field_trial::FindFullName(kFieldTrial));
configs_ = GetValidOrDefault(configs.Get());
RTC_DCHECK_GT(configs_.size(), 1);
}
BalancedDegradationSettings::~BalancedDegradationSettings() {}
std::vector<BalancedDegradationSettings::Config>
BalancedDegradationSettings::GetConfigs() const {
return configs_;
}
int BalancedDegradationSettings::MinFps(int pixels) const {
for (const auto& config : configs_) {
if (pixels <= config.pixels)
return config.fps;
}
return std::numeric_limits<int>::max();
}
int BalancedDegradationSettings::MaxFps(int pixels) const {
for (size_t i = 0; i < configs_.size() - 1; ++i) {
if (pixels <= configs_[i].pixels)
return configs_[i + 1].fps;
}
return std::numeric_limits<int>::max();
}
} // namespace webrtc

View File

@ -0,0 +1,49 @@
/*
* Copyright 2019 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef RTC_BASE_EXPERIMENTS_BALANCED_DEGRADATION_SETTINGS_H_
#define RTC_BASE_EXPERIMENTS_BALANCED_DEGRADATION_SETTINGS_H_
#include <vector>
namespace webrtc {
class BalancedDegradationSettings {
public:
BalancedDegradationSettings();
~BalancedDegradationSettings();
struct Config {
Config();
Config(int pixels, int fps);
bool operator==(const Config& o) const {
return pixels == o.pixels && fps == o.fps;
}
int pixels = 0; // The video frame size.
int fps = 0; // The framerate to be used if the frame size is less than
// or equal to |pixels|.
};
// Returns configurations from field trial on success (default on failure).
std::vector<Config> GetConfigs() const;
// Gets the min/max framerate from |configs_| based on |pixels|.
int MinFps(int pixels) const;
int MaxFps(int pixels) const;
private:
std::vector<Config> configs_;
};
} // namespace webrtc
#endif // RTC_BASE_EXPERIMENTS_BALANCED_DEGRADATION_SETTINGS_H_

View File

@ -0,0 +1,99 @@
/*
* Copyright 2019 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "rtc_base/experiments/balanced_degradation_settings.h"
#include <limits>
#include "rtc_base/gunit.h"
#include "test/field_trial.h"
#include "test/gmock.h"
namespace webrtc {
namespace {
void VerifyIsDefault(
const std::vector<BalancedDegradationSettings::Config>& config) {
EXPECT_THAT(config, ::testing::ElementsAre(
BalancedDegradationSettings::Config{320 * 240, 7},
BalancedDegradationSettings::Config{480 * 270, 10},
BalancedDegradationSettings::Config{640 * 480, 15}));
}
} // namespace
TEST(BalancedDegradationSettings, GetsDefaultConfigIfNoList) {
webrtc::test::ScopedFieldTrials field_trials("");
BalancedDegradationSettings settings;
VerifyIsDefault(settings.GetConfigs());
}
TEST(BalancedDegradationSettings, GetsConfig) {
webrtc::test::ScopedFieldTrials field_trials(
"WebRTC-Video-BalancedDegradationSettings/"
"pixels:1000|2000|3000,fps:5|15|25/");
BalancedDegradationSettings settings;
EXPECT_THAT(
settings.GetConfigs(),
::testing::ElementsAre(BalancedDegradationSettings::Config{1000, 5},
BalancedDegradationSettings::Config{2000, 15},
BalancedDegradationSettings::Config{3000, 25}));
}
TEST(BalancedDegradationSettings, GetsDefaultConfigForZeroFpsValue) {
webrtc::test::ScopedFieldTrials field_trials(
"WebRTC-Video-BalancedDegradationSettings/"
"pixels:1000|2000|3000,fps:0|15|25/");
BalancedDegradationSettings settings;
VerifyIsDefault(settings.GetConfigs());
}
TEST(BalancedDegradationSettings, GetsDefaultConfigIfPixelsDecreases) {
webrtc::test::ScopedFieldTrials field_trials(
"WebRTC-Video-BalancedDegradationSettings/"
"pixels:1000|999|3000,fps:5|15|25/");
BalancedDegradationSettings settings;
VerifyIsDefault(settings.GetConfigs());
}
TEST(BalancedDegradationSettings, GetsDefaultConfigIfFramerateDecreases) {
webrtc::test::ScopedFieldTrials field_trials(
"WebRTC-Video-BalancedDegradationSettings/"
"pixels:1000|2000|3000,fps:5|4|25/");
BalancedDegradationSettings settings;
VerifyIsDefault(settings.GetConfigs());
}
TEST(BalancedDegradationSettings, GetsMinFps) {
webrtc::test::ScopedFieldTrials field_trials(
"WebRTC-Video-BalancedDegradationSettings/"
"pixels:1000|2000|3000,fps:5|15|25/");
BalancedDegradationSettings settings;
EXPECT_EQ(5, settings.MinFps(1));
EXPECT_EQ(5, settings.MinFps(1000));
EXPECT_EQ(15, settings.MinFps(1000 + 1));
EXPECT_EQ(15, settings.MinFps(2000));
EXPECT_EQ(25, settings.MinFps(2000 + 1));
EXPECT_EQ(25, settings.MinFps(3000));
EXPECT_EQ(std::numeric_limits<int>::max(), settings.MinFps(3000 + 1));
}
TEST(BalancedDegradationSettings, GetsMaxFps) {
webrtc::test::ScopedFieldTrials field_trials(
"WebRTC-Video-BalancedDegradationSettings/"
"pixels:1000|2000|3000,fps:5|15|25/");
BalancedDegradationSettings settings;
EXPECT_EQ(15, settings.MaxFps(1));
EXPECT_EQ(15, settings.MaxFps(1000));
EXPECT_EQ(25, settings.MaxFps(1000 + 1));
EXPECT_EQ(25, settings.MaxFps(2000));
EXPECT_EQ(std::numeric_limits<int>::max(), settings.MaxFps(2000 + 1));
}
} // namespace webrtc

View File

@ -138,7 +138,7 @@ struct TypedFieldTrialListWrapper : FieldTrialListWrapper {
sink_(struct_to_write, list_[index]);
}
FieldTrialListBase* GetList() { return &list_; }
FieldTrialListBase* GetList() override { return &list_; }
private:
FieldTrialList<T> list_;

View File

@ -205,6 +205,7 @@ rtc_source_set("video_stream_encoder_impl") {
"../rtc_base:rtc_task_queue",
"../rtc_base:timeutils",
"../rtc_base/experiments:alr_experiment",
"../rtc_base/experiments:balanced_degradation_settings",
"../rtc_base/experiments:field_trial_parser",
"../rtc_base/experiments:quality_scaling_experiment",
"../rtc_base/experiments:rate_control_settings",

View File

@ -64,29 +64,6 @@ const int64_t kFrameRateAvergingWindowSizeMs = (1000 / 30) * 90;
const size_t kDefaultPayloadSize = 1440;
// Initial limits for BALANCED degradation preference.
int MinFps(int pixels) {
if (pixels <= 320 * 240) {
return 7;
} else if (pixels <= 480 * 270) {
return 10;
} else if (pixels <= 640 * 480) {
return 15;
} else {
return std::numeric_limits<int>::max();
}
}
int MaxFps(int pixels) {
if (pixels <= 320 * 240) {
return 10;
} else if (pixels <= 480 * 270) {
return 15;
} else {
return std::numeric_limits<int>::max();
}
}
uint32_t abs_diff(uint32_t a, uint32_t b) {
return (a < b) ? b - a : a - b;
}
@ -1687,7 +1664,7 @@ void VideoStreamEncoder::AdaptDown(AdaptReason reason) {
switch (degradation_preference_) {
case DegradationPreference::BALANCED: {
// Try scale down framerate, if lower.
int fps = MinFps(last_frame_info_->pixel_count());
int fps = balanced_settings_.MinFps(last_frame_info_->pixel_count());
if (source_proxy_->RestrictFramerate(fps)) {
GetAdaptCounter().IncrementFramerate(reason);
break;
@ -1763,7 +1740,7 @@ void VideoStreamEncoder::AdaptUp(AdaptReason reason) {
switch (degradation_preference_) {
case DegradationPreference::BALANCED: {
// Try scale up framerate, if higher.
int fps = MaxFps(last_frame_info_->pixel_count());
int fps = balanced_settings_.MaxFps(last_frame_info_->pixel_count());
if (source_proxy_->IncreaseFramerate(fps)) {
GetAdaptCounter().DecrementFramerate(reason, fps);
// Reset framerate in case of fewer fps steps down than up.

View File

@ -30,6 +30,7 @@
#include "modules/video_coding/video_coding_impl.h"
#include "rtc_base/critical_section.h"
#include "rtc_base/event.h"
#include "rtc_base/experiments/balanced_degradation_settings.h"
#include "rtc_base/experiments/rate_control_settings.h"
#include "rtc_base/race_checker.h"
#include "rtc_base/rate_statistics.h"
@ -281,6 +282,8 @@ class VideoStreamEncoder : public VideoStreamEncoderInterface,
// Set depending on degradation preferences.
DegradationPreference degradation_preference_ RTC_GUARDED_BY(&encoder_queue_);
BalancedDegradationSettings balanced_settings_;
struct AdaptationRequest {
// The pixel count produced by the source at the time of the adaptation.
int input_pixel_count_;