| Index: webrtc/modules/audio_coding/audio_network_adaptor/frame_length_controller_unittest.cc
|
| diff --git a/webrtc/modules/audio_coding/audio_network_adaptor/frame_length_controller_unittest.cc b/webrtc/modules/audio_coding/audio_network_adaptor/frame_length_controller_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..68f3b109b18176a9f52844869f23db9b88e33098
|
| --- /dev/null
|
| +++ b/webrtc/modules/audio_coding/audio_network_adaptor/frame_length_controller_unittest.cc
|
| @@ -0,0 +1,301 @@
|
| +/*
|
| + * 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
|
|
|