Implement stable rate support in SimulcastRateAllocator
Bug: webrtc:10126 Change-Id: I2ea8d27b0bd6f7ffd1ebbba451bd1ce1f2eee3d9 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/151121 Reviewed-by: Florent Castelli <orphis@webrtc.org> Commit-Queue: Erik Språng <sprang@webrtc.org> Cr-Commit-Position: refs/heads/master@{#29097}
This commit is contained in:
@ -264,6 +264,7 @@ rtc_source_set("video_coding_utility") {
|
|||||||
"../../rtc_base/experiments:quality_scaler_settings",
|
"../../rtc_base/experiments:quality_scaler_settings",
|
||||||
"../../rtc_base/experiments:quality_scaling_experiment",
|
"../../rtc_base/experiments:quality_scaling_experiment",
|
||||||
"../../rtc_base/experiments:rate_control_settings",
|
"../../rtc_base/experiments:rate_control_settings",
|
||||||
|
"../../rtc_base/experiments:stable_target_rate_experiment",
|
||||||
"../../rtc_base/synchronization:sequence_checker",
|
"../../rtc_base/synchronization:sequence_checker",
|
||||||
"../../rtc_base/system:arch",
|
"../../rtc_base/system:arch",
|
||||||
"../../rtc_base/system:file_wrapper",
|
"../../rtc_base/system:file_wrapper",
|
||||||
|
@ -200,15 +200,11 @@ VideoBitrateAllocation SvcRateAllocator::Allocate(
|
|||||||
// Figure out how many spatial layers should be active.
|
// Figure out how many spatial layers should be active.
|
||||||
if (experiment_settings_.IsEnabled() &&
|
if (experiment_settings_.IsEnabled() &&
|
||||||
parameters.stable_bitrate > DataRate::Zero()) {
|
parameters.stable_bitrate > DataRate::Zero()) {
|
||||||
double hysteresis_factor = 1.0;
|
double hysteresis_factor;
|
||||||
if (codec_.mode == VideoCodecMode::kScreensharing) {
|
if (codec_.mode == VideoCodecMode::kScreensharing) {
|
||||||
hysteresis_factor =
|
hysteresis_factor = experiment_settings_.GetScreenshareHysteresisFactor();
|
||||||
experiment_settings_.GetScreenshareHysteresisFactor().value_or(
|
|
||||||
hysteresis_factor);
|
|
||||||
} else {
|
} else {
|
||||||
hysteresis_factor =
|
hysteresis_factor = experiment_settings_.GetVideoHysteresisFactor();
|
||||||
experiment_settings_.GetVideoHysteresisFactor().value_or(
|
|
||||||
hysteresis_factor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DataRate stable_rate =
|
DataRate stable_rate =
|
||||||
|
@ -283,7 +283,9 @@ TEST_P(SvcRateAllocatorTestParametrizedContentType, PaddingBitrate) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(SvcRateAllocatorTestParametrizedContentType, StableBitrate) {
|
TEST_P(SvcRateAllocatorTestParametrizedContentType, StableBitrate) {
|
||||||
ScopedFieldTrials field_trial("WebRTC-StableTargetRate/enabled:true/");
|
ScopedFieldTrials field_trial(
|
||||||
|
"WebRTC-StableTargetRate/enabled:true,video_hysteresis_factor:1.0,"
|
||||||
|
"screenshare_hysteresis_factor:1.0/");
|
||||||
|
|
||||||
const VideoCodec codec = Configure(1280, 720, 3, 1, is_screen_sharing_);
|
const VideoCodec codec = Configure(1280, 720, 3, 1, is_screen_sharing_);
|
||||||
const auto start_rates = SvcRateAllocator::GetLayerStartBitrates(codec);
|
const auto start_rates = SvcRateAllocator::GetLayerStartBitrates(codec);
|
||||||
|
@ -59,32 +59,45 @@ float SimulcastRateAllocator::GetTemporalRateAllocation(int num_layers,
|
|||||||
|
|
||||||
SimulcastRateAllocator::SimulcastRateAllocator(const VideoCodec& codec)
|
SimulcastRateAllocator::SimulcastRateAllocator(const VideoCodec& codec)
|
||||||
: codec_(codec),
|
: codec_(codec),
|
||||||
hysteresis_factor_(RateControlSettings::ParseFromFieldTrials()
|
stable_rate_settings_(
|
||||||
.GetSimulcastHysteresisFactor(codec.mode)) {}
|
StableTargetRateExperiment::ParseFromFieldTrials()) {}
|
||||||
|
|
||||||
SimulcastRateAllocator::~SimulcastRateAllocator() = default;
|
SimulcastRateAllocator::~SimulcastRateAllocator() = default;
|
||||||
|
|
||||||
VideoBitrateAllocation SimulcastRateAllocator::Allocate(
|
VideoBitrateAllocation SimulcastRateAllocator::Allocate(
|
||||||
VideoBitrateAllocationParameters parameters) {
|
VideoBitrateAllocationParameters parameters) {
|
||||||
VideoBitrateAllocation allocated_bitrates_bps;
|
VideoBitrateAllocation allocated_bitrates;
|
||||||
DistributeAllocationToSimulcastLayers(parameters.total_bitrate.bps(),
|
DataRate stable_rate = parameters.total_bitrate;
|
||||||
&allocated_bitrates_bps);
|
if (stable_rate_settings_.IsEnabled() &&
|
||||||
DistributeAllocationToTemporalLayers(&allocated_bitrates_bps);
|
parameters.stable_bitrate > DataRate::Zero()) {
|
||||||
return allocated_bitrates_bps;
|
stable_rate = std::min(parameters.stable_bitrate, parameters.total_bitrate);
|
||||||
|
}
|
||||||
|
DistributeAllocationToSimulcastLayers(parameters.total_bitrate, stable_rate,
|
||||||
|
&allocated_bitrates);
|
||||||
|
DistributeAllocationToTemporalLayers(&allocated_bitrates);
|
||||||
|
return allocated_bitrates;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimulcastRateAllocator::DistributeAllocationToSimulcastLayers(
|
void SimulcastRateAllocator::DistributeAllocationToSimulcastLayers(
|
||||||
uint32_t total_bitrate_bps,
|
DataRate total_bitrate,
|
||||||
VideoBitrateAllocation* allocated_bitrates_bps) {
|
DataRate stable_bitrate,
|
||||||
uint32_t left_to_allocate = total_bitrate_bps;
|
VideoBitrateAllocation* allocated_bitrates) {
|
||||||
if (codec_.maxBitrate && codec_.maxBitrate * 1000 < left_to_allocate)
|
DataRate left_in_total_allocation = total_bitrate;
|
||||||
left_to_allocate = codec_.maxBitrate * 1000;
|
DataRate left_in_stable_allocation = stable_bitrate;
|
||||||
|
|
||||||
|
if (codec_.maxBitrate) {
|
||||||
|
DataRate max_rate = DataRate::kbps(codec_.maxBitrate);
|
||||||
|
left_in_total_allocation = std::min(left_in_total_allocation, max_rate);
|
||||||
|
left_in_stable_allocation = std::min(left_in_stable_allocation, max_rate);
|
||||||
|
}
|
||||||
|
|
||||||
if (codec_.numberOfSimulcastStreams == 0) {
|
if (codec_.numberOfSimulcastStreams == 0) {
|
||||||
// No simulcast, just set the target as this has been capped already.
|
// No simulcast, just set the target as this has been capped already.
|
||||||
if (codec_.active) {
|
if (codec_.active) {
|
||||||
allocated_bitrates_bps->SetBitrate(
|
allocated_bitrates->SetBitrate(
|
||||||
0, 0, std::max(codec_.minBitrate * 1000, left_to_allocate));
|
0, 0,
|
||||||
|
std::max(DataRate::kbps(codec_.minBitrate), left_in_total_allocation)
|
||||||
|
.bps());
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -115,9 +128,10 @@ void SimulcastRateAllocator::DistributeAllocationToSimulcastLayers(
|
|||||||
// Always allocate enough bitrate for the minimum bitrate of the first
|
// Always allocate enough bitrate for the minimum bitrate of the first
|
||||||
// active layer. Suspending below min bitrate is controlled outside the
|
// active layer. Suspending below min bitrate is controlled outside the
|
||||||
// codec implementation and is not overridden by this.
|
// codec implementation and is not overridden by this.
|
||||||
left_to_allocate = std::max(
|
DataRate min_rate = DataRate::kbps(
|
||||||
codec_.simulcastStream[layer_index[active_layer]].minBitrate * 1000,
|
codec_.simulcastStream[layer_index[active_layer]].minBitrate);
|
||||||
left_to_allocate);
|
left_in_total_allocation = std::max(left_in_total_allocation, min_rate);
|
||||||
|
left_in_stable_allocation = std::max(left_in_stable_allocation, min_rate);
|
||||||
|
|
||||||
// Begin by allocating bitrate to simulcast streams, putting all bitrate in
|
// Begin by allocating bitrate to simulcast streams, putting all bitrate in
|
||||||
// temporal layer 0. We'll then distribute this bitrate, across potential
|
// temporal layer 0. We'll then distribute this bitrate, across potential
|
||||||
@ -142,25 +156,28 @@ void SimulcastRateAllocator::DistributeAllocationToSimulcastLayers(
|
|||||||
}
|
}
|
||||||
// If we can't allocate to the current layer we can't allocate to higher
|
// If we can't allocate to the current layer we can't allocate to higher
|
||||||
// layers because they require a higher minimum bitrate.
|
// layers because they require a higher minimum bitrate.
|
||||||
uint32_t min_bitrate = stream.minBitrate * 1000;
|
DataRate min_bitrate = DataRate::kbps(stream.minBitrate);
|
||||||
|
DataRate target_bitrate = DataRate::kbps(stream.targetBitrate);
|
||||||
|
double hysteresis_factor =
|
||||||
|
codec_.mode == VideoCodecMode::kRealtimeVideo
|
||||||
|
? stable_rate_settings_.GetVideoHysteresisFactor()
|
||||||
|
: stable_rate_settings_.GetScreenshareHysteresisFactor();
|
||||||
if (!first_allocation && !stream_enabled_[layer_index[active_layer]]) {
|
if (!first_allocation && !stream_enabled_[layer_index[active_layer]]) {
|
||||||
min_bitrate = std::min(
|
min_bitrate = std::min(hysteresis_factor * min_bitrate, target_bitrate);
|
||||||
static_cast<uint32_t>(hysteresis_factor_ * min_bitrate + 0.5),
|
|
||||||
stream.targetBitrate * 1000);
|
|
||||||
}
|
}
|
||||||
if (left_to_allocate < min_bitrate) {
|
if (left_in_stable_allocation < min_bitrate) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We are allocating to this layer so it is the current active allocation.
|
// We are allocating to this layer so it is the current active allocation.
|
||||||
top_active_layer = layer_index[active_layer];
|
top_active_layer = layer_index[active_layer];
|
||||||
stream_enabled_[layer_index[active_layer]] = true;
|
stream_enabled_[layer_index[active_layer]] = true;
|
||||||
uint32_t allocation =
|
DataRate layer_rate = std::min(left_in_total_allocation, target_bitrate);
|
||||||
std::min(left_to_allocate, stream.targetBitrate * 1000);
|
allocated_bitrates->SetBitrate(layer_index[active_layer], 0,
|
||||||
allocated_bitrates_bps->SetBitrate(layer_index[active_layer], 0,
|
layer_rate.bps());
|
||||||
allocation);
|
left_in_total_allocation -= layer_rate;
|
||||||
RTC_DCHECK_LE(allocation, left_to_allocate);
|
left_in_stable_allocation -=
|
||||||
left_to_allocate -= allocation;
|
std::min(left_in_stable_allocation, target_bitrate);
|
||||||
}
|
}
|
||||||
|
|
||||||
// All layers above this one are not active.
|
// All layers above this one are not active.
|
||||||
@ -172,16 +189,16 @@ void SimulcastRateAllocator::DistributeAllocationToSimulcastLayers(
|
|||||||
// stream.
|
// stream.
|
||||||
// TODO(sprang): Allocate up to max bitrate for all layers once we have a
|
// TODO(sprang): Allocate up to max bitrate for all layers once we have a
|
||||||
// better idea of possible performance implications.
|
// better idea of possible performance implications.
|
||||||
if (left_to_allocate > 0) {
|
if (left_in_total_allocation > DataRate::Zero()) {
|
||||||
const SimulcastStream& stream = codec_.simulcastStream[top_active_layer];
|
const SimulcastStream& stream = codec_.simulcastStream[top_active_layer];
|
||||||
uint32_t bitrate_bps =
|
DataRate initial_layer_rate =
|
||||||
allocated_bitrates_bps->GetSpatialLayerSum(top_active_layer);
|
DataRate::bps(allocated_bitrates->GetSpatialLayerSum(top_active_layer));
|
||||||
uint32_t allocation =
|
DataRate additional_allocation =
|
||||||
std::min(left_to_allocate, stream.maxBitrate * 1000 - bitrate_bps);
|
std::min(left_in_total_allocation,
|
||||||
bitrate_bps += allocation;
|
DataRate::kbps(stream.maxBitrate) - initial_layer_rate);
|
||||||
RTC_DCHECK_LE(allocation, left_to_allocate);
|
allocated_bitrates->SetBitrate(
|
||||||
left_to_allocate -= allocation;
|
top_active_layer, 0,
|
||||||
allocated_bitrates_bps->SetBitrate(top_active_layer, 0, bitrate_bps);
|
(initial_layer_rate + additional_allocation).bps());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "api/video/video_bitrate_allocator.h"
|
#include "api/video/video_bitrate_allocator.h"
|
||||||
#include "api/video_codecs/video_codec.h"
|
#include "api/video_codecs/video_codec.h"
|
||||||
#include "rtc_base/constructor_magic.h"
|
#include "rtc_base/constructor_magic.h"
|
||||||
|
#include "rtc_base/experiments/stable_target_rate_experiment.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
@ -36,10 +37,11 @@ class SimulcastRateAllocator : public VideoBitrateAllocator {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void DistributeAllocationToSimulcastLayers(
|
void DistributeAllocationToSimulcastLayers(
|
||||||
uint32_t total_bitrate_bps,
|
DataRate total_bitrate,
|
||||||
VideoBitrateAllocation* allocated_bitrates_bps);
|
DataRate stable_bitrate,
|
||||||
|
VideoBitrateAllocation* allocated_bitrates);
|
||||||
void DistributeAllocationToTemporalLayers(
|
void DistributeAllocationToTemporalLayers(
|
||||||
VideoBitrateAllocation* allocated_bitrates_bps) const;
|
VideoBitrateAllocation* allocated_bitrates) const;
|
||||||
std::vector<uint32_t> DefaultTemporalLayerAllocation(int bitrate_kbps,
|
std::vector<uint32_t> DefaultTemporalLayerAllocation(int bitrate_kbps,
|
||||||
int max_bitrate_kbps,
|
int max_bitrate_kbps,
|
||||||
int simulcast_id) const;
|
int simulcast_id) const;
|
||||||
@ -50,7 +52,7 @@ class SimulcastRateAllocator : public VideoBitrateAllocator {
|
|||||||
int NumTemporalStreams(size_t simulcast_id) const;
|
int NumTemporalStreams(size_t simulcast_id) const;
|
||||||
|
|
||||||
const VideoCodec codec_;
|
const VideoCodec codec_;
|
||||||
const double hysteresis_factor_;
|
const StableTargetRateExperiment stable_rate_settings_;
|
||||||
std::vector<bool> stream_enabled_;
|
std::vector<bool> stream_enabled_;
|
||||||
|
|
||||||
RTC_DISALLOW_COPY_AND_ASSIGN(SimulcastRateAllocator);
|
RTC_DISALLOW_COPY_AND_ASSIGN(SimulcastRateAllocator);
|
||||||
|
@ -136,6 +136,24 @@ class SimulcastRateAllocatorTest : public ::testing::TestWithParam<bool> {
|
|||||||
DataRate::kbps(target_bitrate), kDefaultFrameRate));
|
DataRate::kbps(target_bitrate), kDefaultFrameRate));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VideoBitrateAllocation GetAllocation(DataRate target_rate,
|
||||||
|
DataRate stable_rate) {
|
||||||
|
return allocator_->Allocate(VideoBitrateAllocationParameters(
|
||||||
|
target_rate, stable_rate, kDefaultFrameRate));
|
||||||
|
}
|
||||||
|
|
||||||
|
DataRate MinRate(size_t layer_index) const {
|
||||||
|
return DataRate::kbps(codec_.simulcastStream[layer_index].minBitrate);
|
||||||
|
}
|
||||||
|
|
||||||
|
DataRate TargetRate(size_t layer_index) const {
|
||||||
|
return DataRate::kbps(codec_.simulcastStream[layer_index].targetBitrate);
|
||||||
|
}
|
||||||
|
|
||||||
|
DataRate MaxRate(size_t layer_index) const {
|
||||||
|
return DataRate::kbps(codec_.simulcastStream[layer_index].maxBitrate);
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static const int kDefaultFrameRate = 30;
|
static const int kDefaultFrameRate = 30;
|
||||||
VideoCodec codec_;
|
VideoCodec codec_;
|
||||||
@ -524,6 +542,71 @@ TEST_F(SimulcastRateAllocatorTest, NonConferenceModeScreenshare) {
|
|||||||
EXPECT_EQ(alloc.GetTemporalLayerAllocation(2).size(), 3u);
|
EXPECT_EQ(alloc.GetTemporalLayerAllocation(2).size(), 3u);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(SimulcastRateAllocatorTest, StableRate) {
|
||||||
|
webrtc::test::ScopedFieldTrials field_trials(
|
||||||
|
"WebRTC-StableTargetRate/"
|
||||||
|
"enabled:true,"
|
||||||
|
"video_hysteresis_factor:1.1/");
|
||||||
|
|
||||||
|
SetupCodec3SL3TL({true, true, true});
|
||||||
|
CreateAllocator();
|
||||||
|
|
||||||
|
// Let the volatile rate always be be enough for all streams, in this test we
|
||||||
|
// are only interested in how the stable rate affects enablement.
|
||||||
|
const DataRate volatile_rate =
|
||||||
|
(TargetRate(0) + TargetRate(1) + MinRate(2)) * 1.1;
|
||||||
|
|
||||||
|
{
|
||||||
|
// On the first call to a new SimulcastRateAllocator instance, hysteresis
|
||||||
|
// is disabled, but stable rate still caps layers.
|
||||||
|
uint32_t expected[] = {TargetRate(0).kbps<uint32_t>(),
|
||||||
|
MaxRate(1).kbps<uint32_t>()};
|
||||||
|
ExpectEqual(expected,
|
||||||
|
GetAllocation(volatile_rate, TargetRate(0) + MinRate(1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Let stable rate go to a bitrate below what is needed for two streams.
|
||||||
|
uint32_t expected[] = {MaxRate(0).kbps<uint32_t>(), 0};
|
||||||
|
ExpectEqual(expected,
|
||||||
|
GetAllocation(volatile_rate,
|
||||||
|
TargetRate(0) + MinRate(1) - DataRate::bps(1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Don't enable stream as we need to get up above hysteresis threshold.
|
||||||
|
uint32_t expected[] = {MaxRate(0).kbps<uint32_t>(), 0};
|
||||||
|
ExpectEqual(expected,
|
||||||
|
GetAllocation(volatile_rate, TargetRate(0) + MinRate(1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Above threshold with hysteresis, enable second stream.
|
||||||
|
uint32_t expected[] = {TargetRate(0).kbps<uint32_t>(),
|
||||||
|
MaxRate(1).kbps<uint32_t>()};
|
||||||
|
ExpectEqual(expected, GetAllocation(volatile_rate,
|
||||||
|
(TargetRate(0) + MinRate(1)) * 1.1));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Enough to enable all thee layers.
|
||||||
|
uint32_t expected[] = {
|
||||||
|
TargetRate(0).kbps<uint32_t>(), TargetRate(1).kbps<uint32_t>(),
|
||||||
|
(volatile_rate - TargetRate(0) - TargetRate(1)).kbps<uint32_t>()};
|
||||||
|
ExpectEqual(expected, GetAllocation(volatile_rate, volatile_rate));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Drop hysteresis, all three still on.
|
||||||
|
uint32_t expected[] = {
|
||||||
|
TargetRate(0).kbps<uint32_t>(), TargetRate(1).kbps<uint32_t>(),
|
||||||
|
(volatile_rate - TargetRate(0) - TargetRate(1)).kbps<uint32_t>()};
|
||||||
|
ExpectEqual(expected,
|
||||||
|
GetAllocation(volatile_rate,
|
||||||
|
TargetRate(0) + TargetRate(1) + MinRate(2)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class ScreenshareRateAllocationTest : public SimulcastRateAllocatorTest {
|
class ScreenshareRateAllocationTest : public SimulcastRateAllocatorTest {
|
||||||
public:
|
public:
|
||||||
void SetupConferenceScreenshare(bool use_simulcast, bool active = true) {
|
void SetupConferenceScreenshare(bool use_simulcast, bool active = true) {
|
||||||
|
@ -20,8 +20,8 @@ constexpr char kFieldTrialName[] = "WebRTC-StableTargetRate";
|
|||||||
|
|
||||||
StableTargetRateExperiment::StableTargetRateExperiment(
|
StableTargetRateExperiment::StableTargetRateExperiment(
|
||||||
const WebRtcKeyValueConfig* const key_value_config,
|
const WebRtcKeyValueConfig* const key_value_config,
|
||||||
absl::optional<double> default_video_hysteresis,
|
double default_video_hysteresis,
|
||||||
absl::optional<double> default_screenshare_hysteresis)
|
double default_screenshare_hysteresis)
|
||||||
: enabled_("enabled", false),
|
: enabled_("enabled", false),
|
||||||
video_hysteresis_factor_("video_hysteresis_factor",
|
video_hysteresis_factor_("video_hysteresis_factor",
|
||||||
default_video_hysteresis),
|
default_video_hysteresis),
|
||||||
@ -44,31 +44,25 @@ StableTargetRateExperiment StableTargetRateExperiment::ParseFromFieldTrials() {
|
|||||||
|
|
||||||
StableTargetRateExperiment StableTargetRateExperiment::ParseFromKeyValueConfig(
|
StableTargetRateExperiment StableTargetRateExperiment::ParseFromKeyValueConfig(
|
||||||
const WebRtcKeyValueConfig* const key_value_config) {
|
const WebRtcKeyValueConfig* const key_value_config) {
|
||||||
if (key_value_config->Lookup("WebRTC-VideoRateControl") != "") {
|
RateControlSettings rate_control =
|
||||||
RateControlSettings rate_control =
|
RateControlSettings::ParseFromKeyValueConfig(key_value_config);
|
||||||
RateControlSettings::ParseFromKeyValueConfig(key_value_config);
|
return StableTargetRateExperiment(
|
||||||
return StableTargetRateExperiment(key_value_config,
|
key_value_config,
|
||||||
rate_control.GetSimulcastHysteresisFactor(
|
rate_control.GetSimulcastHysteresisFactor(VideoCodecMode::kRealtimeVideo),
|
||||||
VideoCodecMode::kRealtimeVideo),
|
rate_control.GetSimulcastHysteresisFactor(
|
||||||
rate_control.GetSimulcastHysteresisFactor(
|
VideoCodecMode::kScreensharing));
|
||||||
VideoCodecMode::kScreensharing));
|
|
||||||
}
|
|
||||||
return StableTargetRateExperiment(key_value_config, absl::nullopt,
|
|
||||||
absl::nullopt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StableTargetRateExperiment::IsEnabled() const {
|
bool StableTargetRateExperiment::IsEnabled() const {
|
||||||
return enabled_.Get();
|
return enabled_.Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
absl::optional<double> StableTargetRateExperiment::GetVideoHysteresisFactor()
|
double StableTargetRateExperiment::GetVideoHysteresisFactor() const {
|
||||||
const {
|
return video_hysteresis_factor_.Get();
|
||||||
return video_hysteresis_factor_.GetOptional();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
absl::optional<double>
|
double StableTargetRateExperiment::GetScreenshareHysteresisFactor() const {
|
||||||
StableTargetRateExperiment::GetScreenshareHysteresisFactor() const {
|
return screenshare_hysteresis_factor_.Get();
|
||||||
return screenshare_hysteresis_factor_.GetOptional();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -25,18 +25,18 @@ class StableTargetRateExperiment {
|
|||||||
const WebRtcKeyValueConfig* const key_value_config);
|
const WebRtcKeyValueConfig* const key_value_config);
|
||||||
|
|
||||||
bool IsEnabled() const;
|
bool IsEnabled() const;
|
||||||
absl::optional<double> GetVideoHysteresisFactor() const;
|
double GetVideoHysteresisFactor() const;
|
||||||
absl::optional<double> GetScreenshareHysteresisFactor() const;
|
double GetScreenshareHysteresisFactor() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit StableTargetRateExperiment(
|
explicit StableTargetRateExperiment(
|
||||||
const WebRtcKeyValueConfig* const key_value_config,
|
const WebRtcKeyValueConfig* const key_value_config,
|
||||||
absl::optional<double> default_video_hysteresis,
|
double default_video_hysteresis,
|
||||||
absl::optional<double> default_screenshare_hysteresis);
|
double default_screenshare_hysteresis);
|
||||||
|
|
||||||
FieldTrialParameter<bool> enabled_;
|
FieldTrialParameter<bool> enabled_;
|
||||||
FieldTrialOptional<double> video_hysteresis_factor_;
|
FieldTrialParameter<double> video_hysteresis_factor_;
|
||||||
FieldTrialOptional<double> screenshare_hysteresis_factor_;
|
FieldTrialParameter<double> screenshare_hysteresis_factor_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -19,8 +19,8 @@ TEST(StableBweExperimentTest, Default) {
|
|||||||
StableTargetRateExperiment config =
|
StableTargetRateExperiment config =
|
||||||
StableTargetRateExperiment::ParseFromFieldTrials();
|
StableTargetRateExperiment::ParseFromFieldTrials();
|
||||||
EXPECT_FALSE(config.IsEnabled());
|
EXPECT_FALSE(config.IsEnabled());
|
||||||
EXPECT_FALSE(config.GetVideoHysteresisFactor());
|
EXPECT_EQ(config.GetVideoHysteresisFactor(), 1.0);
|
||||||
EXPECT_FALSE(config.GetScreenshareHysteresisFactor());
|
EXPECT_EQ(config.GetScreenshareHysteresisFactor(), 1.35);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(StableBweExperimentTest, EnabledNoHysteresis) {
|
TEST(StableBweExperimentTest, EnabledNoHysteresis) {
|
||||||
@ -30,8 +30,8 @@ TEST(StableBweExperimentTest, EnabledNoHysteresis) {
|
|||||||
StableTargetRateExperiment config =
|
StableTargetRateExperiment config =
|
||||||
StableTargetRateExperiment::ParseFromFieldTrials();
|
StableTargetRateExperiment::ParseFromFieldTrials();
|
||||||
EXPECT_TRUE(config.IsEnabled());
|
EXPECT_TRUE(config.IsEnabled());
|
||||||
EXPECT_FALSE(config.GetVideoHysteresisFactor());
|
EXPECT_EQ(config.GetVideoHysteresisFactor(), 1.0);
|
||||||
EXPECT_FALSE(config.GetScreenshareHysteresisFactor());
|
EXPECT_EQ(config.GetScreenshareHysteresisFactor(), 1.35);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(StableBweExperimentTest, EnabledWithHysteresis) {
|
TEST(StableBweExperimentTest, EnabledWithHysteresis) {
|
||||||
|
Reference in New Issue
Block a user