Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(281)

Unified Diff: webrtc/modules/audio_coding/audio_network_adaptor/fec_controller_unittest.cc

Issue 2337103006: Adding FecController to audio network adaptor. (Closed)
Patch Set: fixing death test Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: webrtc/modules/audio_coding/audio_network_adaptor/fec_controller_unittest.cc
diff --git a/webrtc/modules/audio_coding/audio_network_adaptor/fec_controller_unittest.cc b/webrtc/modules/audio_coding/audio_network_adaptor/fec_controller_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..c66482f4e254d3cea2a72466d7bffc17ea153cb8
--- /dev/null
+++ b/webrtc/modules/audio_coding/audio_network_adaptor/fec_controller_unittest.cc
@@ -0,0 +1,312 @@
+/*
+ * 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 <utility>
+
+#include "webrtc/modules/audio_coding/audio_network_adaptor/fec_controller.h"
+#include "webrtc/modules/audio_coding/audio_network_adaptor/mock/mock_smoothing_filter.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace webrtc {
+
+using ::testing::NiceMock;
+using ::testing::Return;
+using ::testing::_;
+
+namespace {
+
+// The test uses the following settings:
+//
+// packet-loss ^ | |
+// | A| C| FEC
+// | \ \ ON
+// | FEC \ D\_______
+// | OFF B\_________
+// |-----------------> bandwidth
+//
+// A : (kDisablingBandwidthLow, kDisablingPacketLossAtLowBw)
+// B : (kDisablingBandwidthHigh, kDisablingPacketLossAtHighBw)
+// C : (kEnablingBandwidthLow, kEnablingPacketLossAtLowBw)
+// D : (kEnablingBandwidthHigh, kEnablingPacketLossAtHighBw)
+
+constexpr int kDisablingBandwidthLow = 15000;
+constexpr float kDisablingPacketLossAtLowBw = 0.08f;
+constexpr int kDisablingBandwidthHigh = 64000;
+constexpr float kDisablingPacketLossAtHighBw = 0.01f;
+constexpr int kEnablingBandwidthLow = 17000;
+constexpr float kEnablingPacketLossAtLowBw = 0.1f;
+constexpr int kEnablingBandwidthHigh = 64000;
+constexpr float kEnablingPacketLossAtHighBw = 0.05f;
+
+struct FecControllerStates {
+ std::unique_ptr<FecController> controller;
+ MockSmoothingFilter* packet_loss_smoothed;
+};
+
+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();
+ EXPECT_CALL(*states.packet_loss_smoothed, Die());
+ using Threshold = FecController::Config::Threshold;
+ states.controller.reset(new FecController(
+ FecController::Config(
+ initial_fec_enabled,
+ Threshold(kEnablingBandwidthLow, kEnablingPacketLossAtLowBw,
+ kEnablingBandwidthHigh, kEnablingPacketLossAtHighBw),
+ Threshold(kDisablingBandwidthLow, kDisablingPacketLossAtLowBw,
+ kDisablingBandwidthHigh, kDisablingPacketLossAtHighBw),
+ 0, nullptr),
+ std::move(mock_smoothing_filter)));
+ 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));
+ }
+
+ EXPECT_CALL(*states->packet_loss_smoothed, GetAverage())
+ .WillRepeatedly(Return(uplink_packet_loss));
+
+ AudioNetworkAdaptor::EncoderRuntimeConfig config;
+ states->controller->MakeDecision(metrics, &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),
+ config.uplink_packet_loss_fraction);
+}
+
+} // namespace
+
+TEST(FecControllerTest, OutputInitValueWhenUplinkBandwidthUnknown) {
+ constexpr bool kInitialFecEnabled = true;
+ 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);
+}
+
+TEST(FecControllerTest, OutputInitValueWhenUplinkPacketLossFractionUnknown) {
+ constexpr bool kInitialFecEnabled = true;
+ 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);
+}
+
+TEST(FecControllerTest, EnableFecForHighBandwidth) {
+ auto states = CreateFecController(false);
+ CheckDecision(&states, rtc::Optional<int>(kEnablingBandwidthHigh),
+ rtc::Optional<float>(kEnablingPacketLossAtHighBw), true);
+}
+
+TEST(FecControllerTest, MaintainFecOffForHighBandwidth) {
+ auto states = CreateFecController(false);
+ CheckDecision(&states, rtc::Optional<int>(kEnablingBandwidthHigh),
+ rtc::Optional<float>(kEnablingPacketLossAtHighBw * 0.99f),
+ false);
+}
+
+TEST(FecControllerTest, EnableFecForMediumBandwidth) {
+ auto states = CreateFecController(false);
+ CheckDecision(
+ &states,
+ rtc::Optional<int>((kEnablingBandwidthHigh + kEnablingBandwidthLow) / 2),
+ rtc::Optional<float>(
+ (kEnablingPacketLossAtLowBw + kEnablingPacketLossAtHighBw) / 2.0),
+ true);
+}
+
+TEST(FecControllerTest, MaintainFecOffForMediumBandwidth) {
+ auto states = CreateFecController(false);
+ CheckDecision(
+ &states,
+ rtc::Optional<int>((kEnablingBandwidthHigh + kEnablingBandwidthLow) / 2),
+ rtc::Optional<float>(kEnablingPacketLossAtLowBw * 0.49f +
+ kEnablingPacketLossAtHighBw * 0.51f),
+ false);
+}
+
+TEST(FecControllerTest, EnableFecForLowBandwidth) {
+ auto states = CreateFecController(false);
+ CheckDecision(&states, rtc::Optional<int>(kEnablingBandwidthLow),
+ rtc::Optional<float>(kEnablingPacketLossAtLowBw), true);
+}
+
+TEST(FecControllerTest, MaintainFecOffForLowBandwidth) {
+ auto states = CreateFecController(false);
+ CheckDecision(&states, rtc::Optional<int>(kEnablingBandwidthLow),
+ rtc::Optional<float>(kEnablingPacketLossAtLowBw * 0.99f),
+ false);
+}
+
+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);
+}
+
+TEST(FecControllerTest, DisableFecForHighBandwidth) {
+ auto states = CreateFecController(true);
+ CheckDecision(&states, rtc::Optional<int>(kDisablingBandwidthHigh),
+ rtc::Optional<float>(kDisablingPacketLossAtHighBw), false);
+}
+
+TEST(FecControllerTest, MaintainFecOnForHighBandwidth) {
+ auto states = CreateFecController(true);
+ CheckDecision(&states, rtc::Optional<int>(kDisablingBandwidthHigh),
+ rtc::Optional<float>(kDisablingPacketLossAtHighBw * 1.01f),
+ true);
+}
+
+TEST(FecControllerTest, DisableFecOnMediumBandwidth) {
+ auto states = CreateFecController(true);
+ CheckDecision(
+ &states, rtc::Optional<int>(
+ (kDisablingBandwidthHigh + kDisablingBandwidthLow) / 2),
+ rtc::Optional<float>(
+ (kDisablingPacketLossAtLowBw + kDisablingPacketLossAtHighBw) / 2.0f),
+ false);
+}
+
+TEST(FecControllerTest, MaintainFecOnForMediumBandwidth) {
+ auto states = CreateFecController(true);
+ CheckDecision(
+ &states,
+ rtc::Optional<int>((kEnablingBandwidthHigh + kDisablingBandwidthLow) / 2),
+ rtc::Optional<float>(kDisablingPacketLossAtLowBw * 0.51f +
+ kDisablingPacketLossAtHighBw * 0.49f),
+ true);
+}
+
+TEST(FecControllerTest, DisableFecForLowBandwidth) {
+ auto states = CreateFecController(true);
+ CheckDecision(&states, rtc::Optional<int>(kDisablingBandwidthLow),
+ rtc::Optional<float>(kDisablingPacketLossAtLowBw), false);
+}
+
+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);
+}
+
+TEST(FecControllerTest, CheckBehaviorOnChangingNetworkMetrics) {
+ // In this test, we let the network metrics to traverse from 1 to 5.
+ // packet-loss ^ 1 | |
+ // | | 2|
+ // | \ \ 3
+ // | \4 \_______
+ // | \_________
+ // |---------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);
+}
+
+TEST(FecControllerTest, CheckBehaviorOnSpecialCurves) {
+ // We test a special configuration, where the points to define the FEC
+ // enabling/disabling curves are placed like the following, otherwise the test
+ // is the same as CheckBehaviorOnChangingNetworkMetrics.
+ //
+ // packet-loss ^ | |
+ // | | C|
+ // | | |
+ // | | D|_______
+ // | A|___B______
+ // |-----------------> bandwidth
+
+ constexpr int kEnablingBandwidthHigh = kEnablingBandwidthLow;
+ constexpr float kDisablingPacketLossAtLowBw = kDisablingPacketLossAtHighBw;
+ FecControllerStates states;
+ std::unique_ptr<MockSmoothingFilter> mock_smoothing_filter(
+ new NiceMock<MockSmoothingFilter>());
+ states.packet_loss_smoothed = mock_smoothing_filter.get();
+ EXPECT_CALL(*states.packet_loss_smoothed, Die());
+ using Threshold = FecController::Config::Threshold;
+ states.controller.reset(new FecController(
+ FecController::Config(
+ true, Threshold(kEnablingBandwidthLow, kEnablingPacketLossAtLowBw,
+ kEnablingBandwidthHigh, kEnablingPacketLossAtHighBw),
+ Threshold(kDisablingBandwidthLow, kDisablingPacketLossAtLowBw,
+ kDisablingBandwidthHigh, kDisablingPacketLossAtHighBw),
+ 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);
+}
+
+#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
+TEST(FecControllerDeathTest, InvalidConfig) {
+ FecControllerStates states;
+ std::unique_ptr<MockSmoothingFilter> mock_smoothing_filter(
+ new NiceMock<MockSmoothingFilter>());
+ states.packet_loss_smoothed = mock_smoothing_filter.get();
+ EXPECT_CALL(*states.packet_loss_smoothed, Die());
+ using Threshold = FecController::Config::Threshold;
+ EXPECT_DEATH(
minyue-webrtc 2016/09/22 11:28:01 It looks like that RTC_DCHECK_IS_ON for some non-d
+ states.controller.reset(new FecController(
+ FecController::Config(
+ true,
+ Threshold(kDisablingBandwidthLow - 1, kEnablingPacketLossAtLowBw,
+ kEnablingBandwidthHigh, kEnablingPacketLossAtHighBw),
+ Threshold(kDisablingBandwidthLow, kDisablingPacketLossAtLowBw,
+ kDisablingBandwidthHigh, kDisablingPacketLossAtHighBw),
+ 0, nullptr),
+ std::move(mock_smoothing_filter))),
+ "Check failed");
+}
+#endif
+
+} // namespace webrtc

Powered by Google App Engine
This is Rietveld 408576698