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:
@ -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
|
||||
|
||||
@ -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_;
|
||||
|
||||
@ -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)))
|
||||
|
||||
@ -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_);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
};
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
};
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
|
||||
@ -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),
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
};
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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_);
|
||||
}
|
||||
|
||||
@ -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_;
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
};
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
Reference in New Issue
Block a user