Extracted bitrate configuration from call class.

This separates the bitrate configuration logic from other call specific
logic, creating a greater separation of concern and simplifying testing.
The old call tests are kept but can be removed in the future reducing
the dependencies on rtp transport control interface and congestion
control in the system, which will simplify future refactoring.

This also prepares for moving the bitrate configuration responsibility
to the rtp transport controller in a later CL.

Bug: webrtc:8415
Change-Id: I97126e89f30b63fc9b5d98a0bed1c29f18a6ed44
Reviewed-on: https://webrtc-review.googlesource.com/54401
Reviewed-by: Zach Stein <zstein@webrtc.org>
Reviewed-by: Niels Moller <nisse@webrtc.org>
Commit-Queue: Sebastian Jansson <srte@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22124}
This commit is contained in:
Sebastian Jansson 2018-02-20 19:38:37 +01:00 committed by Commit Bot
parent fc8d26bd8a
commit df023aa6b4
5 changed files with 529 additions and 105 deletions

View File

@ -100,6 +100,18 @@ rtc_source_set("rtp_sender") {
]
}
rtc_source_set("bitrate_configurator") {
sources = [
"rtp_bitrate_configurator.cc",
"rtp_bitrate_configurator.h",
]
deps = [
":rtp_interfaces",
"../rtc_base:checks",
"../rtc_base:rtc_base_approved",
]
}
rtc_source_set("bitrate_allocator") {
sources = [
"bitrate_allocator.cc",
@ -135,6 +147,7 @@ rtc_static_library("call") {
deps = [
":bitrate_allocator",
":bitrate_configurator",
":call_interfaces",
":rtp_interfaces",
":rtp_receiver",
@ -201,12 +214,14 @@ if (rtc_include_tests) {
"call_unittest.cc",
"flexfec_receive_stream_unittest.cc",
"rtcp_demuxer_unittest.cc",
"rtp_bitrate_configurator_unittest.cc",
"rtp_demuxer_unittest.cc",
"rtp_rtcp_demuxer_helper_unittest.cc",
"rtx_receive_stream_unittest.cc",
]
deps = [
":bitrate_allocator",
":bitrate_configurator",
":call",
":call_interfaces",
":mock_rtp_interfaces",

View File

@ -24,6 +24,7 @@
#include "call/bitrate_allocator.h"
#include "call/call.h"
#include "call/flexfec_receive_stream_impl.h"
#include "call/rtp_bitrate_configurator.h"
#include "call/rtp_stream_receiver_controller.h"
#include "call/rtp_transport_controller_send.h"
#include "logging/rtc_event_log/events/rtc_event_audio_receive_stream_config.h"
@ -261,10 +262,6 @@ class Call : public webrtc::Call,
void UpdateHistograms();
void UpdateAggregateNetworkState();
// Applies update to the BitrateConstraints cached in |config_|, restarting
// bandwidth estimation from |new_start| if set.
void UpdateCurrentBitrateConfig(const rtc::Optional<int>& new_start);
Clock* const clock_;
const int num_cpu_cores_;
@ -372,14 +369,7 @@ class Call : public webrtc::Call,
// and deleted before any other members.
rtc::TaskQueue worker_queue_;
// The config mask set by SetBitrateConfigMask.
// 0 <= min <= start <= max
BitrateConstraintsMask bitrate_config_mask_;
// The config set by SetBitrateConfig.
// min >= 0, start != 0, max == -1 || max > 0
BitrateConstraints base_bitrate_config_;
RtpBitrateConfigurator bitrate_configurator_;
RTC_DISALLOW_COPY_AND_ASSIGN(Call);
};
} // namespace internal
@ -446,21 +436,15 @@ Call::Call(const Call::Config& config,
video_send_delay_stats_(new SendDelayStats(clock_)),
start_ms_(clock_->TimeInMilliseconds()),
worker_queue_("call_worker_queue"),
base_bitrate_config_(config.bitrate_config) {
bitrate_configurator_(config.bitrate_config) {
RTC_DCHECK(config.event_log != nullptr);
RTC_DCHECK_GE(config.bitrate_config.min_bitrate_bps, 0);
RTC_DCHECK_GE(config.bitrate_config.start_bitrate_bps,
config.bitrate_config.min_bitrate_bps);
if (config.bitrate_config.max_bitrate_bps != -1) {
RTC_DCHECK_GE(config.bitrate_config.max_bitrate_bps,
config.bitrate_config.start_bitrate_bps);
}
transport_send->RegisterNetworkObserver(this);
transport_send_ = std::move(transport_send);
transport_send_->OnNetworkAvailability(false);
transport_send_->SetBweBitrates(config_.bitrate_config.min_bitrate_bps,
config_.bitrate_config.start_bitrate_bps,
config_.bitrate_config.max_bitrate_bps);
transport_send_->SetBweBitrates(
bitrate_configurator_.GetConfig().min_bitrate_bps,
bitrate_configurator_.GetConfig().start_bitrate_bps,
bitrate_configurator_.GetConfig().max_bitrate_bps);
call_stats_->RegisterStatsObserver(&receive_side_cc_);
call_stats_->RegisterStatsObserver(transport_send_->GetCallStatsObserver());
@ -957,80 +941,29 @@ Call::Stats Call::GetStats() const {
void Call::SetBitrateConfig(const BitrateConstraints& bitrate_config) {
TRACE_EVENT0("webrtc", "Call::SetBitrateConfig");
RTC_DCHECK_CALLED_SEQUENTIALLY(&configuration_sequence_checker_);
RTC_DCHECK_GE(bitrate_config.min_bitrate_bps, 0);
RTC_DCHECK_NE(bitrate_config.start_bitrate_bps, 0);
if (bitrate_config.max_bitrate_bps != -1) {
RTC_DCHECK_GT(bitrate_config.max_bitrate_bps, 0);
}
rtc::Optional<int> new_start;
// Only update the "start" bitrate if it's set, and different from the old
// value. In practice, this value comes from the x-google-start-bitrate codec
// parameter in SDP, and setting the same remote description twice shouldn't
// restart bandwidth estimation.
if (bitrate_config.start_bitrate_bps != -1 &&
bitrate_config.start_bitrate_bps !=
base_bitrate_config_.start_bitrate_bps) {
new_start.emplace(bitrate_config.start_bitrate_bps);
}
base_bitrate_config_ = bitrate_config;
UpdateCurrentBitrateConfig(new_start);
}
void Call::SetBitrateConfigMask(const BitrateConstraintsMask& mask) {
TRACE_EVENT0("webrtc", "Call::SetBitrateConfigMask");
RTC_DCHECK_CALLED_SEQUENTIALLY(&configuration_sequence_checker_);
bitrate_config_mask_ = mask;
UpdateCurrentBitrateConfig(mask.start_bitrate_bps);
}
void Call::UpdateCurrentBitrateConfig(const rtc::Optional<int>& new_start) {
BitrateConstraints updated;
updated.min_bitrate_bps =
std::max(bitrate_config_mask_.min_bitrate_bps.value_or(0),
base_bitrate_config_.min_bitrate_bps);
updated.max_bitrate_bps =
MinPositive(bitrate_config_mask_.max_bitrate_bps.value_or(-1),
base_bitrate_config_.max_bitrate_bps);
// If the combined min ends up greater than the combined max, the max takes
// priority.
if (updated.max_bitrate_bps != -1 &&
updated.min_bitrate_bps > updated.max_bitrate_bps) {
updated.min_bitrate_bps = updated.max_bitrate_bps;
}
// If there is nothing to update (min/max unchanged, no new bandwidth
// estimation start value), return early.
if (updated.min_bitrate_bps == config_.bitrate_config.min_bitrate_bps &&
updated.max_bitrate_bps == config_.bitrate_config.max_bitrate_bps &&
!new_start) {
RTC_LOG(LS_VERBOSE) << "WebRTC.Call.UpdateCurrentBitrateConfig: "
<< "nothing to update";
return;
}
if (new_start) {
// Clamp start by min and max.
updated.start_bitrate_bps = MinPositive(
std::max(*new_start, updated.min_bitrate_bps), updated.max_bitrate_bps);
rtc::Optional<BitrateConstraints> config =
bitrate_configurator_.UpdateWithSdpParameters(bitrate_config);
if (config.has_value()) {
transport_send_->SetBweBitrates(config->min_bitrate_bps,
config->start_bitrate_bps,
config->max_bitrate_bps);
} else {
updated.start_bitrate_bps = -1;
RTC_LOG(LS_VERBOSE) << "WebRTC.Call.SetBitrateConfig: "
<< "nothing to update";
}
}
RTC_LOG(INFO) << "WebRTC.Call.UpdateCurrentBitrateConfig: "
<< "calling SetBweBitrates with args ("
<< updated.min_bitrate_bps << ", " << updated.start_bitrate_bps
<< ", " << updated.max_bitrate_bps << ")";
transport_send_->SetBweBitrates(updated.min_bitrate_bps,
updated.start_bitrate_bps,
updated.max_bitrate_bps);
if (!new_start) {
updated.start_bitrate_bps = config_.bitrate_config.start_bitrate_bps;
void Call::SetBitrateConfigMask(const BitrateConstraintsMask& bitrate_mask) {
rtc::Optional<BitrateConstraints> config =
bitrate_configurator_.UpdateWithClientPreferences(bitrate_mask);
if (config.has_value()) {
transport_send_->SetBweBitrates(config->min_bitrate_bps,
config->start_bitrate_bps,
config->max_bitrate_bps);
} else {
RTC_LOG(LS_VERBOSE) << "WebRTC.Call.SetBitrateConfigMask: "
<< "nothing to update";
}
config_.bitrate_config = updated;
}
void Call::SetBitrateAllocationStrategy(
@ -1134,19 +1067,21 @@ void Call::OnNetworkRouteChanged(const std::string& transport_name,
}
if (kv->second != network_route) {
kv->second = network_route;
RTC_LOG(LS_INFO)
<< "Network route changed on transport " << transport_name
<< ": new local network id " << network_route.local_network_id
<< " new remote network id " << network_route.remote_network_id
<< " Reset bitrates to min: " << config_.bitrate_config.min_bitrate_bps
<< " bps, start: " << config_.bitrate_config.start_bitrate_bps
<< " bps, max: " << config_.bitrate_config.start_bitrate_bps
<< " bps.";
RTC_DCHECK_GT(config_.bitrate_config.start_bitrate_bps, 0);
BitrateConstraints bitrate_config = bitrate_configurator_.GetConfig();
RTC_LOG(LS_INFO) << "Network route changed on transport " << transport_name
<< ": new local network id "
<< network_route.local_network_id
<< " new remote network id "
<< network_route.remote_network_id
<< " Reset bitrates to min: "
<< bitrate_config.min_bitrate_bps
<< " bps, start: " << bitrate_config.start_bitrate_bps
<< " bps, max: " << bitrate_config.max_bitrate_bps
<< " bps.";
RTC_DCHECK_GT(bitrate_config.start_bitrate_bps, 0);
transport_send_->OnNetworkRouteChanged(
network_route, config_.bitrate_config.start_bitrate_bps,
config_.bitrate_config.min_bitrate_bps,
config_.bitrate_config.max_bitrate_bps);
network_route, bitrate_config.start_bitrate_bps,
bitrate_config.min_bitrate_bps, bitrate_config.max_bitrate_bps);
}
}

View File

@ -0,0 +1,107 @@
/*
* Copyright (c) 2018 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 "call/rtp_bitrate_configurator.h"
#include <algorithm>
#include "rtc_base/checks.h"
namespace webrtc {
RtpBitrateConfigurator::RtpBitrateConfigurator(
const BitrateConstraints& bitrate_config)
: bitrate_config_(bitrate_config), base_bitrate_config_(bitrate_config) {
RTC_DCHECK_GE(bitrate_config.min_bitrate_bps, 0);
RTC_DCHECK_GE(bitrate_config.start_bitrate_bps,
bitrate_config.min_bitrate_bps);
if (bitrate_config.max_bitrate_bps != -1) {
RTC_DCHECK_GE(bitrate_config.max_bitrate_bps,
bitrate_config.start_bitrate_bps);
}
}
RtpBitrateConfigurator::~RtpBitrateConfigurator() = default;
BitrateConstraints RtpBitrateConfigurator::GetConfig() const {
return bitrate_config_;
}
rtc::Optional<BitrateConstraints>
RtpBitrateConfigurator::UpdateWithSdpParameters(
const BitrateConstraints& bitrate_config) {
RTC_DCHECK_GE(bitrate_config.min_bitrate_bps, 0);
RTC_DCHECK_NE(bitrate_config.start_bitrate_bps, 0);
if (bitrate_config.max_bitrate_bps != -1) {
RTC_DCHECK_GT(bitrate_config.max_bitrate_bps, 0);
}
rtc::Optional<int> new_start;
// Only update the "start" bitrate if it's set, and different from the old
// value. In practice, this value comes from the x-google-start-bitrate codec
// parameter in SDP, and setting the same remote description twice shouldn't
// restart bandwidth estimation.
if (bitrate_config.start_bitrate_bps != -1 &&
bitrate_config.start_bitrate_bps !=
base_bitrate_config_.start_bitrate_bps) {
new_start.emplace(bitrate_config.start_bitrate_bps);
}
base_bitrate_config_ = bitrate_config;
return UpdateConstraints(new_start);
}
rtc::Optional<BitrateConstraints>
RtpBitrateConfigurator::UpdateWithClientPreferences(
const BitrateConstraintsMask& bitrate_mask) {
bitrate_config_mask_ = bitrate_mask;
return UpdateConstraints(bitrate_mask.start_bitrate_bps);
}
rtc::Optional<BitrateConstraints> RtpBitrateConfigurator::UpdateConstraints(
const rtc::Optional<int>& new_start) {
BitrateConstraints updated;
updated.min_bitrate_bps =
std::max(bitrate_config_mask_.min_bitrate_bps.value_or(0),
base_bitrate_config_.min_bitrate_bps);
updated.max_bitrate_bps =
MinPositive(bitrate_config_mask_.max_bitrate_bps.value_or(-1),
base_bitrate_config_.max_bitrate_bps);
// If the combined min ends up greater than the combined max, the max takes
// priority.
if (updated.max_bitrate_bps != -1 &&
updated.min_bitrate_bps > updated.max_bitrate_bps) {
updated.min_bitrate_bps = updated.max_bitrate_bps;
}
// If there is nothing to update (min/max unchanged, no new bandwidth
// estimation start value), return early.
if (updated.min_bitrate_bps == bitrate_config_.min_bitrate_bps &&
updated.max_bitrate_bps == bitrate_config_.max_bitrate_bps &&
!new_start) {
return rtc::nullopt;
}
if (new_start) {
// Clamp start by min and max.
updated.start_bitrate_bps = MinPositive(
std::max(*new_start, updated.min_bitrate_bps), updated.max_bitrate_bps);
} else {
updated.start_bitrate_bps = -1;
}
BitrateConstraints config_to_return = updated;
if (!new_start) {
updated.start_bitrate_bps = bitrate_config_.start_bitrate_bps;
}
bitrate_config_ = updated;
return config_to_return;
}
} // namespace webrtc

View File

@ -0,0 +1,68 @@
/*
* Copyright (c) 2018 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 CALL_RTP_BITRATE_CONFIGURATOR_H_
#define CALL_RTP_BITRATE_CONFIGURATOR_H_
#include "call/bitrate_constraints.h"
#include "rtc_base/constructormagic.h"
namespace webrtc {
// RtpBitrateConfigurator calculates the bitrate configuration based on received
// remote configuration combined with local overrides.
class RtpBitrateConfigurator {
public:
explicit RtpBitrateConfigurator(const BitrateConstraints& bitrate_config);
~RtpBitrateConfigurator();
BitrateConstraints GetConfig() const;
// The greater min and smaller max set by this and SetBitrateConfigMask will
// be used. The latest non-negative start value from either call will be used.
// Specifying a start bitrate (>0) will reset the current bitrate estimate.
// This is due to how the 'x-google-start-bitrate' flag is currently
// implemented. Passing -1 leaves the start bitrate unchanged. Behavior is not
// guaranteed for other negative values or 0.
// The optional return value is set with new configuration if it was updated.
rtc::Optional<BitrateConstraints> UpdateWithSdpParameters(
const BitrateConstraints& bitrate_config_);
// The greater min and smaller max set by this and SetBitrateConfig will be
// used. The latest non-negative start value form either call will be used.
// Specifying a start bitrate will reset the current bitrate estimate.
// Assumes 0 <= min <= start <= max holds for set parameters.
// Update the bitrate configuration
// The optional return value is set with new configuration if it was updated.
rtc::Optional<BitrateConstraints> UpdateWithClientPreferences(
const BitrateConstraintsMask& bitrate_mask);
private:
// Applies update to the BitrateConstraints cached in |config_|, resetting
// with |new_start| if set.
rtc::Optional<BitrateConstraints> UpdateConstraints(
const rtc::Optional<int>& new_start);
// Bitrate config used until valid bitrate estimates are calculated. Also
// used to cap total bitrate used. This comes from the remote connection.
BitrateConstraints bitrate_config_;
// The config mask set by SetBitrateConfigMask.
// 0 <= min <= start <= max
BitrateConstraintsMask bitrate_config_mask_;
// The config set by SetBitrateConfig.
// min >= 0, start != 0, max == -1 || max > 0
BitrateConstraints base_bitrate_config_;
RTC_DISALLOW_COPY_AND_ASSIGN(RtpBitrateConfigurator);
};
} // namespace webrtc
#endif // CALL_RTP_BITRATE_CONFIGURATOR_H_

View File

@ -0,0 +1,299 @@
/*
* Copyright (c) 2018 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 <memory>
#include "call/rtp_bitrate_configurator.h"
#include "test/gtest.h"
namespace webrtc {
using rtc::nullopt;
class RtpBitrateConfiguratorTest : public testing::Test {
public:
RtpBitrateConfiguratorTest()
: configurator_(new RtpBitrateConfigurator(BitrateConstraints())) {}
std::unique_ptr<RtpBitrateConfigurator> configurator_;
void UpdateConfigMatches(BitrateConstraints bitrate_config,
rtc::Optional<int> min_bitrate_bps,
rtc::Optional<int> start_bitrate_bps,
rtc::Optional<int> max_bitrate_bps) {
rtc::Optional<BitrateConstraints> result =
configurator_->UpdateWithSdpParameters(bitrate_config);
EXPECT_TRUE(result.has_value());
if (start_bitrate_bps.has_value())
EXPECT_EQ(result->start_bitrate_bps, start_bitrate_bps);
if (min_bitrate_bps.has_value())
EXPECT_EQ(result->min_bitrate_bps, min_bitrate_bps);
if (max_bitrate_bps.has_value())
EXPECT_EQ(result->max_bitrate_bps, max_bitrate_bps);
}
void UpdateMaskMatches(BitrateConstraintsMask bitrate_mask,
rtc::Optional<int> min_bitrate_bps,
rtc::Optional<int> start_bitrate_bps,
rtc::Optional<int> max_bitrate_bps) {
rtc::Optional<BitrateConstraints> result =
configurator_->UpdateWithClientPreferences(bitrate_mask);
EXPECT_TRUE(result.has_value());
if (start_bitrate_bps.has_value())
EXPECT_EQ(result->start_bitrate_bps, start_bitrate_bps);
if (min_bitrate_bps.has_value())
EXPECT_EQ(result->min_bitrate_bps, min_bitrate_bps);
if (max_bitrate_bps.has_value())
EXPECT_EQ(result->max_bitrate_bps, max_bitrate_bps);
}
};
TEST_F(RtpBitrateConfiguratorTest, NewConfigWithValidConfigReturnsNewConfig) {
BitrateConstraints bitrate_config;
bitrate_config.min_bitrate_bps = 1;
bitrate_config.start_bitrate_bps = 2;
bitrate_config.max_bitrate_bps = 3;
UpdateConfigMatches(bitrate_config, 1, 2, 3);
}
TEST_F(RtpBitrateConfiguratorTest, NewConfigWithDifferentMinReturnsNewConfig) {
BitrateConstraints bitrate_config;
bitrate_config.min_bitrate_bps = 10;
bitrate_config.start_bitrate_bps = 20;
bitrate_config.max_bitrate_bps = 30;
configurator_.reset(new RtpBitrateConfigurator(bitrate_config));
bitrate_config.min_bitrate_bps = 11;
UpdateConfigMatches(bitrate_config, 11, -1, 30);
}
TEST_F(RtpBitrateConfiguratorTest,
NewConfigWithDifferentStartReturnsNewConfig) {
BitrateConstraints bitrate_config;
bitrate_config.min_bitrate_bps = 10;
bitrate_config.start_bitrate_bps = 20;
bitrate_config.max_bitrate_bps = 30;
configurator_.reset(new RtpBitrateConfigurator(bitrate_config));
bitrate_config.start_bitrate_bps = 21;
UpdateConfigMatches(bitrate_config, 10, 21, 30);
}
TEST_F(RtpBitrateConfiguratorTest, NewConfigWithDifferentMaxReturnsNewConfig) {
BitrateConstraints bitrate_config;
bitrate_config.min_bitrate_bps = 10;
bitrate_config.start_bitrate_bps = 20;
bitrate_config.max_bitrate_bps = 30;
configurator_.reset(new RtpBitrateConfigurator(bitrate_config));
bitrate_config.max_bitrate_bps = 31;
UpdateConfigMatches(bitrate_config, 10, -1, 31);
}
TEST_F(RtpBitrateConfiguratorTest, NewConfigWithSameConfigElidesSecondCall) {
BitrateConstraints bitrate_config;
bitrate_config.min_bitrate_bps = 1;
bitrate_config.start_bitrate_bps = 2;
bitrate_config.max_bitrate_bps = 3;
UpdateConfigMatches(bitrate_config, 1, 2, 3);
EXPECT_FALSE(
configurator_->UpdateWithSdpParameters(bitrate_config).has_value());
}
TEST_F(RtpBitrateConfiguratorTest,
NewConfigWithSameMinMaxAndNegativeStartElidesSecondCall) {
BitrateConstraints bitrate_config;
bitrate_config.min_bitrate_bps = 1;
bitrate_config.start_bitrate_bps = 2;
bitrate_config.max_bitrate_bps = 3;
UpdateConfigMatches(bitrate_config, 1, 2, 3);
bitrate_config.start_bitrate_bps = -1;
EXPECT_FALSE(
configurator_->UpdateWithSdpParameters(bitrate_config).has_value());
}
TEST_F(RtpBitrateConfiguratorTest, BiggerMaskMinUsed) {
BitrateConstraintsMask mask;
mask.min_bitrate_bps = 1234;
UpdateMaskMatches(mask, *mask.min_bitrate_bps, nullopt, nullopt);
}
TEST_F(RtpBitrateConfiguratorTest, BiggerConfigMinUsed) {
BitrateConstraintsMask mask;
mask.min_bitrate_bps = 1000;
UpdateMaskMatches(mask, 1000, nullopt, nullopt);
BitrateConstraints config;
config.min_bitrate_bps = 1234;
UpdateConfigMatches(config, 1234, nullopt, nullopt);
}
// The last call to set start should be used.
TEST_F(RtpBitrateConfiguratorTest, LatestStartMaskPreferred) {
BitrateConstraintsMask mask;
mask.start_bitrate_bps = 1300;
UpdateMaskMatches(mask, nullopt, *mask.start_bitrate_bps, nullopt);
BitrateConstraints bitrate_config;
bitrate_config.start_bitrate_bps = 1200;
UpdateConfigMatches(bitrate_config, nullopt, bitrate_config.start_bitrate_bps,
nullopt);
}
TEST_F(RtpBitrateConfiguratorTest, SmallerMaskMaxUsed) {
BitrateConstraints bitrate_config;
bitrate_config.max_bitrate_bps = bitrate_config.start_bitrate_bps + 2000;
configurator_.reset(new RtpBitrateConfigurator(bitrate_config));
BitrateConstraintsMask mask;
mask.max_bitrate_bps = bitrate_config.start_bitrate_bps + 1000;
UpdateMaskMatches(mask, nullopt, nullopt, *mask.max_bitrate_bps);
}
TEST_F(RtpBitrateConfiguratorTest, SmallerConfigMaxUsed) {
BitrateConstraints bitrate_config;
bitrate_config.max_bitrate_bps = bitrate_config.start_bitrate_bps + 1000;
configurator_.reset(new RtpBitrateConfigurator(bitrate_config));
BitrateConstraintsMask mask;
mask.max_bitrate_bps = bitrate_config.start_bitrate_bps + 2000;
// Expect no return because nothing changes
EXPECT_FALSE(configurator_->UpdateWithClientPreferences(mask).has_value());
}
TEST_F(RtpBitrateConfiguratorTest, MaskStartLessThanConfigMinClamped) {
BitrateConstraints bitrate_config;
bitrate_config.min_bitrate_bps = 2000;
configurator_.reset(new RtpBitrateConfigurator(bitrate_config));
BitrateConstraintsMask mask;
mask.start_bitrate_bps = 1000;
UpdateMaskMatches(mask, 2000, 2000, nullopt);
}
TEST_F(RtpBitrateConfiguratorTest, MaskStartGreaterThanConfigMaxClamped) {
BitrateConstraints bitrate_config;
bitrate_config.start_bitrate_bps = 2000;
configurator_.reset(new RtpBitrateConfigurator(bitrate_config));
BitrateConstraintsMask mask;
mask.max_bitrate_bps = 1000;
UpdateMaskMatches(mask, nullopt, -1, 1000);
}
TEST_F(RtpBitrateConfiguratorTest, MaskMinGreaterThanConfigMaxClamped) {
BitrateConstraints bitrate_config;
bitrate_config.min_bitrate_bps = 2000;
configurator_.reset(new RtpBitrateConfigurator(bitrate_config));
BitrateConstraintsMask mask;
mask.max_bitrate_bps = 1000;
UpdateMaskMatches(mask, 1000, nullopt, 1000);
}
TEST_F(RtpBitrateConfiguratorTest, SettingMaskStartForcesUpdate) {
BitrateConstraintsMask mask;
mask.start_bitrate_bps = 1000;
// Config should be returned twice with the same params since
// start_bitrate_bps is set.
UpdateMaskMatches(mask, nullopt, 1000, nullopt);
UpdateMaskMatches(mask, nullopt, 1000, nullopt);
}
TEST_F(RtpBitrateConfiguratorTest, NewConfigWithNoChangesDoesNotCallNewConfig) {
BitrateConstraints config1;
config1.min_bitrate_bps = 0;
config1.start_bitrate_bps = 1000;
config1.max_bitrate_bps = -1;
BitrateConstraints config2;
config2.min_bitrate_bps = 0;
config2.start_bitrate_bps = -1;
config2.max_bitrate_bps = -1;
// The second call should not return anything because it doesn't
// change any values.
UpdateConfigMatches(config1, 0, 1000, -1);
EXPECT_FALSE(configurator_->UpdateWithSdpParameters(config2).has_value());
}
// If config changes the max, but not the effective max,
// new config shouldn't be returned, to avoid unnecessary encoder
// reconfigurations.
TEST_F(RtpBitrateConfiguratorTest,
NewConfigNotReturnedWhenEffectiveMaxUnchanged) {
BitrateConstraints config;
config.min_bitrate_bps = 0;
config.start_bitrate_bps = -1;
config.max_bitrate_bps = 2000;
UpdateConfigMatches(config, nullopt, nullopt, 2000);
// Reduce effective max to 1000 with the mask.
BitrateConstraintsMask mask;
mask.max_bitrate_bps = 1000;
UpdateMaskMatches(mask, nullopt, nullopt, 1000);
// This leaves the effective max unchanged, so new config shouldn't be
// returned again.
config.max_bitrate_bps = 1000;
EXPECT_FALSE(configurator_->UpdateWithSdpParameters(config).has_value());
}
// When the "start bitrate" mask is removed, new config shouldn't be returned
// again, since nothing's changing.
TEST_F(RtpBitrateConfiguratorTest, NewConfigNotReturnedWhenStartMaskRemoved) {
BitrateConstraintsMask mask;
mask.start_bitrate_bps = 1000;
UpdateMaskMatches(mask, 0, 1000, -1);
mask.start_bitrate_bps.reset();
EXPECT_FALSE(configurator_->UpdateWithClientPreferences(mask).has_value());
}
// Test that if a new config is returned after BitrateConstraintsMask applies a
// "start" value, the new config won't return that start value a
// second time.
TEST_F(RtpBitrateConfiguratorTest, NewConfigAfterBitrateConfigMaskWithStart) {
BitrateConstraintsMask mask;
mask.start_bitrate_bps = 1000;
UpdateMaskMatches(mask, 0, 1000, -1);
BitrateConstraints config;
config.min_bitrate_bps = 0;
config.start_bitrate_bps = -1;
config.max_bitrate_bps = 5000;
// The start value isn't changing, so new config should be returned with
// -1.
UpdateConfigMatches(config, 0, -1, 5000);
}
TEST_F(RtpBitrateConfiguratorTest,
NewConfigNotReturnedWhenClampedMinUnchanged) {
BitrateConstraints bitrate_config;
bitrate_config.start_bitrate_bps = 500;
bitrate_config.max_bitrate_bps = 1000;
configurator_.reset(new RtpBitrateConfigurator(bitrate_config));
// Set min to 2000; it is clamped to the max (1000).
BitrateConstraintsMask mask;
mask.min_bitrate_bps = 2000;
UpdateMaskMatches(mask, 1000, -1, 1000);
// Set min to 3000; the clamped value stays the same so nothing happens.
mask.min_bitrate_bps = 3000;
EXPECT_FALSE(configurator_->UpdateWithClientPreferences(mask).has_value());
}
} // namespace webrtc