Add ability to configure quality scaler settings through field trial.
optional<int> min_frames: The minimum number frames to observe to make a scaling decision. Default: kMinFramesNeededToScale in quality_scaler.cc optional<double> initial_scale_factor: The sample period scale factor. Default: kSamplePeriodScaleFactor in quality_scaler.cc optional<double> scale_factor: Option to use a reduced sampling interval when last check did not result in an adaptation (if unset the initial_scale_factor is used). Bug: none Change-Id: I3bb955d1f8d7d7d49bc118361614b5aa59605231 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/135125 Commit-Queue: Åsa Persson <asapersson@webrtc.org> Reviewed-by: Stefan Holmer <stefan@webrtc.org> Cr-Commit-Position: refs/heads/master@{#27860}
This commit is contained in:
@ -257,6 +257,7 @@ rtc_source_set("video_coding_utility") {
|
||||
"../../rtc_base:rtc_base_approved",
|
||||
"../../rtc_base:rtc_numerics",
|
||||
"../../rtc_base:rtc_task_queue",
|
||||
"../../rtc_base/experiments:quality_scaler_settings",
|
||||
"../../rtc_base/experiments:quality_scaling_experiment",
|
||||
"../../rtc_base/experiments:rate_control_settings",
|
||||
"../../rtc_base/synchronization:sequence_checker",
|
||||
|
@ -13,8 +13,8 @@
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/experiments/quality_scaler_settings.h"
|
||||
#include "rtc_base/logging.h"
|
||||
#include "rtc_base/numerics/exp_filter.h"
|
||||
#include "rtc_base/task_queue.h"
|
||||
@ -33,7 +33,7 @@ namespace {
|
||||
static const int kMeasureMs = 2000;
|
||||
static const float kSamplePeriodScaleFactor = 2.5;
|
||||
static const int kFramedropPercentThreshold = 60;
|
||||
static const int kMinFramesNeededToScale = 2 * 30;
|
||||
static const size_t kMinFramesNeededToScale = 2 * 30;
|
||||
|
||||
} // namespace
|
||||
|
||||
@ -87,7 +87,16 @@ QualityScaler::QualityScaler(rtc::TaskQueue* task_queue,
|
||||
framedrop_percent_media_opt_(5 * 30),
|
||||
framedrop_percent_all_(5 * 30),
|
||||
experiment_enabled_(QualityScalingExperiment::Enabled()),
|
||||
observed_enough_frames_(false) {
|
||||
observed_enough_frames_(false),
|
||||
min_frames_needed_(
|
||||
QualityScalerSettings::ParseFromFieldTrials().MinFrames().value_or(
|
||||
kMinFramesNeededToScale)),
|
||||
initial_scale_factor_(QualityScalerSettings::ParseFromFieldTrials()
|
||||
.InitialScaleFactor()
|
||||
.value_or(kSamplePeriodScaleFactor)),
|
||||
scale_factor_(
|
||||
QualityScalerSettings::ParseFromFieldTrials().ScaleFactor()),
|
||||
last_adapted_(false) {
|
||||
RTC_DCHECK_RUN_ON(&task_checker_);
|
||||
if (experiment_enabled_) {
|
||||
config_ = QualityScalingExperiment::GetConfig();
|
||||
@ -118,7 +127,11 @@ int64_t QualityScaler::GetSamplingPeriodMs() const {
|
||||
// Use half the interval while waiting for enough frames.
|
||||
return sampling_period_ms_ / 2;
|
||||
}
|
||||
return sampling_period_ms_ * kSamplePeriodScaleFactor;
|
||||
if (scale_factor_ && !last_adapted_) {
|
||||
// Last check did not result in a AdaptDown/Up, possibly reduce interval.
|
||||
return sampling_period_ms_ * scale_factor_.value();
|
||||
}
|
||||
return sampling_period_ms_ * initial_scale_factor_;
|
||||
}
|
||||
|
||||
void QualityScaler::ReportDroppedFrameByMediaOpt() {
|
||||
@ -147,13 +160,14 @@ void QualityScaler::CheckQp() {
|
||||
RTC_DCHECK_RUN_ON(&task_checker_);
|
||||
// Should be set through InitEncode -> Should be set by now.
|
||||
RTC_DCHECK_GE(thresholds_.low, 0);
|
||||
last_adapted_ = false;
|
||||
|
||||
// If we have not observed at least this many frames we can't make a good
|
||||
// scaling decision.
|
||||
const size_t frames = config_.use_all_drop_reasons
|
||||
? framedrop_percent_all_.Size()
|
||||
: framedrop_percent_media_opt_.Size();
|
||||
if (frames < kMinFramesNeededToScale) {
|
||||
if (frames < min_frames_needed_) {
|
||||
observed_enough_frames_ = false;
|
||||
return;
|
||||
}
|
||||
@ -196,6 +210,7 @@ void QualityScaler::ReportQpLow() {
|
||||
RTC_DCHECK_RUN_ON(&task_checker_);
|
||||
ClearSamples();
|
||||
observer_->AdaptUp(AdaptationObserverInterface::AdaptReason::kQuality);
|
||||
last_adapted_ = true;
|
||||
}
|
||||
|
||||
void QualityScaler::ReportQpHigh() {
|
||||
@ -206,6 +221,7 @@ void QualityScaler::ReportQpHigh() {
|
||||
if (fast_rampup_) {
|
||||
fast_rampup_ = false;
|
||||
}
|
||||
last_adapted_ = true;
|
||||
}
|
||||
|
||||
void QualityScaler::ClearSamples() {
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <stdint.h>
|
||||
#include <memory>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "api/video_codecs/video_encoder.h"
|
||||
#include "rtc_base/experiments/quality_scaling_experiment.h"
|
||||
#include "rtc_base/numerics/moving_average.h"
|
||||
@ -93,6 +94,11 @@ class QualityScaler {
|
||||
std::unique_ptr<QpSmoother> qp_smoother_high_ RTC_GUARDED_BY(&task_checker_);
|
||||
std::unique_ptr<QpSmoother> qp_smoother_low_ RTC_GUARDED_BY(&task_checker_);
|
||||
bool observed_enough_frames_ RTC_GUARDED_BY(&task_checker_);
|
||||
|
||||
const size_t min_frames_needed_;
|
||||
const double initial_scale_factor_;
|
||||
const absl::optional<double> scale_factor_;
|
||||
bool last_adapted_ RTC_GUARDED_BY(&task_checker_);
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
|
@ -59,6 +59,21 @@ rtc_static_library("field_trial_parser") {
|
||||
]
|
||||
}
|
||||
|
||||
rtc_static_library("quality_scaler_settings") {
|
||||
sources = [
|
||||
"quality_scaler_settings.cc",
|
||||
"quality_scaler_settings.h",
|
||||
]
|
||||
deps = [
|
||||
":field_trial_parser",
|
||||
"../:rtc_base_approved",
|
||||
"../../api/transport:field_trial_based_config",
|
||||
"../../api/transport:webrtc_key_value_config",
|
||||
"../../system_wrappers:field_trial",
|
||||
"//third_party/abseil-cpp/absl/types:optional",
|
||||
]
|
||||
}
|
||||
|
||||
rtc_static_library("quality_scaling_experiment") {
|
||||
sources = [
|
||||
"quality_scaling_experiment.cc",
|
||||
@ -160,6 +175,7 @@ if (rtc_include_tests) {
|
||||
"field_trial_units_unittest.cc",
|
||||
"keyframe_interval_settings_unittest.cc",
|
||||
"normalize_simulcast_size_experiment_unittest.cc",
|
||||
"quality_scaler_settings_unittest.cc",
|
||||
"quality_scaling_experiment_unittest.cc",
|
||||
"rate_control_settings_unittest.cc",
|
||||
"rtt_mult_experiment_unittest.cc",
|
||||
@ -169,6 +185,7 @@ if (rtc_include_tests) {
|
||||
":field_trial_parser",
|
||||
":keyframe_interval_settings_experiment",
|
||||
":normalize_simulcast_size_experiment",
|
||||
":quality_scaler_settings",
|
||||
":quality_scaling_experiment",
|
||||
":rate_control_settings",
|
||||
":rtt_mult_experiment",
|
||||
|
62
rtc_base/experiments/quality_scaler_settings.cc
Normal file
62
rtc_base/experiments/quality_scaler_settings.cc
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) 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/quality_scaler_settings.h"
|
||||
|
||||
#include "api/transport/field_trial_based_config.h"
|
||||
#include "rtc_base/logging.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
const int kMinFrames = 10;
|
||||
const double kMinScaleFactor = 0.01;
|
||||
} // namespace
|
||||
|
||||
QualityScalerSettings::QualityScalerSettings(
|
||||
const WebRtcKeyValueConfig* const key_value_config)
|
||||
: min_frames_("min_frames"),
|
||||
initial_scale_factor_("initial_scale_factor"),
|
||||
scale_factor_("scale_factor") {
|
||||
ParseFieldTrial(
|
||||
{&min_frames_, &initial_scale_factor_, &scale_factor_},
|
||||
key_value_config->Lookup("WebRTC-Video-QualityScalerSettings"));
|
||||
}
|
||||
|
||||
QualityScalerSettings QualityScalerSettings::ParseFromFieldTrials() {
|
||||
FieldTrialBasedConfig field_trial_config;
|
||||
return QualityScalerSettings(&field_trial_config);
|
||||
}
|
||||
|
||||
absl::optional<int> QualityScalerSettings::MinFrames() const {
|
||||
if (min_frames_ && min_frames_.Value() < kMinFrames) {
|
||||
RTC_LOG(LS_WARNING) << "Unsupported min_frames value, ignored.";
|
||||
return absl::nullopt;
|
||||
}
|
||||
return min_frames_.GetOptional();
|
||||
}
|
||||
|
||||
absl::optional<double> QualityScalerSettings::InitialScaleFactor() const {
|
||||
if (initial_scale_factor_ &&
|
||||
initial_scale_factor_.Value() < kMinScaleFactor) {
|
||||
RTC_LOG(LS_WARNING) << "Unsupported initial_scale_factor value, ignored.";
|
||||
return absl::nullopt;
|
||||
}
|
||||
return initial_scale_factor_.GetOptional();
|
||||
}
|
||||
|
||||
absl::optional<double> QualityScalerSettings::ScaleFactor() const {
|
||||
if (scale_factor_ && scale_factor_.Value() < kMinScaleFactor) {
|
||||
RTC_LOG(LS_WARNING) << "Unsupported scale_factor value, ignored.";
|
||||
return absl::nullopt;
|
||||
}
|
||||
return scale_factor_.GetOptional();
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
39
rtc_base/experiments/quality_scaler_settings.h
Normal file
39
rtc_base/experiments/quality_scaler_settings.h
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 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_QUALITY_SCALER_SETTINGS_H_
|
||||
#define RTC_BASE_EXPERIMENTS_QUALITY_SCALER_SETTINGS_H_
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "api/transport/webrtc_key_value_config.h"
|
||||
#include "rtc_base/experiments/field_trial_parser.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class QualityScalerSettings final {
|
||||
public:
|
||||
static QualityScalerSettings ParseFromFieldTrials();
|
||||
|
||||
absl::optional<int> MinFrames() const;
|
||||
absl::optional<double> InitialScaleFactor() const;
|
||||
absl::optional<double> ScaleFactor() const;
|
||||
|
||||
private:
|
||||
explicit QualityScalerSettings(
|
||||
const WebRtcKeyValueConfig* const key_value_config);
|
||||
|
||||
FieldTrialOptional<int> min_frames_;
|
||||
FieldTrialOptional<double> initial_scale_factor_;
|
||||
FieldTrialOptional<double> scale_factor_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // RTC_BASE_EXPERIMENTS_QUALITY_SCALER_SETTINGS_H_
|
76
rtc_base/experiments/quality_scaler_settings_unittest.cc
Normal file
76
rtc_base/experiments/quality_scaler_settings_unittest.cc
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 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/quality_scaler_settings.h"
|
||||
|
||||
#include "test/field_trial.h"
|
||||
#include "test/gtest.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
|
||||
TEST(QualityScalerSettingsTest, ValuesNotSetByDefault) {
|
||||
EXPECT_FALSE(QualityScalerSettings::ParseFromFieldTrials().MinFrames());
|
||||
EXPECT_FALSE(
|
||||
QualityScalerSettings::ParseFromFieldTrials().InitialScaleFactor());
|
||||
EXPECT_FALSE(QualityScalerSettings::ParseFromFieldTrials().ScaleFactor());
|
||||
}
|
||||
|
||||
TEST(QualityScalerSettingsTest, ParseMinFrames) {
|
||||
test::ScopedFieldTrials field_trials(
|
||||
"WebRTC-Video-QualityScalerSettings/min_frames:100/");
|
||||
EXPECT_EQ(100, QualityScalerSettings::ParseFromFieldTrials().MinFrames());
|
||||
}
|
||||
|
||||
TEST(QualityScalerSettingsTest, ParseInitialScaleFactor) {
|
||||
test::ScopedFieldTrials field_trials(
|
||||
"WebRTC-Video-QualityScalerSettings/initial_scale_factor:1.5/");
|
||||
EXPECT_EQ(1.5,
|
||||
QualityScalerSettings::ParseFromFieldTrials().InitialScaleFactor());
|
||||
}
|
||||
|
||||
TEST(QualityScalerSettingsTest, ParseScaleFactor) {
|
||||
test::ScopedFieldTrials field_trials(
|
||||
"WebRTC-Video-QualityScalerSettings/scale_factor:1.1/");
|
||||
EXPECT_EQ(1.1, QualityScalerSettings::ParseFromFieldTrials().ScaleFactor());
|
||||
}
|
||||
|
||||
TEST(QualityScalerSettingsTest, ParseAll) {
|
||||
test::ScopedFieldTrials field_trials(
|
||||
"WebRTC-Video-QualityScalerSettings/"
|
||||
"min_frames:100,initial_scale_factor:1.5,scale_factor:0.9/");
|
||||
const auto settings = QualityScalerSettings::ParseFromFieldTrials();
|
||||
EXPECT_EQ(100, settings.MinFrames());
|
||||
EXPECT_EQ(1.5, settings.InitialScaleFactor());
|
||||
EXPECT_EQ(0.9, settings.ScaleFactor());
|
||||
}
|
||||
|
||||
TEST(QualityScalerSettingsTest, DoesNotParseIncorrectValue) {
|
||||
test::ScopedFieldTrials field_trials(
|
||||
"WebRTC-Video-QualityScalerSettings/"
|
||||
"min_frames:a,initial_scale_factor:b,scale_factor:c/");
|
||||
const auto settings = QualityScalerSettings::ParseFromFieldTrials();
|
||||
EXPECT_FALSE(settings.MinFrames());
|
||||
EXPECT_FALSE(settings.InitialScaleFactor());
|
||||
EXPECT_FALSE(settings.ScaleFactor());
|
||||
}
|
||||
|
||||
TEST(QualityScalerSettingsTest, DoesNotReturnTooSmallValue) {
|
||||
test::ScopedFieldTrials field_trials(
|
||||
"WebRTC-Video-QualityScalerSettings/"
|
||||
"min_frames:0,initial_scale_factor:0.0,scale_factor:0.0/");
|
||||
const auto settings = QualityScalerSettings::ParseFromFieldTrials();
|
||||
EXPECT_FALSE(settings.MinFrames());
|
||||
EXPECT_FALSE(settings.InitialScaleFactor());
|
||||
EXPECT_FALSE(settings.ScaleFactor());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace webrtc
|
Reference in New Issue
Block a user