blob: 68f3b109b18176a9f52844869f23db9b88e33098 [file] [log] [blame]
/*
* Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <memory>
#include <utility>
#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/modules/audio_coding/audio_network_adaptor/frame_length_controller.h"
namespace webrtc {
namespace {
constexpr float kFlIncreasingPacketLossFraction = 0.04f;
constexpr float kFlDecreasingPacketLossFraction = 0.05f;
constexpr int kFl20msTo60msBandwidthBps = 22000;
constexpr int kFl60msTo20msBandwidthBps = 88000;
constexpr int kMinReceiverFrameLengthMs = 10;
constexpr int kMaxReceiverFrameLengthMs = 120;
constexpr int kMediumBandwidthBps =
(kFl60msTo20msBandwidthBps + kFl20msTo60msBandwidthBps) / 2;
constexpr float kMediumPacketLossFraction =
(kFlDecreasingPacketLossFraction + kFlIncreasingPacketLossFraction) / 2;
void SetReceiverFrameLengthRange(FrameLengthController* controller,
int min_frame_length_ms,
int max_frame_length_ms) {
Controller::Constraints constraints;
using FrameLengthRange = Controller::Constraints::FrameLengthRange;
constraints.receiver_frame_length_range = rtc::Optional<FrameLengthRange>(
FrameLengthRange(min_frame_length_ms, max_frame_length_ms));
controller->SetConstraints(constraints);
}
std::unique_ptr<FrameLengthController> CreateController(
int initial_frame_length_ms) {
std::unique_ptr<FrameLengthController> controller(
new FrameLengthController(FrameLengthController::Config(
{20, 60}, initial_frame_length_ms, kFlIncreasingPacketLossFraction,
kFlDecreasingPacketLossFraction, kFl20msTo60msBandwidthBps,
kFl60msTo20msBandwidthBps)));
SetReceiverFrameLengthRange(controller.get(), kMinReceiverFrameLengthMs,
kMaxReceiverFrameLengthMs);
return controller;
}
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);
EXPECT_EQ(rtc::Optional<int>(expected_frame_length_ms),
config.frame_length_ms);
}
} // namespace
TEST(FrameLengthControllerTest,
OutputInitValueWhenReceiverFrameLengthRangeUnset) {
constexpr int kInitialFrameLenghtMs = 60;
std::unique_ptr<FrameLengthController> controller(
new FrameLengthController(FrameLengthController::Config(
{20, 60}, kInitialFrameLenghtMs, kFlIncreasingPacketLossFraction,
kFlDecreasingPacketLossFraction, kFl20msTo60msBandwidthBps,
kFl60msTo20msBandwidthBps)));
// Use a high uplink bandwidth that would cause frame length to decrease if
// receiver frame length is set.
CheckDecision(controller.get(), rtc::Optional<int>(kFl60msTo20msBandwidthBps),
rtc::Optional<float>(), rtc::Optional<bool>(),
kInitialFrameLenghtMs);
}
TEST(FrameLengthControllerTest, DecreaseTo20MsOnHighUplinkBandwidth) {
auto controller = CreateController(60);
CheckDecision(controller.get(), rtc::Optional<int>(kFl60msTo20msBandwidthBps),
rtc::Optional<float>(), rtc::Optional<bool>(), 20);
}
TEST(FrameLengthControllerTest, DecreaseTo20MsOnHighUplinkPacketLossFraction) {
auto controller = CreateController(60);
CheckDecision(controller.get(), rtc::Optional<int>(),
rtc::Optional<float>(kFlDecreasingPacketLossFraction),
rtc::Optional<bool>(), 20);
}
TEST(FrameLengthControllerTest, DecreaseTo20MsWhenFecIsOn) {
auto controller = CreateController(60);
CheckDecision(controller.get(), rtc::Optional<int>(), rtc::Optional<float>(),
rtc::Optional<bool>(true), 20);
}
TEST(FrameLengthControllerTest,
Maintain60MsIf20MsNotInReceiverFrameLengthRange) {
auto controller = CreateController(60);
SetReceiverFrameLengthRange(controller.get(), 21, 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);
}
TEST(FrameLengthControllerTest, Maintain60MsOnMultipleConditions) {
// Maintain 60ms frame length if
// 1. |uplink_bandwidth_bps| is at medium level,
// 2. |uplink_packet_loss_fraction| is at medium,
// 3. FEC is not decided ON.
auto controller = CreateController(60);
CheckDecision(controller.get(), rtc::Optional<int>(kMediumBandwidthBps),
rtc::Optional<float>(kMediumPacketLossFraction),
rtc::Optional<bool>(), 60);
}
TEST(FrameLengthControllerTest, IncreaseTo60MsOnMultipleConditions) {
// Increase to 60ms frame length if
// 1. |uplink_bandwidth_bps| is known to be smaller than a threshold AND
// 2. |uplink_packet_loss_fraction| is known to be smaller than a threshold
// AND
// 3. FEC is not decided or OFF.
auto controller = CreateController(20);
CheckDecision(controller.get(), rtc::Optional<int>(kFl20msTo60msBandwidthBps),
rtc::Optional<float>(kFlIncreasingPacketLossFraction),
rtc::Optional<bool>(), 60);
}
TEST(FrameLengthControllerTest,
Maintain20MsIf60MsNotInReceiverFrameLengthRange) {
auto controller = CreateController(20);
SetReceiverFrameLengthRange(controller.get(), 10, 59);
// 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);
}
TEST(FrameLengthControllerTest, Maintain20MsOnMediumUplinkBandwidth) {
auto controller = CreateController(20);
CheckDecision(controller.get(), rtc::Optional<int>(kMediumBandwidthBps),
rtc::Optional<float>(kFlIncreasingPacketLossFraction),
rtc::Optional<bool>(), 20);
}
TEST(FrameLengthControllerTest, Maintain20MsOnMediumUplinkPacketLossFraction) {
auto controller = CreateController(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);
}
TEST(FrameLengthControllerTest, Maintain20MsWhenFecIsOn) {
auto controller = CreateController(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);
}
TEST(FrameLengthControllerTest,
MaintainFrameLengthOnSetReceiverFrameLengthRange) {
auto controller = CreateController(60);
CheckDecision(controller.get(), rtc::Optional<int>(), rtc::Optional<float>(),
rtc::Optional<bool>(true), 20);
SetReceiverFrameLengthRange(controller.get(), 10, 60);
CheckDecision(controller.get(), rtc::Optional<int>(), rtc::Optional<float>(),
rtc::Optional<bool>(), 20);
}
namespace {
constexpr int kFl60msTo120msBandwidthBps = 18000;
constexpr int kFl120msTo60msBandwidthBps = 72000;
}
class FrameLengthControllerForTest {
public:
// This class is to test multiple frame lengths. FrameLengthController is
// implemented to support this, but is not enabled for the default constructor
// for the time being. We use this class to test it.
explicit FrameLengthControllerForTest(int initial_frame_length_ms)
: frame_length_controller_(
FrameLengthController::Config({20, 60, 120},
initial_frame_length_ms,
kFlIncreasingPacketLossFraction,
kFlDecreasingPacketLossFraction,
kFl20msTo60msBandwidthBps,
kFl60msTo20msBandwidthBps)) {
frame_length_controller_.frame_length_change_criteria_.insert(
std::make_pair(FrameLengthController::FrameLengthChange(60, 120),
kFl60msTo120msBandwidthBps));
frame_length_controller_.frame_length_change_criteria_.insert(
std::make_pair(FrameLengthController::FrameLengthChange(120, 60),
kFl120msTo60msBandwidthBps));
frame_length_controller_.SetReceiverFrameLengthRange(20, 120);
}
FrameLengthController* get() { return &frame_length_controller_; }
private:
FrameLengthController frame_length_controller_;
};
TEST(FrameLengthControllerTest, From120MsTo20MsOnHighUplinkBandwidth) {
FrameLengthControllerForTest controller(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);
}
TEST(FrameLengthControllerTest, From120MsTo20MsOnHighUplinkPacketLossFraction) {
FrameLengthControllerForTest controller(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);
}
TEST(FrameLengthControllerTest, From120MsTo20MsWhenFecIsOn) {
FrameLengthControllerForTest controller(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);
}
TEST(FrameLengthControllerTest, From20MsTo120MsOnMultipleConditions) {
// Increase to 120ms frame length if
// 1. |uplink_bandwidth_bps| is known to be smaller than a threshold AND
// 2. |uplink_packet_loss_fraction| is known to be smaller than a threshold
// AND
// 3. FEC is not decided or OFF.
FrameLengthControllerForTest controller(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);
}
TEST(FrameLengthControllerTest, Stall60MsIf120MsNotInReceiverFrameLengthRange) {
FrameLengthControllerForTest controller(20);
SetReceiverFrameLengthRange(controller.get(), 20, 119);
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);
}
TEST(FrameLengthControllerTest, CheckBehaviorOnChangingNetworkMetrics) {
FrameLengthControllerForTest controller(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);
}
} // namespace webrtc