Instantly pass network changes to controllers in audio network adaptor.

This allows controllers to do internal logic upon the network metric changes, e.g., filtering.

BUG=webrtc:6303

Review-Url: https://codereview.webrtc.org/2643133003
Cr-Commit-Position: refs/heads/master@{#16363}
This commit is contained in:
minyue
2017-01-30 10:50:00 -08:00
committed by Commit bot
parent 7b8cddd34c
commit a6a6d65278
21 changed files with 633 additions and 384 deletions

View File

@ -49,6 +49,11 @@ AudioNetworkAdaptorImpl::~AudioNetworkAdaptorImpl() = default;
void AudioNetworkAdaptorImpl::SetUplinkBandwidth(int uplink_bandwidth_bps) {
last_metrics_.uplink_bandwidth_bps = rtc::Optional<int>(uplink_bandwidth_bps);
DumpNetworkMetrics();
Controller::NetworkMetrics network_metrics;
network_metrics.uplink_bandwidth_bps =
rtc::Optional<int>(uplink_bandwidth_bps);
UpdateNetworkMetrics(network_metrics);
}
void AudioNetworkAdaptorImpl::SetUplinkPacketLossFraction(
@ -56,11 +61,20 @@ void AudioNetworkAdaptorImpl::SetUplinkPacketLossFraction(
last_metrics_.uplink_packet_loss_fraction =
rtc::Optional<float>(uplink_packet_loss_fraction);
DumpNetworkMetrics();
Controller::NetworkMetrics network_metrics;
network_metrics.uplink_packet_loss_fraction =
rtc::Optional<float>(uplink_packet_loss_fraction);
UpdateNetworkMetrics(network_metrics);
}
void AudioNetworkAdaptorImpl::SetRtt(int rtt_ms) {
last_metrics_.rtt_ms = rtc::Optional<int>(rtt_ms);
DumpNetworkMetrics();
Controller::NetworkMetrics network_metrics;
network_metrics.rtt_ms = rtc::Optional<int>(rtt_ms);
UpdateNetworkMetrics(network_metrics);
}
void AudioNetworkAdaptorImpl::SetTargetAudioBitrate(
@ -68,12 +82,22 @@ void AudioNetworkAdaptorImpl::SetTargetAudioBitrate(
last_metrics_.target_audio_bitrate_bps =
rtc::Optional<int>(target_audio_bitrate_bps);
DumpNetworkMetrics();
Controller::NetworkMetrics network_metrics;
network_metrics.target_audio_bitrate_bps =
rtc::Optional<int>(target_audio_bitrate_bps);
UpdateNetworkMetrics(network_metrics);
}
void AudioNetworkAdaptorImpl::SetOverhead(size_t overhead_bytes_per_packet) {
last_metrics_.overhead_bytes_per_packet =
rtc::Optional<size_t>(overhead_bytes_per_packet);
DumpNetworkMetrics();
Controller::NetworkMetrics network_metrics;
network_metrics.overhead_bytes_per_packet =
rtc::Optional<size_t>(overhead_bytes_per_packet);
UpdateNetworkMetrics(network_metrics);
}
AudioNetworkAdaptor::EncoderRuntimeConfig
@ -81,7 +105,7 @@ AudioNetworkAdaptorImpl::GetEncoderRuntimeConfig() {
EncoderRuntimeConfig config;
for (auto& controller :
controller_manager_->GetSortedControllers(last_metrics_))
controller->MakeDecision(last_metrics_, &config);
controller->MakeDecision(&config);
if (debug_dump_writer_)
debug_dump_writer_->DumpEncoderRuntimeConfig(
@ -107,4 +131,10 @@ void AudioNetworkAdaptorImpl::DumpNetworkMetrics() {
config_.clock->TimeInMilliseconds());
}
void AudioNetworkAdaptorImpl::UpdateNetworkMetrics(
const Controller::NetworkMetrics& network_metrics) {
for (auto& controller : controller_manager_->GetControllers())
controller->UpdateNetworkMetrics(network_metrics);
}
} // namespace webrtc

View File

@ -60,6 +60,8 @@ class AudioNetworkAdaptorImpl final : public AudioNetworkAdaptor {
private:
void DumpNetworkMetrics();
void UpdateNetworkMetrics(const Controller::NetworkMetrics& network_metrics);
const Config config_;
std::unique_ptr<ControllerManager> controller_manager_;

View File

@ -96,52 +96,70 @@ AudioNetworkAdaptorStates CreateAudioNetworkAdaptor() {
return states;
}
void SetExpectCallToUpdateNetworkMetrics(
const std::vector<std::unique_ptr<MockController>>& controllers,
const Controller::NetworkMetrics& check) {
for (auto& mock_controller : controllers) {
EXPECT_CALL(*mock_controller,
UpdateNetworkMetrics(NetworkMetricsIs(check)));
}
}
} // namespace
TEST(AudioNetworkAdaptorImplTest,
UpdateNetworkMetricsIsCalledOnSetUplinkBandwidth) {
auto states = CreateAudioNetworkAdaptor();
constexpr int kBandwidth = 16000;
Controller::NetworkMetrics check;
check.uplink_bandwidth_bps = rtc::Optional<int>(kBandwidth);
SetExpectCallToUpdateNetworkMetrics(states.mock_controllers, check);
states.audio_network_adaptor->SetUplinkBandwidth(kBandwidth);
}
TEST(AudioNetworkAdaptorImplTest,
UpdateNetworkMetricsIsCalledOnSetUplinkPacketLossFraction) {
auto states = CreateAudioNetworkAdaptor();
constexpr float kPacketLoss = 0.7f;
Controller::NetworkMetrics check;
check.uplink_packet_loss_fraction = rtc::Optional<float>(kPacketLoss);
SetExpectCallToUpdateNetworkMetrics(states.mock_controllers, check);
states.audio_network_adaptor->SetUplinkPacketLossFraction(kPacketLoss);
}
TEST(AudioNetworkAdaptorImplTest, UpdateNetworkMetricsIsCalledOnSetRtt) {
auto states = CreateAudioNetworkAdaptor();
constexpr int kRtt = 100;
Controller::NetworkMetrics check;
check.rtt_ms = rtc::Optional<int>(kRtt);
SetExpectCallToUpdateNetworkMetrics(states.mock_controllers, check);
states.audio_network_adaptor->SetRtt(kRtt);
}
TEST(AudioNetworkAdaptorImplTest,
UpdateNetworkMetricsIsCalledOnSetTargetAudioBitrate) {
auto states = CreateAudioNetworkAdaptor();
constexpr int kTargetAudioBitrate = 15000;
Controller::NetworkMetrics check;
check.target_audio_bitrate_bps = rtc::Optional<int>(kTargetAudioBitrate);
SetExpectCallToUpdateNetworkMetrics(states.mock_controllers, check);
states.audio_network_adaptor->SetTargetAudioBitrate(kTargetAudioBitrate);
}
TEST(AudioNetworkAdaptorImplTest, UpdateNetworkMetricsIsCalledOnSetOverhead) {
auto states = CreateAudioNetworkAdaptor();
constexpr size_t kOverhead = 64;
Controller::NetworkMetrics check;
check.overhead_bytes_per_packet = rtc::Optional<size_t>(kOverhead);
SetExpectCallToUpdateNetworkMetrics(states.mock_controllers, check);
states.audio_network_adaptor->SetOverhead(kOverhead);
}
TEST(AudioNetworkAdaptorImplTest,
MakeDecisionIsCalledOnGetEncoderRuntimeConfig) {
auto states = CreateAudioNetworkAdaptor();
constexpr int kBandwidth = 16000;
constexpr float kPacketLoss = 0.7f;
constexpr int kRtt = 100;
constexpr int kTargetAudioBitrate = 15000;
constexpr size_t kOverhead = 64;
Controller::NetworkMetrics check;
check.uplink_bandwidth_bps = rtc::Optional<int>(kBandwidth);
for (auto& mock_controller : states.mock_controllers) {
EXPECT_CALL(*mock_controller, MakeDecision(NetworkMetricsIs(check), _));
}
states.audio_network_adaptor->SetUplinkBandwidth(kBandwidth);
states.audio_network_adaptor->GetEncoderRuntimeConfig();
check.uplink_packet_loss_fraction = rtc::Optional<float>(kPacketLoss);
for (auto& mock_controller : states.mock_controllers) {
EXPECT_CALL(*mock_controller, MakeDecision(NetworkMetricsIs(check), _));
}
states.audio_network_adaptor->SetUplinkPacketLossFraction(kPacketLoss);
states.audio_network_adaptor->GetEncoderRuntimeConfig();
check.rtt_ms = rtc::Optional<int>(kRtt);
for (auto& mock_controller : states.mock_controllers) {
EXPECT_CALL(*mock_controller, MakeDecision(NetworkMetricsIs(check), _));
}
states.audio_network_adaptor->SetRtt(kRtt);
states.audio_network_adaptor->GetEncoderRuntimeConfig();
check.target_audio_bitrate_bps = rtc::Optional<int>(kTargetAudioBitrate);
for (auto& mock_controller : states.mock_controllers) {
EXPECT_CALL(*mock_controller, MakeDecision(NetworkMetricsIs(check), _));
}
states.audio_network_adaptor->SetTargetAudioBitrate(kTargetAudioBitrate);
states.audio_network_adaptor->GetEncoderRuntimeConfig();
check.overhead_bytes_per_packet = rtc::Optional<size_t>(kOverhead);
for (auto& mock_controller : states.mock_controllers) {
EXPECT_CALL(*mock_controller, MakeDecision(NetworkMetricsIs(check), _));
}
states.audio_network_adaptor->SetOverhead(kOverhead);
for (auto& mock_controller : states.mock_controllers)
EXPECT_CALL(*mock_controller, MakeDecision(_));
states.audio_network_adaptor->GetEncoderRuntimeConfig();
}
@ -153,8 +171,8 @@ TEST(AudioNetworkAdaptorImplTest,
config.bitrate_bps = rtc::Optional<int>(32000);
config.enable_fec = rtc::Optional<bool>(true);
EXPECT_CALL(*states.mock_controllers[0], MakeDecision(_, _))
.WillOnce(SetArgPointee<1>(config));
EXPECT_CALL(*states.mock_controllers[0], MakeDecision(_))
.WillOnce(SetArgPointee<0>(config));
EXPECT_CALL(*states.mock_debug_dump_writer,
DumpEncoderRuntimeConfig(EncoderRuntimeConfigIs(config),
@ -216,8 +234,8 @@ TEST(AudioNetworkAdaptorImplTest, LogRuntimeConfigOnGetEncoderRuntimeConfig) {
config.bitrate_bps = rtc::Optional<int>(32000);
config.enable_fec = rtc::Optional<bool>(true);
EXPECT_CALL(*states.mock_controllers[0], MakeDecision(_, _))
.WillOnce(SetArgPointee<1>(config));
EXPECT_CALL(*states.mock_controllers[0], MakeDecision(_))
.WillOnce(SetArgPointee<0>(config));
EXPECT_CALL(*states.event_log,
LogAudioNetworkAdaptation(EncoderRuntimeConfigIs(config)))

View File

@ -33,12 +33,21 @@ BitrateController::BitrateController(const Config& config)
RTC_DCHECK_GT(frame_length_ms_, 0);
}
BitrateController::~BitrateController() = default;
void BitrateController::UpdateNetworkMetrics(
const NetworkMetrics& network_metrics) {
if (network_metrics.target_audio_bitrate_bps)
target_audio_bitrate_bps_ = network_metrics.target_audio_bitrate_bps;
if (network_metrics.overhead_bytes_per_packet)
overhead_bytes_per_packet_ = network_metrics.overhead_bytes_per_packet;
}
void BitrateController::MakeDecision(
const NetworkMetrics& metrics,
AudioNetworkAdaptor::EncoderRuntimeConfig* config) {
// Decision on |bitrate_bps| should not have been made.
RTC_DCHECK(!config->bitrate_bps);
if (metrics.target_audio_bitrate_bps && metrics.overhead_bytes_per_packet) {
if (target_audio_bitrate_bps_ && overhead_bytes_per_packet_) {
// Current implementation of BitrateController can only work when
// |metrics.target_audio_bitrate_bps| includes overhead is enabled. This is
// currently governed by the following field trial.
@ -47,9 +56,8 @@ void BitrateController::MakeDecision(
if (config->frame_length_ms)
frame_length_ms_ = *config->frame_length_ms;
int overhead_rate_bps =
*metrics.overhead_bytes_per_packet * 8 * 1000 / frame_length_ms_;
bitrate_bps_ =
std::max(0, *metrics.target_audio_bitrate_bps - overhead_rate_bps);
*overhead_bytes_per_packet_ * 8 * 1000 / frame_length_ms_;
bitrate_bps_ = std::max(0, *target_audio_bitrate_bps_ - overhead_rate_bps);
}
config->bitrate_bps = rtc::Optional<int>(bitrate_bps_);
}

View File

@ -28,13 +28,18 @@ class BitrateController final : public Controller {
explicit BitrateController(const Config& config);
void MakeDecision(const NetworkMetrics& metrics,
AudioNetworkAdaptor::EncoderRuntimeConfig* config) override;
~BitrateController() override;
void UpdateNetworkMetrics(const NetworkMetrics& network_metrics) override;
void MakeDecision(AudioNetworkAdaptor::EncoderRuntimeConfig* config) override;
private:
const Config config_;
int bitrate_bps_;
int frame_length_ms_;
rtc::Optional<int> target_audio_bitrate_bps_;
rtc::Optional<size_t> overhead_bytes_per_packet_;
RTC_DISALLOW_COPY_AND_ASSIGN(BitrateController);
};

View File

@ -17,17 +17,31 @@ namespace audio_network_adaptor {
namespace {
void UpdateNetworkMetrics(
BitrateController* controller,
const rtc::Optional<int>& target_audio_bitrate_bps,
const rtc::Optional<size_t>& overhead_bytes_per_packet) {
// UpdateNetworkMetrics can accept multiple network metric updates at once.
// However, currently, the most used case is to update one metric at a time.
// To reflect this fact, we separate the calls.
if (target_audio_bitrate_bps) {
Controller::NetworkMetrics network_metrics;
network_metrics.target_audio_bitrate_bps = target_audio_bitrate_bps;
controller->UpdateNetworkMetrics(network_metrics);
}
if (overhead_bytes_per_packet) {
Controller::NetworkMetrics network_metrics;
network_metrics.overhead_bytes_per_packet = overhead_bytes_per_packet;
controller->UpdateNetworkMetrics(network_metrics);
}
}
void CheckDecision(BitrateController* controller,
const rtc::Optional<int>& target_audio_bitrate_bps,
const rtc::Optional<size_t>& overhead_bytes_per_packet,
const rtc::Optional<int>& frame_length_ms,
int expected_bitrate_bps) {
Controller::NetworkMetrics metrics;
metrics.target_audio_bitrate_bps = target_audio_bitrate_bps;
metrics.overhead_bytes_per_packet = overhead_bytes_per_packet;
AudioNetworkAdaptor::EncoderRuntimeConfig config;
config.frame_length_ms = frame_length_ms;
controller->MakeDecision(metrics, &config);
controller->MakeDecision(&config);
EXPECT_EQ(rtc::Optional<int>(expected_bitrate_bps), config.bitrate_bps);
}
@ -43,9 +57,9 @@ TEST(AnaBitrateControllerTest, OutputInitValueWhenTargetBitrateUnknown) {
constexpr size_t kOverheadBytesPerPacket = 64;
BitrateController controller(
BitrateController::Config(kInitialBitrateBps, kInitialFrameLengthMs));
CheckDecision(&controller, rtc::Optional<int>(),
rtc::Optional<size_t>(kOverheadBytesPerPacket),
rtc::Optional<int>(kInitialFrameLengthMs * 2),
UpdateNetworkMetrics(&controller, rtc::Optional<int>(),
rtc::Optional<size_t>(kOverheadBytesPerPacket));
CheckDecision(&controller, rtc::Optional<int>(kInitialFrameLengthMs * 2),
kInitialBitrateBps);
}
@ -55,9 +69,9 @@ TEST(AnaBitrateControllerTest, OutputInitValueWhenOverheadUnknown) {
constexpr int kTargetBitrateBps = 48000;
BitrateController controller(
BitrateController::Config(kInitialBitrateBps, kInitialFrameLengthMs));
CheckDecision(&controller, rtc::Optional<int>(kTargetBitrateBps),
rtc::Optional<size_t>(),
rtc::Optional<int>(kInitialFrameLengthMs * 2),
UpdateNetworkMetrics(&controller, rtc::Optional<int>(kTargetBitrateBps),
rtc::Optional<size_t>());
CheckDecision(&controller, rtc::Optional<int>(kInitialFrameLengthMs * 2),
kInitialBitrateBps);
}
@ -74,9 +88,38 @@ TEST(AnaBitrateControllerTest, ChangeBitrateOnTargetBitrateChanged) {
kOverheadBytesPerPacket * 8 * 1000 / kInitialFrameLengthMs;
// Frame length unchanged, bitrate changes in accordance with
// |metrics.target_audio_bitrate_bps| and |metrics.overhead_bytes_per_packet|.
CheckDecision(&controller, rtc::Optional<int>(kTargetBitrateBps),
rtc::Optional<size_t>(kOverheadBytesPerPacket),
rtc::Optional<int>(kInitialFrameLengthMs), kBitrateBps);
UpdateNetworkMetrics(&controller, rtc::Optional<int>(kTargetBitrateBps),
rtc::Optional<size_t>(kOverheadBytesPerPacket));
CheckDecision(&controller, rtc::Optional<int>(kInitialFrameLengthMs),
kBitrateBps);
}
TEST(AnaBitrateControllerTest, UpdateMultipleNetworkMetricsAtOnce) {
// This test is similar to ChangeBitrateOnTargetBitrateChanged. But instead of
// using ::UpdateNetworkMetrics(...), which calls
// BitrateController::UpdateNetworkMetrics(...) multiple times, we
// we call it only once. This is to verify that
// BitrateController::UpdateNetworkMetrics(...) can handle multiple
// network updates at once. This is, however, not a common use case in current
// audio_network_adaptor_impl.cc.
test::ScopedFieldTrials override_field_trials(
"WebRTC-SendSideBwe-WithOverhead/Enabled/");
constexpr int kInitialFrameLengthMs = 20;
BitrateController controller(
BitrateController::Config(32000, kInitialFrameLengthMs));
constexpr int kTargetBitrateBps = 48000;
constexpr size_t kOverheadBytesPerPacket = 64;
constexpr int kBitrateBps =
kTargetBitrateBps -
kOverheadBytesPerPacket * 8 * 1000 / kInitialFrameLengthMs;
Controller::NetworkMetrics network_metrics;
network_metrics.target_audio_bitrate_bps =
rtc::Optional<int>(kTargetBitrateBps);
network_metrics.overhead_bytes_per_packet =
rtc::Optional<size_t>(kOverheadBytesPerPacket);
controller.UpdateNetworkMetrics(network_metrics);
CheckDecision(&controller, rtc::Optional<int>(kInitialFrameLengthMs),
kBitrateBps);
}
TEST(AnaBitrateControllerTest, TreatUnknownFrameLengthAsFrameLengthUnchanged) {
@ -90,9 +133,9 @@ TEST(AnaBitrateControllerTest, TreatUnknownFrameLengthAsFrameLengthUnchanged) {
constexpr int kBitrateBps =
kTargetBitrateBps -
kOverheadBytesPerPacket * 8 * 1000 / kInitialFrameLengthMs;
CheckDecision(&controller, rtc::Optional<int>(kTargetBitrateBps),
rtc::Optional<size_t>(kOverheadBytesPerPacket),
rtc::Optional<int>(), kBitrateBps);
UpdateNetworkMetrics(&controller, rtc::Optional<int>(kTargetBitrateBps),
rtc::Optional<size_t>(kOverheadBytesPerPacket));
CheckDecision(&controller, rtc::Optional<int>(), kBitrateBps);
}
TEST(AnaBitrateControllerTest, IncreaseBitrateOnFrameLengthIncreased) {
@ -107,17 +150,17 @@ TEST(AnaBitrateControllerTest, IncreaseBitrateOnFrameLengthIncreased) {
constexpr int kBitrateBps =
kTargetBitrateBps -
kOverheadBytesPerPacket * 8 * 1000 / kInitialFrameLengthMs;
CheckDecision(&controller, rtc::Optional<int>(kTargetBitrateBps),
rtc::Optional<size_t>(kOverheadBytesPerPacket),
rtc::Optional<int>(), kBitrateBps);
UpdateNetworkMetrics(&controller, rtc::Optional<int>(kTargetBitrateBps),
rtc::Optional<size_t>(kOverheadBytesPerPacket));
CheckDecision(&controller, rtc::Optional<int>(), kBitrateBps);
constexpr int kFrameLengthMs = 60;
constexpr size_t kPacketOverheadRateDiff =
kOverheadBytesPerPacket * 8 * 1000 / 20 -
kOverheadBytesPerPacket * 8 * 1000 / 60;
CheckDecision(&controller, rtc::Optional<int>(kTargetBitrateBps),
rtc::Optional<size_t>(kOverheadBytesPerPacket),
rtc::Optional<int>(kFrameLengthMs),
UpdateNetworkMetrics(&controller, rtc::Optional<int>(kTargetBitrateBps),
rtc::Optional<size_t>(kOverheadBytesPerPacket));
CheckDecision(&controller, rtc::Optional<int>(kFrameLengthMs),
kBitrateBps + kPacketOverheadRateDiff);
}
@ -133,17 +176,17 @@ TEST(AnaBitrateControllerTest, DecreaseBitrateOnFrameLengthDecreased) {
constexpr int kBitrateBps =
kTargetBitrateBps -
kOverheadBytesPerPacket * 8 * 1000 / kInitialFrameLengthMs;
CheckDecision(&controller, rtc::Optional<int>(kTargetBitrateBps),
rtc::Optional<size_t>(kOverheadBytesPerPacket),
rtc::Optional<int>(), kBitrateBps);
UpdateNetworkMetrics(&controller, rtc::Optional<int>(kTargetBitrateBps),
rtc::Optional<size_t>(kOverheadBytesPerPacket));
CheckDecision(&controller, rtc::Optional<int>(), kBitrateBps);
constexpr int kFrameLengthMs = 20;
constexpr size_t kPacketOverheadRateDiff =
kOverheadBytesPerPacket * 8 * 1000 / 20 -
kOverheadBytesPerPacket * 8 * 1000 / 60;
CheckDecision(&controller, rtc::Optional<int>(kTargetBitrateBps),
rtc::Optional<size_t>(kOverheadBytesPerPacket),
rtc::Optional<int>(kFrameLengthMs),
UpdateNetworkMetrics(&controller, rtc::Optional<int>(kTargetBitrateBps),
rtc::Optional<size_t>(kOverheadBytesPerPacket));
CheckDecision(&controller, rtc::Optional<int>(kFrameLengthMs),
kBitrateBps - kPacketOverheadRateDiff);
}
@ -156,9 +199,9 @@ TEST(AnaBitrateControllerTest, BitrateNeverBecomesNegative) {
// Set a target rate smaller than overhead rate, the bitrate is bounded by 0.
constexpr int kTargetBitrateBps =
kOverheadBytesPerPacket * 8 * 1000 / kFrameLengthMs - 1;
CheckDecision(&controller, rtc::Optional<int>(kTargetBitrateBps),
rtc::Optional<size_t>(kOverheadBytesPerPacket),
rtc::Optional<int>(kFrameLengthMs), 0);
UpdateNetworkMetrics(&controller, rtc::Optional<int>(kTargetBitrateBps),
rtc::Optional<size_t>(kOverheadBytesPerPacket));
CheckDecision(&controller, rtc::Optional<int>(kFrameLengthMs), 0);
}
TEST(AnaBitrateControllerTest, CheckBehaviorOnChangingCondition) {
@ -173,39 +216,44 @@ TEST(AnaBitrateControllerTest, CheckBehaviorOnChangingCondition) {
int current_bitrate =
overall_bitrate - overhead_bytes_per_packet * 8 * 1000 / frame_length_ms;
CheckDecision(&controller, rtc::Optional<int>(overall_bitrate),
rtc::Optional<size_t>(overhead_bytes_per_packet),
rtc::Optional<int>(frame_length_ms), current_bitrate);
UpdateNetworkMetrics(&controller, rtc::Optional<int>(overall_bitrate),
rtc::Optional<size_t>(overhead_bytes_per_packet));
CheckDecision(&controller, rtc::Optional<int>(frame_length_ms),
current_bitrate);
// Next: increase overall bitrate.
overall_bitrate += 100;
current_bitrate += 100;
CheckDecision(&controller, rtc::Optional<int>(overall_bitrate),
rtc::Optional<size_t>(overhead_bytes_per_packet),
rtc::Optional<int>(frame_length_ms), current_bitrate);
UpdateNetworkMetrics(&controller, rtc::Optional<int>(overall_bitrate),
rtc::Optional<size_t>(overhead_bytes_per_packet));
CheckDecision(&controller, rtc::Optional<int>(frame_length_ms),
current_bitrate);
// Next: change frame length.
frame_length_ms = 60;
current_bitrate += overhead_bytes_per_packet * 8 * 1000 / 20 -
overhead_bytes_per_packet * 8 * 1000 / 60;
CheckDecision(&controller, rtc::Optional<int>(overall_bitrate),
rtc::Optional<size_t>(overhead_bytes_per_packet),
rtc::Optional<int>(frame_length_ms), current_bitrate);
UpdateNetworkMetrics(&controller, rtc::Optional<int>(overall_bitrate),
rtc::Optional<size_t>(overhead_bytes_per_packet));
CheckDecision(&controller, rtc::Optional<int>(frame_length_ms),
current_bitrate);
// Next: change overhead.
overhead_bytes_per_packet -= 30;
current_bitrate += 30 * 8 * 1000 / frame_length_ms;
CheckDecision(&controller, rtc::Optional<int>(overall_bitrate),
rtc::Optional<size_t>(overhead_bytes_per_packet),
rtc::Optional<int>(frame_length_ms), current_bitrate);
UpdateNetworkMetrics(&controller, rtc::Optional<int>(overall_bitrate),
rtc::Optional<size_t>(overhead_bytes_per_packet));
CheckDecision(&controller, rtc::Optional<int>(frame_length_ms),
current_bitrate);
// Next: change frame length.
frame_length_ms = 20;
current_bitrate -= overhead_bytes_per_packet * 8 * 1000 / 20 -
overhead_bytes_per_packet * 8 * 1000 / 60;
CheckDecision(&controller, rtc::Optional<int>(overall_bitrate),
rtc::Optional<size_t>(overhead_bytes_per_packet),
rtc::Optional<int>(frame_length_ms), current_bitrate);
UpdateNetworkMetrics(&controller, rtc::Optional<int>(overall_bitrate),
rtc::Optional<size_t>(overhead_bytes_per_packet));
CheckDecision(&controller, rtc::Optional<int>(frame_length_ms),
current_bitrate);
// Next: decrease overall bitrate and frame length.
overall_bitrate -= 100;
@ -214,9 +262,10 @@ TEST(AnaBitrateControllerTest, CheckBehaviorOnChangingCondition) {
current_bitrate += overhead_bytes_per_packet * 8 * 1000 / 20 -
overhead_bytes_per_packet * 8 * 1000 / 60;
CheckDecision(&controller, rtc::Optional<int>(overall_bitrate),
rtc::Optional<size_t>(overhead_bytes_per_packet),
rtc::Optional<int>(frame_length_ms), current_bitrate);
UpdateNetworkMetrics(&controller, rtc::Optional<int>(overall_bitrate),
rtc::Optional<size_t>(overhead_bytes_per_packet));
CheckDecision(&controller, rtc::Optional<int>(frame_length_ms),
current_bitrate);
}
} // namespace audio_network_adaptor

View File

@ -33,19 +33,25 @@ ChannelController::ChannelController(const Config& config)
config_.intial_channels_to_encode);
}
ChannelController::~ChannelController() = default;
void ChannelController::UpdateNetworkMetrics(
const NetworkMetrics& network_metrics) {
if (network_metrics.uplink_bandwidth_bps)
uplink_bandwidth_bps_ = network_metrics.uplink_bandwidth_bps;
}
void ChannelController::MakeDecision(
const NetworkMetrics& metrics,
AudioNetworkAdaptor::EncoderRuntimeConfig* config) {
// Decision on |num_channels| should not have been made.
RTC_DCHECK(!config->num_channels);
if (metrics.uplink_bandwidth_bps) {
if (uplink_bandwidth_bps_) {
if (channels_to_encode_ == 2 &&
*metrics.uplink_bandwidth_bps <= config_.channel_2_to_1_bandwidth_bps) {
*uplink_bandwidth_bps_ <= config_.channel_2_to_1_bandwidth_bps) {
channels_to_encode_ = 1;
} else if (channels_to_encode_ == 1 &&
*metrics.uplink_bandwidth_bps >=
config_.channel_1_to_2_bandwidth_bps) {
*uplink_bandwidth_bps_ >= config_.channel_1_to_2_bandwidth_bps) {
channels_to_encode_ =
std::min(static_cast<size_t>(2), config_.num_encoder_channels);
}

View File

@ -35,12 +35,16 @@ class ChannelController final : public Controller {
explicit ChannelController(const Config& config);
void MakeDecision(const NetworkMetrics& metrics,
AudioNetworkAdaptor::EncoderRuntimeConfig* config) override;
~ChannelController() override;
void UpdateNetworkMetrics(const NetworkMetrics& network_metrics) override;
void MakeDecision(AudioNetworkAdaptor::EncoderRuntimeConfig* config) override;
private:
const Config config_;
size_t channels_to_encode_;
rtc::Optional<int> uplink_bandwidth_bps_;
RTC_DISALLOW_COPY_AND_ASSIGN(ChannelController);
};

View File

@ -32,10 +32,15 @@ std::unique_ptr<ChannelController> CreateChannelController(int init_channels) {
}
void CheckDecision(ChannelController* controller,
const Controller::NetworkMetrics& metrics,
const rtc::Optional<int>& uplink_bandwidth_bps,
size_t expected_num_channels) {
if (uplink_bandwidth_bps) {
Controller::NetworkMetrics network_metrics;
network_metrics.uplink_bandwidth_bps = uplink_bandwidth_bps;
controller->UpdateNetworkMetrics(network_metrics);
}
AudioNetworkAdaptor::EncoderRuntimeConfig config;
controller->MakeDecision(metrics, &config);
controller->MakeDecision(&config);
EXPECT_EQ(rtc::Optional<size_t>(expected_num_channels), config.num_channels);
}
@ -44,70 +49,56 @@ void CheckDecision(ChannelController* controller,
TEST(ChannelControllerTest, OutputInitValueWhenUplinkBandwidthUnknown) {
constexpr int kInitChannels = 2;
auto controller = CreateChannelController(kInitChannels);
Controller::NetworkMetrics metrics;
CheckDecision(controller.get(), metrics, kInitChannels);
CheckDecision(controller.get(), rtc::Optional<int>(), kInitChannels);
}
TEST(ChannelControllerTest, SwitchTo2ChannelsOnHighUplinkBandwidth) {
constexpr int kInitChannels = 1;
auto controller = CreateChannelController(kInitChannels);
Controller::NetworkMetrics metrics;
// Use high bandwidth to check output switch to 2.
metrics.uplink_bandwidth_bps = rtc::Optional<int>(kChannel1To2BandwidthBps);
CheckDecision(controller.get(), metrics, 2);
CheckDecision(controller.get(), rtc::Optional<int>(kChannel1To2BandwidthBps),
2);
}
TEST(ChannelControllerTest, SwitchTo1ChannelOnLowUplinkBandwidth) {
constexpr int kInitChannels = 2;
auto controller = CreateChannelController(kInitChannels);
Controller::NetworkMetrics metrics;
// Use low bandwidth to check output switch to 1.
metrics.uplink_bandwidth_bps = rtc::Optional<int>(kChannel2To1BandwidthBps);
CheckDecision(controller.get(), metrics, 1);
CheckDecision(controller.get(), rtc::Optional<int>(kChannel2To1BandwidthBps),
1);
}
TEST(ChannelControllerTest, Maintain1ChannelOnMediumUplinkBandwidth) {
constexpr int kInitChannels = 1;
auto controller = CreateChannelController(kInitChannels);
Controller::NetworkMetrics metrics;
// Use between-thresholds bandwidth to check output remains at 1.
metrics.uplink_bandwidth_bps = rtc::Optional<int>(kMediumBandwidthBps);
CheckDecision(controller.get(), metrics, 1);
CheckDecision(controller.get(), rtc::Optional<int>(kMediumBandwidthBps), 1);
}
TEST(ChannelControllerTest, Maintain2ChannelsOnMediumUplinkBandwidth) {
constexpr int kInitChannels = 2;
auto controller = CreateChannelController(kInitChannels);
Controller::NetworkMetrics metrics;
// Use between-thresholds bandwidth to check output remains at 2.
metrics.uplink_bandwidth_bps = rtc::Optional<int>(kMediumBandwidthBps);
CheckDecision(controller.get(), metrics, 2);
CheckDecision(controller.get(), rtc::Optional<int>(kMediumBandwidthBps), 2);
}
TEST(ChannelControllerTest, CheckBehaviorOnChangingUplinkBandwidth) {
constexpr int kInitChannels = 1;
auto controller = CreateChannelController(kInitChannels);
Controller::NetworkMetrics metrics;
// Use between-thresholds bandwidth to check output remains at 1.
metrics.uplink_bandwidth_bps = rtc::Optional<int>(kMediumBandwidthBps);
CheckDecision(controller.get(), metrics, 1);
CheckDecision(controller.get(), rtc::Optional<int>(kMediumBandwidthBps), 1);
// Use high bandwidth to check output switch to 2.
metrics.uplink_bandwidth_bps = rtc::Optional<int>(kChannel1To2BandwidthBps);
CheckDecision(controller.get(), metrics, 2);
CheckDecision(controller.get(), rtc::Optional<int>(kChannel1To2BandwidthBps),
2);
// Use between-thresholds bandwidth to check output remains at 2.
metrics.uplink_bandwidth_bps = rtc::Optional<int>(kMediumBandwidthBps);
CheckDecision(controller.get(), metrics, 2);
CheckDecision(controller.get(), rtc::Optional<int>(kMediumBandwidthBps), 2);
// Use low bandwidth to check output switch to 1.
metrics.uplink_bandwidth_bps = rtc::Optional<int>(kChannel2To1BandwidthBps);
CheckDecision(controller.get(), metrics, 1);
CheckDecision(controller.get(), rtc::Optional<int>(kChannel2To1BandwidthBps),
1);
}
} // namespace webrtc

View File

@ -30,8 +30,11 @@ class Controller {
virtual ~Controller() = default;
// Informs network metrics update to this controller. Any non-empty field
// indicates an update on the corresponding network metric.
virtual void UpdateNetworkMetrics(const NetworkMetrics& network_metrics) = 0;
virtual void MakeDecision(
const NetworkMetrics& metrics,
AudioNetworkAdaptor::EncoderRuntimeConfig* config) = 0;
};

View File

@ -299,14 +299,13 @@ void CheckControllersOrder(const std::vector<Controller*>& controllers,
// We also check that the controllers follow the initial settings.
AudioNetworkAdaptor::EncoderRuntimeConfig encoder_config;
// We do not check the internal logic of controllers. We only check that
// when no network metrics are known, controllers provide the initial values.
Controller::NetworkMetrics metrics;
for (size_t i = 0; i < controllers.size(); ++i) {
AudioNetworkAdaptor::EncoderRuntimeConfig encoder_config;
// We check the order of |controllers| by judging their decisions.
controllers[i]->MakeDecision(metrics, &encoder_config);
controllers[i]->MakeDecision(&encoder_config);
// Since controllers are not provided with network metrics, they give the
// initial values.
switch (expected_types[i]) {
case ControllerType::FEC:
EXPECT_EQ(rtc::Optional<bool>(kInitialFecEnabled),

View File

@ -23,19 +23,25 @@ DtxController::Config::Config(bool initial_dtx_enabled,
DtxController::DtxController(const Config& config)
: config_(config), dtx_enabled_(config_.initial_dtx_enabled) {}
DtxController::~DtxController() = default;
void DtxController::UpdateNetworkMetrics(
const NetworkMetrics& network_metrics) {
if (network_metrics.uplink_bandwidth_bps)
uplink_bandwidth_bps_ = network_metrics.uplink_bandwidth_bps;
}
void DtxController::MakeDecision(
const NetworkMetrics& metrics,
AudioNetworkAdaptor::EncoderRuntimeConfig* config) {
// Decision on |enable_dtx| should not have been made.
RTC_DCHECK(!config->enable_dtx);
if (metrics.uplink_bandwidth_bps) {
if (uplink_bandwidth_bps_) {
if (dtx_enabled_ &&
*metrics.uplink_bandwidth_bps >= config_.dtx_disabling_bandwidth_bps) {
*uplink_bandwidth_bps_ >= config_.dtx_disabling_bandwidth_bps) {
dtx_enabled_ = false;
} else if (!dtx_enabled_ &&
*metrics.uplink_bandwidth_bps <=
config_.dtx_enabling_bandwidth_bps) {
*uplink_bandwidth_bps_ <= config_.dtx_enabling_bandwidth_bps) {
dtx_enabled_ = true;
}
}

View File

@ -31,12 +31,16 @@ class DtxController final : public Controller {
explicit DtxController(const Config& config);
void MakeDecision(const NetworkMetrics& metrics,
AudioNetworkAdaptor::EncoderRuntimeConfig* config) override;
~DtxController() override;
void UpdateNetworkMetrics(const NetworkMetrics& network_metrics) override;
void MakeDecision(AudioNetworkAdaptor::EncoderRuntimeConfig* config) override;
private:
const Config config_;
bool dtx_enabled_;
rtc::Optional<int> uplink_bandwidth_bps_;
RTC_DISALLOW_COPY_AND_ASSIGN(DtxController);
};

View File

@ -32,10 +32,13 @@ std::unique_ptr<DtxController> CreateController(int initial_dtx_enabled) {
void CheckDecision(DtxController* controller,
const rtc::Optional<int>& uplink_bandwidth_bps,
bool expected_dtx_enabled) {
if (uplink_bandwidth_bps) {
Controller::NetworkMetrics network_metrics;
network_metrics.uplink_bandwidth_bps = uplink_bandwidth_bps;
controller->UpdateNetworkMetrics(network_metrics);
}
AudioNetworkAdaptor::EncoderRuntimeConfig config;
Controller::NetworkMetrics metrics;
metrics.uplink_bandwidth_bps = uplink_bandwidth_bps;
controller->MakeDecision(metrics, &config);
controller->MakeDecision(&config);
EXPECT_EQ(rtc::Optional<bool>(expected_dtx_enabled), config.enable_dtx);
}

View File

@ -37,11 +37,11 @@ FecController::Config::Config(bool initial_fec_enabled,
time_constant_ms(time_constant_ms),
clock(clock) {}
FecController::FecController(const Config& config)
FecController::FecController(const Config& config,
std::unique_ptr<SmoothingFilter> smoothing_filter)
: config_(config),
fec_enabled_(config.initial_fec_enabled),
packet_loss_smoothed_(
new SmoothingFilterImpl(config_.time_constant_ms, config_.clock)),
packet_loss_smoother_(std::move(smoothing_filter)),
fec_enabling_threshold_info_(config_.fec_enabling_threshold),
fec_disabling_threshold_info_(config_.fec_disabling_threshold) {
RTC_DCHECK_LE(fec_enabling_threshold_info_.slope, 0);
@ -58,33 +58,39 @@ FecController::FecController(const Config& config)
config_.fec_enabling_threshold.high_bandwidth_packet_loss);
}
FecController::FecController(const Config& config,
std::unique_ptr<SmoothingFilter> smoothing_filter)
: FecController(config) {
packet_loss_smoothed_ = std::move(smoothing_filter);
FecController::FecController(const Config& config)
: FecController(
config,
std::unique_ptr<SmoothingFilter>(
new SmoothingFilterImpl(config.time_constant_ms, config.clock))) {
}
FecController::~FecController() = default;
void FecController::UpdateNetworkMetrics(
const NetworkMetrics& network_metrics) {
if (network_metrics.uplink_bandwidth_bps)
uplink_bandwidth_bps_ = network_metrics.uplink_bandwidth_bps;
if (network_metrics.uplink_packet_loss_fraction) {
packet_loss_smoother_->AddSample(
*network_metrics.uplink_packet_loss_fraction);
}
}
void FecController::MakeDecision(
const NetworkMetrics& metrics,
AudioNetworkAdaptor::EncoderRuntimeConfig* config) {
RTC_DCHECK(!config->enable_fec);
RTC_DCHECK(!config->uplink_packet_loss_fraction);
if (metrics.uplink_packet_loss_fraction)
packet_loss_smoothed_->AddSample(*metrics.uplink_packet_loss_fraction);
const auto& packet_loss = packet_loss_smoother_->GetAverage();
const auto& packet_loss = packet_loss_smoothed_->GetAverage();
fec_enabled_ = fec_enabled_ ? !FecDisablingDecision(metrics, packet_loss)
: FecEnablingDecision(metrics, packet_loss);
fec_enabled_ = fec_enabled_ ? !FecDisablingDecision(packet_loss)
: FecEnablingDecision(packet_loss);
config->enable_fec = rtc::Optional<bool>(fec_enabled_);
auto packet_loss_fraction = packet_loss_smoothed_->GetAverage();
config->uplink_packet_loss_fraction = rtc::Optional<float>(
packet_loss_fraction ? *packet_loss_fraction : 0.0);
config->uplink_packet_loss_fraction =
rtc::Optional<float>(packet_loss ? *packet_loss : 0.0);
}
FecController::ThresholdInfo::ThresholdInfo(
@ -110,25 +116,23 @@ float FecController::GetPacketLossThreshold(
}
bool FecController::FecEnablingDecision(
const NetworkMetrics& metrics,
const rtc::Optional<float>& packet_loss) const {
if (!metrics.uplink_bandwidth_bps)
if (!uplink_bandwidth_bps_)
return false;
if (!packet_loss)
return false;
return *packet_loss >= GetPacketLossThreshold(*metrics.uplink_bandwidth_bps,
return *packet_loss >= GetPacketLossThreshold(*uplink_bandwidth_bps_,
config_.fec_enabling_threshold,
fec_enabling_threshold_info_);
}
bool FecController::FecDisablingDecision(
const NetworkMetrics& metrics,
const rtc::Optional<float>& packet_loss) const {
if (!metrics.uplink_bandwidth_bps)
if (!uplink_bandwidth_bps_)
return false;
if (!packet_loss)
return false;
return *packet_loss <= GetPacketLossThreshold(*metrics.uplink_bandwidth_bps,
return *packet_loss <= GetPacketLossThreshold(*uplink_bandwidth_bps_,
config_.fec_disabling_threshold,
fec_disabling_threshold_info_);
}

View File

@ -64,16 +64,17 @@ class FecController final : public Controller {
const Clock* clock;
};
explicit FecController(const Config& config);
// Dependency injection for testing.
FecController(const Config& config,
std::unique_ptr<SmoothingFilter> smoothing_filter);
explicit FecController(const Config& config);
~FecController() override;
void MakeDecision(const NetworkMetrics& metrics,
AudioNetworkAdaptor::EncoderRuntimeConfig* config) override;
void UpdateNetworkMetrics(const NetworkMetrics& network_metrics) override;
void MakeDecision(AudioNetworkAdaptor::EncoderRuntimeConfig* config) override;
private:
// Characterize Threshold with packet_loss = slope * bandwidth + offset.
@ -87,14 +88,13 @@ class FecController final : public Controller {
const Config::Threshold& threshold,
const ThresholdInfo& threshold_info) const;
bool FecEnablingDecision(const NetworkMetrics& metrics,
const rtc::Optional<float>& packet_loss) const;
bool FecDisablingDecision(const NetworkMetrics& metrics,
const rtc::Optional<float>& packet_loss) const;
bool FecEnablingDecision(const rtc::Optional<float>& packet_loss) const;
bool FecDisablingDecision(const rtc::Optional<float>& packet_loss) const;
const Config config_;
bool fec_enabled_;
std::unique_ptr<SmoothingFilter> packet_loss_smoothed_;
rtc::Optional<int> uplink_bandwidth_bps_;
const std::unique_ptr<SmoothingFilter> packet_loss_smoother_;
const ThresholdInfo fec_enabling_threshold_info_;
const ThresholdInfo fec_disabling_threshold_info_;

View File

@ -47,14 +47,14 @@ constexpr float kEnablingPacketLossAtHighBw = 0.05f;
struct FecControllerStates {
std::unique_ptr<FecController> controller;
MockSmoothingFilter* packet_loss_smoothed;
MockSmoothingFilter* packet_loss_smoother;
};
FecControllerStates CreateFecController(bool initial_fec_enabled) {
FecControllerStates states;
std::unique_ptr<MockSmoothingFilter> mock_smoothing_filter(
new NiceMock<MockSmoothingFilter>());
states.packet_loss_smoothed = mock_smoothing_filter.get();
states.packet_loss_smoother = mock_smoothing_filter.get();
using Threshold = FecController::Config::Threshold;
states.controller.reset(new FecController(
FecController::Config(
@ -68,32 +68,38 @@ FecControllerStates CreateFecController(bool initial_fec_enabled) {
return states;
}
// Checks that the FEC decision given by |states->controller->MakeDecision|
// matches |expected_enable_fec|. It also checks that
// |uplink_packet_loss_fraction| returned by |states->controller->MakeDecision|
// matches |uplink_packet_loss|.
void CheckDecision(FecControllerStates* states,
const rtc::Optional<int>& uplink_bandwidth_bps,
const rtc::Optional<float>& uplink_packet_loss,
bool expected_enable_fec) {
Controller::NetworkMetrics metrics;
metrics.uplink_bandwidth_bps = uplink_bandwidth_bps;
metrics.uplink_packet_loss_fraction = uplink_packet_loss;
if (uplink_packet_loss) {
// Check that smoothing filter is updated.
EXPECT_CALL(*states->packet_loss_smoothed, AddSample(*uplink_packet_loss));
void UpdateNetworkMetrics(FecControllerStates* states,
const rtc::Optional<int>& uplink_bandwidth_bps,
const rtc::Optional<float>& uplink_packet_loss) {
// UpdateNetworkMetrics can accept multiple network metric updates at once.
// However, currently, the most used case is to update one metric at a time.
// To reflect this fact, we separate the calls.
if (uplink_bandwidth_bps) {
Controller::NetworkMetrics network_metrics;
network_metrics.uplink_bandwidth_bps = uplink_bandwidth_bps;
states->controller->UpdateNetworkMetrics(network_metrics);
}
if (uplink_packet_loss) {
Controller::NetworkMetrics network_metrics;
network_metrics.uplink_packet_loss_fraction = uplink_packet_loss;
EXPECT_CALL(*states->packet_loss_smoother, AddSample(*uplink_packet_loss));
states->controller->UpdateNetworkMetrics(network_metrics);
// This is called during CheckDecision().
EXPECT_CALL(*states->packet_loss_smoother, GetAverage())
.WillOnce(Return(rtc::Optional<float>(*uplink_packet_loss)));
}
}
EXPECT_CALL(*states->packet_loss_smoothed, GetAverage())
.WillRepeatedly(Return(uplink_packet_loss));
// Checks that the FEC decision and |uplink_packet_loss_fraction| given by
// |states->controller->MakeDecision| matches |expected_enable_fec| and
// |expected_uplink_packet_loss_fraction|, respectively.
void CheckDecision(FecControllerStates* states,
bool expected_enable_fec,
float expected_uplink_packet_loss_fraction) {
AudioNetworkAdaptor::EncoderRuntimeConfig config;
states->controller->MakeDecision(metrics, &config);
states->controller->MakeDecision(&config);
EXPECT_EQ(rtc::Optional<bool>(expected_enable_fec), config.enable_fec);
// Check that |config.uplink_packet_loss_fraction| is properly filled.
EXPECT_EQ(uplink_packet_loss ? uplink_packet_loss : rtc::Optional<float>(0.0),
EXPECT_EQ(rtc::Optional<float>(expected_uplink_packet_loss_fraction),
config.uplink_packet_loss_fraction);
}
@ -104,9 +110,9 @@ TEST(FecControllerTest, OutputInitValueWhenUplinkBandwidthUnknown) {
auto states = CreateFecController(kInitialFecEnabled);
// Let uplink packet loss fraction be so low that would cause FEC to turn off
// if uplink bandwidth was known.
CheckDecision(&states, rtc::Optional<int>(),
rtc::Optional<float>(kDisablingPacketLossAtHighBw),
kInitialFecEnabled);
UpdateNetworkMetrics(&states, rtc::Optional<int>(),
rtc::Optional<float>(kDisablingPacketLossAtHighBw));
CheckDecision(&states, kInitialFecEnabled, kDisablingPacketLossAtHighBw);
}
TEST(FecControllerTest, OutputInitValueWhenUplinkPacketLossFractionUnknown) {
@ -114,109 +120,143 @@ TEST(FecControllerTest, OutputInitValueWhenUplinkPacketLossFractionUnknown) {
auto states = CreateFecController(kInitialFecEnabled);
// Let uplink bandwidth be so low that would cause FEC to turn off if uplink
// bandwidth packet loss fraction was known.
CheckDecision(&states, rtc::Optional<int>(kDisablingBandwidthLow - 1),
rtc::Optional<float>(), kInitialFecEnabled);
UpdateNetworkMetrics(&states, rtc::Optional<int>(kDisablingBandwidthLow - 1),
rtc::Optional<float>());
CheckDecision(&states, kInitialFecEnabled, 0.0);
}
TEST(FecControllerTest, EnableFecForHighBandwidth) {
auto states = CreateFecController(false);
CheckDecision(&states, rtc::Optional<int>(kEnablingBandwidthHigh),
rtc::Optional<float>(kEnablingPacketLossAtHighBw), true);
UpdateNetworkMetrics(&states, rtc::Optional<int>(kEnablingBandwidthHigh),
rtc::Optional<float>(kEnablingPacketLossAtHighBw));
CheckDecision(&states, true, kEnablingPacketLossAtHighBw);
}
TEST(FecControllerTest, UpdateMultipleNetworkMetricsAtOnce) {
// This test is similar to EnableFecForHighBandwidth. But instead of
// using ::UpdateNetworkMetrics(...), which calls
// FecController::UpdateNetworkMetrics(...) multiple times, we
// we call it only once. This is to verify that
// FecController::UpdateNetworkMetrics(...) can handle multiple
// network updates at once. This is, however, not a common use case in current
// audio_network_adaptor_impl.cc.
auto states = CreateFecController(false);
Controller::NetworkMetrics network_metrics;
network_metrics.uplink_bandwidth_bps =
rtc::Optional<int>(kEnablingBandwidthHigh);
network_metrics.uplink_packet_loss_fraction =
rtc::Optional<float>(kEnablingPacketLossAtHighBw);
EXPECT_CALL(*states.packet_loss_smoother, GetAverage())
.WillOnce(Return(rtc::Optional<float>(kEnablingPacketLossAtHighBw)));
states.controller->UpdateNetworkMetrics(network_metrics);
CheckDecision(&states, true, kEnablingPacketLossAtHighBw);
}
TEST(FecControllerTest, MaintainFecOffForHighBandwidth) {
auto states = CreateFecController(false);
CheckDecision(&states, rtc::Optional<int>(kEnablingBandwidthHigh),
rtc::Optional<float>(kEnablingPacketLossAtHighBw * 0.99f),
false);
constexpr float kPacketLoss = kEnablingPacketLossAtHighBw * 0.99f;
UpdateNetworkMetrics(&states, rtc::Optional<int>(kEnablingBandwidthHigh),
rtc::Optional<float>(kPacketLoss));
CheckDecision(&states, false, kPacketLoss);
}
TEST(FecControllerTest, EnableFecForMediumBandwidth) {
auto states = CreateFecController(false);
CheckDecision(
constexpr float kPacketLoss =
(kEnablingPacketLossAtLowBw + kEnablingPacketLossAtHighBw) / 2.0;
UpdateNetworkMetrics(
&states,
rtc::Optional<int>((kEnablingBandwidthHigh + kEnablingBandwidthLow) / 2),
rtc::Optional<float>(
(kEnablingPacketLossAtLowBw + kEnablingPacketLossAtHighBw) / 2.0),
true);
rtc::Optional<float>(kPacketLoss));
CheckDecision(&states, true, kPacketLoss);
}
TEST(FecControllerTest, MaintainFecOffForMediumBandwidth) {
auto states = CreateFecController(false);
CheckDecision(
constexpr float kPacketLoss =
kEnablingPacketLossAtLowBw * 0.49f + kEnablingPacketLossAtHighBw * 0.51f;
UpdateNetworkMetrics(
&states,
rtc::Optional<int>((kEnablingBandwidthHigh + kEnablingBandwidthLow) / 2),
rtc::Optional<float>(kEnablingPacketLossAtLowBw * 0.49f +
kEnablingPacketLossAtHighBw * 0.51f),
false);
rtc::Optional<float>(kPacketLoss));
CheckDecision(&states, false, kPacketLoss);
}
TEST(FecControllerTest, EnableFecForLowBandwidth) {
auto states = CreateFecController(false);
CheckDecision(&states, rtc::Optional<int>(kEnablingBandwidthLow),
rtc::Optional<float>(kEnablingPacketLossAtLowBw), true);
UpdateNetworkMetrics(&states, rtc::Optional<int>(kEnablingBandwidthLow),
rtc::Optional<float>(kEnablingPacketLossAtLowBw));
CheckDecision(&states, true, kEnablingPacketLossAtLowBw);
}
TEST(FecControllerTest, MaintainFecOffForLowBandwidth) {
auto states = CreateFecController(false);
CheckDecision(&states, rtc::Optional<int>(kEnablingBandwidthLow),
rtc::Optional<float>(kEnablingPacketLossAtLowBw * 0.99f),
false);
constexpr float kPacketLoss = kEnablingPacketLossAtLowBw * 0.99f;
UpdateNetworkMetrics(&states, rtc::Optional<int>(kEnablingBandwidthLow),
rtc::Optional<float>(kPacketLoss));
CheckDecision(&states, false, kPacketLoss);
}
TEST(FecControllerTest, MaintainFecOffForVeryLowBandwidth) {
auto states = CreateFecController(false);
// Below |kEnablingBandwidthLow|, no packet loss fraction can cause FEC to
// turn on.
CheckDecision(&states, rtc::Optional<int>(kEnablingBandwidthLow - 1),
rtc::Optional<float>(1.0), false);
UpdateNetworkMetrics(&states, rtc::Optional<int>(kEnablingBandwidthLow - 1),
rtc::Optional<float>(1.0));
CheckDecision(&states, false, 1.0);
}
TEST(FecControllerTest, DisableFecForHighBandwidth) {
auto states = CreateFecController(true);
CheckDecision(&states, rtc::Optional<int>(kDisablingBandwidthHigh),
rtc::Optional<float>(kDisablingPacketLossAtHighBw), false);
UpdateNetworkMetrics(&states, rtc::Optional<int>(kDisablingBandwidthHigh),
rtc::Optional<float>(kDisablingPacketLossAtHighBw));
CheckDecision(&states, false, kDisablingPacketLossAtHighBw);
}
TEST(FecControllerTest, MaintainFecOnForHighBandwidth) {
auto states = CreateFecController(true);
CheckDecision(&states, rtc::Optional<int>(kDisablingBandwidthHigh),
rtc::Optional<float>(kDisablingPacketLossAtHighBw * 1.01f),
true);
constexpr float kPacketLoss = kDisablingPacketLossAtHighBw * 1.01f;
UpdateNetworkMetrics(&states, rtc::Optional<int>(kDisablingBandwidthHigh),
rtc::Optional<float>(kPacketLoss));
CheckDecision(&states, true, kPacketLoss);
}
TEST(FecControllerTest, DisableFecOnMediumBandwidth) {
auto states = CreateFecController(true);
CheckDecision(
constexpr float kPacketLoss =
(kDisablingPacketLossAtLowBw + kDisablingPacketLossAtHighBw) / 2.0f;
UpdateNetworkMetrics(
&states, rtc::Optional<int>(
(kDisablingBandwidthHigh + kDisablingBandwidthLow) / 2),
rtc::Optional<float>(
(kDisablingPacketLossAtLowBw + kDisablingPacketLossAtHighBw) / 2.0f),
false);
rtc::Optional<float>(kPacketLoss));
CheckDecision(&states, false, kPacketLoss);
}
TEST(FecControllerTest, MaintainFecOnForMediumBandwidth) {
auto states = CreateFecController(true);
CheckDecision(
constexpr float kPacketLoss = kDisablingPacketLossAtLowBw * 0.51f +
kDisablingPacketLossAtHighBw * 0.49f;
UpdateNetworkMetrics(
&states,
rtc::Optional<int>((kEnablingBandwidthHigh + kDisablingBandwidthLow) / 2),
rtc::Optional<float>(kDisablingPacketLossAtLowBw * 0.51f +
kDisablingPacketLossAtHighBw * 0.49f),
true);
rtc::Optional<float>(kPacketLoss));
CheckDecision(&states, true, kPacketLoss);
}
TEST(FecControllerTest, DisableFecForLowBandwidth) {
auto states = CreateFecController(true);
CheckDecision(&states, rtc::Optional<int>(kDisablingBandwidthLow),
rtc::Optional<float>(kDisablingPacketLossAtLowBw), false);
UpdateNetworkMetrics(&states, rtc::Optional<int>(kDisablingBandwidthLow),
rtc::Optional<float>(kDisablingPacketLossAtLowBw));
CheckDecision(&states, false, kDisablingPacketLossAtLowBw);
}
TEST(FecControllerTest, DisableFecForVeryLowBandwidth) {
auto states = CreateFecController(true);
// Below |kEnablingBandwidthLow|, any packet loss fraction can cause FEC to
// turn off.
CheckDecision(&states, rtc::Optional<int>(kDisablingBandwidthLow - 1),
rtc::Optional<float>(1.0), false);
UpdateNetworkMetrics(&states, rtc::Optional<int>(kDisablingBandwidthLow - 1),
rtc::Optional<float>(1.0));
CheckDecision(&states, false, 1.0);
}
TEST(FecControllerTest, CheckBehaviorOnChangingNetworkMetrics) {
@ -229,18 +269,27 @@ TEST(FecControllerTest, CheckBehaviorOnChangingNetworkMetrics) {
// |---------5-------> bandwidth
auto states = CreateFecController(true);
CheckDecision(&states, rtc::Optional<int>(kDisablingBandwidthLow - 1),
rtc::Optional<float>(1.0), false);
CheckDecision(&states, rtc::Optional<int>(kEnablingBandwidthLow),
rtc::Optional<float>(kEnablingPacketLossAtLowBw * 0.99f),
false);
CheckDecision(&states, rtc::Optional<int>(kEnablingBandwidthHigh),
rtc::Optional<float>(kEnablingPacketLossAtHighBw), true);
CheckDecision(&states, rtc::Optional<int>(kDisablingBandwidthHigh),
rtc::Optional<float>(kDisablingPacketLossAtHighBw * 1.01f),
true);
CheckDecision(&states, rtc::Optional<int>(kDisablingBandwidthHigh + 1),
rtc::Optional<float>(0.0), false);
UpdateNetworkMetrics(&states, rtc::Optional<int>(kDisablingBandwidthLow - 1),
rtc::Optional<float>(1.0));
CheckDecision(&states, false, 1.0);
UpdateNetworkMetrics(
&states, rtc::Optional<int>(kEnablingBandwidthLow),
rtc::Optional<float>(kEnablingPacketLossAtLowBw * 0.99f));
CheckDecision(&states, false, kEnablingPacketLossAtLowBw * 0.99f);
UpdateNetworkMetrics(&states, rtc::Optional<int>(kEnablingBandwidthHigh),
rtc::Optional<float>(kEnablingPacketLossAtHighBw));
CheckDecision(&states, true, kEnablingPacketLossAtHighBw);
UpdateNetworkMetrics(
&states, rtc::Optional<int>(kDisablingBandwidthHigh),
rtc::Optional<float>(kDisablingPacketLossAtHighBw * 1.01f));
CheckDecision(&states, true, kDisablingPacketLossAtHighBw * 1.01f);
UpdateNetworkMetrics(&states, rtc::Optional<int>(kDisablingBandwidthHigh + 1),
rtc::Optional<float>(0.0));
CheckDecision(&states, false, 0.0);
}
TEST(FecControllerTest, CheckBehaviorOnSpecialCurves) {
@ -260,7 +309,7 @@ TEST(FecControllerTest, CheckBehaviorOnSpecialCurves) {
FecControllerStates states;
std::unique_ptr<MockSmoothingFilter> mock_smoothing_filter(
new NiceMock<MockSmoothingFilter>());
states.packet_loss_smoothed = mock_smoothing_filter.get();
states.packet_loss_smoother = mock_smoothing_filter.get();
using Threshold = FecController::Config::Threshold;
states.controller.reset(new FecController(
FecController::Config(
@ -271,18 +320,27 @@ TEST(FecControllerTest, CheckBehaviorOnSpecialCurves) {
0, nullptr),
std::move(mock_smoothing_filter)));
CheckDecision(&states, rtc::Optional<int>(kDisablingBandwidthLow - 1),
rtc::Optional<float>(1.0), false);
CheckDecision(&states, rtc::Optional<int>(kEnablingBandwidthLow),
rtc::Optional<float>(kEnablingPacketLossAtHighBw * 0.99f),
false);
CheckDecision(&states, rtc::Optional<int>(kEnablingBandwidthHigh),
rtc::Optional<float>(kEnablingPacketLossAtHighBw), true);
CheckDecision(&states, rtc::Optional<int>(kDisablingBandwidthHigh),
rtc::Optional<float>(kDisablingPacketLossAtHighBw * 1.01f),
true);
CheckDecision(&states, rtc::Optional<int>(kDisablingBandwidthHigh + 1),
rtc::Optional<float>(0.0), false);
UpdateNetworkMetrics(&states, rtc::Optional<int>(kDisablingBandwidthLow - 1),
rtc::Optional<float>(1.0));
CheckDecision(&states, false, 1.0);
UpdateNetworkMetrics(
&states, rtc::Optional<int>(kEnablingBandwidthLow),
rtc::Optional<float>(kEnablingPacketLossAtHighBw * 0.99f));
CheckDecision(&states, false, kEnablingPacketLossAtHighBw * 0.99f);
UpdateNetworkMetrics(&states, rtc::Optional<int>(kEnablingBandwidthHigh),
rtc::Optional<float>(kEnablingPacketLossAtHighBw));
CheckDecision(&states, true, kEnablingPacketLossAtHighBw);
UpdateNetworkMetrics(
&states, rtc::Optional<int>(kDisablingBandwidthHigh),
rtc::Optional<float>(kDisablingPacketLossAtHighBw * 1.01f));
CheckDecision(&states, true, kDisablingPacketLossAtHighBw * 1.01f);
UpdateNetworkMetrics(&states, rtc::Optional<int>(kDisablingBandwidthHigh + 1),
rtc::Optional<float>(0.0));
CheckDecision(&states, false, 0.0);
}
#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
@ -290,7 +348,7 @@ TEST(FecControllerDeathTest, InvalidConfig) {
FecControllerStates states;
std::unique_ptr<MockSmoothingFilter> mock_smoothing_filter(
new NiceMock<MockSmoothingFilter>());
states.packet_loss_smoothed = mock_smoothing_filter.get();
states.packet_loss_smoother = mock_smoothing_filter.get();
using Threshold = FecController::Config::Threshold;
EXPECT_DEATH(
states.controller.reset(new FecController(

View File

@ -51,15 +51,22 @@ FrameLengthController::FrameLengthController(const Config& config)
FrameLengthController::~FrameLengthController() = default;
void FrameLengthController::UpdateNetworkMetrics(
const NetworkMetrics& network_metrics) {
if (network_metrics.uplink_bandwidth_bps)
uplink_bandwidth_bps_ = network_metrics.uplink_bandwidth_bps;
if (network_metrics.uplink_packet_loss_fraction)
uplink_packet_loss_fraction_ = network_metrics.uplink_packet_loss_fraction;
}
void FrameLengthController::MakeDecision(
const NetworkMetrics& metrics,
AudioNetworkAdaptor::EncoderRuntimeConfig* config) {
// Decision on |frame_length_ms| should not have been made.
RTC_DCHECK(!config->frame_length_ms);
if (FrameLengthIncreasingDecision(metrics, *config)) {
if (FrameLengthIncreasingDecision(*config)) {
++frame_length_ms_;
} else if (FrameLengthDecreasingDecision(metrics, *config)) {
} else if (FrameLengthDecreasingDecision(*config)) {
--frame_length_ms_;
}
config->frame_length_ms = rtc::Optional<int>(*frame_length_ms_);
@ -81,7 +88,6 @@ bool FrameLengthController::FrameLengthChange::operator<(
}
bool FrameLengthController::FrameLengthIncreasingDecision(
const NetworkMetrics& metrics,
const AudioNetworkAdaptor::EncoderRuntimeConfig& config) const {
// Increase frame length if
// 1. longer frame length is available AND
@ -99,16 +105,15 @@ bool FrameLengthController::FrameLengthIncreasingDecision(
if (increase_threshold == frame_length_change_criteria_.end())
return false;
return (metrics.uplink_bandwidth_bps &&
*metrics.uplink_bandwidth_bps <= increase_threshold->second) &&
(metrics.uplink_packet_loss_fraction &&
*metrics.uplink_packet_loss_fraction <=
return (uplink_bandwidth_bps_ &&
*uplink_bandwidth_bps_ <= increase_threshold->second) &&
(uplink_packet_loss_fraction_ &&
*uplink_packet_loss_fraction_ <=
config_.fl_increasing_packet_loss_fraction) &&
!config.enable_fec.value_or(false);
}
bool FrameLengthController::FrameLengthDecreasingDecision(
const NetworkMetrics& metrics,
const AudioNetworkAdaptor::EncoderRuntimeConfig& config) const {
// Decrease frame length if
// 1. shorter frame length is available AND one or more of the followings:
@ -125,10 +130,10 @@ bool FrameLengthController::FrameLengthDecreasingDecision(
if (decrease_threshold == frame_length_change_criteria_.end())
return false;
return (metrics.uplink_bandwidth_bps &&
*metrics.uplink_bandwidth_bps >= decrease_threshold->second) ||
(metrics.uplink_packet_loss_fraction &&
*metrics.uplink_packet_loss_fraction >=
return (uplink_bandwidth_bps_ &&
*uplink_bandwidth_bps_ >= decrease_threshold->second) ||
(uplink_packet_loss_fraction_ &&
*uplink_packet_loss_fraction_ >=
config_.fl_decreasing_packet_loss_fraction) ||
config.enable_fec.value_or(false);
}

View File

@ -49,8 +49,9 @@ class FrameLengthController final : public Controller {
~FrameLengthController() override;
void MakeDecision(const NetworkMetrics& metrics,
AudioNetworkAdaptor::EncoderRuntimeConfig* config) override;
void UpdateNetworkMetrics(const NetworkMetrics& network_metrics) override;
void MakeDecision(AudioNetworkAdaptor::EncoderRuntimeConfig* config) override;
private:
friend class FrameLengthControllerForTest;
@ -64,11 +65,9 @@ class FrameLengthController final : public Controller {
};
bool FrameLengthIncreasingDecision(
const NetworkMetrics& metrics,
const AudioNetworkAdaptor::EncoderRuntimeConfig& config) const;
bool FrameLengthDecreasingDecision(
const NetworkMetrics& metrics,
const AudioNetworkAdaptor::EncoderRuntimeConfig& config) const;
const Config config_;
@ -77,6 +76,10 @@ class FrameLengthController final : public Controller {
std::map<FrameLengthChange, int> frame_length_change_criteria_;
rtc::Optional<int> uplink_bandwidth_bps_;
rtc::Optional<float> uplink_packet_loss_fraction_;
RTC_DISALLOW_COPY_AND_ASSIGN(FrameLengthController);
};

View File

@ -38,17 +38,31 @@ std::unique_ptr<FrameLengthController> CreateController(
return controller;
}
void UpdateNetworkMetrics(
FrameLengthController* controller,
const rtc::Optional<int>& uplink_bandwidth_bps,
const rtc::Optional<float>& uplink_packet_loss_fraction) {
// UpdateNetworkMetrics can accept multiple network metric updates at once.
// However, currently, the most used case is to update one metric at a time.
// To reflect this fact, we separate the calls.
if (uplink_bandwidth_bps) {
Controller::NetworkMetrics network_metrics;
network_metrics.uplink_bandwidth_bps = uplink_bandwidth_bps;
controller->UpdateNetworkMetrics(network_metrics);
}
if (uplink_packet_loss_fraction) {
Controller::NetworkMetrics network_metrics;
network_metrics.uplink_packet_loss_fraction = uplink_packet_loss_fraction;
controller->UpdateNetworkMetrics(network_metrics);
}
}
void CheckDecision(FrameLengthController* controller,
const rtc::Optional<int>& uplink_bandwidth_bps,
const rtc::Optional<float>& uplink_packet_loss_fraction,
const rtc::Optional<bool>& enable_fec,
int expected_frame_length_ms) {
Controller::NetworkMetrics metrics;
metrics.uplink_bandwidth_bps = uplink_bandwidth_bps;
metrics.uplink_packet_loss_fraction = uplink_packet_loss_fraction;
AudioNetworkAdaptor::EncoderRuntimeConfig config;
config.enable_fec = enable_fec;
controller->MakeDecision(metrics, &config);
controller->MakeDecision(&config);
EXPECT_EQ(rtc::Optional<int>(expected_frame_length_ms),
config.frame_length_ms);
}
@ -57,21 +71,22 @@ void CheckDecision(FrameLengthController* controller,
TEST(FrameLengthControllerTest, DecreaseTo20MsOnHighUplinkBandwidth) {
auto controller = CreateController({20, 60}, 60);
CheckDecision(controller.get(), rtc::Optional<int>(kFl60msTo20msBandwidthBps),
rtc::Optional<float>(), rtc::Optional<bool>(), 20);
UpdateNetworkMetrics(controller.get(),
rtc::Optional<int>(kFl60msTo20msBandwidthBps),
rtc::Optional<float>());
CheckDecision(controller.get(), rtc::Optional<bool>(), 20);
}
TEST(FrameLengthControllerTest, DecreaseTo20MsOnHighUplinkPacketLossFraction) {
auto controller = CreateController({20, 60}, 60);
CheckDecision(controller.get(), rtc::Optional<int>(),
rtc::Optional<float>(kFlDecreasingPacketLossFraction),
rtc::Optional<bool>(), 20);
UpdateNetworkMetrics(controller.get(), rtc::Optional<int>(),
rtc::Optional<float>(kFlDecreasingPacketLossFraction));
CheckDecision(controller.get(), rtc::Optional<bool>(), 20);
}
TEST(FrameLengthControllerTest, DecreaseTo20MsWhenFecIsOn) {
auto controller = CreateController({20, 60}, 60);
CheckDecision(controller.get(), rtc::Optional<int>(), rtc::Optional<float>(),
rtc::Optional<bool>(true), 20);
CheckDecision(controller.get(), rtc::Optional<bool>(true), 20);
}
TEST(FrameLengthControllerTest,
@ -79,8 +94,7 @@ TEST(FrameLengthControllerTest,
auto controller = CreateController({60}, 60);
// Set FEC on that would cause frame length to decrease if receiver frame
// length range included 20ms.
CheckDecision(controller.get(), rtc::Optional<int>(), rtc::Optional<float>(),
rtc::Optional<bool>(true), 60);
CheckDecision(controller.get(), rtc::Optional<bool>(true), 60);
}
TEST(FrameLengthControllerTest, Maintain60MsOnMultipleConditions) {
@ -89,9 +103,10 @@ TEST(FrameLengthControllerTest, Maintain60MsOnMultipleConditions) {
// 2. |uplink_packet_loss_fraction| is at medium,
// 3. FEC is not decided ON.
auto controller = CreateController({20, 60}, 60);
CheckDecision(controller.get(), rtc::Optional<int>(kMediumBandwidthBps),
rtc::Optional<float>(kMediumPacketLossFraction),
rtc::Optional<bool>(), 60);
UpdateNetworkMetrics(controller.get(),
rtc::Optional<int>(kMediumBandwidthBps),
rtc::Optional<float>(kMediumPacketLossFraction));
CheckDecision(controller.get(), rtc::Optional<bool>(), 60);
}
TEST(FrameLengthControllerTest, IncreaseTo60MsOnMultipleConditions) {
@ -101,9 +116,28 @@ TEST(FrameLengthControllerTest, IncreaseTo60MsOnMultipleConditions) {
// AND
// 3. FEC is not decided or OFF.
auto controller = CreateController({20, 60}, 20);
CheckDecision(controller.get(), rtc::Optional<int>(kFl20msTo60msBandwidthBps),
rtc::Optional<float>(kFlIncreasingPacketLossFraction),
rtc::Optional<bool>(), 60);
UpdateNetworkMetrics(controller.get(),
rtc::Optional<int>(kFl20msTo60msBandwidthBps),
rtc::Optional<float>(kFlIncreasingPacketLossFraction));
CheckDecision(controller.get(), rtc::Optional<bool>(), 60);
}
TEST(FrameLengthControllerTest, UpdateMultipleNetworkMetricsAtOnce) {
// This test is similar to IncreaseTo60MsOnMultipleConditions. But instead of
// using ::UpdateNetworkMetrics(...), which calls
// FrameLengthController::UpdateNetworkMetrics(...) multiple times, we
// we call it only once. This is to verify that
// FrameLengthController::UpdateNetworkMetrics(...) can handle multiple
// network updates at once. This is, however, not a common use case in current
// audio_network_adaptor_impl.cc.
auto controller = CreateController({20, 60}, 20);
Controller::NetworkMetrics network_metrics;
network_metrics.uplink_bandwidth_bps =
rtc::Optional<int>(kFl20msTo60msBandwidthBps);
network_metrics.uplink_packet_loss_fraction =
rtc::Optional<float>(kFlIncreasingPacketLossFraction);
controller->UpdateNetworkMetrics(network_metrics);
CheckDecision(controller.get(), rtc::Optional<bool>(), 60);
}
TEST(FrameLengthControllerTest,
@ -111,34 +145,38 @@ TEST(FrameLengthControllerTest,
auto controller = CreateController({20}, 20);
// Use a low uplink bandwidth and a low uplink packet loss fraction that would
// cause frame length to increase if receiver frame length included 60ms.
CheckDecision(controller.get(), rtc::Optional<int>(kFl20msTo60msBandwidthBps),
rtc::Optional<float>(kFlIncreasingPacketLossFraction),
rtc::Optional<bool>(), 20);
UpdateNetworkMetrics(controller.get(),
rtc::Optional<int>(kFl20msTo60msBandwidthBps),
rtc::Optional<float>(kFlIncreasingPacketLossFraction));
CheckDecision(controller.get(), rtc::Optional<bool>(), 20);
}
TEST(FrameLengthControllerTest, Maintain20MsOnMediumUplinkBandwidth) {
auto controller = CreateController({20, 60}, 20);
CheckDecision(controller.get(), rtc::Optional<int>(kMediumBandwidthBps),
rtc::Optional<float>(kFlIncreasingPacketLossFraction),
rtc::Optional<bool>(), 20);
UpdateNetworkMetrics(controller.get(),
rtc::Optional<int>(kMediumBandwidthBps),
rtc::Optional<float>(kFlIncreasingPacketLossFraction));
CheckDecision(controller.get(), rtc::Optional<bool>(), 20);
}
TEST(FrameLengthControllerTest, Maintain20MsOnMediumUplinkPacketLossFraction) {
auto controller = CreateController({20, 60}, 20);
// Use a low uplink bandwidth that would cause frame length to increase if
// uplink packet loss fraction was low.
CheckDecision(controller.get(), rtc::Optional<int>(kFl20msTo60msBandwidthBps),
rtc::Optional<float>(kMediumPacketLossFraction),
rtc::Optional<bool>(), 20);
UpdateNetworkMetrics(controller.get(),
rtc::Optional<int>(kFl20msTo60msBandwidthBps),
rtc::Optional<float>(kMediumPacketLossFraction));
CheckDecision(controller.get(), rtc::Optional<bool>(), 20);
}
TEST(FrameLengthControllerTest, Maintain20MsWhenFecIsOn) {
auto controller = CreateController({20, 60}, 20);
// Use a low uplink bandwidth and a low uplink packet loss fraction that would
// cause frame length to increase if FEC was not ON.
CheckDecision(controller.get(), rtc::Optional<int>(kFl20msTo60msBandwidthBps),
rtc::Optional<float>(kFlIncreasingPacketLossFraction),
rtc::Optional<bool>(true), 20);
UpdateNetworkMetrics(controller.get(),
rtc::Optional<int>(kFl20msTo60msBandwidthBps),
rtc::Optional<float>(kFlIncreasingPacketLossFraction));
CheckDecision(controller.get(), rtc::Optional<bool>(true), 20);
}
namespace {
@ -176,30 +214,34 @@ class FrameLengthControllerForTest {
TEST(FrameLengthControllerTest, From120MsTo20MsOnHighUplinkBandwidth) {
FrameLengthControllerForTest controller({20, 60, 120}, 120);
// It takes two steps for frame length to go from 120ms to 20ms.
CheckDecision(controller.get(), rtc::Optional<int>(kFl60msTo20msBandwidthBps),
rtc::Optional<float>(), rtc::Optional<bool>(), 60);
CheckDecision(controller.get(), rtc::Optional<int>(kFl60msTo20msBandwidthBps),
rtc::Optional<float>(), rtc::Optional<bool>(), 20);
UpdateNetworkMetrics(controller.get(),
rtc::Optional<int>(kFl60msTo20msBandwidthBps),
rtc::Optional<float>());
CheckDecision(controller.get(), rtc::Optional<bool>(), 60);
UpdateNetworkMetrics(controller.get(),
rtc::Optional<int>(kFl60msTo20msBandwidthBps),
rtc::Optional<float>());
CheckDecision(controller.get(), rtc::Optional<bool>(), 20);
}
TEST(FrameLengthControllerTest, From120MsTo20MsOnHighUplinkPacketLossFraction) {
FrameLengthControllerForTest controller({20, 60, 120}, 120);
// It takes two steps for frame length to go from 120ms to 20ms.
CheckDecision(controller.get(), rtc::Optional<int>(),
rtc::Optional<float>(kFlDecreasingPacketLossFraction),
rtc::Optional<bool>(), 60);
CheckDecision(controller.get(), rtc::Optional<int>(),
rtc::Optional<float>(kFlDecreasingPacketLossFraction),
rtc::Optional<bool>(), 20);
UpdateNetworkMetrics(controller.get(), rtc::Optional<int>(),
rtc::Optional<float>(kFlDecreasingPacketLossFraction));
CheckDecision(controller.get(), rtc::Optional<bool>(), 60);
UpdateNetworkMetrics(controller.get(), rtc::Optional<int>(),
rtc::Optional<float>(kFlDecreasingPacketLossFraction));
CheckDecision(controller.get(), rtc::Optional<bool>(), 20);
}
TEST(FrameLengthControllerTest, From120MsTo20MsWhenFecIsOn) {
FrameLengthControllerForTest controller({20, 60, 120}, 120);
// It takes two steps for frame length to go from 120ms to 20ms.
CheckDecision(controller.get(), rtc::Optional<int>(), rtc::Optional<float>(),
rtc::Optional<bool>(true), 60);
CheckDecision(controller.get(), rtc::Optional<int>(), rtc::Optional<float>(),
rtc::Optional<bool>(true), 20);
CheckDecision(controller.get(), rtc::Optional<bool>(true), 60);
CheckDecision(controller.get(), rtc::Optional<bool>(true), 20);
}
TEST(FrameLengthControllerTest, From20MsTo120MsOnMultipleConditions) {
@ -210,51 +252,59 @@ TEST(FrameLengthControllerTest, From20MsTo120MsOnMultipleConditions) {
// 3. FEC is not decided or OFF.
FrameLengthControllerForTest controller({20, 60, 120}, 20);
// It takes two steps for frame length to go from 20ms to 120ms.
CheckDecision(controller.get(),
rtc::Optional<int>(kFl60msTo120msBandwidthBps),
rtc::Optional<float>(kFlIncreasingPacketLossFraction),
rtc::Optional<bool>(), 60);
CheckDecision(controller.get(),
rtc::Optional<int>(kFl60msTo120msBandwidthBps),
rtc::Optional<float>(kFlIncreasingPacketLossFraction),
rtc::Optional<bool>(), 120);
UpdateNetworkMetrics(controller.get(),
rtc::Optional<int>(kFl60msTo120msBandwidthBps),
rtc::Optional<float>(kFlIncreasingPacketLossFraction));
CheckDecision(controller.get(), rtc::Optional<bool>(), 60);
UpdateNetworkMetrics(controller.get(),
rtc::Optional<int>(kFl60msTo120msBandwidthBps),
rtc::Optional<float>(kFlIncreasingPacketLossFraction));
CheckDecision(controller.get(), rtc::Optional<bool>(), 120);
}
TEST(FrameLengthControllerTest, Stall60MsIf120MsNotInReceiverFrameLengthRange) {
FrameLengthControllerForTest controller({20, 60}, 20);
CheckDecision(controller.get(),
rtc::Optional<int>(kFl60msTo120msBandwidthBps),
rtc::Optional<float>(kFlIncreasingPacketLossFraction),
rtc::Optional<bool>(), 60);
CheckDecision(controller.get(),
rtc::Optional<int>(kFl60msTo120msBandwidthBps),
rtc::Optional<float>(kFlIncreasingPacketLossFraction),
rtc::Optional<bool>(), 60);
UpdateNetworkMetrics(controller.get(),
rtc::Optional<int>(kFl60msTo120msBandwidthBps),
rtc::Optional<float>(kFlIncreasingPacketLossFraction));
CheckDecision(controller.get(), rtc::Optional<bool>(), 60);
UpdateNetworkMetrics(controller.get(),
rtc::Optional<int>(kFl60msTo120msBandwidthBps),
rtc::Optional<float>(kFlIncreasingPacketLossFraction));
CheckDecision(controller.get(), rtc::Optional<bool>(), 60);
}
TEST(FrameLengthControllerTest, CheckBehaviorOnChangingNetworkMetrics) {
FrameLengthControllerForTest controller({20, 60, 120}, 20);
CheckDecision(controller.get(), rtc::Optional<int>(kMediumBandwidthBps),
rtc::Optional<float>(kFlIncreasingPacketLossFraction),
rtc::Optional<bool>(), 20);
CheckDecision(controller.get(), rtc::Optional<int>(kFl20msTo60msBandwidthBps),
rtc::Optional<float>(kFlIncreasingPacketLossFraction),
rtc::Optional<bool>(), 60);
CheckDecision(controller.get(),
rtc::Optional<int>(kFl60msTo120msBandwidthBps),
rtc::Optional<float>(kMediumPacketLossFraction),
rtc::Optional<bool>(), 60);
CheckDecision(controller.get(),
rtc::Optional<int>(kFl60msTo120msBandwidthBps),
rtc::Optional<float>(kFlIncreasingPacketLossFraction),
rtc::Optional<bool>(), 120);
CheckDecision(controller.get(),
rtc::Optional<int>(kFl120msTo60msBandwidthBps),
rtc::Optional<float>(kFlIncreasingPacketLossFraction),
rtc::Optional<bool>(), 60);
CheckDecision(controller.get(), rtc::Optional<int>(kMediumPacketLossFraction),
rtc::Optional<float>(kFlDecreasingPacketLossFraction),
rtc::Optional<bool>(), 20);
UpdateNetworkMetrics(controller.get(),
rtc::Optional<int>(kMediumBandwidthBps),
rtc::Optional<float>(kFlIncreasingPacketLossFraction));
CheckDecision(controller.get(), rtc::Optional<bool>(), 20);
UpdateNetworkMetrics(controller.get(),
rtc::Optional<int>(kFl20msTo60msBandwidthBps),
rtc::Optional<float>(kFlIncreasingPacketLossFraction));
CheckDecision(controller.get(), rtc::Optional<bool>(), 60);
UpdateNetworkMetrics(controller.get(),
rtc::Optional<int>(kFl60msTo120msBandwidthBps),
rtc::Optional<float>(kMediumPacketLossFraction));
CheckDecision(controller.get(), rtc::Optional<bool>(), 60);
UpdateNetworkMetrics(controller.get(),
rtc::Optional<int>(kFl60msTo120msBandwidthBps),
rtc::Optional<float>(kFlIncreasingPacketLossFraction));
CheckDecision(controller.get(), rtc::Optional<bool>(), 120);
UpdateNetworkMetrics(controller.get(),
rtc::Optional<int>(kFl120msTo60msBandwidthBps),
rtc::Optional<float>(kFlIncreasingPacketLossFraction));
CheckDecision(controller.get(), rtc::Optional<bool>(), 60);
UpdateNetworkMetrics(controller.get(),
rtc::Optional<int>(kMediumPacketLossFraction),
rtc::Optional<float>(kFlDecreasingPacketLossFraction));
CheckDecision(controller.get(), rtc::Optional<bool>(), 20);
}
} // namespace webrtc

View File

@ -20,9 +20,10 @@ class MockController : public Controller {
public:
virtual ~MockController() { Die(); }
MOCK_METHOD0(Die, void());
MOCK_METHOD2(MakeDecision,
void(const NetworkMetrics& metrics,
AudioNetworkAdaptor::EncoderRuntimeConfig* config));
MOCK_METHOD1(UpdateNetworkMetrics,
void(const NetworkMetrics& network_metrics));
MOCK_METHOD1(MakeDecision,
void(AudioNetworkAdaptor::EncoderRuntimeConfig* config));
};
} // namespace webrtc