diff --git a/modules/remote_bitrate_estimator/BUILD.gn b/modules/remote_bitrate_estimator/BUILD.gn index ea2a5279fb..b4fe0d5b97 100644 --- a/modules/remote_bitrate_estimator/BUILD.gn +++ b/modules/remote_bitrate_estimator/BUILD.gn @@ -80,108 +80,9 @@ if (!build_with_chromium) { } if (rtc_include_tests) { - rtc_static_library("bwe_simulator_lib") { - testonly = true - sources = [ - "test/bbr_paced_sender.cc", - "test/bbr_paced_sender.h", - "test/bwe.cc", - "test/bwe.h", - "test/bwe_test.cc", - "test/bwe_test.h", - "test/bwe_test_baselinefile.cc", - "test/bwe_test_baselinefile.h", - "test/bwe_test_fileutils.cc", - "test/bwe_test_fileutils.h", - "test/bwe_test_framework.cc", - "test/bwe_test_framework.h", - "test/bwe_test_logging.h", - "test/estimators/bbr.cc", - "test/estimators/bbr.h", - "test/estimators/congestion_window.cc", - "test/estimators/congestion_window.h", - "test/estimators/max_bandwidth_filter.cc", - "test/estimators/max_bandwidth_filter.h", - "test/estimators/min_rtt_filter.cc", - "test/estimators/min_rtt_filter.h", - "test/estimators/nada.cc", - "test/estimators/nada.h", - "test/estimators/remb.cc", - "test/estimators/remb.h", - "test/estimators/send_side.cc", - "test/estimators/send_side.h", - "test/estimators/tcp.cc", - "test/estimators/tcp.h", - "test/metric_recorder.cc", - "test/metric_recorder.h", - "test/packet.cc", - "test/packet.h", - "test/packet_receiver.cc", - "test/packet_receiver.h", - "test/packet_sender.cc", - "test/packet_sender.h", - ] - - if (rtc_enable_bwe_test_logging) { - defines = [ "BWE_TEST_LOGGING_COMPILE_TIME_ENABLE=1" ] - } else { - defines = [ "BWE_TEST_LOGGING_COMPILE_TIME_ENABLE=0" ] - } - - deps = [ - ":remote_bitrate_estimator", - "..:module_api", - "..:module_api_public", - "../..:webrtc_common", - "../../api:rtp_headers", - "../../api/transport:field_trial_based_config", - "../../api/transport:network_control", - "../../logging:mocks", - "../../rtc_base", - "../../rtc_base:checks", - "../../rtc_base:gtest_prod", - "../../rtc_base:rtc_base_approved", - "../../rtc_base:rtc_numerics", - "../../rtc_base:safe_minmax", - "../../rtc_base/experiments:alr_experiment", - "../../rtc_base/system:fallthrough", - "../../rtc_base/system:unused", - "../../system_wrappers", - "../../system_wrappers:field_trial", - "../../test:fileutils", - "../../test:perf_test", - "../../test:test_support", - "../bitrate_controller", - "../congestion_controller", - "../congestion_controller:transport_feedback", - "../congestion_controller/goog_cc:delay_based_bwe", - "../congestion_controller/goog_cc:estimators", - "../congestion_controller/rtp:transport_feedback", - "../pacing", - "../rtp_rtcp", - "../rtp_rtcp:rtp_rtcp_format", - "../video_coding:video_coding_utility", - "//testing/gtest", - "//third_party/abseil-cpp/absl/memory", - "//third_party/abseil-cpp/absl/types:optional", - ] - } - + # TODO(srte): Remove this target when the dependency in root BUILD.gn is removed. rtc_source_set("remote_bitrate_estimator_perf_tests") { testonly = true - - sources = [ - "remote_bitrate_estimators_test.cc", - ] - deps = [ - ":bwe_simulator_lib", - ":remote_bitrate_estimator", - "../../rtc_base:rtc_base_approved", - "../../system_wrappers", - "../../test:field_trial", - "../../test:fileutils", - "../../test:test_support", - ] } rtc_source_set("remote_bitrate_estimator_unittests") { @@ -196,16 +97,8 @@ if (rtc_include_tests) { "remote_bitrate_estimator_unittest_helper.cc", "remote_bitrate_estimator_unittest_helper.h", "remote_estimator_proxy_unittest.cc", - "test/bwe_test_framework_unittest.cc", - "test/bwe_unittest.cc", - "test/estimators/congestion_window_unittest.cc", - "test/estimators/max_bandwidth_filter_unittest.cc", - "test/estimators/min_rtt_filter_unittest.cc", - "test/estimators/nada_unittest.cc", - "test/metric_recorder_unittest.cc", ] deps = [ - ":bwe_simulator_lib", ":remote_bitrate_estimator", "..:module_api_public", "../..:webrtc_common", @@ -222,27 +115,12 @@ if (rtc_include_tests) { ] } + # TODO(srte): Remove this target when the dependency in root BUILD.gn is removed. rtc_test("bwe_simulations_tests") { testonly = true - - sources = [ - "bwe_simulations.cc", - ] deps = [ - ":bwe_simulator_lib", - ":remote_bitrate_estimator", - "../..:webrtc_common", - "../../rtc_base:rtc_base_approved", - "../../system_wrappers", - "../../test:fileutils", "../../test:test_main", - "../../test:test_support", "//testing/gtest", ] - data = [ - "//resources/sprint-uplink.rx", - "//resources/verizon4g-downlink.rx", - "//resources/google-wifi-3mbps.rx", - ] } } diff --git a/modules/remote_bitrate_estimator/bwe_simulations.cc b/modules/remote_bitrate_estimator/bwe_simulations.cc deleted file mode 100644 index 68ba01cb42..0000000000 --- a/modules/remote_bitrate_estimator/bwe_simulations.cc +++ /dev/null @@ -1,560 +0,0 @@ -/* - * Copyright (c) 2014 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 -#include -#include -#include -#include - -#include "modules/remote_bitrate_estimator/test/bwe.h" -#include "modules/remote_bitrate_estimator/test/bwe_test.h" -#include "modules/remote_bitrate_estimator/test/bwe_test_framework.h" -#include "modules/remote_bitrate_estimator/test/packet_receiver.h" -#include "modules/remote_bitrate_estimator/test/packet_sender.h" -#include "rtc_base/constructor_magic.h" -#include "rtc_base/random.h" -#include "system_wrappers/include/clock.h" -#include "test/gtest.h" -#include "test/testsupport/file_utils.h" - -namespace webrtc { -namespace testing { -namespace bwe { - -// This test fixture is used to instantiate tests running with adaptive video -// senders. -class BweSimulation : public BweTest, - public ::testing::TestWithParam { - public: - BweSimulation() - : BweTest(), random_(Clock::GetRealTimeClock()->TimeInMicroseconds()) {} - ~BweSimulation() override {} - - protected: - void SetUp() override { - BweTest::SetUp(); - VerboseLogging(true); - } - - Random random_; - - private: - RTC_DISALLOW_COPY_AND_ASSIGN(BweSimulation); -}; - -INSTANTIATE_TEST_SUITE_P(VideoSendersTest, - BweSimulation, - ::testing::Values(kRembEstimator, - kSendSideEstimator, - kNadaEstimator, - kBbrEstimator)); - -TEST_P(BweSimulation, SprintUplinkTest) { - AdaptiveVideoSource source(0, 30, 300, 0, 0); - VideoSender sender(&uplink_, &source, GetParam()); - RateCounterFilter counter1(&uplink_, 0, "sender_output", - bwe_names[GetParam()]); - TraceBasedDeliveryFilter filter(&uplink_, 0, "link_capacity"); - RateCounterFilter counter2(&uplink_, 0, "Receiver", bwe_names[GetParam()]); - PacketReceiver receiver(&uplink_, 0, GetParam(), true, true); - ASSERT_TRUE(filter.Init(test::ResourcePath("sprint-uplink", "rx"))); - RunFor(60 * 1000); -} - -TEST_P(BweSimulation, Verizon4gDownlinkTest) { - AdaptiveVideoSource source(0, 30, 300, 0, 0); - VideoSender sender(&downlink_, &source, GetParam()); - RateCounterFilter counter1(&downlink_, 0, "sender_output", - std::string() + bwe_names[GetParam()] + "_up"); - TraceBasedDeliveryFilter filter(&downlink_, 0, "link_capacity"); - RateCounterFilter counter2(&downlink_, 0, "Receiver", - std::string() + bwe_names[GetParam()] + "_down"); - PacketReceiver receiver(&downlink_, 0, GetParam(), true, true); - ASSERT_TRUE(filter.Init(test::ResourcePath("verizon4g-downlink", "rx"))); - RunFor(22 * 60 * 1000); -} - -TEST_P(BweSimulation, Choke1000kbps500kbps1000kbpsBiDirectional) { - const int kFlowIds[] = {0, 1}; - const size_t kNumFlows = sizeof(kFlowIds) / sizeof(kFlowIds[0]); - - AdaptiveVideoSource source(kFlowIds[0], 30, 300, 0, 0); - VideoSender sender(&uplink_, &source, GetParam()); - ChokeFilter choke(&uplink_, kFlowIds[0]); - RateCounterFilter counter(&uplink_, kFlowIds[0], "Receiver_0", - bwe_names[GetParam()]); - PacketReceiver receiver(&uplink_, kFlowIds[0], GetParam(), true, false); - - AdaptiveVideoSource source2(kFlowIds[1], 30, 300, 0, 0); - VideoSender sender2(&downlink_, &source2, GetParam()); - ChokeFilter choke2(&downlink_, kFlowIds[1]); - DelayFilter delay(&downlink_, CreateFlowIds(kFlowIds, kNumFlows)); - RateCounterFilter counter2(&downlink_, kFlowIds[1], "Receiver_1", - bwe_names[GetParam()]); - PacketReceiver receiver2(&downlink_, kFlowIds[1], GetParam(), true, false); - - choke2.set_capacity_kbps(500); - delay.SetOneWayDelayMs(0); - - choke.set_capacity_kbps(1000); - choke.set_max_delay_ms(500); - RunFor(60 * 1000); - choke.set_capacity_kbps(500); - RunFor(60 * 1000); - choke.set_capacity_kbps(1000); - RunFor(60 * 1000); -} - -TEST_P(BweSimulation, Choke1000kbps500kbps1000kbps) { - AdaptiveVideoSource source(0, 30, 300, 0, 0); - VideoSender sender(&uplink_, &source, GetParam()); - ChokeFilter choke(&uplink_, 0); - RateCounterFilter counter(&uplink_, 0, "Receiver", bwe_names[GetParam()]); - PacketReceiver receiver(&uplink_, 0, GetParam(), true, false); - - choke.set_capacity_kbps(1000); - choke.set_max_delay_ms(500); - RunFor(60 * 1000); - choke.set_capacity_kbps(500); - RunFor(60 * 1000); - choke.set_capacity_kbps(1000); - RunFor(60 * 1000); -} - -TEST_P(BweSimulation, SimulationsCompiled) { - AdaptiveVideoSource source(0, 30, 300, 0, 0); - PacedVideoSender sender(&uplink_, &source, GetParam()); - int zero = 0; - // CreateFlowIds() doesn't support passing int as a flow id, so we pass - // pointer instead. - DelayFilter delay(&uplink_, CreateFlowIds(&zero, 1)); - delay.SetOneWayDelayMs(100); - ChokeFilter filter(&uplink_, 0); - RateCounterFilter counter(&uplink_, 0, "Receiver", bwe_names[GetParam()]); - PacketReceiver receiver(&uplink_, 0, GetParam(), true, true); - filter.set_max_delay_ms(500); - filter.set_capacity_kbps(1000); - RunFor(60 * 1000); - filter.set_capacity_kbps(500); - RunFor(50 * 1000); - filter.set_capacity_kbps(1000); - RunFor(60 * 1000); - filter.set_capacity_kbps(200); - RunFor(60 * 1000); - filter.set_capacity_kbps(50); - RunFor(60 * 1000); - filter.set_capacity_kbps(200); - RunFor(60 * 1000); - filter.set_capacity_kbps(500); - RunFor(60 * 1000); - filter.set_capacity_kbps(300); - RunFor(60 * 1000); - filter.set_capacity_kbps(1000); - RunFor(60 * 1000); - const int kStartingCapacityKbps = 150; - const int kEndingCapacityKbps = 1500; - const int kStepKbps = 5; - const int kStepTimeMs = 1000; - for (int i = kStartingCapacityKbps; i <= kEndingCapacityKbps; - i += kStepKbps) { - filter.set_capacity_kbps(i); - RunFor(kStepTimeMs); - } - for (int i = kEndingCapacityKbps; i >= kStartingCapacityKbps; - i -= kStepKbps) { - filter.set_capacity_kbps(i); - RunFor(kStepTimeMs); - } - filter.set_capacity_kbps(150); - RunFor(120 * 1000); - filter.set_capacity_kbps(500); - RunFor(60 * 1000); -} - -TEST_P(BweSimulation, PacerChoke1000kbps500kbps1000kbps) { - AdaptiveVideoSource source(0, 30, 300, 0, 0); - PacedVideoSender sender(&uplink_, &source, GetParam()); - const int kFlowId = 0; - // CreateFlowIds() doesn't support passing int as a flow id, so we pass - // pointer instead. - DelayFilter delay(&uplink_, CreateFlowIds(&kFlowId, 1)); - delay.SetOneWayDelayMs(100); - ChokeFilter filter(&uplink_, 0); - RateCounterFilter counter(&uplink_, 0, "Receiver", bwe_names[GetParam()]); - PacketReceiver receiver(&uplink_, 0, GetParam(), true, true); - filter.set_capacity_kbps(1000); - filter.set_max_delay_ms(500); - RunFor(60 * 1000); - filter.set_capacity_kbps(500); - RunFor(60 * 1000); - filter.set_capacity_kbps(1000); - RunFor(60 * 1000); -} - -TEST_P(BweSimulation, PacerChoke10000kbps) { - PeriodicKeyFrameSource source(0, 30, 300, 0, 0, 1000); - PacedVideoSender sender(&uplink_, &source, GetParam()); - ChokeFilter filter(&uplink_, 0); - RateCounterFilter counter(&uplink_, 0, "Receiver", bwe_names[GetParam()]); - PacketReceiver receiver(&uplink_, 0, GetParam(), true, true); - filter.set_capacity_kbps(10000); - filter.set_max_delay_ms(500); - RunFor(60 * 1000); -} - -TEST_P(BweSimulation, PacerChoke200kbps30kbps200kbps) { - AdaptiveVideoSource source(0, 30, 300, 0, 0); - PacedVideoSender sender(&uplink_, &source, GetParam()); - ChokeFilter filter(&uplink_, 0); - RateCounterFilter counter(&uplink_, 0, "Receiver", bwe_names[GetParam()]); - PacketReceiver receiver(&uplink_, 0, GetParam(), true, true); - filter.set_capacity_kbps(200); - filter.set_max_delay_ms(500); - RunFor(60 * 1000); - filter.set_capacity_kbps(30); - RunFor(60 * 1000); - filter.set_capacity_kbps(200); - RunFor(60 * 1000); -} - -TEST_P(BweSimulation, Choke200kbps30kbps200kbps) { - AdaptiveVideoSource source(0, 30, 300, 0, 0); - VideoSender sender(&uplink_, &source, GetParam()); - ChokeFilter filter(&uplink_, 0); - RateCounterFilter counter(&uplink_, 0, "Receiver", bwe_names[GetParam()]); - PacketReceiver receiver(&uplink_, 0, GetParam(), true, true); - filter.set_capacity_kbps(200); - filter.set_max_delay_ms(500); - RunFor(60 * 1000); - filter.set_capacity_kbps(30); - RunFor(60 * 1000); - filter.set_capacity_kbps(200); - RunFor(60 * 1000); -} - -TEST_P(BweSimulation, PacerChoke50kbps15kbps50kbps) { - AdaptiveVideoSource source(0, 30, 300, 0, 0); - PacedVideoSender sender(&uplink_, &source, GetParam()); - ChokeFilter filter(&uplink_, 0); - RateCounterFilter counter(&uplink_, 0, "Receiver", bwe_names[GetParam()]); - PacketReceiver receiver(&uplink_, 0, GetParam(), true, true); - filter.set_capacity_kbps(50); - filter.set_max_delay_ms(500); - RunFor(60 * 1000); - filter.set_capacity_kbps(15); - RunFor(60 * 1000); - filter.set_capacity_kbps(50); - RunFor(60 * 1000); -} - -TEST_P(BweSimulation, Choke50kbps15kbps50kbps) { - AdaptiveVideoSource source(0, 30, 300, 0, 0); - VideoSender sender(&uplink_, &source, GetParam()); - ChokeFilter filter(&uplink_, 0); - RateCounterFilter counter(&uplink_, 0, "Receiver", bwe_names[GetParam()]); - PacketReceiver receiver(&uplink_, 0, GetParam(), true, true); - filter.set_capacity_kbps(50); - filter.set_max_delay_ms(500); - RunFor(60 * 1000); - filter.set_capacity_kbps(15); - RunFor(60 * 1000); - filter.set_capacity_kbps(50); - RunFor(60 * 1000); -} - -TEST_P(BweSimulation, GoogleWifiTrace3Mbps) { - AdaptiveVideoSource source(0, 30, 300, 0, 0); - VideoSender sender(&uplink_, &source, GetParam()); - RateCounterFilter counter1(&uplink_, 0, "sender_output", - bwe_names[GetParam()]); - TraceBasedDeliveryFilter filter(&uplink_, 0, "link_capacity"); - filter.set_max_delay_ms(500); - RateCounterFilter counter2(&uplink_, 0, "Receiver", bwe_names[GetParam()]); - PacketReceiver receiver(&uplink_, 0, GetParam(), true, true); - ASSERT_TRUE(filter.Init(test::ResourcePath("google-wifi-3mbps", "rx"))); - RunFor(300 * 1000); -} - -TEST_P(BweSimulation, LinearIncreasingCapacity) { - PeriodicKeyFrameSource source(0, 30, 300, 0, 0, 1000000); - PacedVideoSender sender(&uplink_, &source, GetParam()); - ChokeFilter filter(&uplink_, 0); - RateCounterFilter counter(&uplink_, 0, "Receiver", bwe_names[GetParam()]); - PacketReceiver receiver(&uplink_, 0, GetParam(), true, true); - filter.set_max_delay_ms(500); - const int kStartingCapacityKbps = 150; - const int kEndingCapacityKbps = 1500; - const int kStepKbps = 5; - const int kStepTimeMs = 1000; - - for (int i = kStartingCapacityKbps; i <= kEndingCapacityKbps; - i += kStepKbps) { - filter.set_capacity_kbps(i); - RunFor(kStepTimeMs); - } -} - -TEST_P(BweSimulation, LinearDecreasingCapacity) { - PeriodicKeyFrameSource source(0, 30, 300, 0, 0, 1000000); - PacedVideoSender sender(&uplink_, &source, GetParam()); - ChokeFilter filter(&uplink_, 0); - RateCounterFilter counter(&uplink_, 0, "Receiver", bwe_names[GetParam()]); - PacketReceiver receiver(&uplink_, 0, GetParam(), true, true); - filter.set_max_delay_ms(500); - const int kStartingCapacityKbps = 1500; - const int kEndingCapacityKbps = 150; - const int kStepKbps = -5; - const int kStepTimeMs = 1000; - - for (int i = kStartingCapacityKbps; i >= kEndingCapacityKbps; - i += kStepKbps) { - filter.set_capacity_kbps(i); - RunFor(kStepTimeMs); - } -} - -TEST_P(BweSimulation, PacerGoogleWifiTrace3Mbps) { - PeriodicKeyFrameSource source(0, 30, 300, 0, 0, 1000); - PacedVideoSender sender(&uplink_, &source, GetParam()); - int kFlowId = 0; - // CreateFlowIds() doesn't support passing int as a flow id, so we pass - // pointer instead. - DelayFilter delay(&uplink_, CreateFlowIds(&kFlowId, 1)); - delay.SetOneWayDelayMs(100); - RateCounterFilter counter1(&uplink_, 0, "sender_output", - bwe_names[GetParam()]); - TraceBasedDeliveryFilter filter(&uplink_, 0, "link_capacity"); - filter.set_max_delay_ms(500); - RateCounterFilter counter2(&uplink_, 0, "Receiver", bwe_names[GetParam()]); - PacketReceiver receiver(&uplink_, 0, GetParam(), true, true); - ASSERT_TRUE(filter.Init(test::ResourcePath("google-wifi-3mbps", "rx"))); - RunFor(300 * 1000); -} - -TEST_P(BweSimulation, PacerGoogleWifiTrace3MbpsLowFramerate) { - PeriodicKeyFrameSource source(0, 5, 300, 0, 0, 1000); - PacedVideoSender sender(&uplink_, &source, GetParam()); - RateCounterFilter counter1(&uplink_, 0, "sender_output", - bwe_names[GetParam()]); - TraceBasedDeliveryFilter filter(&uplink_, 0, "link_capacity"); - filter.set_max_delay_ms(500); - RateCounterFilter counter2(&uplink_, 0, "Receiver", bwe_names[GetParam()]); - PacketReceiver receiver(&uplink_, 0, GetParam(), true, true); - ASSERT_TRUE(filter.Init(test::ResourcePath("google-wifi-3mbps", "rx"))); - RunFor(300 * 1000); -} - -TEST_P(BweSimulation, SelfFairnessTest) { - Random prng(Clock::GetRealTimeClock()->TimeInMicroseconds()); - const int kAllFlowIds[] = {0, 1, 2, 3}; - const size_t kNumFlows = sizeof(kAllFlowIds) / sizeof(kAllFlowIds[0]); - std::unique_ptr sources[kNumFlows]; - std::unique_ptr senders[kNumFlows]; - for (size_t i = 0; i < kNumFlows; ++i) { - // Streams started 20 seconds apart to give them different advantage when - // competing for the bandwidth. - sources[i].reset(new AdaptiveVideoSource(kAllFlowIds[i], 30, 300, 0, - i * prng.Rand(39999))); - senders[i].reset(new VideoSender(&uplink_, sources[i].get(), GetParam())); - } - - ChokeFilter choke(&uplink_, CreateFlowIds(kAllFlowIds, kNumFlows)); - choke.set_capacity_kbps(1000); - - std::unique_ptr rate_counters[kNumFlows]; - for (size_t i = 0; i < kNumFlows; ++i) { - rate_counters[i].reset( - new RateCounterFilter(&uplink_, CreateFlowIds(&kAllFlowIds[i], 1), - "Receiver", bwe_names[GetParam()])); - } - - RateCounterFilter total_utilization( - &uplink_, CreateFlowIds(kAllFlowIds, kNumFlows), "total_utilization", - "Total_link_utilization"); - - std::unique_ptr receivers[kNumFlows]; - for (size_t i = 0; i < kNumFlows; ++i) { - receivers[i].reset(new PacketReceiver(&uplink_, kAllFlowIds[i], GetParam(), - i == 0, false)); - } - - RunFor(30 * 60 * 1000); -} - -TEST_P(BweSimulation, PacedSelfFairness50msTest) { - const int64_t kAverageOffsetMs = 20 * 1000; - const int kNumRmcatFlows = 4; - int64_t offsets_ms[kNumRmcatFlows]; - offsets_ms[0] = random_.Rand(2 * kAverageOffsetMs); - for (int i = 1; i < kNumRmcatFlows; ++i) { - offsets_ms[i] = offsets_ms[i - 1] + random_.Rand(2 * kAverageOffsetMs); - } - RunFairnessTest(GetParam(), kNumRmcatFlows, 0, 1000, 3000, 50, 50, 0, - offsets_ms); -} - -TEST_P(BweSimulation, PacedSelfFairness500msTest) { - const int64_t kAverageOffsetMs = 20 * 1000; - const int kNumRmcatFlows = 4; - int64_t offsets_ms[kNumRmcatFlows]; - offsets_ms[0] = random_.Rand(2 * kAverageOffsetMs); - for (int i = 1; i < kNumRmcatFlows; ++i) { - offsets_ms[i] = offsets_ms[i - 1] + random_.Rand(2 * kAverageOffsetMs); - } - RunFairnessTest(GetParam(), kNumRmcatFlows, 0, 1000, 3000, 500, 50, 0, - offsets_ms); -} - -TEST_P(BweSimulation, PacedSelfFairness1000msTest) { - const int64_t kAverageOffsetMs = 20 * 1000; - const int kNumRmcatFlows = 4; - int64_t offsets_ms[kNumRmcatFlows]; - offsets_ms[0] = random_.Rand(2 * kAverageOffsetMs); - for (int i = 1; i < kNumRmcatFlows; ++i) { - offsets_ms[i] = offsets_ms[i - 1] + random_.Rand(2 * kAverageOffsetMs); - } - RunFairnessTest(GetParam(), 4, 0, 1000, 3000, 1000, 50, 0, offsets_ms); -} - -TEST_P(BweSimulation, TcpFairness50msTest) { - const int64_t kAverageOffsetMs = 20 * 1000; - int64_t offset_ms[] = {random_.Rand(2 * kAverageOffsetMs), 0}; - RunFairnessTest(GetParam(), 1, 1, 1000, 2000, 50, 50, 0, offset_ms); -} - -TEST_P(BweSimulation, TcpFairness500msTest) { - const int64_t kAverageOffsetMs = 20 * 1000; - int64_t offset_ms[] = {random_.Rand(2 * kAverageOffsetMs), 0}; - RunFairnessTest(GetParam(), 1, 1, 1000, 2000, 500, 50, 0, offset_ms); -} - -TEST_P(BweSimulation, TcpFairness1000msTest) { - const int kAverageOffsetMs = 20 * 1000; - int64_t offset_ms[] = {random_.Rand(2 * kAverageOffsetMs), 0}; - RunFairnessTest(GetParam(), 1, 1, 1000, 2000, 1000, 50, 0, offset_ms); -} - -// The following test cases begin with "Evaluation" as a reference to the -// Internet draft https://tools.ietf.org/html/draft-ietf-rmcat-eval-test-01. - -TEST_P(BweSimulation, Evaluation1) { - RunVariableCapacity1SingleFlow(GetParam()); -} - -TEST_P(BweSimulation, Evaluation2) { - const size_t kNumFlows = 2; - RunVariableCapacity2MultipleFlows(GetParam(), kNumFlows); -} - -TEST_P(BweSimulation, Evaluation3) { - RunBidirectionalFlow(GetParam()); -} - -TEST_P(BweSimulation, Evaluation4) { - RunSelfFairness(GetParam()); -} - -TEST_P(BweSimulation, Evaluation5) { - RunRoundTripTimeFairness(GetParam()); -} - -TEST_P(BweSimulation, Evaluation6) { - RunLongTcpFairness(GetParam()); -} - -// Different calls to the Evaluation7 will create the same FileSizes -// and StartingTimes as long as the seeds remain unchanged. This is essential -// when calling it with multiple estimators for comparison purposes. -TEST_P(BweSimulation, Evaluation7) { - const int kNumTcpFiles = 10; - RunMultipleShortTcpFairness(GetParam(), - BweTest::GetFileSizesBytes(kNumTcpFiles), - BweTest::GetStartingTimesMs(kNumTcpFiles)); -} - -TEST_P(BweSimulation, Evaluation8) { - RunPauseResumeFlows(GetParam()); -} - -// Following test cases begin with "GoogCcComparison" run the -// evaluation test cases for both GoogCc and other calling RMCAT. - -TEST_P(BweSimulation, GoogCcComparison1) { - RunVariableCapacity1SingleFlow(GetParam()); - BweTest goog_cc_test(false); - goog_cc_test.RunVariableCapacity1SingleFlow(kSendSideEstimator); -} - -TEST_P(BweSimulation, GoogCcComparison2) { - const size_t kNumFlows = 2; - RunVariableCapacity2MultipleFlows(GetParam(), kNumFlows); - BweTest goog_cc_test(false); - goog_cc_test.RunVariableCapacity2MultipleFlows(kSendSideEstimator, kNumFlows); -} - -TEST_P(BweSimulation, GoogCcComparison3) { - RunBidirectionalFlow(GetParam()); - BweTest goog_cc_test(false); - goog_cc_test.RunBidirectionalFlow(kSendSideEstimator); -} - -TEST_P(BweSimulation, GoogCcComparison4) { - RunSelfFairness(GetParam()); - BweTest goog_cc_test(false); - goog_cc_test.RunSelfFairness(GetParam()); -} - -TEST_P(BweSimulation, GoogCcComparison5) { - RunRoundTripTimeFairness(GetParam()); - BweTest goog_cc_test(false); - goog_cc_test.RunRoundTripTimeFairness(kSendSideEstimator); -} - -TEST_P(BweSimulation, GoogCcComparison6) { - RunLongTcpFairness(GetParam()); - BweTest goog_cc_test(false); - goog_cc_test.RunLongTcpFairness(kSendSideEstimator); -} - -TEST_P(BweSimulation, GoogCcComparison7) { - const int kNumTcpFiles = 10; - - std::vector tcp_file_sizes_bytes = - BweTest::GetFileSizesBytes(kNumTcpFiles); - std::vector tcp_starting_times_ms = - BweTest::GetStartingTimesMs(kNumTcpFiles); - - RunMultipleShortTcpFairness(GetParam(), tcp_file_sizes_bytes, - tcp_starting_times_ms); - - BweTest goog_cc_test(false); - goog_cc_test.RunMultipleShortTcpFairness( - kSendSideEstimator, tcp_file_sizes_bytes, tcp_starting_times_ms); -} - -TEST_P(BweSimulation, GoogCcComparison8) { - RunPauseResumeFlows(GetParam()); - BweTest goog_cc_test(false); - goog_cc_test.RunPauseResumeFlows(kSendSideEstimator); -} - -TEST_P(BweSimulation, GoogCcComparisonChoke) { - int array[] = {1000, 500, 1000}; - std::vector capacities_kbps(array, array + 3); - RunChoke(GetParam(), capacities_kbps); - - BweTest goog_cc_test(false); - goog_cc_test.RunChoke(kSendSideEstimator, capacities_kbps); -} - -} // namespace bwe -} // namespace testing -} // namespace webrtc diff --git a/modules/remote_bitrate_estimator/remote_bitrate_estimators_test.cc b/modules/remote_bitrate_estimator/remote_bitrate_estimators_test.cc deleted file mode 100644 index f58e9d3995..0000000000 --- a/modules/remote_bitrate_estimator/remote_bitrate_estimators_test.cc +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Copyright (c) 2013 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. - */ - -#ifndef WEBRTC_WIN -#include -#endif - -#include -#include - -#include "modules/remote_bitrate_estimator/test/bwe.h" -#include "modules/remote_bitrate_estimator/test/bwe_test.h" -#include "modules/remote_bitrate_estimator/test/bwe_test_framework.h" -#include "modules/remote_bitrate_estimator/test/packet_receiver.h" -#include "modules/remote_bitrate_estimator/test/packet_sender.h" -#include "rtc_base/constructor_magic.h" -#include "rtc_base/random.h" -#include "system_wrappers/include/clock.h" -#include "test/field_trial.h" -#include "test/gtest.h" -#include "test/testsupport/file_utils.h" - -namespace webrtc { -namespace testing { -namespace bwe { - -// This test fixture is used to instantiate tests running with adaptive video -// senders. -class BweFeedbackTest - : public BweTest, - public ::testing::TestWithParam { - public: -#ifdef WEBRTC_WIN - BweFeedbackTest() - : BweTest(), random_(Clock::GetRealTimeClock()->TimeInMicroseconds()) {} -#else - BweFeedbackTest() - : BweTest(), - // Multiply the time by a random-ish odd number derived from the PID. - random_((getpid() | 1) * - Clock::GetRealTimeClock()->TimeInMicroseconds()) {} -#endif - virtual ~BweFeedbackTest() {} - - protected: - Random random_; - - private: - RTC_DISALLOW_COPY_AND_ASSIGN(BweFeedbackTest); -}; - -INSTANTIATE_TEST_SUITE_P(VideoSendersTest, - BweFeedbackTest, - ::testing::Values(kRembEstimator, kSendSideEstimator)); - -TEST_P(BweFeedbackTest, ConstantCapacity) { - AdaptiveVideoSource source(0, 30, 300, 0, 0); - PacedVideoSender sender(&uplink_, &source, GetParam()); - ChokeFilter filter(&uplink_, 0); - RateCounterFilter counter(&uplink_, 0, "Receiver", bwe_names[GetParam()]); - PacketReceiver receiver(&uplink_, 0, GetParam(), false, false); - const int kCapacityKbps = 1000; - filter.set_capacity_kbps(kCapacityKbps); - filter.set_max_delay_ms(500); - RunFor(180 * 1000); - PrintResults(kCapacityKbps, counter.GetBitrateStats(), 0, - receiver.GetDelayStats(), counter.GetBitrateStats()); -} - -TEST_P(BweFeedbackTest, Choke1000kbps500kbps1000kbps) { - AdaptiveVideoSource source(0, 30, 300, 0, 0); - PacedVideoSender sender(&uplink_, &source, GetParam()); - ChokeFilter filter(&uplink_, 0); - RateCounterFilter counter(&uplink_, 0, "Receiver", bwe_names[GetParam()]); - PacketReceiver receiver(&uplink_, 0, GetParam(), false, false); - const int kHighCapacityKbps = 1000; - const int kLowCapacityKbps = 500; - filter.set_capacity_kbps(kHighCapacityKbps); - filter.set_max_delay_ms(500); - RunFor(60 * 1000); - filter.set_capacity_kbps(kLowCapacityKbps); - RunFor(60 * 1000); - filter.set_capacity_kbps(kHighCapacityKbps); - RunFor(60 * 1000); - PrintResults((2 * kHighCapacityKbps + kLowCapacityKbps) / 3.0, - counter.GetBitrateStats(), 0, receiver.GetDelayStats(), - counter.GetBitrateStats()); -} - -TEST_P(BweFeedbackTest, Choke200kbps30kbps200kbps) { - AdaptiveVideoSource source(0, 30, 300, 0, 0); - PacedVideoSender sender(&uplink_, &source, GetParam()); - ChokeFilter filter(&uplink_, 0); - RateCounterFilter counter(&uplink_, 0, "Receiver", bwe_names[GetParam()]); - PacketReceiver receiver(&uplink_, 0, GetParam(), false, false); - const int kHighCapacityKbps = 200; - const int kLowCapacityKbps = 30; - filter.set_capacity_kbps(kHighCapacityKbps); - filter.set_max_delay_ms(500); - RunFor(60 * 1000); - filter.set_capacity_kbps(kLowCapacityKbps); - RunFor(60 * 1000); - filter.set_capacity_kbps(kHighCapacityKbps); - RunFor(60 * 1000); - - PrintResults((2 * kHighCapacityKbps + kLowCapacityKbps) / 3.0, - counter.GetBitrateStats(), 0, receiver.GetDelayStats(), - counter.GetBitrateStats()); -} - -TEST_P(BweFeedbackTest, Verizon4gDownlinkTest) { - AdaptiveVideoSource source(0, 30, 300, 0, 0); - VideoSender sender(&uplink_, &source, GetParam()); - RateCounterFilter counter1(&uplink_, 0, "sender_output", - bwe_names[GetParam()]); - TraceBasedDeliveryFilter filter(&uplink_, 0, "link_capacity"); - RateCounterFilter counter2(&uplink_, 0, "Receiver", bwe_names[GetParam()]); - PacketReceiver receiver(&uplink_, 0, GetParam(), false, false); - ASSERT_TRUE(filter.Init(test::ResourcePath("verizon4g-downlink", "rx"))); - RunFor(22 * 60 * 1000); - PrintResults(filter.GetBitrateStats().GetMean(), counter2.GetBitrateStats(), - 0, receiver.GetDelayStats(), counter2.GetBitrateStats()); -} - -// webrtc:3277 -TEST_P(BweFeedbackTest, GoogleWifiTrace3Mbps) { - AdaptiveVideoSource source(0, 30, 300, 0, 0); - VideoSender sender(&uplink_, &source, GetParam()); - RateCounterFilter counter1(&uplink_, 0, "sender_output", - bwe_names[GetParam()]); - TraceBasedDeliveryFilter filter(&uplink_, 0, "link_capacity"); - filter.set_max_delay_ms(500); - RateCounterFilter counter2(&uplink_, 0, "Receiver", bwe_names[GetParam()]); - PacketReceiver receiver(&uplink_, 0, GetParam(), false, false); - ASSERT_TRUE(filter.Init(test::ResourcePath("google-wifi-3mbps", "rx"))); - RunFor(300 * 1000); - PrintResults(filter.GetBitrateStats().GetMean(), counter2.GetBitrateStats(), - 0, receiver.GetDelayStats(), counter2.GetBitrateStats()); -} - -TEST_P(BweFeedbackTest, GoogleWifiTrace3MbpsStreaming) { - test::ScopedFieldTrials override_field_trials( - "WebRTC-BweWindowSizeInPackets/Enabled-100/" - "WebRTC-BweBackOffFactor/Enabled-0.95/"); - AdaptiveVideoSource source(0, 30, 300, 0, 0); - VideoSender sender(&uplink_, &source, GetParam()); - RateCounterFilter counter1(&uplink_, 0, "sender_output", - bwe_names[GetParam()]); - TraceBasedDeliveryFilter filter(&uplink_, 0, "link_capacity"); - filter.set_max_delay_ms(500); - RateCounterFilter counter2(&uplink_, 0, "Receiver", bwe_names[GetParam()]); - PacketReceiver receiver(&uplink_, 0, GetParam(), false, false); - ASSERT_TRUE(filter.Init(test::ResourcePath("google-wifi-3mbps", "rx"))); - RunFor(300 * 1000); - PrintResults(filter.GetBitrateStats().GetMean(), counter2.GetBitrateStats(), - 0, receiver.GetDelayStats(), counter2.GetBitrateStats()); -} - -TEST_P(BweFeedbackTest, PacedSelfFairness50msTest) { - int64_t kRttMs = 100; - int64_t kMaxJitterMs = 15; - - const int kNumRmcatFlows = 4; - int64_t offset_ms[kNumRmcatFlows]; - for (int i = 0; i < kNumRmcatFlows; ++i) { - offset_ms[i] = std::max(0, 5000 * i + random_.Rand(-1000, 1000)); - } - - RunFairnessTest(GetParam(), kNumRmcatFlows, 0, 300, 3000, 50, kRttMs, - kMaxJitterMs, offset_ms); -} - -TEST_P(BweFeedbackTest, PacedSelfFairness500msTest) { - int64_t kRttMs = 100; - int64_t kMaxJitterMs = 15; - - const int kNumRmcatFlows = 4; - int64_t offset_ms[kNumRmcatFlows]; - for (int i = 0; i < kNumRmcatFlows; ++i) { - offset_ms[i] = std::max(0, 5000 * i + random_.Rand(-1000, 1000)); - } - - RunFairnessTest(GetParam(), kNumRmcatFlows, 0, 300, 3000, 500, kRttMs, - kMaxJitterMs, offset_ms); -} - -TEST_P(BweFeedbackTest, PacedSelfFairness1000msTest) { - int64_t kRttMs = 100; - int64_t kMaxJitterMs = 15; - - const int kNumRmcatFlows = 4; - int64_t offset_ms[kNumRmcatFlows]; - for (int i = 0; i < kNumRmcatFlows; ++i) { - offset_ms[i] = std::max(0, 5000 * i + random_.Rand(-1000, 1000)); - } - - RunFairnessTest(GetParam(), kNumRmcatFlows, 0, 300, 3000, 1000, kRttMs, - kMaxJitterMs, offset_ms); -} - -TEST_P(BweFeedbackTest, TcpFairness50msTest) { - int64_t kRttMs = 100; - int64_t kMaxJitterMs = 15; - - int64_t offset_ms[2]; // One TCP, one RMCAT flow. - for (int i = 0; i < 2; ++i) { - offset_ms[i] = std::max(0, 5000 * i + random_.Rand(-1000, 1000)); - } - - RunFairnessTest(GetParam(), 1, 1, 300, 2000, 50, kRttMs, kMaxJitterMs, - offset_ms); -} - -TEST_P(BweFeedbackTest, TcpFairness500msTest) { - int64_t kRttMs = 100; - int64_t kMaxJitterMs = 15; - - int64_t offset_ms[2]; // One TCP, one RMCAT flow. - for (int i = 0; i < 2; ++i) { - offset_ms[i] = std::max(0, 5000 * i + random_.Rand(-1000, 1000)); - } - - RunFairnessTest(GetParam(), 1, 1, 300, 2000, 500, kRttMs, kMaxJitterMs, - offset_ms); -} - -TEST_P(BweFeedbackTest, TcpFairness1000msTest) { - int64_t kRttMs = 100; - int64_t kMaxJitterMs = 15; - - int64_t offset_ms[2]; // One TCP, one RMCAT flow. - for (int i = 0; i < 2; ++i) { - offset_ms[i] = std::max(0, 5000 * i + random_.Rand(-1000, 1000)); - } - - RunFairnessTest(GetParam(), 1, 1, 300, 2000, 1000, kRttMs, kMaxJitterMs, - offset_ms); -} -} // namespace bwe -} // namespace testing -} // namespace webrtc diff --git a/modules/remote_bitrate_estimator/test/bbr_paced_sender.cc b/modules/remote_bitrate_estimator/test/bbr_paced_sender.cc deleted file mode 100644 index 620fd1bb0c..0000000000 --- a/modules/remote_bitrate_estimator/test/bbr_paced_sender.cc +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) 2017 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 "modules/remote_bitrate_estimator/test/bbr_paced_sender.h" - -#include - -#include "api/transport/network_types.h" -#include "modules/pacing/paced_sender.h" -#include "modules/remote_bitrate_estimator/test/estimators/congestion_window.h" -#include "system_wrappers/include/clock.h" - -namespace webrtc { - -BbrPacedSender::BbrPacedSender(Clock* clock, - PacedSender::PacketSender* packet_sender, - RtcEventLog* event_log) - : clock_(clock), - packet_sender_(packet_sender), - estimated_bitrate_bps_(100000), - min_send_bitrate_kbps_(0), - pacing_bitrate_kbps_(0), - time_last_update_us_(clock->TimeInMicroseconds()), - time_last_update_ms_(clock->TimeInMilliseconds()), - next_packet_send_time_(clock_->TimeInMilliseconds()), - rounding_error_time_ms_(0.0f), - packets_(), - max_data_inflight_bytes_(10000), - congestion_window_(new testing::bwe::CongestionWindow()) {} -BbrPacedSender::~BbrPacedSender() {} - -void BbrPacedSender::SetEstimatedBitrateAndCongestionWindow( - uint32_t bitrate_bps, - bool in_probe_rtt, - uint64_t congestion_window) { - estimated_bitrate_bps_ = bitrate_bps; - max_data_inflight_bytes_ = congestion_window; -} - -void BbrPacedSender::SetMinBitrate(int min_send_bitrate_bps) { - min_send_bitrate_kbps_ = min_send_bitrate_bps / 1000; - pacing_bitrate_kbps_ = - std::max(min_send_bitrate_kbps_, estimated_bitrate_bps_ / 1000); -} - -void BbrPacedSender::InsertPacket(RtpPacketSender::Priority priority, - uint32_t ssrc, - uint16_t sequence_number, - int64_t capture_time_ms, - size_t bytes, - bool retransmission) { - int64_t now_ms = clock_->TimeInMilliseconds(); - if (capture_time_ms < 0) - capture_time_ms = now_ms; - packets_.push_back(new Packet(priority, ssrc, sequence_number, - capture_time_ms, now_ms, bytes, - retransmission)); -} - -int64_t BbrPacedSender::TimeUntilNextProcess() { - // Once errors absolute value hits 1 millisecond, add compensating term to - // the |next_packet_send_time_|, so that we can send packet earlier or later, - // depending on the error. - rounding_error_time_ms_ = std::min(rounding_error_time_ms_, 1.0f); - if (rounding_error_time_ms_ < -0.9f) - rounding_error_time_ms_ = -1.0f; - int64_t result = - std::max(next_packet_send_time_ + time_last_update_ms_ - - clock_->TimeInMilliseconds(), - 0); - if (rounding_error_time_ms_ == 1.0f || rounding_error_time_ms_ == -1.0f) { - next_packet_send_time_ -= rounding_error_time_ms_; - result = std::max(next_packet_send_time_ + time_last_update_ms_ - - clock_->TimeInMilliseconds(), - 0); - rounding_error_time_ms_ = 0; - } - return result; -} - -void BbrPacedSender::OnBytesAcked(size_t bytes) { - congestion_window_->AckReceived(bytes); -} - -void BbrPacedSender::Process() { - pacing_bitrate_kbps_ = - std::max(min_send_bitrate_kbps_, estimated_bitrate_bps_ / 1000); - // If we have nothing to send, try sending again in 1 millisecond. - if (packets_.empty()) { - next_packet_send_time_ = 1; - return; - } - // If congestion window doesn't allow sending, try again in 1 millisecond. - if (packets_.front()->size_in_bytes + congestion_window_->data_inflight() > - max_data_inflight_bytes_) { - next_packet_send_time_ = 1; - return; - } - bool sent = TryToSendPacket(packets_.front()); - if (sent) { - congestion_window_->PacketSent(packets_.front()->size_in_bytes); - delete packets_.front(); - packets_.pop_front(); - time_last_update_ms_ = clock_->TimeInMilliseconds(); - if (!packets_.empty()) { - // Calculate in what time we should send current packet. - next_packet_send_time_ = (packets_.front()->size_in_bytes * 8000 + - estimated_bitrate_bps_ / 2) / - estimated_bitrate_bps_; - // As rounding errors may happen, |rounding_error_time_ms_| could be - // positive or negative depending on packet was sent earlier or later, - // after it hits certain threshold we will send a packet earlier or later - // depending on error we had so far. - rounding_error_time_ms_ += - (next_packet_send_time_ - packets_.front()->size_in_bytes * 8000.0f / - estimated_bitrate_bps_ * 1.0f); - } else { - // If sending was unsuccessful try again in 1 millisecond. - next_packet_send_time_ = 1; - } - } -} - -bool BbrPacedSender::TryToSendPacket(Packet* packet) { - PacedPacketInfo pacing_info; - return packet_sender_->TimeToSendPacket( - packet->ssrc, packet->sequence_number, packet->capture_time_ms, - packet->retransmission, - pacing_info) != RtpPacketSendResult::kTransportUnavailable; -} - -} // namespace webrtc diff --git a/modules/remote_bitrate_estimator/test/bbr_paced_sender.h b/modules/remote_bitrate_estimator/test/bbr_paced_sender.h deleted file mode 100644 index c782fd946d..0000000000 --- a/modules/remote_bitrate_estimator/test/bbr_paced_sender.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2017 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. - */ - -#ifndef MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_BBR_PACED_SENDER_H_ -#define MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_BBR_PACED_SENDER_H_ - -#include -#include - -#include "modules/pacing/paced_sender.h" -#include "modules/pacing/pacer.h" - -namespace webrtc { -namespace testing { -namespace bwe { -class CongestionWindow; -} -} // namespace testing - -struct Packet { - Packet(RtpPacketSender::Priority priority, - uint32_t ssrc, - uint16_t seq_number, - int64_t capture_time_ms, - int64_t enqueue_time_ms, - size_t size_in_bytes, - bool retransmission) - : priority(priority), - ssrc(ssrc), - sequence_number(seq_number), - capture_time_ms(capture_time_ms), - enqueue_time_ms(enqueue_time_ms), - size_in_bytes(size_in_bytes), - retransmission(retransmission) {} - RtpPacketSender::Priority priority; - uint32_t ssrc; - uint16_t sequence_number; - int64_t capture_time_ms; - int64_t enqueue_time_ms; - size_t size_in_bytes; - bool retransmission; -}; - -class Clock; -class RtcEventLog; -struct Packet; -class BbrPacedSender : public Pacer { - public: - BbrPacedSender(Clock* clock, - PacedSender::PacketSender* packet_sender, - RtcEventLog* event_log); - ~BbrPacedSender() override; - void SetEstimatedBitrateAndCongestionWindow( - uint32_t bitrate_bps, - bool in_probe_rtt, - uint64_t congestion_window) override; - void SetMinBitrate(int min_send_bitrate_bps); - void InsertPacket(RtpPacketSender::Priority priority, - uint32_t ssrc, - uint16_t sequence_number, - int64_t capture_time_ms, - size_t bytes, - bool retransmission) override; - void SetAccountForAudioPackets(bool account_for_audio) override {} - int64_t TimeUntilNextProcess() override; - void OnBytesAcked(size_t bytes) override; - void Process() override; - bool TryToSendPacket(Packet* packet); - - private: - Clock* const clock_; - PacedSender::PacketSender* const packet_sender_; - uint32_t estimated_bitrate_bps_; - uint32_t min_send_bitrate_kbps_; - uint32_t pacing_bitrate_kbps_; - int64_t time_last_update_us_; - int64_t time_last_update_ms_; - int64_t next_packet_send_time_; - float rounding_error_time_ms_; - std::list packets_; - // TODO(gnish): integrate |max_data_inflight| into congestion window class. - size_t max_data_inflight_bytes_; - std::unique_ptr congestion_window_; -}; -} // namespace webrtc -#endif // MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_BBR_PACED_SENDER_H_ diff --git a/modules/remote_bitrate_estimator/test/bwe.cc b/modules/remote_bitrate_estimator/test/bwe.cc deleted file mode 100644 index b672ddde06..0000000000 --- a/modules/remote_bitrate_estimator/test/bwe.cc +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Copyright (c) 2015 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 "modules/remote_bitrate_estimator/test/bwe.h" - -#include -#include - -#include "modules/remote_bitrate_estimator/test/estimators/bbr.h" -#include "modules/remote_bitrate_estimator/test/estimators/nada.h" -#include "modules/remote_bitrate_estimator/test/estimators/remb.h" -#include "modules/remote_bitrate_estimator/test/estimators/send_side.h" -#include "modules/remote_bitrate_estimator/test/estimators/tcp.h" -#include "rtc_base/constructor_magic.h" -#include "rtc_base/numerics/safe_conversions.h" -#include "rtc_base/system/fallthrough.h" - -namespace webrtc { -namespace testing { -namespace bwe { - -const int kSetCapacity = 1000; - -BweReceiver::BweReceiver(int flow_id) - : flow_id_(flow_id), - received_packets_(kSetCapacity), - rate_counter_(), - loss_account_() {} - -BweReceiver::BweReceiver(int flow_id, int64_t window_size_ms) - : flow_id_(flow_id), - received_packets_(kSetCapacity), - rate_counter_(window_size_ms), - loss_account_() {} - -void BweReceiver::ReceivePacket(int64_t arrival_time_ms, - const MediaPacket& media_packet) { - if (received_packets_.size() == kSetCapacity) { - RelieveSetAndUpdateLoss(); - } - - received_packets_.Insert(media_packet.sequence_number(), - media_packet.send_time_ms(), arrival_time_ms, - media_packet.payload_size()); - - rate_counter_.UpdateRates(media_packet.send_time_ms() * 1000, - static_cast(media_packet.payload_size())); -} - -FeedbackPacket* BweReceiver::GetFeedback(int64_t now_ms) { - return nullptr; -} - -class NullBweSender : public BweSender { - public: - NullBweSender() {} - ~NullBweSender() override {} - - int GetFeedbackIntervalMs() const override { return 1000; } - void GiveFeedback(const FeedbackPacket& feedback) override {} - void OnPacketsSent(const Packets& packets) override {} - int64_t TimeUntilNextProcess() override { - return std::numeric_limits::max(); - } - void Process() override {} - - private: - RTC_DISALLOW_COPY_AND_ASSIGN(NullBweSender); -}; - -int64_t GetAbsSendTimeInMs(uint32_t abs_send_time) { - const int kInterArrivalShift = 26; - const int kAbsSendTimeInterArrivalUpshift = 8; - const double kTimestampToMs = - 1000.0 / static_cast(1 << kInterArrivalShift); - uint32_t timestamp = abs_send_time << kAbsSendTimeInterArrivalUpshift; - return static_cast(timestamp) * kTimestampToMs; -} - -BweSender* CreateBweSender(BandwidthEstimatorType estimator, - int kbps, - BitrateObserver* observer, - Clock* clock) { - switch (estimator) { - case kRembEstimator: - return new RembBweSender(kbps, observer, clock); - case kSendSideEstimator: - return new SendSideBweSender(kbps, observer, clock); - case kNadaEstimator: - return new NadaBweSender(kbps, observer, clock); - case kBbrEstimator: - return new BbrBweSender(observer, clock); - case kTcpEstimator: - RTC_FALLTHROUGH(); - case kNullEstimator: - return new NullBweSender(); - } - assert(false); - return NULL; -} - -BweReceiver* CreateBweReceiver(BandwidthEstimatorType type, - int flow_id, - bool plot) { - switch (type) { - case kRembEstimator: - return new RembReceiver(flow_id, plot); - case kSendSideEstimator: - return new SendSideBweReceiver(flow_id); - case kNadaEstimator: - return new NadaBweReceiver(flow_id); - case kBbrEstimator: - return new BbrBweReceiver(flow_id); - case kTcpEstimator: - return new TcpBweReceiver(flow_id); - case kNullEstimator: - return new BweReceiver(flow_id); - } - assert(false); - return NULL; -} - -// Take into account all LinkedSet content. -void BweReceiver::UpdateLoss() { - loss_account_.Add(LinkedSetPacketLossRatio()); -} - -// Preserve 10% latest packets and update packet loss based on the oldest -// 90%, that will be removed. -void BweReceiver::RelieveSetAndUpdateLoss() { - // Compute Loss for the whole LinkedSet and updates loss_account_. - UpdateLoss(); - - size_t num_preserved_elements = received_packets_.size() / 10; - PacketNodeIt it = received_packets_.begin(); - std::advance(it, num_preserved_elements); - - while (it != received_packets_.end()) { - received_packets_.Erase(it++); - } - - // Compute Loss for the preserved elements - loss_account_.Subtract(LinkedSetPacketLossRatio()); -} - -float BweReceiver::GlobalReceiverPacketLossRatio() { - UpdateLoss(); - return loss_account_.LossRatio(); -} - -// This function considers at most kSetCapacity = 1000 packets. -LossAccount BweReceiver::LinkedSetPacketLossRatio() { - if (received_packets_.empty()) { - return LossAccount(); - } - - size_t set_total_packets = received_packets_.Range(); - size_t set_received_packets = received_packets_.size(); - size_t set_lost_packets = set_total_packets - set_received_packets; - - return LossAccount(set_total_packets, set_lost_packets); -} - -uint32_t BweReceiver::RecentKbps() const { - return (rate_counter_.bits_per_second() + 500) / 1000; -} - -// Go through a fixed time window of most recent packets received and -// counts packets missing to obtain the packet loss ratio. If an unordered -// packet falls out of the timewindow it will be counted as missing. -// E.g.: for a timewindow covering 5 packets of the following arrival sequence -// {10 7 9 5 6} 8 3 2 4 1, the output will be 1/6 (#8 is considered as missing). -float BweReceiver::RecentPacketLossRatio() { - if (received_packets_.empty()) { - return 0.0f; - } - int number_packets_received = 0; - - PacketNodeIt node_it = received_packets_.begin(); // Latest. - - // Lowest timestamp limit, oldest one that should be checked. - int64_t time_limit_ms = node_it->arrival_time_ms - kPacketLossTimeWindowMs; - // Oldest and newest values found within the given time window. - int64_t oldest_seq_num = node_it->unwrapped_sequence_number; - int64_t newest_seq_num = oldest_seq_num; - - while (node_it != received_packets_.end()) { - if (node_it->arrival_time_ms < time_limit_ms) { - break; - } - int64_t seq_num = node_it->unwrapped_sequence_number; - newest_seq_num = std::max(newest_seq_num, seq_num); - oldest_seq_num = std::min(oldest_seq_num, seq_num); - ++node_it; - ++number_packets_received; - } - // Interval width between oldest and newest sequence number. - int gap = rtc::dchecked_cast(newest_seq_num - oldest_seq_num + 1); - - return static_cast(gap - number_packets_received) / gap; -} - -LinkedSet::LinkedSet(int capacity) : capacity_(capacity) {} - -LinkedSet::~LinkedSet() { -} - -void LinkedSet::Insert(uint16_t sequence_number, - int64_t send_time_ms, - int64_t arrival_time_ms, - size_t payload_size) { - auto unwrapped_sequence_number = unwrapper_.Unwrap(sequence_number); - auto it = map_.find(unwrapped_sequence_number); - // Handle duplicate unwrapped sequence number. - if (it != map_.end()) { - PacketNodeIt node_it = it->second; - PacketIdentifierNode& node = *node_it; - node.arrival_time_ms = arrival_time_ms; - // Move to front, without invalidating iterators. - list_.splice(list_.begin(), list_, node_it); - } else { - if (size() == capacity_) { - RemoveTail(); - } - // Push new element to the front of the list and insert it in the map. - PacketIdentifierNode new_head(unwrapped_sequence_number, send_time_ms, - arrival_time_ms, payload_size); - list_.push_front(new_head); - map_[unwrapped_sequence_number] = list_.begin(); - } -} - -void LinkedSet::RemoveTail() { - Erase(--list_.end()); -} - -void LinkedSet::Erase(PacketNodeIt node_it) { - map_.erase(node_it->unwrapped_sequence_number); - list_.erase(node_it); -} - -void LossAccount::Add(LossAccount rhs) { - num_total += rhs.num_total; - num_lost += rhs.num_lost; -} -void LossAccount::Subtract(LossAccount rhs) { - num_total -= rhs.num_total; - num_lost -= rhs.num_lost; -} - -float LossAccount::LossRatio() { - if (num_total == 0) - return 0.0f; - return static_cast(num_lost) / num_total; -} - -} // namespace bwe -} // namespace testing -} // namespace webrtc diff --git a/modules/remote_bitrate_estimator/test/bwe.h b/modules/remote_bitrate_estimator/test/bwe.h deleted file mode 100644 index cf2517c822..0000000000 --- a/modules/remote_bitrate_estimator/test/bwe.h +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (c) 2015 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. - */ - -#ifndef MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_BWE_H_ -#define MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_BWE_H_ - -#include -#include -#include -#include -#include -#include - -#include "modules/bitrate_controller/include/bitrate_controller.h" -#include "modules/include/module.h" -#include "modules/remote_bitrate_estimator/test/bwe_test_framework.h" -#include "modules/remote_bitrate_estimator/test/packet.h" -#include "rtc_base/constructor_magic.h" -#include "rtc_base/gtest_prod_util.h" -#include "rtc_base/numerics/sequence_number_util.h" -#include "system_wrappers/include/clock.h" - -namespace webrtc { -namespace testing { -namespace bwe { - -// Holds information for computing global packet loss. -struct LossAccount { - LossAccount() : num_total(0), num_lost(0) {} - LossAccount(size_t num_total, size_t num_lost) - : num_total(num_total), num_lost(num_lost) {} - void Add(LossAccount rhs); - void Subtract(LossAccount rhs); - float LossRatio(); - size_t num_total; - size_t num_lost; -}; - -// Holds only essential information about packets to be saved for -// further use, e.g. for calculating packet loss and receiving rate. -struct PacketIdentifierNode { - PacketIdentifierNode(int64_t unwrapped_sequence_number, - int64_t send_time_ms, - int64_t arrival_time_ms, - size_t payload_size) - : unwrapped_sequence_number(unwrapped_sequence_number), - send_time_ms(send_time_ms), - arrival_time_ms(arrival_time_ms), - payload_size(payload_size) {} - - int64_t unwrapped_sequence_number; - int64_t send_time_ms; - int64_t arrival_time_ms; - size_t payload_size; -}; - -typedef std::list::iterator PacketNodeIt; - -// FIFO implementation for a limited capacity set. -// Used for keeping the latest arrived packets while avoiding duplicates. -// Allows efficient insertion, deletion and search. -class LinkedSet { - public: - explicit LinkedSet(int capacity); - ~LinkedSet(); - - // If the arriving packet (identified by its sequence number) is already - // in the LinkedSet, move its Node to the head of the list. - // Else, add a PacketIdentifierNode n_ at the head of the list, - // calling RemoveTail() if the LinkedSet reached its maximum capacity. - void Insert(uint16_t sequence_number, - int64_t send_time_ms, - int64_t arrival_time_ms, - size_t payload_size); - - PacketNodeIt begin() { return list_.begin(); } - PacketNodeIt end() { return list_.end(); } - - bool empty() const { return list_.empty(); } - size_t size() const { return list_.size(); } - size_t capacity() const { return capacity_; } - - // Return size of interval covering current set, i.e.: - // unwrapped newest seq number - unwrapped oldest seq number + 1 - int64_t Range() const { - return empty() ? 0 : map_.rbegin()->first - map_.begin()->first + 1; - } - - void Erase(PacketNodeIt node_it); - - private: - // Pop oldest element from the back of the list and remove it from the map. - void RemoveTail(); - size_t capacity_; - // We want to keep track of the current oldest and newest sequence_numbers. - // To get strict weak ordering, we unwrap uint16_t into an int64_t. - SeqNumUnwrapper unwrapper_; - std::map map_; - std::list list_; -}; - -const int kMinBitrateKbps = 10; -const int kMaxBitrateKbps = 25000; - -class BweSender : public Module { - public: - BweSender() {} - explicit BweSender(int bitrate_kbps) : bitrate_kbps_(bitrate_kbps) {} - ~BweSender() override {} - - virtual int GetFeedbackIntervalMs() const = 0; - virtual void GiveFeedback(const FeedbackPacket& feedback) = 0; - virtual void OnPacketsSent(const Packets& packets) = 0; - - protected: - int bitrate_kbps_; - - private: - RTC_DISALLOW_COPY_AND_ASSIGN(BweSender); -}; - -class BweReceiver { - public: - explicit BweReceiver(int flow_id); - BweReceiver(int flow_id, int64_t window_size_ms); - - virtual ~BweReceiver() {} - - virtual void ReceivePacket(int64_t arrival_time_ms, - const MediaPacket& media_packet); - virtual FeedbackPacket* GetFeedback(int64_t now_ms); - - size_t GetSetCapacity() { return received_packets_.capacity(); } - double BitrateWindowS() const { return rate_counter_.BitrateWindowS(); } - uint32_t RecentKbps() const; // Receiving Rate. - - // Computes packet loss during an entire simulation, up to 4 billion packets. - float GlobalReceiverPacketLossRatio(); // Plot histogram. - float RecentPacketLossRatio(); // Plot dynamics. - - static const int64_t kPacketLossTimeWindowMs = 500; - static const int64_t kReceivingRateTimeWindowMs = 1000; - - protected: - int flow_id_; - // Deals with packets sent more than once. - LinkedSet received_packets_; - // Used for calculating recent receiving rate. - RateCounter rate_counter_; - - private: - FRIEND_TEST_ALL_PREFIXES(BweReceiverTest, RecentKbps); - FRIEND_TEST_ALL_PREFIXES(BweReceiverTest, Loss); - - void UpdateLoss(); - void RelieveSetAndUpdateLoss(); - // Packet loss for packets stored in the LinkedSet, up to 1000 packets. - // Used to update global loss account whenever the set is filled and cleared. - LossAccount LinkedSetPacketLossRatio(); - - // Used for calculating global packet loss ratio. - LossAccount loss_account_; -}; - -enum BandwidthEstimatorType { - kNullEstimator, - kNadaEstimator, - kRembEstimator, - kSendSideEstimator, - kTcpEstimator, - kBbrEstimator -}; - -const char* const bwe_names[] = {"Null", "NADA", "REMB", - "GoogCc", "TCP", "BBR"}; - -int64_t GetAbsSendTimeInMs(uint32_t abs_send_time); - -BweSender* CreateBweSender(BandwidthEstimatorType estimator, - int kbps, - BitrateObserver* observer, - Clock* clock); - -BweReceiver* CreateBweReceiver(BandwidthEstimatorType type, - int flow_id, - bool plot); -} // namespace bwe -} // namespace testing -} // namespace webrtc -#endif // MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_BWE_H_ diff --git a/modules/remote_bitrate_estimator/test/bwe_test.cc b/modules/remote_bitrate_estimator/test/bwe_test.cc deleted file mode 100644 index 9fad58dc28..0000000000 --- a/modules/remote_bitrate_estimator/test/bwe_test.cc +++ /dev/null @@ -1,1005 +0,0 @@ -/* - * Copyright (c) 2013 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 "modules/remote_bitrate_estimator/test/bwe_test.h" - -#include -#include - -#include "modules/include/module_common_types.h" -#include "modules/remote_bitrate_estimator/test/bwe_test_framework.h" -#include "modules/remote_bitrate_estimator/test/metric_recorder.h" -#include "modules/remote_bitrate_estimator/test/packet_receiver.h" -#include "modules/remote_bitrate_estimator/test/packet_sender.h" -#include "rtc_base/arraysize.h" -#include "system_wrappers/include/clock.h" -#include "system_wrappers/include/field_trial.h" -#include "test/testsupport/perf_test.h" - -using std::vector; - -namespace { -const int kQuickTestTimeoutMs = 500; - -double SafeDiv(double a, double b) { - return b ? a / b : 0; -} -} - -namespace webrtc { -namespace testing { -namespace bwe { - -PacketProcessorRunner::PacketProcessorRunner(PacketProcessor* processor) - : processor_(processor) {} - -PacketProcessorRunner::PacketProcessorRunner( - const PacketProcessorRunner& runner) = default; - -PacketProcessorRunner::~PacketProcessorRunner() { - for (Packet* packet : queue_) - delete packet; -} - -bool PacketProcessorRunner::RunsProcessor( - const PacketProcessor* processor) const { - return processor == processor_; -} - -void PacketProcessorRunner::RunFor(int64_t time_ms, - int64_t time_now_ms, - Packets* in_out) { - Packets to_process; - FindPacketsToProcess(processor_->flow_ids(), in_out, &to_process); - processor_->RunFor(time_ms, &to_process); - QueuePackets(&to_process, time_now_ms * 1000); - if (!to_process.empty()) { - processor_->Plot(to_process.back()->send_time_ms()); - } - in_out->merge(to_process, DereferencingComparator); -} - -void PacketProcessorRunner::FindPacketsToProcess(const FlowIds& flow_ids, - Packets* in, - Packets* out) { - assert(out->empty()); - for (Packets::iterator it = in->begin(); it != in->end();) { - // TODO(holmer): Further optimize this by looking for consecutive flow ids - // in the packet list and only doing the binary search + splice once for a - // sequence. - if (flow_ids.find((*it)->flow_id()) != flow_ids.end()) { - Packets::iterator next = it; - ++next; - out->splice(out->end(), *in, it); - it = next; - } else { - ++it; - } - } -} - -void PacketProcessorRunner::QueuePackets(Packets* batch, - int64_t end_of_batch_time_us) { - queue_.merge(*batch, DereferencingComparator); - if (queue_.empty()) { - return; - } - Packets::iterator it = queue_.begin(); - for (; it != queue_.end(); ++it) { - if ((*it)->send_time_us() > end_of_batch_time_us) { - break; - } - } - Packets to_transfer; - to_transfer.splice(to_transfer.begin(), queue_, queue_.begin(), it); - batch->merge(to_transfer, DereferencingComparator); -} - -// Plot link capacity by default. -BweTest::BweTest() : BweTest(true) {} - -BweTest::BweTest(bool plot_capacity) - : run_time_ms_(0), - time_now_ms_(-1), - simulation_interval_ms_(-1), - plot_total_available_capacity_(plot_capacity) { - links_.push_back(&uplink_); - links_.push_back(&downlink_); -} - -BweTest::~BweTest() { - for (Packet* packet : packets_) - delete packet; -} - -void BweTest::SetUp() { - const ::testing::TestInfo* const test_info = - ::testing::UnitTest::GetInstance()->current_test_info(); - std::string test_name = std::string(test_info->test_case_name()) + "_" + - std::string(test_info->name()); - BWE_TEST_LOGGING_GLOBAL_CONTEXT(test_name); - BWE_TEST_LOGGING_GLOBAL_ENABLE(false); -} - -Link::Link() = default; -Link::~Link() = default; - -void Link::AddPacketProcessor(PacketProcessor* processor, - ProcessorType processor_type) { - assert(processor); - switch (processor_type) { - case kSender: - senders_.push_back(static_cast(processor)); - break; - case kReceiver: - receivers_.push_back(static_cast(processor)); - break; - case kRegular: - break; - } - processors_.push_back(PacketProcessorRunner(processor)); -} - -void Link::RemovePacketProcessor(PacketProcessor* processor) { - for (std::vector::iterator it = processors_.begin(); - it != processors_.end(); ++it) { - if (it->RunsProcessor(processor)) { - processors_.erase(it); - return; - } - } - assert(false); -} - -// Ownership of the created packets is handed over to the caller. -void Link::Run(int64_t run_for_ms, int64_t now_ms, Packets* packets) { - for (auto& processor : processors_) { - processor.RunFor(run_for_ms, now_ms, packets); - } -} - -void BweTest::VerboseLogging(bool enable) { - BWE_TEST_LOGGING_GLOBAL_ENABLE(enable); -} - -void BweTest::RunFor(int64_t time_ms) { - // Set simulation interval from first packet sender. - // TODO(holmer): Support different feedback intervals for different flows. - - // For quick perf tests ignore passed timeout - if (field_trial::IsEnabled("WebRTC-QuickPerfTest")) { - time_ms = kQuickTestTimeoutMs; - } - if (!uplink_.senders().empty()) { - simulation_interval_ms_ = uplink_.senders()[0]->GetFeedbackIntervalMs(); - } else if (!downlink_.senders().empty()) { - simulation_interval_ms_ = downlink_.senders()[0]->GetFeedbackIntervalMs(); - } - assert(simulation_interval_ms_ > 0); - if (time_now_ms_ == -1) { - time_now_ms_ = simulation_interval_ms_; - } - for (run_time_ms_ += time_ms; - time_now_ms_ <= run_time_ms_ - simulation_interval_ms_; - time_now_ms_ += simulation_interval_ms_) { - // Packets are first generated on the first link, passed through all the - // PacketProcessors and PacketReceivers. The PacketReceivers produces - // FeedbackPackets which are then processed by the next link, where they - // at some point will be consumed by a PacketSender. - for (Link* link : links_) - link->Run(simulation_interval_ms_, time_now_ms_, &packets_); - } -} - -std::string BweTest::GetTestName() const { - const ::testing::TestInfo* const test_info = - ::testing::UnitTest::GetInstance()->current_test_info(); - return std::string(test_info->name()); -} - -void BweTest::PrintResults(double max_throughput_kbps, - Stats throughput_kbps, - int flow_id, - Stats flow_delay_ms, - Stats flow_throughput_kbps) { - std::map> flow_delays_ms; - flow_delays_ms[flow_id] = flow_delay_ms; - std::map> flow_throughputs_kbps; - flow_throughputs_kbps[flow_id] = flow_throughput_kbps; - PrintResults(max_throughput_kbps, throughput_kbps, flow_delays_ms, - flow_throughputs_kbps); -} - -void BweTest::PrintResults(double max_throughput_kbps, - Stats throughput_kbps, - std::map> flow_delay_ms, - std::map> flow_throughput_kbps) { - double utilization = SafeDiv(throughput_kbps.GetMean(), max_throughput_kbps); - webrtc::test::PrintResult("BwePerformance", GetTestName(), "Utilization", - utilization * 100.0, "%", false); - webrtc::test::PrintResult( - "BwePerformance", GetTestName(), "Utilization var coeff", - SafeDiv(throughput_kbps.GetStdDev(), throughput_kbps.GetMean()), "", - false); - std::stringstream ss; - for (auto& kv : flow_throughput_kbps) { - ss.str(""); - ss << "Throughput flow " << kv.first; - webrtc::test::PrintResultMeanAndError("BwePerformance", GetTestName(), - ss.str(), kv.second.GetMean(), - kv.second.GetStdDev(), "kbps", false); - } - for (auto& kv : flow_delay_ms) { - ss.str(""); - ss << "Delay flow " << kv.first; - webrtc::test::PrintResultMeanAndError("BwePerformance", GetTestName(), - ss.str(), kv.second.GetMean(), - kv.second.GetStdDev(), "ms", false); - } - double fairness_index = 1.0; - if (!flow_throughput_kbps.empty()) { - double squared_bitrate_sum = 0.0; - fairness_index = 0.0; - for (auto kv : flow_throughput_kbps) { - squared_bitrate_sum += kv.second.GetMean() * kv.second.GetMean(); - fairness_index += kv.second.GetMean(); - } - fairness_index *= SafeDiv( - fairness_index, flow_throughput_kbps.size() * squared_bitrate_sum); - } - webrtc::test::PrintResult("BwePerformance", GetTestName(), "Fairness", - fairness_index * 100, "%", false); -} - -void BweTest::RunFairnessTest(BandwidthEstimatorType bwe_type, - size_t num_media_flows, - size_t num_tcp_flows, - int64_t run_time_seconds, - uint32_t capacity_kbps, - int64_t max_delay_ms, - int64_t rtt_ms, - int64_t max_jitter_ms, - const int64_t* offsets_ms) { - RunFairnessTest(bwe_type, num_media_flows, num_tcp_flows, run_time_seconds, - capacity_kbps, max_delay_ms, rtt_ms, max_jitter_ms, - offsets_ms, "Fairness_test", bwe_names[bwe_type]); -} - -void BweTest::RunFairnessTest(BandwidthEstimatorType bwe_type, - size_t num_media_flows, - size_t num_tcp_flows, - int64_t run_time_seconds, - uint32_t capacity_kbps, - int64_t max_delay_ms, - int64_t rtt_ms, - int64_t max_jitter_ms, - const int64_t* offsets_ms, - const std::string& title, - const std::string& flow_name) { - std::set all_flow_ids; - std::set media_flow_ids; - std::set tcp_flow_ids; - int next_flow_id = 0; - for (size_t i = 0; i < num_media_flows; ++i) { - media_flow_ids.insert(next_flow_id); - all_flow_ids.insert(next_flow_id); - ++next_flow_id; - } - for (size_t i = 0; i < num_tcp_flows; ++i) { - tcp_flow_ids.insert(next_flow_id); - all_flow_ids.insert(next_flow_id); - ++next_flow_id; - } - - std::vector sources; - std::vector senders; - std::vector metric_recorders; - - int64_t max_offset_ms = 0; - - for (int media_flow : media_flow_ids) { - sources.push_back(new AdaptiveVideoSource(media_flow, 30, 300, 0, - offsets_ms[media_flow])); - senders.push_back(new PacedVideoSender(&uplink_, sources.back(), bwe_type)); - max_offset_ms = std::max(max_offset_ms, offsets_ms[media_flow]); - } - - for (int tcp_flow : tcp_flow_ids) { - senders.push_back(new TcpSender(&uplink_, tcp_flow, offsets_ms[tcp_flow])); - max_offset_ms = std::max(max_offset_ms, offsets_ms[tcp_flow]); - } - - ChokeFilter choke(&uplink_, all_flow_ids); - choke.set_capacity_kbps(capacity_kbps); - choke.set_max_delay_ms(max_delay_ms); - LinkShare link_share(&choke); - - int64_t one_way_delay_ms = rtt_ms / 2; - DelayFilter delay_uplink(&uplink_, all_flow_ids); - delay_uplink.SetOneWayDelayMs(one_way_delay_ms); - - JitterFilter jitter(&uplink_, all_flow_ids); - jitter.SetMaxJitter(max_jitter_ms); - - std::vector rate_counters; - rate_counters.reserve(media_flow_ids.size()); - for (int flow : media_flow_ids) { - rate_counters.push_back( - new RateCounterFilter(&uplink_, flow, "Receiver", bwe_names[bwe_type])); - } - for (int flow : tcp_flow_ids) { - rate_counters.push_back(new RateCounterFilter(&uplink_, flow, "Receiver", - bwe_names[kTcpEstimator])); - } - - RateCounterFilter total_utilization( - &uplink_, all_flow_ids, "total_utilization", "Total_link_utilization"); - - std::vector receivers; - // Delays is being plotted only for the first flow. - // To plot all of them, replace "i == 0" with "true" on new PacketReceiver(). - for (int media_flow : media_flow_ids) { - metric_recorders.push_back( - new MetricRecorder(bwe_names[bwe_type], static_cast(media_flow), - senders[media_flow], &link_share)); - receivers.push_back(new PacketReceiver(&uplink_, media_flow, bwe_type, - media_flow == 0, false, - metric_recorders[media_flow])); - metric_recorders[media_flow]->set_plot_available_capacity( - media_flow == 0 && plot_total_available_capacity_); - metric_recorders[media_flow]->set_start_computing_metrics_ms(max_offset_ms); - } - // Delays is not being plotted only for TCP flows. To plot all of them, - // replace first "false" occurence with "true" on new PacketReceiver(). - for (int tcp_flow : tcp_flow_ids) { - metric_recorders.push_back( - new MetricRecorder(bwe_names[kTcpEstimator], static_cast(tcp_flow), - senders[tcp_flow], &link_share)); - receivers.push_back(new PacketReceiver(&uplink_, tcp_flow, kTcpEstimator, - false, false, - metric_recorders[tcp_flow])); - metric_recorders[tcp_flow]->set_plot_available_capacity( - tcp_flow == 0 && plot_total_available_capacity_); - } - - DelayFilter delay_downlink(&downlink_, all_flow_ids); - delay_downlink.SetOneWayDelayMs(one_way_delay_ms); - - RunFor(run_time_seconds * 1000); - - std::map> flow_throughput_kbps; - for (RateCounterFilter* rate_counter : rate_counters) { - int flow_id = *rate_counter->flow_ids().begin(); - flow_throughput_kbps[flow_id] = rate_counter->GetBitrateStats(); - } - - std::map> flow_delay_ms; - for (PacketReceiver* receiver : receivers) { - int flow_id = *receiver->flow_ids().begin(); - flow_delay_ms[flow_id] = receiver->GetDelayStats(); - } - - PrintResults(capacity_kbps, total_utilization.GetBitrateStats(), - flow_delay_ms, flow_throughput_kbps); - - if (!field_trial::IsEnabled("WebRTC-QuickPerfTest")) { - for (int i : all_flow_ids) { - metric_recorders[i]->PlotThroughputHistogram( - title, flow_name, static_cast(num_media_flows), 0); - - metric_recorders[i]->PlotLossHistogram(title, flow_name, - static_cast(num_media_flows), - receivers[i]->GlobalPacketLoss()); - } - - // Pointless to show delay histogram for TCP flow. - for (int i : media_flow_ids) { - metric_recorders[i]->PlotDelayHistogram(title, bwe_names[bwe_type], - static_cast(num_media_flows), - one_way_delay_ms); - BWE_TEST_LOGGING_BASELINEBAR(5, bwe_names[bwe_type], one_way_delay_ms, i); - } - } - - for (VideoSource* source : sources) - delete source; - for (PacketSender* sender : senders) - delete sender; - for (RateCounterFilter* rate_counter : rate_counters) - delete rate_counter; - for (PacketReceiver* receiver : receivers) - delete receiver; - for (MetricRecorder* recorder : metric_recorders) - delete recorder; -} - -void BweTest::RunChoke(BandwidthEstimatorType bwe_type, - std::vector capacities_kbps) { - int flow_id = bwe_type; - AdaptiveVideoSource source(flow_id, 30, 300, 0, 0); - VideoSender sender(&uplink_, &source, bwe_type); - ChokeFilter choke(&uplink_, flow_id); - LinkShare link_share(&choke); - MetricRecorder metric_recorder(bwe_names[bwe_type], flow_id, &sender, - &link_share); - PacketReceiver receiver(&uplink_, flow_id, bwe_type, true, false, - &metric_recorder); - metric_recorder.set_plot_available_capacity(plot_total_available_capacity_); - - choke.set_max_delay_ms(500); - const int64_t kRunTimeMs = 60 * 1000; - - std::stringstream title("Choke"); - char delimiter = '_'; - - for (auto it = capacities_kbps.begin(); it != capacities_kbps.end(); ++it) { - choke.set_capacity_kbps(*it); - RunFor(kRunTimeMs); - title << delimiter << (*it); - delimiter = '-'; - } - - title << "_kbps,_" << (kRunTimeMs / 1000) << "s_each"; - metric_recorder.PlotThroughputHistogram(title.str(), bwe_names[bwe_type], 1, - 0); - metric_recorder.PlotDelayHistogram(title.str(), bwe_names[bwe_type], 1, 0); - // receiver.PlotLossHistogram(title, bwe_names[bwe_type], 1); - // receiver.PlotObjectiveHistogram(title, bwe_names[bwe_type], 1); -} - -// 5.1. Single Video and Audio media traffic, forward direction. -void BweTest::RunVariableCapacity1SingleFlow(BandwidthEstimatorType bwe_type) { - const int kFlowId = 0; // Arbitrary value. - AdaptiveVideoSource source(kFlowId, 30, 300, 0, 0); - PacedVideoSender sender(&uplink_, &source, bwe_type); - - DefaultEvaluationFilter up_filter(&uplink_, kFlowId); - LinkShare link_share(&(up_filter.choke)); - MetricRecorder metric_recorder(bwe_names[bwe_type], kFlowId, &sender, - &link_share); - - PacketReceiver receiver(&uplink_, kFlowId, bwe_type, true, true, - &metric_recorder); - - metric_recorder.set_plot_available_capacity(plot_total_available_capacity_); - - DelayFilter down_filter(&downlink_, kFlowId); - down_filter.SetOneWayDelayMs(kOneWayDelayMs); - - // Test also with one way propagation delay = 100ms. - // up_filter.delay.SetOneWayDelayMs(100); - // down_filter.SetOneWayDelayMs(100); - - up_filter.choke.set_capacity_kbps(1000); - RunFor(40 * 1000); // 0-40s. - up_filter.choke.set_capacity_kbps(2500); - RunFor(20 * 1000); // 40-60s. - up_filter.choke.set_capacity_kbps(600); - RunFor(20 * 1000); // 60-80s. - up_filter.choke.set_capacity_kbps(1000); - RunFor(20 * 1000); // 80-100s. - - std::string title("5.1_Variable_capacity_single_flow"); - metric_recorder.PlotThroughputHistogram(title, bwe_names[bwe_type], 1, 0); - metric_recorder.PlotDelayHistogram(title, bwe_names[bwe_type], 1, - kOneWayDelayMs); - metric_recorder.PlotLossHistogram(title, bwe_names[bwe_type], 1, - receiver.GlobalPacketLoss()); - BWE_TEST_LOGGING_BASELINEBAR(5, bwe_names[bwe_type], kOneWayDelayMs, kFlowId); -} - -// 5.2. Two forward direction competing flows, variable capacity. -void BweTest::RunVariableCapacity2MultipleFlows(BandwidthEstimatorType bwe_type, - size_t num_flows) { - std::vector sources; - std::vector senders; - std::vector metric_recorders; - std::vector receivers; - - const int64_t kStartingApartMs = 0; // Flows initialized simultaneously. - - for (size_t i = 0; i < num_flows; ++i) { - sources.push_back(new AdaptiveVideoSource(static_cast(i), 30, 300, 0, - i * kStartingApartMs)); - senders.push_back(new VideoSender(&uplink_, sources[i], bwe_type)); - } - - FlowIds flow_ids = CreateFlowIdRange(0, static_cast(num_flows - 1)); - - DefaultEvaluationFilter up_filter(&uplink_, flow_ids); - LinkShare link_share(&(up_filter.choke)); - - RateCounterFilter total_utilization(&uplink_, flow_ids, "Total_utilization", - "Total_link_utilization"); - - // Delays is being plotted only for the first flow. - // To plot all of them, replace "i == 0" with "true" on new PacketReceiver(). - for (size_t i = 0; i < num_flows; ++i) { - metric_recorders.push_back(new MetricRecorder( - bwe_names[bwe_type], static_cast(i), senders[i], &link_share)); - - receivers.push_back(new PacketReceiver(&uplink_, static_cast(i), - bwe_type, i == 0, false, - metric_recorders[i])); - metric_recorders[i]->set_plot_available_capacity( - i == 0 && plot_total_available_capacity_); - } - - DelayFilter down_filter(&downlink_, flow_ids); - down_filter.SetOneWayDelayMs(kOneWayDelayMs); - // Test also with one way propagation delay = 100ms. - // up_filter.delay.SetOneWayDelayMs(100); - // down_filter.SetOneWayDelayMs(100); - - up_filter.choke.set_capacity_kbps(4000); - RunFor(25 * 1000); // 0-25s. - up_filter.choke.set_capacity_kbps(2000); - RunFor(25 * 1000); // 25-50s. - up_filter.choke.set_capacity_kbps(3500); - RunFor(25 * 1000); // 50-75s. - up_filter.choke.set_capacity_kbps(1000); - RunFor(25 * 1000); // 75-100s. - up_filter.choke.set_capacity_kbps(2000); - RunFor(25 * 1000); // 100-125s. - - std::string title("5.2_Variable_capacity_two_flows"); - for (size_t i = 0; i < num_flows; ++i) { - metric_recorders[i]->PlotThroughputHistogram(title, bwe_names[bwe_type], - num_flows, 0); - metric_recorders[i]->PlotDelayHistogram(title, bwe_names[bwe_type], - num_flows, kOneWayDelayMs); - metric_recorders[i]->PlotLossHistogram(title, bwe_names[bwe_type], - num_flows, - receivers[i]->GlobalPacketLoss()); - BWE_TEST_LOGGING_BASELINEBAR(5, bwe_names[bwe_type], kOneWayDelayMs, i); - } - - for (VideoSource* source : sources) - delete source; - for (PacketSender* sender : senders) - delete sender; - for (MetricRecorder* recorder : metric_recorders) - delete recorder; - for (PacketReceiver* receiver : receivers) - delete receiver; -} - -// 5.3. Bi-directional RMCAT flows. -void BweTest::RunBidirectionalFlow(BandwidthEstimatorType bwe_type) { - enum direction { kForward = 0, kBackward }; - const size_t kNumFlows = 2; - std::unique_ptr sources[kNumFlows]; - std::unique_ptr senders[kNumFlows]; - std::unique_ptr metric_recorders[kNumFlows]; - std::unique_ptr receivers[kNumFlows]; - - sources[kForward].reset(new AdaptiveVideoSource(kForward, 30, 300, 0, 0)); - senders[kForward].reset( - new VideoSender(&uplink_, sources[kForward].get(), bwe_type)); - - sources[kBackward].reset(new AdaptiveVideoSource(kBackward, 30, 300, 0, 0)); - senders[kBackward].reset( - new VideoSender(&downlink_, sources[kBackward].get(), bwe_type)); - - DefaultEvaluationFilter up_filter(&uplink_, kForward); - LinkShare up_link_share(&(up_filter.choke)); - - metric_recorders[kForward].reset(new MetricRecorder( - bwe_names[bwe_type], kForward, senders[kForward].get(), &up_link_share)); - receivers[kForward].reset( - new PacketReceiver(&uplink_, kForward, bwe_type, true, false, - metric_recorders[kForward].get())); - - metric_recorders[kForward].get()->set_plot_available_capacity( - plot_total_available_capacity_); - - DefaultEvaluationFilter down_filter(&downlink_, kBackward); - LinkShare down_link_share(&(down_filter.choke)); - - metric_recorders[kBackward].reset( - new MetricRecorder(bwe_names[bwe_type], kBackward, - senders[kBackward].get(), &down_link_share)); - receivers[kBackward].reset( - new PacketReceiver(&downlink_, kBackward, bwe_type, true, false, - metric_recorders[kBackward].get())); - - metric_recorders[kBackward].get()->set_plot_available_capacity( - plot_total_available_capacity_); - - // Test also with one way propagation delay = 100ms. - // up_filter.delay.SetOneWayDelayMs(100); - // down_filter.delay.SetOneWayDelayMs(100); - - up_filter.choke.set_capacity_kbps(2000); - down_filter.choke.set_capacity_kbps(2000); - RunFor(20 * 1000); // 0-20s. - - up_filter.choke.set_capacity_kbps(1000); - RunFor(15 * 1000); // 20-35s. - - down_filter.choke.set_capacity_kbps(800); - RunFor(5 * 1000); // 35-40s. - - up_filter.choke.set_capacity_kbps(500); - RunFor(20 * 1000); // 40-60s. - - up_filter.choke.set_capacity_kbps(2000); - RunFor(10 * 1000); // 60-70s. - - down_filter.choke.set_capacity_kbps(2000); - RunFor(30 * 1000); // 70-100s. - - std::string title("5.3_Bidirectional_flows"); - for (size_t i = 0; i < kNumFlows; ++i) { - metric_recorders[i].get()->PlotThroughputHistogram( - title, bwe_names[bwe_type], kNumFlows, 0); - metric_recorders[i].get()->PlotDelayHistogram(title, bwe_names[bwe_type], - kNumFlows, kOneWayDelayMs); - metric_recorders[i].get()->PlotLossHistogram( - title, bwe_names[bwe_type], kNumFlows, - receivers[i].get()->GlobalPacketLoss()); - BWE_TEST_LOGGING_BASELINEBAR(5, bwe_names[bwe_type], kOneWayDelayMs, i); - } -} - -// 5.4. Three forward direction competing flows, constant capacity. -void BweTest::RunSelfFairness(BandwidthEstimatorType bwe_type) { - const int kNumRmcatFlows = 3; - const int kNumTcpFlows = 0; - const int64_t kRunTimeS = 120; - const int kLinkCapacity = 3500; - - int64_t max_delay_ms = kMaxQueueingDelayMs; - int64_t rtt_ms = 2 * kOneWayDelayMs; - - const int64_t kStartingApartMs = 20 * 1000; - int64_t offsets_ms[kNumRmcatFlows]; - for (int i = 0; i < kNumRmcatFlows; ++i) { - offsets_ms[i] = kStartingApartMs * i; - } - - // Test also with one way propagation delay = 100ms. - // rtt_ms = 2 * 100; - // Test also with bottleneck queue size = 20ms and 1000ms. - // max_delay_ms = 20; - // max_delay_ms = 1000; - - std::string title("5.4_Self_fairness_test"); - - // Test also with one way propagation delay = 100ms. - RunFairnessTest(bwe_type, kNumRmcatFlows, kNumTcpFlows, kRunTimeS, - kLinkCapacity, max_delay_ms, rtt_ms, kMaxJitterMs, offsets_ms, - title, bwe_names[bwe_type]); -} - -// 5.5. Five competing RMCAT flows under different RTTs. -void BweTest::RunRoundTripTimeFairness(BandwidthEstimatorType bwe_type) { - const int kAllFlowIds[] = {0, 1, 2, 3, 4}; // Five RMCAT flows. - const int64_t kAllOneWayDelayMs[] = {10, 25, 50, 100, 150}; - const size_t kNumFlows = arraysize(kAllFlowIds); - std::unique_ptr sources[kNumFlows]; - std::unique_ptr senders[kNumFlows]; - std::unique_ptr metric_recorders[kNumFlows]; - - // Flows initialized 10 seconds apart. - const int64_t kStartingApartMs = 10 * 1000; - - for (size_t i = 0; i < kNumFlows; ++i) { - sources[i].reset(new AdaptiveVideoSource(kAllFlowIds[i], 30, 300, 0, - i * kStartingApartMs)); - senders[i].reset(new VideoSender(&uplink_, sources[i].get(), bwe_type)); - } - - ChokeFilter choke_filter(&uplink_, CreateFlowIds(kAllFlowIds, kNumFlows)); - LinkShare link_share(&choke_filter); - - JitterFilter jitter_filter(&uplink_, CreateFlowIds(kAllFlowIds, kNumFlows)); - - std::unique_ptr up_delay_filters[kNumFlows]; - for (size_t i = 0; i < kNumFlows; ++i) { - up_delay_filters[i].reset(new DelayFilter(&uplink_, kAllFlowIds[i])); - } - - RateCounterFilter total_utilization( - &uplink_, CreateFlowIds(kAllFlowIds, kNumFlows), "Total_utilization", - "Total_link_utilization"); - - // Delays is being plotted only for the first flow. - // To plot all of them, replace "i == 0" with "true" on new PacketReceiver(). - std::unique_ptr receivers[kNumFlows]; - for (size_t i = 0; i < kNumFlows; ++i) { - metric_recorders[i].reset( - new MetricRecorder(bwe_names[bwe_type], static_cast(i), - senders[i].get(), &link_share)); - - receivers[i].reset(new PacketReceiver(&uplink_, kAllFlowIds[i], bwe_type, - i == 0, false, - metric_recorders[i].get())); - metric_recorders[i].get()->set_start_computing_metrics_ms(kStartingApartMs * - (kNumFlows - 1)); - metric_recorders[i].get()->set_plot_available_capacity( - i == 0 && plot_total_available_capacity_); - } - - std::unique_ptr down_delay_filters[kNumFlows]; - for (size_t i = 0; i < kNumFlows; ++i) { - down_delay_filters[i].reset(new DelayFilter(&downlink_, kAllFlowIds[i])); - } - - jitter_filter.SetMaxJitter(kMaxJitterMs); - choke_filter.set_max_delay_ms(kMaxQueueingDelayMs); - - for (size_t i = 0; i < kNumFlows; ++i) { - up_delay_filters[i]->SetOneWayDelayMs(kAllOneWayDelayMs[i]); - down_delay_filters[i]->SetOneWayDelayMs(kAllOneWayDelayMs[i]); - } - - choke_filter.set_capacity_kbps(3500); - - RunFor(300 * 1000); // 0-300s. - - std::string title("5.5_Round_Trip_Time_Fairness"); - for (size_t i = 0; i < kNumFlows; ++i) { - metric_recorders[i].get()->PlotThroughputHistogram( - title, bwe_names[bwe_type], kNumFlows, 0); - metric_recorders[i].get()->PlotDelayHistogram(title, bwe_names[bwe_type], - kNumFlows, kOneWayDelayMs); - metric_recorders[i].get()->PlotLossHistogram( - title, bwe_names[bwe_type], kNumFlows, - receivers[i].get()->GlobalPacketLoss()); - BWE_TEST_LOGGING_BASELINEBAR(5, bwe_names[bwe_type], kAllOneWayDelayMs[i], - i); - } -} - -// 5.6. RMCAT Flow competing with a long TCP Flow. -void BweTest::RunLongTcpFairness(BandwidthEstimatorType bwe_type) { - const size_t kNumRmcatFlows = 1; - const size_t kNumTcpFlows = 1; - const int64_t kRunTimeS = 120; - const int kCapacityKbps = 2000; - // Tcp starts at t = 0, media flow at t = 5s. - const int64_t kOffSetsMs[] = {5000, 0}; - - int64_t max_delay_ms = kMaxQueueingDelayMs; - int64_t rtt_ms = 2 * kOneWayDelayMs; - - // Test also with one way propagation delay = 100ms. - // rtt_ms = 2 * 100; - // Test also with bottleneck queue size = 20ms and 1000ms. - // max_delay_ms = 20; - // max_delay_ms = 1000; - - std::string title("5.6_Long_TCP_Fairness"); - std::string flow_name = - std::string() + bwe_names[bwe_type] + 'x' + bwe_names[kTcpEstimator]; - - RunFairnessTest(bwe_type, kNumRmcatFlows, kNumTcpFlows, kRunTimeS, - kCapacityKbps, max_delay_ms, rtt_ms, kMaxJitterMs, kOffSetsMs, - title, flow_name); -} - -// 5.7. RMCAT Flows competing with multiple short TCP Flows. -void BweTest::RunMultipleShortTcpFairness( - BandwidthEstimatorType bwe_type, - std::vector tcp_file_sizes_bytes, - std::vector tcp_starting_times_ms) { - // Two RMCAT flows and ten TCP flows. - const int kAllRmcatFlowIds[] = {0, 1}; - const int kAllTcpFlowIds[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11}; - - assert(tcp_starting_times_ms.size() == tcp_file_sizes_bytes.size() && - tcp_starting_times_ms.size() == arraysize(kAllTcpFlowIds)); - - const size_t kNumRmcatFlows = arraysize(kAllRmcatFlowIds); - const size_t kNumTotalFlows = kNumRmcatFlows + arraysize(kAllTcpFlowIds); - - std::unique_ptr sources[kNumRmcatFlows]; - std::unique_ptr senders[kNumTotalFlows]; - std::unique_ptr metric_recorders[kNumTotalFlows]; - std::unique_ptr receivers[kNumTotalFlows]; - - // RMCAT Flows are initialized simultaneosly at t=5 seconds. - const int64_t kRmcatStartingTimeMs = 5 * 1000; - for (size_t id : kAllRmcatFlowIds) { - sources[id].reset(new AdaptiveVideoSource(static_cast(id), 30, 300, 0, - kRmcatStartingTimeMs)); - senders[id].reset(new VideoSender(&uplink_, sources[id].get(), bwe_type)); - } - - for (size_t id : kAllTcpFlowIds) { - senders[id].reset(new TcpSender(&uplink_, static_cast(id), - tcp_starting_times_ms[id - kNumRmcatFlows], - tcp_file_sizes_bytes[id - kNumRmcatFlows])); - } - - FlowIds flow_ids = CreateFlowIdRange(0, static_cast(kNumTotalFlows - 1)); - DefaultEvaluationFilter up_filter(&uplink_, flow_ids); - - LinkShare link_share(&(up_filter.choke)); - - RateCounterFilter total_utilization(&uplink_, flow_ids, "Total_utilization", - "Total_link_utilization"); - - // Delays is being plotted only for the first flow. - // To plot all of them, replace "i == 0" with "true" on new PacketReceiver(). - for (size_t id : kAllRmcatFlowIds) { - metric_recorders[id].reset( - new MetricRecorder(bwe_names[bwe_type], static_cast(id), - senders[id].get(), &link_share)); - receivers[id].reset(new PacketReceiver(&uplink_, static_cast(id), - bwe_type, id == 0, false, - metric_recorders[id].get())); - metric_recorders[id].get()->set_start_computing_metrics_ms( - kRmcatStartingTimeMs); - metric_recorders[id].get()->set_plot_available_capacity( - id == 0 && plot_total_available_capacity_); - } - - // Delays is not being plotted only for TCP flows. To plot all of them, - // replace first "false" occurence with "true" on new PacketReceiver(). - for (size_t id : kAllTcpFlowIds) { - metric_recorders[id].reset( - new MetricRecorder(bwe_names[kTcpEstimator], static_cast(id), - senders[id].get(), &link_share)); - receivers[id].reset(new PacketReceiver(&uplink_, static_cast(id), - kTcpEstimator, false, false, - metric_recorders[id].get())); - metric_recorders[id].get()->set_plot_available_capacity( - id == 0 && plot_total_available_capacity_); - } - - DelayFilter down_filter(&downlink_, flow_ids); - down_filter.SetOneWayDelayMs(kOneWayDelayMs); - - // Test also with one way propagation delay = 100ms. - // up_filter.delay.SetOneWayDelayMs(100); - // down_filter.SetOneWayDelayms(100); - - // Test also with bottleneck queue size = 20ms and 1000ms. - // up_filter.choke.set_max_delay_ms(20); - // up_filter.choke.set_max_delay_ms(1000); - - // Test also with no Jitter: - // up_filter.jitter.SetMaxJitter(0); - - up_filter.choke.set_capacity_kbps(2000); - - RunFor(300 * 1000); // 0-300s. - - std::string title("5.7_Multiple_short_TCP_flows"); - for (size_t id : kAllRmcatFlowIds) { - metric_recorders[id].get()->PlotThroughputHistogram( - title, bwe_names[bwe_type], kNumRmcatFlows, 0); - metric_recorders[id].get()->PlotDelayHistogram( - title, bwe_names[bwe_type], kNumRmcatFlows, kOneWayDelayMs); - metric_recorders[id].get()->PlotLossHistogram( - title, bwe_names[bwe_type], kNumRmcatFlows, - receivers[id].get()->GlobalPacketLoss()); - BWE_TEST_LOGGING_BASELINEBAR(5, bwe_names[bwe_type], kOneWayDelayMs, id); - } -} - -// 5.8. Three forward direction competing flows, constant capacity. -// During the test, one of the flows is paused and later resumed. -void BweTest::RunPauseResumeFlows(BandwidthEstimatorType bwe_type) { - const int kAllFlowIds[] = {0, 1, 2}; // Three RMCAT flows. - const size_t kNumFlows = arraysize(kAllFlowIds); - - std::unique_ptr sources[kNumFlows]; - std::unique_ptr senders[kNumFlows]; - std::unique_ptr metric_recorders[kNumFlows]; - std::unique_ptr receivers[kNumFlows]; - - // Flows initialized simultaneously. - const int64_t kStartingApartMs = 0; - - for (size_t i = 0; i < kNumFlows; ++i) { - sources[i].reset(new AdaptiveVideoSource(kAllFlowIds[i], 30, 300, 0, - i * kStartingApartMs)); - senders[i].reset(new VideoSender(&uplink_, sources[i].get(), bwe_type)); - } - - DefaultEvaluationFilter filter(&uplink_, - CreateFlowIds(kAllFlowIds, kNumFlows)); - - LinkShare link_share(&(filter.choke)); - - RateCounterFilter total_utilization( - &uplink_, CreateFlowIds(kAllFlowIds, kNumFlows), "Total_utilization", - "Total_link_utilization"); - - // Delays is being plotted only for the first flow. - // To plot all of them, replace "i == 0" with "true" on new PacketReceiver(). - for (size_t i = 0; i < kNumFlows; ++i) { - metric_recorders[i].reset( - new MetricRecorder(bwe_names[bwe_type], static_cast(i), - senders[i].get(), &link_share)); - receivers[i].reset(new PacketReceiver(&uplink_, kAllFlowIds[i], bwe_type, - i == 0, false, - metric_recorders[i].get())); - metric_recorders[i].get()->set_start_computing_metrics_ms(kStartingApartMs * - (kNumFlows - 1)); - metric_recorders[i].get()->set_plot_available_capacity( - i == 0 && plot_total_available_capacity_); - } - - // Test also with one way propagation delay = 100ms. - // filter.delay.SetOneWayDelayMs(100); - filter.choke.set_capacity_kbps(3500); - - RunFor(40 * 1000); // 0-40s. - senders[0].get()->Pause(); - RunFor(20 * 1000); // 40-60s. - senders[0].get()->Resume(20 * 1000); - RunFor(60 * 1000); // 60-120s. - - int64_t paused[] = {20 * 1000, 0, 0}; - - // First flow is being paused, hence having a different optimum. - const std::string optima_lines[] = {"1", "2", "2"}; - - std::string title("5.8_Pause_and_resume_media_flow"); - for (size_t i = 0; i < kNumFlows; ++i) { - metric_recorders[i].get()->PlotThroughputHistogram( - title, bwe_names[bwe_type], kNumFlows, paused[i], optima_lines[i]); - metric_recorders[i].get()->PlotDelayHistogram(title, bwe_names[bwe_type], - kNumFlows, kOneWayDelayMs); - metric_recorders[i].get()->PlotLossHistogram( - title, bwe_names[bwe_type], kNumFlows, - receivers[i].get()->GlobalPacketLoss()); - BWE_TEST_LOGGING_BASELINEBAR(5, bwe_names[bwe_type], kOneWayDelayMs, i); - } -} - -// Following functions are used for randomizing TCP file size and -// starting time, used on 5.7 RunMultipleShortTcpFairness. -// They are pseudo-random generators, creating always the same -// value sequence for a given Random seed. - -std::vector BweTest::GetFileSizesBytes(int num_files) { - // File size chosen from uniform distribution between [100,1000] kB. - const int kMinKbytes = 100; - const int kMaxKbytes = 1000; - - Random random(0x12345678); - std::vector tcp_file_sizes_bytes; - - while (num_files-- > 0) { - tcp_file_sizes_bytes.push_back(random.Rand(kMinKbytes, kMaxKbytes) * 1000); - } - - return tcp_file_sizes_bytes; -} - -std::vector BweTest::GetStartingTimesMs(int num_files) { - // OFF state behaves as an exp. distribution with mean = 10 seconds. - const float kMeanMs = 10000.0f; - Random random(0x12345678); - - std::vector tcp_starting_times_ms; - - // Two TCP Flows are initialized simultaneosly at t=0 seconds. - for (int i = 0; i < 2; ++i, --num_files) { - tcp_starting_times_ms.push_back(0); - } - - // Other TCP Flows are initialized in an OFF state. - while (num_files-- > 0) { - tcp_starting_times_ms.push_back( - static_cast(random.Exponential(1.0f / kMeanMs))); - } - - return tcp_starting_times_ms; -} - -} // namespace bwe -} // namespace testing -} // namespace webrtc diff --git a/modules/remote_bitrate_estimator/test/bwe_test.h b/modules/remote_bitrate_estimator/test/bwe_test.h deleted file mode 100644 index 275a69637c..0000000000 --- a/modules/remote_bitrate_estimator/test/bwe_test.h +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (c) 2013 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. - */ - -#ifndef MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_BWE_TEST_H_ -#define MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_BWE_TEST_H_ - -#include -#include -#include - -#include "modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h" -#include "modules/remote_bitrate_estimator/test/bwe.h" -#include "modules/remote_bitrate_estimator/test/bwe_test_framework.h" -#include "rtc_base/constructor_magic.h" -#include "test/gtest.h" - -namespace webrtc { - -namespace testing { -namespace bwe { - -class BweReceiver; -class PacketReceiver; -class PacketSender; - -class PacketProcessorRunner { - public: - explicit PacketProcessorRunner(PacketProcessor* processor); - PacketProcessorRunner(const PacketProcessorRunner&); - ~PacketProcessorRunner(); - - bool RunsProcessor(const PacketProcessor* processor) const; - void RunFor(int64_t time_ms, int64_t time_now_ms, Packets* in_out); - - private: - void FindPacketsToProcess(const FlowIds& flow_ids, Packets* in, Packets* out); - void QueuePackets(Packets* batch, int64_t end_of_batch_time_us); - - PacketProcessor* processor_; - Packets queue_; -}; - -class Link : public PacketProcessorListener { - public: - Link(); - ~Link() override; - - void AddPacketProcessor(PacketProcessor* processor, - ProcessorType type) override; - void RemovePacketProcessor(PacketProcessor* processor) override; - - void Run(int64_t run_for_ms, int64_t now_ms, Packets* packets); - - const std::vector& senders() { return senders_; } - const std::vector& processors() { return processors_; } - - private: - std::vector senders_; - std::vector receivers_; - std::vector processors_; -}; - -class BweTest { - public: - BweTest(); - explicit BweTest(bool plot_capacity); - ~BweTest(); - - void RunChoke(BandwidthEstimatorType bwe_type, - std::vector capacities_kbps); - - void RunVariableCapacity1SingleFlow(BandwidthEstimatorType bwe_type); - void RunVariableCapacity2MultipleFlows(BandwidthEstimatorType bwe_type, - size_t num_flows); - void RunBidirectionalFlow(BandwidthEstimatorType bwe_type); - void RunSelfFairness(BandwidthEstimatorType bwe_type); - void RunRoundTripTimeFairness(BandwidthEstimatorType bwe_type); - void RunLongTcpFairness(BandwidthEstimatorType bwe_type); - void RunMultipleShortTcpFairness(BandwidthEstimatorType bwe_type, - std::vector tcp_file_sizes_bytes, - std::vector tcp_starting_times_ms); - void RunPauseResumeFlows(BandwidthEstimatorType bwe_type); - - void RunFairnessTest(BandwidthEstimatorType bwe_type, - size_t num_media_flows, - size_t num_tcp_flows, - int64_t run_time_seconds, - uint32_t capacity_kbps, - int64_t max_delay_ms, - int64_t rtt_ms, - int64_t max_jitter_ms, - const int64_t* offsets_ms); - - void RunFairnessTest(BandwidthEstimatorType bwe_type, - size_t num_media_flows, - size_t num_tcp_flows, - int64_t run_time_seconds, - uint32_t capacity_kbps, - int64_t max_delay_ms, - int64_t rtt_ms, - int64_t max_jitter_ms, - const int64_t* offsets_ms, - const std::string& title, - const std::string& flow_name); - - static std::vector GetFileSizesBytes(int num_files); - static std::vector GetStartingTimesMs(int num_files); - - protected: - void SetUp(); - - void VerboseLogging(bool enable); - void RunFor(int64_t time_ms); - std::string GetTestName() const; - - void PrintResults(double max_throughput_kbps, - Stats throughput_kbps, - int flow_id, - Stats flow_delay_ms, - Stats flow_throughput_kbps); - - void PrintResults(double max_throughput_kbps, - Stats throughput_kbps, - std::map> flow_delay_ms, - std::map> flow_throughput_kbps); - - Link downlink_; - Link uplink_; - - private: - void FindPacketsToProcess(const FlowIds& flow_ids, Packets* in, Packets* out); - void GiveFeedbackToAffectedSenders(PacketReceiver* receiver); - - int64_t run_time_ms_; - int64_t time_now_ms_; - int64_t simulation_interval_ms_; - std::vector links_; - Packets packets_; - bool plot_total_available_capacity_; - - RTC_DISALLOW_COPY_AND_ASSIGN(BweTest); -}; - -// Default Evaluation parameters: -// Link capacity: 4000ms; -// Queueing delay capacity: 300ms. -// One-Way propagation delay: 50ms. -// Jitter model: Truncated gaussian. -// Maximum end-to-end jitter: 30ms = 2*standard_deviation. -// Bottleneck queue type: Drop tail. -// Path loss ratio: 0%. - -const int kOneWayDelayMs = 50; -const int kMaxQueueingDelayMs = 300; -const int kMaxCapacityKbps = 4000; -const int kMaxJitterMs = 15; - -struct DefaultEvaluationFilter { - DefaultEvaluationFilter(PacketProcessorListener* listener, int flow_id) - : choke(listener, flow_id), - delay(listener, flow_id), - jitter(listener, flow_id) { - SetDefaultParameters(); - } - - DefaultEvaluationFilter(PacketProcessorListener* listener, - const FlowIds& flow_ids) - : choke(listener, flow_ids), - delay(listener, flow_ids), - jitter(listener, flow_ids) { - SetDefaultParameters(); - } - - void SetDefaultParameters() { - delay.SetOneWayDelayMs(kOneWayDelayMs); - choke.set_max_delay_ms(kMaxQueueingDelayMs); - choke.set_capacity_kbps(kMaxCapacityKbps); - jitter.SetMaxJitter(kMaxJitterMs); - } - - ChokeFilter choke; - DelayFilter delay; - JitterFilter jitter; -}; - -} // namespace bwe -} // namespace testing -} // namespace webrtc - -#endif // MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_BWE_TEST_H_ diff --git a/modules/remote_bitrate_estimator/test/bwe_test_baselinefile.cc b/modules/remote_bitrate_estimator/test/bwe_test_baselinefile.cc deleted file mode 100644 index 8e4b7b4ec8..0000000000 --- a/modules/remote_bitrate_estimator/test/bwe_test_baselinefile.cc +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (c) 2013 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 "modules/remote_bitrate_estimator/test/bwe_test_baselinefile.h" - -#include -#include -#include -#include -#include - -#include "modules/remote_bitrate_estimator/test/bwe_test_fileutils.h" -#include "rtc_base/constructor_magic.h" -#include "test/testsupport/file_utils.h" - -namespace webrtc { -namespace testing { -namespace bwe { - -// The format of BWE test baseline files is extremely simple: -// 1. All read/written entities are 32-bit unsigned integers in network byte -// order (Big Endian). -// 2. Files beging with a 2 word header containing a magic marker and file -// format version indicator. The Magic marker reads "BWE!" in a hex dump. -// 3. Each estimate is logged as a pair of words: time in milliseconds and -// estimated bit rate, in bits per second. -const uint32_t kMagicMarker = 0x42574521; -const uint32_t kFileVersion1 = 0x00000001; -const char kResourceSubDir[] = "remote_bitrate_estimator"; - -class BaseLineFileVerify : public BaseLineFileInterface { - public: - // If |allow_missing_file| is set, VerifyOrWrite() will return true even if - // the baseline file is missing. This is the default when verifying files, but - // not when updating (i.e. we always write it out if missing). - BaseLineFileVerify(const std::string& filepath, bool allow_missing_file) - : reader_(), fail_to_read_response_(false) { - std::unique_ptr reader; - reader.reset(ResourceFileReader::Create(filepath, "bin")); - if (!reader.get()) { - printf("WARNING: Missing baseline file for BWE test: %s.bin\n", - filepath.c_str()); - fail_to_read_response_ = allow_missing_file; - } else { - uint32_t magic_marker = 0; - uint32_t file_version = 0; - if (reader->Read(&magic_marker) && magic_marker == kMagicMarker && - reader->Read(&file_version) && file_version == kFileVersion1) { - reader_.swap(reader); - } else { - printf("WARNING: Bad baseline file header for BWE test: %s.bin\n", - filepath.c_str()); - } - } - } - ~BaseLineFileVerify() override {} - - void Estimate(int64_t time_ms, uint32_t estimate_bps) override { - if (reader_.get()) { - uint32_t read_ms = 0; - uint32_t read_bps = 0; - if (reader_->Read(&read_ms) && read_ms == time_ms && - reader_->Read(&read_bps) && read_bps == estimate_bps) { - } else { - printf("ERROR: Baseline differs starting at: %d ms (%d vs %d)!\n", - static_cast(time_ms), estimate_bps, read_bps); - reader_.reset(NULL); - } - } - } - - bool VerifyOrWrite() override { - if (reader_.get()) { - if (reader_->IsAtEnd()) { - return true; - } else { - printf("ERROR: Baseline file contains more data!\n"); - return false; - } - } - return fail_to_read_response_; - } - - private: - std::unique_ptr reader_; - bool fail_to_read_response_; - - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(BaseLineFileVerify); -}; - -class BaseLineFileUpdate : public BaseLineFileInterface { - public: - BaseLineFileUpdate(const std::string& filepath, - BaseLineFileInterface* verifier) - : verifier_(verifier), output_content_(), filepath_(filepath) { - output_content_.push_back(kMagicMarker); - output_content_.push_back(kFileVersion1); - } - ~BaseLineFileUpdate() override {} - - void Estimate(int64_t time_ms, uint32_t estimate_bps) override { - verifier_->Estimate(time_ms, estimate_bps); - output_content_.push_back(static_cast(time_ms)); - output_content_.push_back(estimate_bps); - } - - bool VerifyOrWrite() override { - if (!verifier_->VerifyOrWrite()) { - std::string dir_path = webrtc::test::OutputPath() + kResourceSubDir; - if (!webrtc::test::CreateDir(dir_path)) { - printf("WARNING: Cannot create output dir: %s\n", dir_path.c_str()); - return false; - } - std::unique_ptr writer; - writer.reset(OutputFileWriter::Create(filepath_, "bin")); - if (!writer.get()) { - printf("WARNING: Cannot create output file: %s.bin\n", - filepath_.c_str()); - return false; - } - printf("NOTE: Writing baseline file for BWE test: %s.bin\n", - filepath_.c_str()); - for (std::vector::iterator it = output_content_.begin(); - it != output_content_.end(); ++it) { - writer->Write(*it); - } - return true; - } - printf("NOTE: No change, not writing: %s\n", filepath_.c_str()); - return true; - } - - private: - std::unique_ptr verifier_; - std::vector output_content_; - std::string filepath_; - - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(BaseLineFileUpdate); -}; - -BaseLineFileInterface* BaseLineFileInterface::Create( - const std::string& filename, - bool write_output_file) { - std::string filepath = filename; - std::replace(filepath.begin(), filepath.end(), '/', '_'); - filepath = std::string(kResourceSubDir) + "/" + filepath; - - std::unique_ptr result; - result.reset(new BaseLineFileVerify(filepath, !write_output_file)); - if (write_output_file) { - // Takes ownership of the |verifier| instance. - result.reset(new BaseLineFileUpdate(filepath, result.release())); - } - return result.release(); -} -} // namespace bwe -} // namespace testing -} // namespace webrtc diff --git a/modules/remote_bitrate_estimator/test/bwe_test_baselinefile.h b/modules/remote_bitrate_estimator/test/bwe_test_baselinefile.h deleted file mode 100644 index d9f22c02b1..0000000000 --- a/modules/remote_bitrate_estimator/test/bwe_test_baselinefile.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2013 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. - */ - -#ifndef MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_BWE_TEST_BASELINEFILE_H_ -#define MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_BWE_TEST_BASELINEFILE_H_ - -#include -#include - -namespace webrtc { -namespace testing { -namespace bwe { - -class BaseLineFileInterface { - public: - virtual ~BaseLineFileInterface() {} - - // Compare, or log, one estimate against the baseline file. - virtual void Estimate(int64_t time_ms, uint32_t estimate_bps) = 0; - - // Verify whether there are any differences between the logged estimates and - // those read from the baseline file. If updating the baseline file, write out - // new file if there were differences. Return true if logged estimates are - // identical, or if output file was updated successfully. - virtual bool VerifyOrWrite() = 0; - - // Create an instance for either verifying estimates against a baseline file - // with name |filename|, living in the resources/ directory or, if the flag - // |write_updated_file| is set, write logged estimates to a file with the same - // name, living in the out/ directory. - static BaseLineFileInterface* Create(const std::string& filename, - bool write_updated_file); -}; -} // namespace bwe -} // namespace testing -} // namespace webrtc - -#endif // MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_BWE_TEST_BASELINEFILE_H_ diff --git a/modules/remote_bitrate_estimator/test/bwe_test_fileutils.cc b/modules/remote_bitrate_estimator/test/bwe_test_fileutils.cc deleted file mode 100644 index a69f67225a..0000000000 --- a/modules/remote_bitrate_estimator/test/bwe_test_fileutils.cc +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2013 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 "modules/remote_bitrate_estimator/test/bwe_test_fileutils.h" - -#ifdef WIN32 -#include -#else -#include -#endif -#include - -#include "modules/remote_bitrate_estimator/test/bwe_test_logging.h" -#include "test/testsupport/file_utils.h" - -namespace webrtc { -namespace testing { -namespace bwe { - -ResourceFileReader::~ResourceFileReader() { - if (file_ != NULL) { - fclose(file_); - file_ = NULL; - } -} - -bool ResourceFileReader::IsAtEnd() { - int32_t current_pos = ftell(file_); - fseek(file_, 0, SEEK_END); - int32_t end_pos = ftell(file_); - fseek(file_, current_pos, SEEK_SET); - return current_pos == end_pos; -} - -bool ResourceFileReader::Read(uint32_t* out) { - assert(out); - uint32_t tmp = 0; - if (fread(&tmp, 1, sizeof(uint32_t), file_) != sizeof(uint32_t)) { - printf("Error reading!\n"); - return false; - } - *out = ntohl(tmp); - return true; -} - -ResourceFileReader* ResourceFileReader::Create(const std::string& filename, - const std::string& extension) { - std::string filepath = webrtc::test::ResourcePath(filename, extension); - FILE* file = fopen(filepath.c_str(), "rb"); - if (file == NULL) { - BWE_TEST_LOGGING_CONTEXT("ResourceFileReader"); - BWE_TEST_LOGGING_LOG1("Create", "Can't read file: %s", filepath.c_str()); - return 0; - } else { - return new ResourceFileReader(file); - } -} - -OutputFileWriter::~OutputFileWriter() { - if (file_ != NULL) { - fclose(file_); - file_ = NULL; - } -} - -bool OutputFileWriter::Write(uint32_t value) { - uint32_t tmp = htonl(value); - if (fwrite(&tmp, 1, sizeof(uint32_t), file_) != sizeof(uint32_t)) { - return false; - } - return true; -} - -OutputFileWriter* OutputFileWriter::Create(const std::string& filename, - const std::string& extension) { - std::string filepath = - webrtc::test::OutputPath() + filename + "." + extension; - FILE* file = fopen(filepath.c_str(), "wb"); - if (file == NULL) { - BWE_TEST_LOGGING_CONTEXT("OutputFileWriter"); - BWE_TEST_LOGGING_LOG1("Create", "Can't write file: %s", filepath.c_str()); - return NULL; - } else { - return new OutputFileWriter(file); - } -} -} // namespace bwe -} // namespace testing -} // namespace webrtc diff --git a/modules/remote_bitrate_estimator/test/bwe_test_fileutils.h b/modules/remote_bitrate_estimator/test/bwe_test_fileutils.h deleted file mode 100644 index c38bc10104..0000000000 --- a/modules/remote_bitrate_estimator/test/bwe_test_fileutils.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2013 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. - */ - -#ifndef MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_BWE_TEST_FILEUTILS_H_ -#define MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_BWE_TEST_FILEUTILS_H_ - -#include -#include -#include - -#include "rtc_base/constructor_magic.h" - -namespace webrtc { -namespace testing { -namespace bwe { - -class ResourceFileReader { - public: - ~ResourceFileReader(); - - bool IsAtEnd(); - bool Read(uint32_t* out); - - static ResourceFileReader* Create(const std::string& filename, - const std::string& extension); - - private: - explicit ResourceFileReader(FILE* file) : file_(file) {} - FILE* file_; - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(ResourceFileReader); -}; - -class OutputFileWriter { - public: - ~OutputFileWriter(); - - bool Write(uint32_t value); - - static OutputFileWriter* Create(const std::string& filename, - const std::string& extension); - - private: - explicit OutputFileWriter(FILE* file) : file_(file) {} - FILE* file_; - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(OutputFileWriter); -}; -} // namespace bwe -} // namespace testing -} // namespace webrtc - -#endif // MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_BWE_TEST_FILEUTILS_H_ diff --git a/modules/remote_bitrate_estimator/test/bwe_test_framework.cc b/modules/remote_bitrate_estimator/test/bwe_test_framework.cc deleted file mode 100644 index 81d77e1726..0000000000 --- a/modules/remote_bitrate_estimator/test/bwe_test_framework.cc +++ /dev/null @@ -1,812 +0,0 @@ -/* - * Copyright (c) 2013 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 "modules/remote_bitrate_estimator/test/bwe_test_framework.h" - -#include -#include -#include -#include -#include - -#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" -#include "modules/rtp_rtcp/source/rtp_packet_received.h" -#include "rtc_base/constructor_magic.h" -#include "rtc_base/numerics/safe_minmax.h" -#include "rtc_base/system/unused.h" - -namespace webrtc { -namespace testing { -namespace bwe { - -RateCounter::RateCounter(int64_t window_size_ms) - : window_size_us_(1000 * window_size_ms), - recently_received_packets_(0), - recently_received_bytes_(0), - last_accumulated_us_(0), - window_() {} - -RateCounter::RateCounter() : RateCounter(1000) {} - -RateCounter::~RateCounter() = default; - -class DelayCapHelper { - public: - // Max delay = 0 stands for +infinite. - DelayCapHelper() : max_delay_us_(0), delay_stats_() {} - - void set_max_delay_ms(int64_t max_delay_ms) { - BWE_TEST_LOGGING_ENABLE(false); - BWE_TEST_LOGGING_LOG1("Max Delay", "%d ms", static_cast(max_delay_ms)); - assert(max_delay_ms >= 0); - max_delay_us_ = max_delay_ms * 1000; - } - - bool ShouldSendPacket(int64_t send_time_us, int64_t arrival_time_us) { - int64_t packet_delay_us = send_time_us - arrival_time_us; - delay_stats_.Push((std::min(packet_delay_us, max_delay_us_) + 500) / 1000); - return (max_delay_us_ == 0 || max_delay_us_ >= packet_delay_us); - } - - const Stats& delay_stats() const { return delay_stats_; } - - private: - int64_t max_delay_us_; - Stats delay_stats_; - - RTC_DISALLOW_COPY_AND_ASSIGN(DelayCapHelper); -}; - -const FlowIds CreateFlowIds(const int* flow_ids_array, size_t num_flow_ids) { - FlowIds flow_ids(&flow_ids_array[0], flow_ids_array + num_flow_ids); - return flow_ids; -} - -const FlowIds CreateFlowIdRange(int initial_value, int last_value) { - int size = last_value - initial_value + 1; - assert(size > 0); - int* flow_ids_array = new int[size]; - for (int i = initial_value; i <= last_value; ++i) { - flow_ids_array[i - initial_value] = i; - } - return CreateFlowIds(flow_ids_array, size); -} - -void RateCounter::UpdateRates(int64_t send_time_us, uint32_t payload_size) { - ++recently_received_packets_; - recently_received_bytes_ += payload_size; - last_accumulated_us_ = send_time_us; - window_.push_back(std::make_pair(send_time_us, payload_size)); - while (!window_.empty()) { - const TimeSizePair& packet = window_.front(); - if (packet.first > (last_accumulated_us_ - window_size_us_)) { - break; - } - assert(recently_received_packets_ >= 1); - assert(recently_received_bytes_ >= packet.second); - --recently_received_packets_; - recently_received_bytes_ -= packet.second; - window_.pop_front(); - } -} - -uint32_t RateCounter::bits_per_second() const { - return (8 * recently_received_bytes_) / BitrateWindowS(); -} - -uint32_t RateCounter::packets_per_second() const { - return recently_received_packets_ / BitrateWindowS(); -} - -double RateCounter::BitrateWindowS() const { - return static_cast(window_size_us_) / (1000 * 1000); -} - -MediaPacket::MediaPacket() { - memset(&header_, 0, sizeof(header_)); -} - -MediaPacket::MediaPacket(int flow_id, - int64_t send_time_us, - size_t payload_size, - uint16_t sequence_number) - : Packet(flow_id, send_time_us, payload_size) { - header_ = RTPHeader(); - header_.sequenceNumber = sequence_number; -} - -MediaPacket::MediaPacket(int flow_id, - int64_t send_time_us, - size_t payload_size, - const RTPHeader& header) - : Packet(flow_id, send_time_us, payload_size), header_(header) {} - -MediaPacket::MediaPacket(int64_t send_time_us, uint16_t sequence_number) - : Packet(0, send_time_us, 0) { - header_ = RTPHeader(); - header_.sequenceNumber = sequence_number; -} - -void MediaPacket::SetAbsSendTimeMs(int64_t abs_send_time_ms) { - header_.extension.hasAbsoluteSendTime = true; - header_.extension.absoluteSendTime = - ((static_cast(abs_send_time_ms * (1 << 18)) + 500) / 1000) & - 0x00fffffful; -} - -// Copies payload size and sequence number. -RtpPacketReceived MediaPacket::GetRtpPacket() const { - RtpPacketReceived packet; - - packet.SetPayloadSize(payload_size()); - packet.SetSequenceNumber(header_.sequenceNumber); - return packet; -} - -BbrBweFeedback::BbrBweFeedback( - int flow_id, - int64_t send_time_us, - int64_t latest_send_time_ms, - const std::vector& packet_feedback_vector) - : FeedbackPacket(flow_id, send_time_us, latest_send_time_ms), - packet_feedback_vector_(packet_feedback_vector) {} - -RembFeedback::RembFeedback(int flow_id, - int64_t send_time_us, - int64_t last_send_time_ms, - uint32_t estimated_bps, - RTCPReportBlock report_block) - : FeedbackPacket(flow_id, send_time_us, last_send_time_ms), - estimated_bps_(estimated_bps), - report_block_(report_block) {} - -SendSideBweFeedback::SendSideBweFeedback( - int flow_id, - int64_t send_time_us, - int64_t last_send_time_ms, - const std::vector& packet_feedback_vector) - : FeedbackPacket(flow_id, send_time_us, last_send_time_ms), - packet_feedback_vector_(packet_feedback_vector) {} - -bool IsTimeSorted(const Packets& packets) { - PacketsConstIt last_it = packets.begin(); - for (PacketsConstIt it = last_it; it != packets.end(); ++it) { - if (it != last_it && **it < **last_it) { - return false; - } - last_it = it; - } - return true; -} - -PacketProcessor::PacketProcessor(PacketProcessorListener* listener, - int flow_id, - ProcessorType type) - : listener_(listener), flow_ids_(&flow_id, &flow_id + 1) { - if (listener_) { - listener_->AddPacketProcessor(this, type); - } -} - -PacketProcessor::PacketProcessor(PacketProcessorListener* listener, - const FlowIds& flow_ids, - ProcessorType type) - : listener_(listener), flow_ids_(flow_ids) { - if (listener_) { - listener_->AddPacketProcessor(this, type); - } -} - -PacketProcessor::~PacketProcessor() { - if (listener_) { - listener_->RemovePacketProcessor(this); - } -} - -uint32_t PacketProcessor::packets_per_second() const { - return rate_counter_.packets_per_second(); -} - -uint32_t PacketProcessor::bits_per_second() const { - return rate_counter_.bits_per_second(); -} - -RateCounterFilter::RateCounterFilter(PacketProcessorListener* listener, - int flow_id, - const char* name, - const std::string& algorithm_name) - : PacketProcessor(listener, flow_id, kRegular), - packets_per_second_stats_(), - kbps_stats_(), - start_plotting_time_ms_(0), - flow_id_(flow_id), - name_(name), - algorithm_name_(algorithm_name) { - // Only used when compiling with BWE test logging enabled. - RTC_UNUSED(flow_id_); -} - -RateCounterFilter::RateCounterFilter(PacketProcessorListener* listener, - const FlowIds& flow_ids, - const char* name, - const std::string& algorithm_name) - : PacketProcessor(listener, flow_ids, kRegular), - packets_per_second_stats_(), - kbps_stats_(), - start_plotting_time_ms_(0), - name_(name), - algorithm_name_(algorithm_name) { - // TODO(terelius): Appending the flow IDs to the algorithm name is a hack to - // keep the current plot functionality without having to print the full - // context for each PLOT line. It is unclear whether multiple flow IDs are - // needed at all in the long term. - std::stringstream ss; - ss << algorithm_name_; - for (int flow_id : flow_ids) { - ss << ',' << flow_id; - } - algorithm_name_ = ss.str(); -} - -RateCounterFilter::RateCounterFilter(PacketProcessorListener* listener, - const FlowIds& flow_ids, - const char* name, - int64_t start_plotting_time_ms, - const std::string& algorithm_name) - : RateCounterFilter(listener, flow_ids, name, algorithm_name) { - start_plotting_time_ms_ = start_plotting_time_ms; -} - -RateCounterFilter::~RateCounterFilter() { - LogStats(); -} - -void RateCounterFilter::LogStats() { - BWE_TEST_LOGGING_CONTEXT("RateCounterFilter"); - packets_per_second_stats_.Log("pps"); - kbps_stats_.Log("kbps"); -} - -Stats RateCounterFilter::GetBitrateStats() const { - return kbps_stats_; -} - -void RateCounterFilter::Plot(int64_t timestamp_ms) { - // TODO(stefan): Reorganize logging configuration to reduce amount - // of preprocessor conditionals in the code. - uint32_t plot_kbps = 0; - if (timestamp_ms >= start_plotting_time_ms_) { - plot_kbps = rate_counter_.bits_per_second() / 1000.0; - } - BWE_TEST_LOGGING_CONTEXT(name_.c_str()); - if (algorithm_name_.empty()) { - BWE_TEST_LOGGING_PLOT_WITH_SSRC(0, "Throughput_kbps#1", timestamp_ms, - plot_kbps, flow_id_); - } else { - BWE_TEST_LOGGING_PLOT_WITH_NAME_AND_SSRC(0, "Throughput_kbps#1", - timestamp_ms, plot_kbps, flow_id_, - algorithm_name_); - } - RTC_UNUSED(plot_kbps); -} - -void RateCounterFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) { - assert(in_out); - for (const Packet* packet : *in_out) { - rate_counter_.UpdateRates(packet->send_time_us(), - static_cast(packet->payload_size())); - } - packets_per_second_stats_.Push(rate_counter_.packets_per_second()); - kbps_stats_.Push(rate_counter_.bits_per_second() / 1000.0); -} - -LossFilter::LossFilter(PacketProcessorListener* listener, int flow_id) - : PacketProcessor(listener, flow_id, kRegular), - random_(0x12345678), - loss_fraction_(0.0f) {} - -LossFilter::LossFilter(PacketProcessorListener* listener, - const FlowIds& flow_ids) - : PacketProcessor(listener, flow_ids, kRegular), - random_(0x12345678), - loss_fraction_(0.0f) {} - -void LossFilter::SetLoss(float loss_percent) { - BWE_TEST_LOGGING_ENABLE(false); - BWE_TEST_LOGGING_LOG1("Loss", "%f%%", loss_percent); - assert(loss_percent >= 0.0f); - assert(loss_percent <= 100.0f); - loss_fraction_ = loss_percent * 0.01f; -} - -void LossFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) { - assert(in_out); - for (PacketsIt it = in_out->begin(); it != in_out->end();) { - if (random_.Rand() < loss_fraction_) { - delete *it; - it = in_out->erase(it); - } else { - ++it; - } - } -} - -const int64_t kDefaultOneWayDelayUs = 0; - -DelayFilter::DelayFilter(PacketProcessorListener* listener, int flow_id) - : PacketProcessor(listener, flow_id, kRegular), - one_way_delay_us_(kDefaultOneWayDelayUs), - last_send_time_us_(0) {} - -DelayFilter::DelayFilter(PacketProcessorListener* listener, - const FlowIds& flow_ids) - : PacketProcessor(listener, flow_ids, kRegular), - one_way_delay_us_(kDefaultOneWayDelayUs), - last_send_time_us_(0) {} - -void DelayFilter::SetOneWayDelayMs(int64_t one_way_delay_ms) { - BWE_TEST_LOGGING_ENABLE(false); - BWE_TEST_LOGGING_LOG1("Delay", "%d ms", static_cast(one_way_delay_ms)); - assert(one_way_delay_ms >= 0); - one_way_delay_us_ = one_way_delay_ms * 1000; -} - -void DelayFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) { - assert(in_out); - for (Packet* packet : *in_out) { - int64_t new_send_time_us = packet->send_time_us() + one_way_delay_us_; - last_send_time_us_ = std::max(last_send_time_us_, new_send_time_us); - packet->set_send_time_us(last_send_time_us_); - } -} - -JitterFilter::JitterFilter(PacketProcessorListener* listener, int flow_id) - : PacketProcessor(listener, flow_id, kRegular), - random_(0x89674523), - stddev_jitter_us_(0), - last_send_time_us_(0), - reordering_(false) {} - -JitterFilter::JitterFilter(PacketProcessorListener* listener, - const FlowIds& flow_ids) - : PacketProcessor(listener, flow_ids, kRegular), - random_(0x89674523), - stddev_jitter_us_(0), - last_send_time_us_(0), - reordering_(false) {} - -const int kN = 3; // Truncated N sigma gaussian. - -void JitterFilter::SetMaxJitter(int64_t max_jitter_ms) { - BWE_TEST_LOGGING_ENABLE(false); - BWE_TEST_LOGGING_LOG1("Max Jitter", "%d ms", static_cast(max_jitter_ms)); - assert(max_jitter_ms >= 0); - // Truncated gaussian, Max jitter = kN*sigma. - stddev_jitter_us_ = (max_jitter_ms * 1000 + kN / 2) / kN; -} - -namespace { -inline int64_t TruncatedNSigmaGaussian(Random* const random, - int64_t mean, - int64_t std_dev) { - const int64_t gaussian_random = random->Gaussian(mean, std_dev); - return rtc::SafeClamp(gaussian_random, -kN * std_dev, kN * std_dev); -} -} // namespace - -void JitterFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) { - assert(in_out); - for (Packet* packet : *in_out) { - int64_t jitter_us = - std::abs(TruncatedNSigmaGaussian(&random_, 0, stddev_jitter_us_)); - int64_t new_send_time_us = packet->send_time_us() + jitter_us; - - if (!reordering_) { - new_send_time_us = std::max(last_send_time_us_, new_send_time_us); - } - - // Receiver timestamp cannot be lower than sender timestamp. - assert(new_send_time_us >= packet->sender_timestamp_us()); - - packet->set_send_time_us(new_send_time_us); - last_send_time_us_ = new_send_time_us; - } -} - -// Computes the expected value for a right sided (abs) truncated gaussian. -// Does not take into account possible reoerdering updates. -int64_t JitterFilter::MeanUs() { - const double kPi = 3.1415926535897932; - double max_jitter_us = static_cast(kN * stddev_jitter_us_); - double right_sided_mean_us = - static_cast(stddev_jitter_us_) / sqrt(kPi / 2.0); - double truncated_mean_us = - right_sided_mean_us * - (1.0 - exp(-pow(static_cast(kN), 2.0) / 2.0)) + - max_jitter_us * erfc(static_cast(kN)); - return static_cast(truncated_mean_us + 0.5); -} - -ReorderFilter::ReorderFilter(PacketProcessorListener* listener, int flow_id) - : PacketProcessor(listener, flow_id, kRegular), - random_(0x27452389), - reorder_fraction_(0.0f) {} - -ReorderFilter::ReorderFilter(PacketProcessorListener* listener, - const FlowIds& flow_ids) - : PacketProcessor(listener, flow_ids, kRegular), - random_(0x27452389), - reorder_fraction_(0.0f) {} - -void ReorderFilter::SetReorder(float reorder_percent) { - BWE_TEST_LOGGING_ENABLE(false); - BWE_TEST_LOGGING_LOG1("Reordering", "%f%%", reorder_percent); - assert(reorder_percent >= 0.0f); - assert(reorder_percent <= 100.0f); - reorder_fraction_ = reorder_percent * 0.01f; -} - -void ReorderFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) { - assert(in_out); - if (in_out->size() >= 2) { - PacketsIt last_it = in_out->begin(); - PacketsIt it = last_it; - while (++it != in_out->end()) { - if (random_.Rand() < reorder_fraction_) { - int64_t t1 = (*last_it)->send_time_us(); - int64_t t2 = (*it)->send_time_us(); - std::swap(*last_it, *it); - (*last_it)->set_send_time_us(t1); - (*it)->set_send_time_us(t2); - } - last_it = it; - } - } -} - -const uint32_t kDefaultKbps = 1200; - -ChokeFilter::ChokeFilter(PacketProcessorListener* listener, int flow_id) - : PacketProcessor(listener, flow_id, kRegular), - capacity_kbps_(kDefaultKbps), - last_send_time_us_(0), - delay_cap_helper_(new DelayCapHelper()) {} - -ChokeFilter::ChokeFilter(PacketProcessorListener* listener, - const FlowIds& flow_ids) - : PacketProcessor(listener, flow_ids, kRegular), - capacity_kbps_(kDefaultKbps), - last_send_time_us_(0), - delay_cap_helper_(new DelayCapHelper()) {} - -ChokeFilter::~ChokeFilter() {} - -void ChokeFilter::set_capacity_kbps(uint32_t kbps) { - BWE_TEST_LOGGING_ENABLE(false); - BWE_TEST_LOGGING_LOG1("BitrateChoke", "%d kbps", kbps); - capacity_kbps_ = kbps; -} - -uint32_t ChokeFilter::capacity_kbps() { - return capacity_kbps_; -} - -void ChokeFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) { - assert(in_out); - for (PacketsIt it = in_out->begin(); it != in_out->end();) { - int64_t earliest_send_time_us = - std::max(last_send_time_us_, (*it)->send_time_us()); - int64_t new_send_time_us = - earliest_send_time_us + - ((*it)->payload_size() * 8 * 1000 + capacity_kbps_ / 2) / - capacity_kbps_; - BWE_TEST_LOGGING_PLOT(0, "MaxThroughput_", new_send_time_us / 1000, - capacity_kbps_); - if (delay_cap_helper_->ShouldSendPacket(new_send_time_us, - (*it)->send_time_us())) { - (*it)->set_send_time_us(new_send_time_us); - last_send_time_us_ = new_send_time_us; - ++it; - } else { - delete *it; - it = in_out->erase(it); - } - } -} - -void ChokeFilter::set_max_delay_ms(int64_t max_delay_ms) { - delay_cap_helper_->set_max_delay_ms(max_delay_ms); -} - -Stats ChokeFilter::GetDelayStats() const { - return delay_cap_helper_->delay_stats(); -} - -TraceBasedDeliveryFilter::TraceBasedDeliveryFilter( - PacketProcessorListener* listener, - int flow_id) - : PacketProcessor(listener, flow_id, kRegular), - current_offset_us_(0), - delivery_times_us_(), - next_delivery_it_(), - local_time_us_(-1), - rate_counter_(new RateCounter), - name_(""), - delay_cap_helper_(new DelayCapHelper()), - packets_per_second_stats_(), - kbps_stats_() {} - -TraceBasedDeliveryFilter::TraceBasedDeliveryFilter( - PacketProcessorListener* listener, - const FlowIds& flow_ids) - : PacketProcessor(listener, flow_ids, kRegular), - current_offset_us_(0), - delivery_times_us_(), - next_delivery_it_(), - local_time_us_(-1), - rate_counter_(new RateCounter), - name_(""), - delay_cap_helper_(new DelayCapHelper()), - packets_per_second_stats_(), - kbps_stats_() {} - -TraceBasedDeliveryFilter::TraceBasedDeliveryFilter( - PacketProcessorListener* listener, - int flow_id, - const char* name) - : PacketProcessor(listener, flow_id, kRegular), - current_offset_us_(0), - delivery_times_us_(), - next_delivery_it_(), - local_time_us_(-1), - rate_counter_(new RateCounter), - name_(name), - delay_cap_helper_(new DelayCapHelper()), - packets_per_second_stats_(), - kbps_stats_() {} - -TraceBasedDeliveryFilter::~TraceBasedDeliveryFilter() {} - -bool TraceBasedDeliveryFilter::Init(const std::string& filename) { - FILE* trace_file = fopen(filename.c_str(), "r"); - if (!trace_file) { - return false; - } - int64_t first_timestamp = -1; - while (!feof(trace_file)) { - const size_t kMaxLineLength = 100; - char line[kMaxLineLength]; - if (fgets(line, kMaxLineLength, trace_file)) { - std::string line_string(line); - std::istringstream buffer(line_string); - int64_t timestamp; - buffer >> timestamp; - timestamp /= 1000; // Convert to microseconds. - if (first_timestamp == -1) - first_timestamp = timestamp; - assert(delivery_times_us_.empty() || - timestamp - first_timestamp - delivery_times_us_.back() >= 0); - delivery_times_us_.push_back(timestamp - first_timestamp); - } - } - assert(!delivery_times_us_.empty()); - next_delivery_it_ = delivery_times_us_.begin(); - fclose(trace_file); - return true; -} - -void TraceBasedDeliveryFilter::Plot(int64_t timestamp_ms) { - BWE_TEST_LOGGING_CONTEXT(name_.c_str()); - // This plots the max possible throughput of the trace-based delivery filter, - // which will be reached if a packet sent on every packet slot of the trace. - BWE_TEST_LOGGING_PLOT(0, "MaxThroughput_#1", timestamp_ms, - rate_counter_->bits_per_second() / 1000.0); -} - -void TraceBasedDeliveryFilter::RunFor(int64_t time_ms, Packets* in_out) { - assert(in_out); - for (PacketsIt it = in_out->begin(); it != in_out->end();) { - while (local_time_us_ < (*it)->send_time_us()) { - ProceedToNextSlot(); - } - // Drop any packets that have been queued for too long. - while (!delay_cap_helper_->ShouldSendPacket(local_time_us_, - (*it)->send_time_us())) { - delete *it; - it = in_out->erase(it); - if (it == in_out->end()) { - return; - } - } - if (local_time_us_ >= (*it)->send_time_us()) { - (*it)->set_send_time_us(local_time_us_); - ProceedToNextSlot(); - } - ++it; - } - packets_per_second_stats_.Push(rate_counter_->packets_per_second()); - kbps_stats_.Push(rate_counter_->bits_per_second() / 1000.0); -} - -void TraceBasedDeliveryFilter::set_max_delay_ms(int64_t max_delay_ms) { - delay_cap_helper_->set_max_delay_ms(max_delay_ms); -} - -Stats TraceBasedDeliveryFilter::GetDelayStats() const { - return delay_cap_helper_->delay_stats(); -} - -Stats TraceBasedDeliveryFilter::GetBitrateStats() const { - return kbps_stats_; -} - -void TraceBasedDeliveryFilter::ProceedToNextSlot() { - if (*next_delivery_it_ <= local_time_us_) { - ++next_delivery_it_; - if (next_delivery_it_ == delivery_times_us_.end()) { - // When the trace wraps we allow two packets to be sent back-to-back. - for (int64_t& delivery_time_us : delivery_times_us_) { - delivery_time_us += local_time_us_ - current_offset_us_; - } - current_offset_us_ += local_time_us_ - current_offset_us_; - next_delivery_it_ = delivery_times_us_.begin(); - } - } - local_time_us_ = *next_delivery_it_; - const int kPayloadSize = 1200; - rate_counter_->UpdateRates(local_time_us_, kPayloadSize); -} - -VideoSource::VideoSource(int flow_id, - float fps, - uint32_t kbps, - uint32_t ssrc, - int64_t first_frame_offset_ms) - : kMaxPayloadSizeBytes(1200), - kTimestampBase(0xff80ff00ul), - frame_period_ms_(1000.0 / fps), - bits_per_second_(1000 * kbps), - frame_size_bytes_(bits_per_second_ / 8 / fps), - random_(0x12345678), - flow_id_(flow_id), - next_frame_ms_(first_frame_offset_ms), - next_frame_rand_ms_(0), - now_ms_(0), - prototype_header_() { - memset(&prototype_header_, 0, sizeof(prototype_header_)); - prototype_header_.ssrc = ssrc; - prototype_header_.sequenceNumber = 0xf000u; -} - -int VideoSource::flow_id() const { - return flow_id_; -} - -uint32_t VideoSource::NextFrameSize() { - return frame_size_bytes_; -} - -int64_t VideoSource::GetTimeUntilNextFrameMs() const { - return next_frame_ms_ + next_frame_rand_ms_ - now_ms_; -} - -uint32_t VideoSource::NextPacketSize(uint32_t frame_size, - uint32_t remaining_payload) { - return std::min(kMaxPayloadSizeBytes, remaining_payload); -} - -void VideoSource::RunFor(int64_t time_ms, Packets* in_out) { - assert(in_out); - - now_ms_ += time_ms; - Packets new_packets; - - while (now_ms_ >= next_frame_ms_) { - const int64_t kRandAmplitude = 2; - // A variance picked uniformly from {-1, 0, 1} ms is added to the frame - // timestamp. - next_frame_rand_ms_ = kRandAmplitude * (random_.Rand() - 0.5); - - // Ensure frame will not have a negative timestamp. - int64_t next_frame_ms = - std::max(next_frame_ms_ + next_frame_rand_ms_, 0); - - prototype_header_.timestamp = - kTimestampBase + static_cast(next_frame_ms * 90.0); - prototype_header_.extension.transmissionTimeOffset = 0; - - // Generate new packets for this frame, all with the same timestamp, - // but the payload size is capped, so if the whole frame doesn't fit in - // one packet, we will see a number of equally sized packets followed by - // one smaller at the tail. - - int64_t send_time_us = next_frame_ms * 1000.0; - - uint32_t frame_size = NextFrameSize(); - uint32_t payload_size = frame_size; - - while (payload_size > 0) { - ++prototype_header_.sequenceNumber; - uint32_t size = NextPacketSize(frame_size, payload_size); - MediaPacket* new_packet = - new MediaPacket(flow_id_, send_time_us, size, prototype_header_); - new_packets.push_back(new_packet); - new_packet->SetAbsSendTimeMs(next_frame_ms); - new_packet->set_sender_timestamp_us(send_time_us); - payload_size -= size; - } - - next_frame_ms_ += frame_period_ms_; - } - - in_out->merge(new_packets, DereferencingComparator); -} - -AdaptiveVideoSource::AdaptiveVideoSource(int flow_id, - float fps, - uint32_t kbps, - uint32_t ssrc, - int64_t first_frame_offset_ms) - : VideoSource(flow_id, fps, kbps, ssrc, first_frame_offset_ms) {} - -void AdaptiveVideoSource::SetBitrateBps(int bitrate_bps) { - bits_per_second_ = bitrate_bps; - frame_size_bytes_ = (bits_per_second_ / 8 * frame_period_ms_ + 500) / 1000; -} - -PeriodicKeyFrameSource::PeriodicKeyFrameSource(int flow_id, - float fps, - uint32_t kbps, - uint32_t ssrc, - int64_t first_frame_offset_ms, - int key_frame_interval) - : AdaptiveVideoSource(flow_id, fps, kbps, ssrc, first_frame_offset_ms), - key_frame_interval_(key_frame_interval), - frame_counter_(0), - compensation_bytes_(0), - compensation_per_frame_(0) {} - -uint32_t PeriodicKeyFrameSource::NextFrameSize() { - uint32_t payload_size = frame_size_bytes_; - if (frame_counter_ == 0) { - payload_size = kMaxPayloadSizeBytes * 12; - compensation_bytes_ = 4 * frame_size_bytes_; - compensation_per_frame_ = compensation_bytes_ / 30; - } else if (key_frame_interval_ > 0 && - (frame_counter_ % key_frame_interval_ == 0)) { - payload_size *= 5; - compensation_bytes_ = payload_size - frame_size_bytes_; - compensation_per_frame_ = compensation_bytes_ / 30; - } else if (compensation_bytes_ > 0) { - if (compensation_per_frame_ > static_cast(payload_size)) { - // Skip this frame. - compensation_bytes_ -= payload_size; - payload_size = 0; - } else { - payload_size -= compensation_per_frame_; - compensation_bytes_ -= compensation_per_frame_; - } - } - if (compensation_bytes_ < 0) - compensation_bytes_ = 0; - ++frame_counter_; - return payload_size; -} - -uint32_t PeriodicKeyFrameSource::NextPacketSize(uint32_t frame_size, - uint32_t remaining_payload) { - uint32_t fragments = - (frame_size + (kMaxPayloadSizeBytes - 1)) / kMaxPayloadSizeBytes; - uint32_t avg_size = (frame_size + fragments - 1) / fragments; - return std::min(avg_size, remaining_payload); -} -} // namespace bwe -} // namespace testing -} // namespace webrtc diff --git a/modules/remote_bitrate_estimator/test/bwe_test_framework.h b/modules/remote_bitrate_estimator/test/bwe_test_framework.h deleted file mode 100644 index cd1af97698..0000000000 --- a/modules/remote_bitrate_estimator/test/bwe_test_framework.h +++ /dev/null @@ -1,463 +0,0 @@ -/* - * Copyright (c) 2013 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. - */ - -#ifndef MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_BWE_TEST_FRAMEWORK_H_ -#define MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_BWE_TEST_FRAMEWORK_H_ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "modules/bitrate_controller/include/bitrate_controller.h" -#include "modules/include/module_common_types.h" -#include "modules/pacing/paced_sender.h" -#include "modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h" -#include "modules/remote_bitrate_estimator/test/bwe_test_logging.h" -#include "modules/remote_bitrate_estimator/test/packet.h" -#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" -#include "rtc_base/constructor_magic.h" -#include "rtc_base/random.h" -#include "rtc_base/strings/string_builder.h" -#include "system_wrappers/include/clock.h" - -namespace webrtc { - -class RtcpBandwidthObserver; - -namespace testing { -namespace bwe { - -class DelayCapHelper; - -class RateCounter { - public: - explicit RateCounter(int64_t window_size_ms); - RateCounter(); - ~RateCounter(); - - void UpdateRates(int64_t send_time_us, uint32_t payload_size); - - int64_t window_size_ms() const { return (window_size_us_ + 500) / 1000; } - uint32_t packets_per_second() const; - uint32_t bits_per_second() const; - - double BitrateWindowS() const; - - private: - typedef std::pair TimeSizePair; - - int64_t window_size_us_; - uint32_t recently_received_packets_; - uint32_t recently_received_bytes_; - int64_t last_accumulated_us_; - std::list window_; -}; - -typedef std::set FlowIds; -const FlowIds CreateFlowIds(const int* flow_ids_array, size_t num_flow_ids); -const FlowIds CreateFlowIdRange(int initial_value, int last_value); - -template -bool DereferencingComparator(const T* const& a, const T* const& b) { - assert(a != NULL); - assert(b != NULL); - return *a < *b; -} - -template -class Stats { - public: - Stats() - : data_(), - last_mean_count_(0), - last_variance_count_(0), - last_minmax_count_(0), - mean_(0), - variance_(0), - min_(0), - max_(0) {} - - void Push(T data_point) { data_.push_back(data_point); } - - T GetMean() { - if (last_mean_count_ != data_.size()) { - last_mean_count_ = data_.size(); - mean_ = std::accumulate(data_.begin(), data_.end(), static_cast(0)); - assert(last_mean_count_ != 0); - mean_ /= static_cast(last_mean_count_); - } - return mean_; - } - T GetVariance() { - if (last_variance_count_ != data_.size()) { - last_variance_count_ = data_.size(); - T mean = GetMean(); - variance_ = 0; - for (const auto& sample : data_) { - T diff = (sample - mean); - variance_ += diff * diff; - } - assert(last_variance_count_ != 0); - variance_ /= static_cast(last_variance_count_); - } - return variance_; - } - T GetStdDev() { return sqrt(static_cast(GetVariance())); } - T GetMin() { - RefreshMinMax(); - return min_; - } - T GetMax() { - RefreshMinMax(); - return max_; - } - - std::string AsString() { - rtc::StringBuilder ss; - ss << (GetMean() >= 0 ? GetMean() : -1) << ", " - << (GetStdDev() >= 0 ? GetStdDev() : -1); - return ss.Release(); - } - - void Log(const std::string& units) { - BWE_TEST_LOGGING_LOG5("", "%f %s\t+/-%f\t[%f,%f]", GetMean(), units.c_str(), - GetStdDev(), GetMin(), GetMax()); - } - - private: - void RefreshMinMax() { - if (last_minmax_count_ != data_.size()) { - last_minmax_count_ = data_.size(); - min_ = max_ = 0; - if (data_.empty()) { - return; - } - typename std::vector::const_iterator it = data_.begin(); - min_ = max_ = *it; - while (++it != data_.end()) { - min_ = std::min(min_, *it); - max_ = std::max(max_, *it); - } - } - } - - std::vector data_; - typename std::vector::size_type last_mean_count_; - typename std::vector::size_type last_variance_count_; - typename std::vector::size_type last_minmax_count_; - T mean_; - T variance_; - T min_; - T max_; -}; - -bool IsTimeSorted(const Packets& packets); - -class PacketProcessor; - -enum ProcessorType { kSender, kReceiver, kRegular }; - -class PacketProcessorListener { - public: - virtual ~PacketProcessorListener() {} - - virtual void AddPacketProcessor(PacketProcessor* processor, - ProcessorType type) = 0; - virtual void RemovePacketProcessor(PacketProcessor* processor) = 0; -}; - -class PacketProcessor { - public: - PacketProcessor(PacketProcessorListener* listener, - int flow_id, - ProcessorType type); - PacketProcessor(PacketProcessorListener* listener, - const FlowIds& flow_ids, - ProcessorType type); - virtual ~PacketProcessor(); - - // Called after each simulation batch to allow the processor to plot any - // internal data. - virtual void Plot(int64_t timestamp_ms) {} - - // Run simulation for |time_ms| milliseconds, consuming packets from, and - // producing packets into in_out. The outgoing packet list must be sorted on - // |send_time_us_|. The simulation time |time_ms| is optional to use. - virtual void RunFor(int64_t time_ms, Packets* in_out) = 0; - - const FlowIds& flow_ids() const { return flow_ids_; } - - uint32_t packets_per_second() const; - uint32_t bits_per_second() const; - - protected: - RateCounter rate_counter_; - - private: - PacketProcessorListener* listener_; - const FlowIds flow_ids_; - - RTC_DISALLOW_COPY_AND_ASSIGN(PacketProcessor); -}; - -class RateCounterFilter : public PacketProcessor { - public: - RateCounterFilter(PacketProcessorListener* listener, - int flow_id, - const char* name, - const std::string& algorithm_name); - RateCounterFilter(PacketProcessorListener* listener, - const FlowIds& flow_ids, - const char* name, - const std::string& algorithm_name); - RateCounterFilter(PacketProcessorListener* listener, - const FlowIds& flow_ids, - const char* name, - int64_t start_plotting_time_ms, - const std::string& algorithm_name); - ~RateCounterFilter() override; - - void LogStats(); - Stats GetBitrateStats() const; - void Plot(int64_t timestamp_ms) override; - void RunFor(int64_t time_ms, Packets* in_out) override; - - private: - Stats packets_per_second_stats_; - Stats kbps_stats_; - int64_t start_plotting_time_ms_; - int flow_id_ = 0; - std::string name_; - // Algorithm name if single flow, Total link utilization if all flows. - std::string algorithm_name_; - - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RateCounterFilter); -}; - -class LossFilter : public PacketProcessor { - public: - LossFilter(PacketProcessorListener* listener, int flow_id); - LossFilter(PacketProcessorListener* listener, const FlowIds& flow_ids); - ~LossFilter() override {} - - void SetLoss(float loss_percent); - void RunFor(int64_t time_ms, Packets* in_out) override; - - private: - Random random_; - float loss_fraction_; - - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(LossFilter); -}; - -class DelayFilter : public PacketProcessor { - public: - DelayFilter(PacketProcessorListener* listener, int flow_id); - DelayFilter(PacketProcessorListener* listener, const FlowIds& flow_ids); - ~DelayFilter() override {} - - void SetOneWayDelayMs(int64_t one_way_delay_ms); - void RunFor(int64_t time_ms, Packets* in_out) override; - - private: - int64_t one_way_delay_us_; - int64_t last_send_time_us_; - - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(DelayFilter); -}; - -class JitterFilter : public PacketProcessor { - public: - JitterFilter(PacketProcessorListener* listener, int flow_id); - JitterFilter(PacketProcessorListener* listener, const FlowIds& flow_ids); - ~JitterFilter() override {} - - void SetMaxJitter(int64_t stddev_jitter_ms); - void RunFor(int64_t time_ms, Packets* in_out) override; - void set_reorderdering(bool reordering) { reordering_ = reordering; } - int64_t MeanUs(); - - private: - Random random_; - int64_t stddev_jitter_us_; - int64_t last_send_time_us_; - bool reordering_; // False by default. - - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(JitterFilter); -}; - -// Reorders two consecutive packets with a probability of reorder_percent. -class ReorderFilter : public PacketProcessor { - public: - ReorderFilter(PacketProcessorListener* listener, int flow_id); - ReorderFilter(PacketProcessorListener* listener, const FlowIds& flow_ids); - ~ReorderFilter() override {} - - void SetReorder(float reorder_percent); - void RunFor(int64_t time_ms, Packets* in_out) override; - - private: - Random random_; - float reorder_fraction_; - - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(ReorderFilter); -}; - -// Apply a bitrate choke with an infinite queue on the packet stream. -class ChokeFilter : public PacketProcessor { - public: - ChokeFilter(PacketProcessorListener* listener, int flow_id); - ChokeFilter(PacketProcessorListener* listener, const FlowIds& flow_ids); - ~ChokeFilter() override; - - void set_capacity_kbps(uint32_t kbps); - void set_max_delay_ms(int64_t max_queueing_delay_ms); - - uint32_t capacity_kbps(); - - void RunFor(int64_t time_ms, Packets* in_out) override; - - Stats GetDelayStats() const; - - private: - uint32_t capacity_kbps_; - int64_t last_send_time_us_; - std::unique_ptr delay_cap_helper_; - - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(ChokeFilter); -}; - -class TraceBasedDeliveryFilter : public PacketProcessor { - public: - TraceBasedDeliveryFilter(PacketProcessorListener* listener, int flow_id); - TraceBasedDeliveryFilter(PacketProcessorListener* listener, - const FlowIds& flow_ids); - TraceBasedDeliveryFilter(PacketProcessorListener* listener, - int flow_id, - const char* name); - ~TraceBasedDeliveryFilter() override; - - // The file should contain nanosecond timestamps corresponding to the time - // when the network can accept another packet. The timestamps should be - // separated by new lines, e.g., "100000000\n125000000\n321000000\n..." - bool Init(const std::string& filename); - void Plot(int64_t timestamp_ms) override; - void RunFor(int64_t time_ms, Packets* in_out) override; - - void set_max_delay_ms(int64_t max_delay_ms); - Stats GetDelayStats() const; - Stats GetBitrateStats() const; - - private: - void ProceedToNextSlot(); - - typedef std::vector TimeList; - int64_t current_offset_us_; - TimeList delivery_times_us_; - TimeList::const_iterator next_delivery_it_; - int64_t local_time_us_; - std::unique_ptr rate_counter_; - std::string name_; - std::unique_ptr delay_cap_helper_; - Stats packets_per_second_stats_; - Stats kbps_stats_; - - RTC_DISALLOW_COPY_AND_ASSIGN(TraceBasedDeliveryFilter); -}; - -class VideoSource { - public: - VideoSource(int flow_id, - float fps, - uint32_t kbps, - uint32_t ssrc, - int64_t first_frame_offset_ms); - virtual ~VideoSource() {} - - virtual void RunFor(int64_t time_ms, Packets* in_out); - - int flow_id() const; - virtual void SetBitrateBps(int bitrate_bps) {} - uint32_t bits_per_second() const { return bits_per_second_; } - uint32_t max_payload_size_bytes() const { return kMaxPayloadSizeBytes; } - int64_t GetTimeUntilNextFrameMs() const; - - protected: - virtual uint32_t NextFrameSize(); - virtual uint32_t NextPacketSize(uint32_t frame_size, - uint32_t remaining_payload); - - const uint32_t kMaxPayloadSizeBytes; - const uint32_t kTimestampBase; - const double frame_period_ms_; - uint32_t bits_per_second_; - uint32_t frame_size_bytes_; - - private: - Random random_; - const int flow_id_; - int64_t next_frame_ms_; - int64_t next_frame_rand_ms_; - int64_t now_ms_; - RTPHeader prototype_header_; - - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(VideoSource); -}; - -class AdaptiveVideoSource : public VideoSource { - public: - AdaptiveVideoSource(int flow_id, - float fps, - uint32_t kbps, - uint32_t ssrc, - int64_t first_frame_offset_ms); - ~AdaptiveVideoSource() override {} - - void SetBitrateBps(int bitrate_bps) override; - - private: - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(AdaptiveVideoSource); -}; - -class PeriodicKeyFrameSource : public AdaptiveVideoSource { - public: - PeriodicKeyFrameSource(int flow_id, - float fps, - uint32_t kbps, - uint32_t ssrc, - int64_t first_frame_offset_ms, - int key_frame_interval); - ~PeriodicKeyFrameSource() override {} - - protected: - uint32_t NextFrameSize() override; - uint32_t NextPacketSize(uint32_t frame_size, - uint32_t remaining_payload) override; - - private: - int key_frame_interval_; - uint32_t frame_counter_; - int compensation_bytes_; - int compensation_per_frame_; - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(PeriodicKeyFrameSource); -}; -} // namespace bwe -} // namespace testing -} // namespace webrtc - -#endif // MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_BWE_TEST_FRAMEWORK_H_ diff --git a/modules/remote_bitrate_estimator/test/bwe_test_framework_unittest.cc b/modules/remote_bitrate_estimator/test/bwe_test_framework_unittest.cc deleted file mode 100644 index f9da01eaf1..0000000000 --- a/modules/remote_bitrate_estimator/test/bwe_test_framework_unittest.cc +++ /dev/null @@ -1,975 +0,0 @@ -/* - * Copyright (c) 2013 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 "modules/remote_bitrate_estimator/test/bwe_test_framework.h" - -#include "modules/include/module_common_types_public.h" -#include "modules/remote_bitrate_estimator/test/bwe.h" -#include "modules/remote_bitrate_estimator/test/packet.h" -#include "modules/remote_bitrate_estimator/test/packet_sender.h" -#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" -#include "rtc_base/constructor_magic.h" -#include "test/gtest.h" -#include "test/testsupport/file_utils.h" - -namespace webrtc { -namespace testing { -namespace bwe { - -static bool IsSequenceNumberSorted(const Packets& packets) { - PacketsConstIt last_it = packets.begin(); - for (PacketsConstIt it = last_it; it != packets.end(); ++it) { - const MediaPacket* packet = static_cast(*it); - const MediaPacket* last_packet = static_cast(*last_it); - if (IsNewerSequenceNumber(last_packet->header().sequenceNumber, - packet->header().sequenceNumber)) { - return false; - } - last_it = it; - } - return true; -} - -TEST(BweTestFramework_PacketTest, IsTimeSorted) { - Packets packets; - // Insert some packets in order... - EXPECT_TRUE(IsTimeSorted(packets)); - - packets.push_back(new MediaPacket(100, 0)); - EXPECT_TRUE(IsTimeSorted(packets)); - - packets.push_back(new MediaPacket(110, 0)); - EXPECT_TRUE(IsTimeSorted(packets)); - - // ...and one out-of-order... - packets.push_back(new MediaPacket(100, 0)); - EXPECT_FALSE(IsTimeSorted(packets)); - - // ...remove the out-of-order packet, insert another in-order packet. - delete packets.back(); - packets.pop_back(); - packets.push_back(new MediaPacket(120, 0)); - EXPECT_TRUE(IsTimeSorted(packets)); - - for (auto* packet : packets) - delete packet; -} - -TEST(BweTestFramework_PacketTest, IsSequenceNumberSorted) { - Packets packets; - // Insert some packets in order... - EXPECT_TRUE(IsSequenceNumberSorted(packets)); - - packets.push_back(new MediaPacket(0, 100)); - EXPECT_TRUE(IsSequenceNumberSorted(packets)); - - packets.push_back(new MediaPacket(0, 110)); - EXPECT_TRUE(IsSequenceNumberSorted(packets)); - - // ...and one out-of-order... - packets.push_back(new MediaPacket(0, 100)); - EXPECT_FALSE(IsSequenceNumberSorted(packets)); - - // ...remove the out-of-order packet, insert another in-order packet. - delete packets.back(); - packets.pop_back(); - packets.push_back(new MediaPacket(0, 120)); - EXPECT_TRUE(IsSequenceNumberSorted(packets)); - - for (auto* packet : packets) - delete packet; -} - -TEST(BweTestFramework_StatsTest, Mean) { - Stats stats; - EXPECT_EQ(0, stats.GetMean()); - - stats.Push(1); - stats.Push(3); - EXPECT_EQ(2, stats.GetMean()); - - // Integer division rounds (1+3-3)/3 to 0. - stats.Push(-3); - EXPECT_EQ(0, stats.GetMean()); -} - -TEST(BweTestFramework_StatsTest, Variance) { - Stats stats; - EXPECT_EQ(0, stats.GetVariance()); - - // Mean is 2 ; ((1-2)*(1-2)+(3-2)*(3-2))/2 = (1+1)/2 = 1 - stats.Push(1); - stats.Push(3); - EXPECT_EQ(1, stats.GetVariance()); - - // Integer division rounds 26/3 to 8 - // Mean is 0 ; (1*1+3*3+(-4)*(-4))/3 = (1+9+16)/3 = 8 - stats.Push(-4); - EXPECT_EQ(8, stats.GetVariance()); -} - -TEST(BweTestFramework_StatsTest, StdDev) { - Stats stats; - EXPECT_EQ(0, stats.GetStdDev()); - - // Variance is 1 ; sqrt(1) = 1 - stats.Push(1); - stats.Push(3); - EXPECT_EQ(1, stats.GetStdDev()); - - // Variance is 8 ; sqrt(8) = 2 with integers. - stats.Push(-4); - EXPECT_EQ(2, stats.GetStdDev()); -} - -TEST(BweTestFramework_StatsTest, MinMax) { - Stats stats; - EXPECT_EQ(0, stats.GetMin()); - EXPECT_EQ(0, stats.GetMax()); - - stats.Push(1); - EXPECT_EQ(1, stats.GetMin()); - EXPECT_EQ(1, stats.GetMax()); - - stats.Push(3); - EXPECT_EQ(1, stats.GetMin()); - EXPECT_EQ(3, stats.GetMax()); - - stats.Push(-4); - EXPECT_EQ(-4, stats.GetMin()); - EXPECT_EQ(3, stats.GetMax()); -} - -class BweTestFramework_RateCounterFilterTest : public ::testing::Test { - public: - BweTestFramework_RateCounterFilterTest() - : filter_(NULL, 0, "", ""), now_ms_(0) {} - virtual ~BweTestFramework_RateCounterFilterTest() {} - - protected: - void TestRateCounter(int64_t run_for_ms, - uint32_t payload_bits, - uint32_t expected_pps, - uint32_t expected_bps) { - Packets packets; - RTPHeader header; - // "Send" a packet every 10 ms. - for (int64_t i = 0; i < run_for_ms; i += 10, now_ms_ += 10) { - packets.push_back( - new MediaPacket(0, now_ms_ * 1000, payload_bits / 8, header)); - } - filter_.RunFor(run_for_ms, &packets); - ASSERT_TRUE(IsTimeSorted(packets)); - EXPECT_EQ(expected_pps, filter_.packets_per_second()); - EXPECT_EQ(expected_bps, filter_.bits_per_second()); - - for (auto* packet : packets) - delete packet; - } - - private: - RateCounterFilter filter_; - int64_t now_ms_; - - RTC_DISALLOW_COPY_AND_ASSIGN(BweTestFramework_RateCounterFilterTest); -}; - -TEST_F(BweTestFramework_RateCounterFilterTest, Short) { - // 100ms, 100 bytes per packet, should result in 10 pps and 8 kbps. We're - // generating one packet every 10 ms ; 10 * 800 = 8k - TestRateCounter(100, 800, 10, 8000); -} - -TEST_F(BweTestFramework_RateCounterFilterTest, Medium) { - // 100ms, like above. - TestRateCounter(100, 800, 10, 8000); - // 1000ms, 100 bpp, should result in 100 pps and 80 kbps. We're still - // generating packets every 10 ms. - TestRateCounter(900, 800, 100, 80000); -} - -TEST_F(BweTestFramework_RateCounterFilterTest, Long) { - // 100ms, 1000ms, like above. - TestRateCounter(100, 800, 10, 8000); - TestRateCounter(900, 800, 100, 80000); - // 2000ms, should only see rate of last second, so 100 pps, and 40 kbps now. - TestRateCounter(1000, 400, 100, 40000); - // 2500ms, half a second with zero payload size. We should get same pps as - // before, but kbps should drop to half of previous rate. - TestRateCounter(500, 0, 100, 20000); - // Another half second with zero payload size. Now the kbps rate should drop - // to zero. - TestRateCounter(500, 0, 100, 0); - // Increate payload size again. 200 * 100 * 0.5 = 10 kbps. - TestRateCounter(500, 200, 100, 10000); -} - -static void TestLossFilter(float loss_percent, bool zero_tolerance) { - LossFilter filter(NULL, 0); - filter.SetLoss(loss_percent); - Packets::size_type sent_packets = 0; - Packets::size_type remaining_packets = 0; - - // No input should yield no output - { - Packets packets; - sent_packets += packets.size(); - filter.RunFor(0, &packets); - ASSERT_TRUE(IsTimeSorted(packets)); - ASSERT_TRUE(IsSequenceNumberSorted(packets)); - remaining_packets += packets.size(); - EXPECT_EQ(0u, sent_packets); - EXPECT_EQ(0u, remaining_packets); - for (auto* packet : packets) - delete packet; - } - - // Generate and process 10000 packets in different batch sizes (some empty) - for (int i = 0; i < 2225; ++i) { - Packets packets; - for (int j = 0; j < i % 10; ++j) - packets.push_back(new MediaPacket(i, i)); - sent_packets += packets.size(); - filter.RunFor(0, &packets); - ASSERT_TRUE(IsTimeSorted(packets)); - ASSERT_TRUE(IsSequenceNumberSorted(packets)); - remaining_packets += packets.size(); - for (auto* packet : packets) - delete packet; - } - - float loss_fraction = 0.01f * (100.0f - loss_percent); - Packets::size_type expected_packets = loss_fraction * sent_packets; - if (zero_tolerance) { - EXPECT_EQ(expected_packets, remaining_packets); - } else { - // Require within 1% of expected - EXPECT_NEAR(expected_packets, remaining_packets, 100); - } -} - -TEST(BweTestFramework_LossFilterTest, Loss0) { - // With 0% loss, the result should be exact (no loss). - TestLossFilter(0.0f, true); -} - -TEST(BweTestFramework_LossFilterTest, Loss10) { - TestLossFilter(10.0f, false); -} - -TEST(BweTestFramework_LossFilterTest, Loss50) { - TestLossFilter(50.0f, false); -} - -TEST(BweTestFramework_LossFilterTest, Loss100) { - // With 100% loss, the result should be exact (no packets out). - TestLossFilter(100.0f, true); -} - -class BweTestFramework_DelayFilterTest : public ::testing::Test { - public: - BweTestFramework_DelayFilterTest() - : filter_(NULL, 0), now_ms_(0), sequence_number_(0) {} - virtual ~BweTestFramework_DelayFilterTest() { - for (auto* packet : accumulated_packets_) - delete packet; - } - - protected: - void TestDelayFilter(int64_t run_for_ms, - uint32_t in_packets, - uint32_t out_packets) { - Packets packets; - for (uint32_t i = 0; i < in_packets; ++i) { - packets.push_back(new MediaPacket( - now_ms_ * 1000 + (sequence_number_ >> 4), sequence_number_)); - sequence_number_++; - } - filter_.RunFor(run_for_ms, &packets); - ASSERT_TRUE(IsTimeSorted(packets)); - ASSERT_TRUE(IsSequenceNumberSorted(packets)); - for (PacketsConstIt it = packets.begin(); it != packets.end(); ++it) { - EXPECT_LE(now_ms_ * 1000, (*it)->send_time_us()); - } - EXPECT_EQ(out_packets, packets.size()); - accumulated_packets_.splice(accumulated_packets_.end(), packets); - now_ms_ += run_for_ms; - } - - void TestDelayFilter(int64_t delay_ms) { - filter_.SetOneWayDelayMs(delay_ms); - TestDelayFilter(1, 0, 0); // No input should yield no output - - // Single packet - TestDelayFilter(0, 1, 1); - TestDelayFilter(delay_ms, 0, 0); - - for (int i = 0; i < delay_ms; ++i) { - filter_.SetOneWayDelayMs(i); - TestDelayFilter(1, 10, 10); - } - TestDelayFilter(0, 0, 0); - TestDelayFilter(delay_ms, 0, 0); - - // Wait a little longer - should still see no output - TestDelayFilter(delay_ms, 0, 0); - - for (int i = 1; i < delay_ms + 1; ++i) { - filter_.SetOneWayDelayMs(i); - TestDelayFilter(1, 5, 5); - } - TestDelayFilter(0, 0, 0); - filter_.SetOneWayDelayMs(2 * delay_ms); - TestDelayFilter(1, 0, 0); - TestDelayFilter(delay_ms, 13, 13); - TestDelayFilter(delay_ms, 0, 0); - - // Wait a little longer - should still see no output - TestDelayFilter(delay_ms, 0, 0); - - for (int i = 0; i < 2 * delay_ms; ++i) { - filter_.SetOneWayDelayMs(2 * delay_ms - i - 1); - TestDelayFilter(1, 5, 5); - } - TestDelayFilter(0, 0, 0); - filter_.SetOneWayDelayMs(0); - TestDelayFilter(0, 7, 7); - - ASSERT_TRUE(IsTimeSorted(accumulated_packets_)); - ASSERT_TRUE(IsSequenceNumberSorted(accumulated_packets_)); - } - - DelayFilter filter_; - Packets accumulated_packets_; - - private: - int64_t now_ms_; - uint16_t sequence_number_; - - RTC_DISALLOW_COPY_AND_ASSIGN(BweTestFramework_DelayFilterTest); -}; - -TEST_F(BweTestFramework_DelayFilterTest, Delay0) { - TestDelayFilter(1, 0, 0); // No input should yield no output - TestDelayFilter(1, 10, 10); // Expect no delay (delay time is zero) - TestDelayFilter(1, 0, 0); // Check no packets are still in buffer - filter_.SetOneWayDelayMs(0); - TestDelayFilter(1, 5, 5); // Expect no delay (delay time is zero) - TestDelayFilter(1, 0, 0); // Check no packets are still in buffer -} - -TEST_F(BweTestFramework_DelayFilterTest, Delay1) { - TestDelayFilter(1); -} - -TEST_F(BweTestFramework_DelayFilterTest, Delay2) { - TestDelayFilter(2); -} - -TEST_F(BweTestFramework_DelayFilterTest, Delay20) { - TestDelayFilter(20); -} - -TEST_F(BweTestFramework_DelayFilterTest, Delay100) { - TestDelayFilter(100); -} - -TEST_F(BweTestFramework_DelayFilterTest, JumpToZeroDelay) { - DelayFilter delay(NULL, 0); - Packets acc; - Packets packets; - - // Delay a bunch of packets, accumulate them to the 'acc' list. - delay.SetOneWayDelayMs(100.0f); - for (uint32_t i = 0; i < 10; ++i) { - packets.push_back(new MediaPacket(i * 100, i)); - } - delay.RunFor(1000, &packets); - acc.splice(acc.end(), packets); - ASSERT_TRUE(IsTimeSorted(acc)); - ASSERT_TRUE(IsSequenceNumberSorted(acc)); - - // Drop delay to zero, send a few more packets through the delay, append them - // to the 'acc' list and verify that it is all sorted. - delay.SetOneWayDelayMs(0.0f); - for (uint32_t i = 10; i < 50; ++i) { - packets.push_back(new MediaPacket(i * 100, i)); - } - delay.RunFor(1000, &packets); - acc.splice(acc.end(), packets); - ASSERT_TRUE(IsTimeSorted(acc)); - ASSERT_TRUE(IsSequenceNumberSorted(acc)); - - for (auto* packet : acc) - delete packet; -} - -TEST_F(BweTestFramework_DelayFilterTest, IncreasingDelay) { - // Gradually increase delay. - for (int i = 1; i < 50; i += 4) { - TestDelayFilter(i); - } - // Reach a steady state. - filter_.SetOneWayDelayMs(100); - TestDelayFilter(1, 20, 20); - TestDelayFilter(2, 0, 0); - TestDelayFilter(99, 20, 20); - // Drop delay back down to zero. - filter_.SetOneWayDelayMs(0); - TestDelayFilter(1, 100, 100); - TestDelayFilter(23010, 0, 0); - ASSERT_TRUE(IsTimeSorted(accumulated_packets_)); - ASSERT_TRUE(IsSequenceNumberSorted(accumulated_packets_)); -} - -static void TestJitterFilter(int64_t max_jitter_ms) { - JitterFilter filter(NULL, 0); - filter.SetMaxJitter(max_jitter_ms); - - int64_t now_ms = 0; - uint16_t sequence_number = 0; - - // Generate packets, add jitter to them, accumulate the altered packets. - Packets original; - Packets jittered; - for (uint32_t i = 0; i < 1000; ++i) { - Packets packets; - for (uint32_t j = 0; j < i % 100; ++j) { - packets.push_back(new MediaPacket(now_ms * 1000, sequence_number)); - original.push_back(new MediaPacket(now_ms * 1000, sequence_number)); - ++sequence_number; - now_ms += 5 * max_jitter_ms; - } - filter.RunFor(max_jitter_ms, &packets); - jittered.splice(jittered.end(), packets); - } - - // Jittered packets should still be in order. - ASSERT_TRUE(IsTimeSorted(original)); - ASSERT_TRUE(IsTimeSorted(jittered)); - ASSERT_TRUE(IsSequenceNumberSorted(original)); - ASSERT_TRUE(IsSequenceNumberSorted(jittered)); - EXPECT_EQ(original.size(), jittered.size()); - - // Make sure jittered and original packets are in same order. Collect time - // difference (jitter) in stats, then check that mean jitter is close to zero - // and standard deviation of jitter is what we set it to. - Stats jitter_us; - int64_t max_jitter_obtained_us = 0; - for (PacketsIt it1 = original.begin(), it2 = jittered.begin(); - it1 != original.end() && it2 != jittered.end(); ++it1, ++it2) { - const MediaPacket* packet1 = static_cast(*it1); - const MediaPacket* packet2 = static_cast(*it2); - EXPECT_EQ(packet1->header().sequenceNumber, - packet2->header().sequenceNumber); - max_jitter_obtained_us = - std::max(max_jitter_obtained_us, - packet2->send_time_us() - packet1->send_time_us()); - jitter_us.Push(packet2->send_time_us() - packet1->send_time_us()); - } - EXPECT_NEAR(filter.MeanUs(), jitter_us.GetMean(), - max_jitter_ms * 1000.0 * 0.01); - EXPECT_NEAR(max_jitter_ms * 1000.0, max_jitter_obtained_us, - max_jitter_ms * 1000.0 * 0.01); - for (auto* packet : original) - delete packet; - for (auto* packet : jittered) - delete packet; -} - -TEST(BweTestFramework_JitterFilterTest, Jitter0) { - TestJitterFilter(0); -} - -TEST(BweTestFramework_JitterFilterTest, Jitter1) { - TestJitterFilter(1); -} - -TEST(BweTestFramework_JitterFilterTest, Jitter5) { - TestJitterFilter(5); -} - -TEST(BweTestFramework_JitterFilterTest, Jitter10) { - TestJitterFilter(10); -} - -TEST(BweTestFramework_JitterFilterTest, Jitter1031) { - TestJitterFilter(1031); -} - -static void TestReorderFilter(uint16_t reorder_percent) { - const uint16_t kPacketCount = 10000; - - // Generate packets with 10 ms interval. - Packets packets; - int64_t now_ms = 0; - uint16_t sequence_number = 1; - for (uint16_t i = 0; i < kPacketCount; ++i, now_ms += 10) { - packets.push_back(new MediaPacket(now_ms * 1000, sequence_number++)); - } - ASSERT_TRUE(IsTimeSorted(packets)); - ASSERT_TRUE(IsSequenceNumberSorted(packets)); - - // Reorder packets, verify that send times are still in order. - ReorderFilter filter(NULL, 0); - filter.SetReorder(reorder_percent); - filter.RunFor(now_ms, &packets); - ASSERT_TRUE(IsTimeSorted(packets)); - - // We measure the amount of reordering by summing the distance by which out- - // of-order packets have been moved in the stream. - uint16_t distance = 0; - uint16_t last_sequence_number = 0; - for (auto* packet : packets) { - const MediaPacket* media_packet = static_cast(packet); - uint16_t sequence_number = media_packet->header().sequenceNumber; - // The expected position for sequence number s is in position s-1. - if (sequence_number < last_sequence_number) { - distance += last_sequence_number - sequence_number; - } - last_sequence_number = sequence_number; - } - - // The probability that two elements are swapped is p = reorder_percent / 100. - double p = static_cast(reorder_percent) / 100; - // The expected number of swaps we perform is p * (PacketCount - 1), - // and each swap increases the distance by one. - double mean = p * (kPacketCount - 1); - // If pair i is chosen to be swapped with probability p, the variance for that - // pair is p * (1 - p). Since there are (kPacketCount - 1) independent pairs, - // the variance for the number of swaps is (kPacketCount - 1) * p * (1 - p). - double std_deviation = sqrt((kPacketCount - 1) * p * (1 - p)); - EXPECT_NEAR(mean, distance, 3 * std_deviation); - - for (auto* packet : packets) - delete packet; -} - -TEST(BweTestFramework_ReorderFilterTest, Reorder0) { - // For 0% reordering, no packets should have been moved, so result is exact. - TestReorderFilter(0); -} - -TEST(BweTestFramework_ReorderFilterTest, Reorder10) { - TestReorderFilter(10); -} - -TEST(BweTestFramework_ReorderFilterTest, Reorder20) { - TestReorderFilter(20); -} - -TEST(BweTestFramework_ReorderFilterTest, Reorder50) { - TestReorderFilter(50); -} - -TEST(BweTestFramework_ReorderFilterTest, Reorder70) { - TestReorderFilter(70); -} - -TEST(BweTestFramework_ReorderFilterTest, Reorder100) { - // Note that because the implementation works by optionally swapping two - // adjacent packets, when the likelihood of a swap is 1.0, a swap will always - // occur, so the stream will be in order except for the first packet, which - // has been moved to the end. Therefore we expect the result to be exact here. - TestReorderFilter(100.0); -} - -class BweTestFramework_ChokeFilterTest : public ::testing::Test { - public: - BweTestFramework_ChokeFilterTest() - : now_ms_(0), sequence_number_(0), output_packets_(), send_times_us_() {} - virtual ~BweTestFramework_ChokeFilterTest() { - for (auto* packet : output_packets_) - delete packet; - } - - protected: - void TestChoke(PacketProcessor* filter, - int64_t run_for_ms, - uint32_t packets_to_generate, - size_t expected_kbit_transmitted) { - // Generate a bunch of packets, apply choke, verify output is ordered. - Packets packets; - RTPHeader header; - for (uint32_t i = 0; i < packets_to_generate; ++i) { - int64_t send_time_ms = now_ms_ + (i * run_for_ms) / packets_to_generate; - header.sequenceNumber = sequence_number_++; - // Payload is 1000 bits. - packets.push_back(new MediaPacket(0, send_time_ms * 1000, 125, header)); - send_times_us_.push_back(send_time_ms * 1000); - } - ASSERT_TRUE(IsTimeSorted(packets)); - filter->RunFor(run_for_ms, &packets); - now_ms_ += run_for_ms; - output_packets_.splice(output_packets_.end(), packets); - ASSERT_TRUE(IsTimeSorted(output_packets_)); - ASSERT_TRUE(IsSequenceNumberSorted(output_packets_)); - - // Sum up the transmitted bytes up until the current time. - size_t bytes_transmitted = 0; - while (!output_packets_.empty()) { - const Packet* packet = output_packets_.front(); - if (packet->send_time_us() > now_ms_ * 1000) { - break; - } - bytes_transmitted += packet->payload_size(); - delete output_packets_.front(); - output_packets_.pop_front(); - } - EXPECT_EQ(expected_kbit_transmitted, (bytes_transmitted * 8 + 500) / 1000); - } - - void CheckMaxDelay(int64_t max_delay_ms) { - for (const auto* packet : output_packets_) { - const MediaPacket* media_packet = static_cast(packet); - int64_t delay_us = media_packet->send_time_us() - - send_times_us_[media_packet->header().sequenceNumber]; - EXPECT_GE(max_delay_ms * 1000, delay_us); - } - } - - private: - int64_t now_ms_; - uint16_t sequence_number_; - Packets output_packets_; - std::vector send_times_us_; - - RTC_DISALLOW_COPY_AND_ASSIGN(BweTestFramework_ChokeFilterTest); -}; - -TEST_F(BweTestFramework_ChokeFilterTest, NoQueue) { - const int kCapacityKbps = 10; - const size_t kPacketSizeBytes = 125; - const int64_t kExpectedSendTimeUs = - (kPacketSizeBytes * 8 * 1000 + kCapacityKbps / 2) / kCapacityKbps; - uint16_t sequence_number = 0; - int64_t send_time_us = 0; - ChokeFilter filter(NULL, 0); - filter.set_capacity_kbps(10); - Packets packets; - RTPHeader header; - for (int i = 0; i < 2; ++i) { - header.sequenceNumber = sequence_number++; - // Payload is 1000 bits. - packets.push_back( - new MediaPacket(0, send_time_us, kPacketSizeBytes, header)); - // Packets are sent far enough a part plus an extra millisecond so that they - // will never be in the choke queue at the same time. - send_time_us += kExpectedSendTimeUs + 1000; - } - ASSERT_TRUE(IsTimeSorted(packets)); - filter.RunFor(2 * kExpectedSendTimeUs + 1000, &packets); - EXPECT_EQ(kExpectedSendTimeUs, packets.front()->send_time_us()); - delete packets.front(); - packets.pop_front(); - EXPECT_EQ(2 * kExpectedSendTimeUs + 1000, packets.front()->send_time_us()); - delete packets.front(); - packets.pop_front(); -} - -TEST_F(BweTestFramework_ChokeFilterTest, Short) { - // 100ms, 100 packets, 10 kbps choke -> 1 kbit of data should have propagated. - // That is actually just a single packet, since each packet has 1000 bits of - // payload. - ChokeFilter filter(NULL, 0); - filter.set_capacity_kbps(10); - TestChoke(&filter, 100, 100, 1); -} - -TEST_F(BweTestFramework_ChokeFilterTest, Medium) { - // 100ms, 10 packets, 10 kbps choke -> 1 packet through, or 1 kbit. - ChokeFilter filter(NULL, 0); - filter.set_capacity_kbps(10); - TestChoke(&filter, 100, 10, 1); - // 200ms, no new packets -> another packet through. - TestChoke(&filter, 100, 0, 1); - // 1000ms, no new packets -> 8 more packets. - TestChoke(&filter, 800, 0, 8); - // 2000ms, no new packets -> queue is empty so no output. - TestChoke(&filter, 1000, 0, 0); -} - -TEST_F(BweTestFramework_ChokeFilterTest, Long) { - // 100ms, 100 packets in queue, 10 kbps choke -> 1 packet through, or 1 kbit. - ChokeFilter filter(NULL, 0); - filter.set_capacity_kbps(10); - TestChoke(&filter, 100, 100, 1); - // 200ms, no input, another packet through. - TestChoke(&filter, 100, 0, 1); - // 1000ms, no input, 8 packets through. - TestChoke(&filter, 800, 0, 8); - // 10000ms, no input, raise choke to 100 kbps. Remaining 90 packets in queue - // should be propagated, for a total of 90 kbps. - filter.set_capacity_kbps(100); - TestChoke(&filter, 9000, 0, 90); - // 10100ms, 20 more packets -> 10 packets or 10 kbit through. - TestChoke(&filter, 100, 20, 10); - // 10300ms, 10 more packets -> 20 packets out. - TestChoke(&filter, 200, 10, 20); - // 11300ms, no input, queue should be empty. - filter.set_capacity_kbps(10); - TestChoke(&filter, 1000, 0, 0); -} - -TEST_F(BweTestFramework_ChokeFilterTest, MaxDelay) { - // 10 kbps choke, 500 ms delay cap - ChokeFilter filter(NULL, 0); - filter.set_capacity_kbps(10); - filter.set_max_delay_ms(500); - // 100ms, 100 packets in queue, 10 kbps choke -> 1 packet through, or 1 kbit. - TestChoke(&filter, 100, 100, 1); - CheckMaxDelay(500); - // 500ms, no input, 4 more packets through. - TestChoke(&filter, 400, 0, 4); - // 10000ms, no input, remaining packets should have been dropped. - TestChoke(&filter, 9500, 0, 0); - - // 100 ms delay cap - filter.set_max_delay_ms(100); - // 10100ms, 50 more packets -> 1 packets or 1 kbit through. - TestChoke(&filter, 100, 50, 1); - CheckMaxDelay(100); - // 20000ms, no input, remaining packets in queue should have been dropped. - TestChoke(&filter, 9900, 0, 0); - - // Reset delay cap (0 is no cap) and verify no packets are dropped. - filter.set_capacity_kbps(10); - filter.set_max_delay_ms(0); - TestChoke(&filter, 100, 100, 1); - TestChoke(&filter, 9900, 0, 99); -} - -TEST_F(BweTestFramework_ChokeFilterTest, ShortTrace) { - // According to the input file 6 packets should be transmitted within - // 100 milliseconds. - TraceBasedDeliveryFilter filter(NULL, 0); - ASSERT_TRUE(filter.Init(test::ResourcePath("synthetic-trace", "rx"))); - TestChoke(&filter, 100, 100, 6); -} - -TEST_F(BweTestFramework_ChokeFilterTest, ShortTraceTwoWraps) { - // According to the input file 19 packets should be transmitted within - // 280 milliseconds (at the wrapping point two packets are sent back to back). - TraceBasedDeliveryFilter filter(NULL, 0); - ASSERT_TRUE(filter.Init(test::ResourcePath("synthetic-trace", "rx"))); - TestChoke(&filter, 280, 100, 19); -} - -TEST_F(BweTestFramework_ChokeFilterTest, ShortTraceMaxDelay) { - TraceBasedDeliveryFilter filter(NULL, 0); - filter.set_max_delay_ms(25); - ASSERT_TRUE(filter.Init(test::ResourcePath("synthetic-trace", "rx"))); - // Uses all slots up to 110 ms. Several packets are being dropped. - TestChoke(&filter, 110, 20, 9); - CheckMaxDelay(25); - // Simulate enough time for the next slot (at 135 ms) to be used. This makes - // sure that a slot isn't missed between runs. - TestChoke(&filter, 25, 1, 1); -} - -void TestVideoSender(VideoSender* sender, - int64_t run_for_ms, - uint32_t expected_packets, - uint32_t expected_payload_size, - size_t expected_total_payload_size) { - assert(sender); - Packets packets; - sender->RunFor(run_for_ms, &packets); - ASSERT_TRUE(IsTimeSorted(packets)); - ASSERT_TRUE(IsSequenceNumberSorted(packets)); - EXPECT_EQ(expected_packets, packets.size()); - - int64_t send_time_us = -1; - size_t total_payload_size = 0; - uint32_t absolute_send_time = 0; - uint32_t absolute_send_time_wraps = 0; - uint32_t rtp_timestamp = 0; - uint32_t rtp_timestamp_wraps = 0; - - for (const auto* packet : packets) { - const MediaPacket* media_packet = static_cast(packet); - EXPECT_LE(send_time_us, media_packet->send_time_us()); - send_time_us = media_packet->send_time_us(); - if (sender->source()->max_payload_size_bytes() != - media_packet->payload_size()) { - EXPECT_EQ(expected_payload_size, media_packet->payload_size()); - } - total_payload_size += media_packet->payload_size(); - if (absolute_send_time > - media_packet->header().extension.absoluteSendTime) { - absolute_send_time_wraps++; - } - absolute_send_time = media_packet->header().extension.absoluteSendTime; - if (rtp_timestamp > media_packet->header().timestamp) { - rtp_timestamp_wraps++; - } - rtp_timestamp = media_packet->header().timestamp; - } - - EXPECT_EQ(expected_total_payload_size, total_payload_size); - EXPECT_GE(1u, absolute_send_time_wraps); - EXPECT_GE(1u, rtp_timestamp_wraps); - - for (auto* packet : packets) - delete packet; -} - -// Random {-1, 0, +1} ms was added to frame timestamps. - -TEST(BweTestFramework_VideoSenderTest, Fps1Kbps80_1s) { - // 1 fps, 80 kbps - VideoSource source(0, 1.0f, 80, 0x1234, 0); - VideoSender sender(NULL, &source, kNullEstimator); - EXPECT_EQ(80000u, source.bits_per_second()); - // We're at 1 fps, so all packets should be generated on first call, giving 10 - // packets of each 1000 bytes, total 10000 bytes. - TestVideoSender(&sender, 1, 9, 400, 10000); - // 998ms, should see no output here. - TestVideoSender(&sender, 997, 0, 0, 0); - // 1001ms, should get data for one more frame. - TestVideoSender(&sender, 3, 9, 400, 10000); - // 1998ms, should see no output here. - TestVideoSender(&sender, 997, 0, 0, 0); - // 2001ms, one more frame. - TestVideoSender(&sender, 3, 9, 400, 10000); - // 2998ms, should see nothing. - TestVideoSender(&sender, 997, 0, 0, 0); -} - -TEST(BweTestFramework_VideoSenderTest, Fps1Kbps80_1s_Offset) { - // 1 fps, 80 kbps, offset 0.5 of a frame period, ==0.5s in this case. - VideoSource source(0, 1.0f, 80, 0x1234, 500); - VideoSender sender(NULL, &source, kNullEstimator); - EXPECT_EQ(80000u, source.bits_per_second()); - // 498ms, no output. - TestVideoSender(&sender, 498, 0, 0, 0); - // 501ms, first frame (this is the offset we set), 10 packets of 1000 bytes. - TestVideoSender(&sender, 3, 9, 400, 10000); - // 1498ms, nothing. - TestVideoSender(&sender, 997, 0, 0, 0); - // 1501ms, second frame. - TestVideoSender(&sender, 3, 9, 400, 10000); - // 2498ms, nothing. - TestVideoSender(&sender, 997, 0, 0, 0); - // 2501ms, third frame. - TestVideoSender(&sender, 3, 9, 400, 10000); - // 3498ms, nothing. - TestVideoSender(&sender, 997, 0, 0, 0); -} - -TEST(BweTestFramework_VideoSenderTest, Fps50Kpbs80_11s) { - // 50 fps, 80 kbps. - VideoSource source(0, 50.0f, 80, 0x1234, 0); - VideoSender sender(NULL, &source, kNullEstimator); - EXPECT_EQ(80000u, source.bits_per_second()); - // 9981, should see 500 frames, 200 byte payloads, total 100000 bytes. - TestVideoSender(&sender, 9981, 500, 200, 100000); - // 9998ms, nothing. - TestVideoSender(&sender, 17, 0, 0, 0); - // 10001ms, 501st frame as a single packet. - TestVideoSender(&sender, 3, 1, 200, 200); - // 10981ms, 49 more frames. - TestVideoSender(&sender, 981, 49, 200, 9800); - // 10998ms, nothing. - TestVideoSender(&sender, 17, 0, 0, 0); -} - -TEST(BweTestFramework_VideoSenderTest, Fps20Kpbs120_1s) { - // 20 fps, 120 kbps. - VideoSource source(0, 20.0f, 120, 0x1234, 0); - VideoSender sender(NULL, &source, kNullEstimator); - EXPECT_EQ(120000u, source.bits_per_second()); - // 451ms, 10 frames with 750 byte payloads, total 7500 bytes. - TestVideoSender(&sender, 451, 10, 750, 7500); - // 498ms, nothing. - TestVideoSender(&sender, 47, 0, 0, 0); - // 501ms, one more frame. - TestVideoSender(&sender, 3, 1, 750, 750); - // 951ms, 9 more frames. - TestVideoSender(&sender, 450, 9, 750, 6750); - // 998ms, nothing. - TestVideoSender(&sender, 47, 0, 0, 0); -} - -TEST(BweTestFramework_VideoSenderTest, Fps25Kbps820_20s) { - // 25 fps, 820 kbps. - VideoSource source(0, 25.0f, 820, 0x1234, 0); - VideoSender sender(NULL, &source, kNullEstimator); - EXPECT_EQ(820000u, source.bits_per_second()); - // 9961ms, 250 frames. 820 kbps = 102500 bytes/s, so total should be 1025000. - // Each frame is 102500/25=4100 bytes, or 5 packets (4 @1000 bytes, 1 @100), - // so packet count should be 5*250=1250 and last packet of each frame has - // 100 bytes of payload. - TestVideoSender(&sender, 9961, 1000, 500, 1025000); - // 9998ms, nothing. - TestVideoSender(&sender, 37, 0, 0, 0); - // 19961ms, 250 more frames. - TestVideoSender(&sender, 9963, 1000, 500, 1025000); - // 19998ms, nothing. - TestVideoSender(&sender, 37, 0, 0, 0); - // 20001ms, one more frame, as described above (25fps == 40ms/frame). - TestVideoSender(&sender, 3, 4, 500, 4100); - // 20038ms, nothing. - TestVideoSender(&sender, 37, 0, 0, 0); -} - -TEST(BweTestFramework_VideoSenderTest, TestAppendInOrder) { - // 1 fps, 80 kbps, 250ms offset. - VideoSource source1(0, 1.0f, 80, 0x1234, 250); - VideoSender sender1(NULL, &source1, kNullEstimator); - EXPECT_EQ(80000u, source1.bits_per_second()); - Packets packets; - // Generate some packets, verify they are sorted. - sender1.RunFor(999, &packets); - ASSERT_TRUE(IsTimeSorted(packets)); - ASSERT_TRUE(IsSequenceNumberSorted(packets)); - EXPECT_EQ(9u, packets.size()); - // Generate some more packets and verify they are appended to end of list. - sender1.RunFor(1000, &packets); - ASSERT_TRUE(IsTimeSorted(packets)); - ASSERT_TRUE(IsSequenceNumberSorted(packets)); - EXPECT_EQ(18u, packets.size()); - - // Another sender, 2 fps, 160 kbps, 150ms offset - VideoSource source2(0, 2.0f, 160, 0x2234, 150); - VideoSender sender2(NULL, &source2, kNullEstimator); - EXPECT_EQ(160000u, source2.bits_per_second()); - // Generate some packets, verify that they are merged with the packets already - // on the list. - sender2.RunFor(999, &packets); - ASSERT_TRUE(IsTimeSorted(packets)); - EXPECT_EQ(36u, packets.size()); - // Generate some more. - sender2.RunFor(1000, &packets); - ASSERT_TRUE(IsTimeSorted(packets)); - EXPECT_EQ(54u, packets.size()); - - for (auto* packet : packets) - delete packet; -} - -TEST(BweTestFramework_VideoSenderTest, FeedbackIneffective) { - VideoSource source(0, 25.0f, 820, 0x1234, 0); - VideoSender sender(NULL, &source, kNullEstimator); - - EXPECT_EQ(820000u, source.bits_per_second()); - TestVideoSender(&sender, 9961, 1000, 500, 1025000); - - // Make sure feedback has no effect on a regular video sender. - RembFeedback* feedback = new RembFeedback(0, 0, 0, 512000, RTCPReportBlock()); - Packets packets; - packets.push_back(feedback); - sender.RunFor(0, &packets); - EXPECT_EQ(820000u, source.bits_per_second()); - TestVideoSender(&sender, 10000, 1000, 500, 1025000); -} -} // namespace bwe -} // namespace testing -} // namespace webrtc diff --git a/modules/remote_bitrate_estimator/test/bwe_unittest.cc b/modules/remote_bitrate_estimator/test/bwe_unittest.cc deleted file mode 100644 index 15bccd9096..0000000000 --- a/modules/remote_bitrate_estimator/test/bwe_unittest.cc +++ /dev/null @@ -1,393 +0,0 @@ -/* - * Copyright (c) 2015 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 "modules/remote_bitrate_estimator/test/bwe.h" - -#include -#include -#include -#include - -#include "rtc_base/arraysize.h" -#include "test/gtest.h" - -namespace webrtc { -namespace testing { -namespace bwe { - -const int kSetCapacity = 1000; - -class LinkedSetTest : public ::testing::Test { - public: - LinkedSetTest() : linked_set_(kSetCapacity) {} - - ~LinkedSetTest() {} - - protected: - LinkedSet linked_set_; -}; - -TEST_F(LinkedSetTest, EmptySet) { - EXPECT_EQ(linked_set_.Range(), 0); -} - -TEST_F(LinkedSetTest, SinglePacket) { - const uint16_t kSeqNumber = 1; // Arbitrary. - // Other parameters don't matter here. - linked_set_.Insert(kSeqNumber, 0, 0, 0); - - EXPECT_EQ(linked_set_.Range(), 1); -} - -TEST_F(LinkedSetTest, MultiplePackets) { - const uint16_t kNumberPackets = 100; - - std::vector sequence_numbers; - for (size_t i = 0; i < kNumberPackets; ++i) { - sequence_numbers.push_back(static_cast(i + 1)); - } - std::shuffle(sequence_numbers.begin(), sequence_numbers.end(), - std::mt19937(std::random_device()())); - - for (size_t i = 0; i < kNumberPackets; ++i) { - // Other parameters don't matter here. - linked_set_.Insert(static_cast(i), 0, 0, 0); - } - - // Packets arriving out of order should not affect the following value: - EXPECT_EQ(linked_set_.Range(), kNumberPackets); -} - -TEST_F(LinkedSetTest, Overflow) { - const int kFirstSeqNumber = -100; - const int kLastSeqNumber = 100; - - for (int i = kFirstSeqNumber; i <= kLastSeqNumber; ++i) { - // Other parameters don't matter here. - linked_set_.Insert(static_cast(i), 0, 0, 0); - } - - // Wrapping shouldn't matter - EXPECT_EQ(linked_set_.Range(), kLastSeqNumber - kFirstSeqNumber + 1); -} - -TEST_F(LinkedSetTest, SameSequenceNumbers) { - // Test correct behavior when - // sequence numbers wrap (after 0xFFFF). - - // Choose step such as step*capacity < 0x8000 - // (received packets in a reasonable window) - const int kStep = 0x20; - // Choose iteration such as step*iteration > 0x10000 - // (imply wrap) - const int kIterations = 0x1000; - - int kSeqNumber = 1; - for (int i = 0; i < kIterations; ++i) { - // Other parameters don't matter here. - linked_set_.Insert(static_cast(kSeqNumber), 0, 0, 0); - kSeqNumber += kStep; - } - - EXPECT_EQ(linked_set_.Range(), (kSetCapacity - 1) * kStep + 1); -} - -class LossAccountTest : public ::testing::Test { - public: - LossAccountTest() {} - ~LossAccountTest() {} - - protected: - LossAccount loss_account_; -}; - -TEST_F(LossAccountTest, Operations) { - const size_t kTotal = 100; // Arbitrary values. - const size_t kLost = 10; - - LossAccount rhs(kTotal, kLost); - - loss_account_.Add(rhs); - EXPECT_EQ(loss_account_.num_total, kTotal); - EXPECT_EQ(loss_account_.num_lost, kLost); - EXPECT_NEAR(loss_account_.LossRatio(), static_cast(kLost) / kTotal, - 0.001f); - - loss_account_.Subtract(rhs); - EXPECT_EQ(loss_account_.num_total, 0UL); - EXPECT_EQ(loss_account_.num_lost, 0UL); - EXPECT_NEAR(loss_account_.LossRatio(), 0.0f, 0.001f); -} - -class BweReceiverTest : public ::testing::Test { - public: - BweReceiverTest() : bwe_receiver_(kFlowId) {} - ~BweReceiverTest() {} - - protected: - const int kFlowId = 1; // Arbitrary. - BweReceiver bwe_receiver_; -}; - -TEST_F(BweReceiverTest, ReceivingRateNoPackets) { - EXPECT_EQ(bwe_receiver_.RecentKbps(), static_cast(0)); -} - -TEST_F(BweReceiverTest, ReceivingRateSinglePacket) { - const size_t kPayloadSizeBytes = 500 * 1000; - const int64_t kSendTimeUs = 300 * 1000; - const int64_t kArrivalTimeMs = kSendTimeUs / 1000 + 100; - const uint16_t kSequenceNumber = 1; - const int64_t kTimeWindowMs = BweReceiver::kReceivingRateTimeWindowMs; - - const MediaPacket media_packet(kFlowId, kSendTimeUs, kPayloadSizeBytes, - kSequenceNumber); - bwe_receiver_.ReceivePacket(kArrivalTimeMs, media_packet); - - const size_t kReceivingRateKbps = 8 * kPayloadSizeBytes / kTimeWindowMs; - - EXPECT_NEAR(bwe_receiver_.RecentKbps(), kReceivingRateKbps, - static_cast(kReceivingRateKbps) / 100.0f); -} - -TEST_F(BweReceiverTest, ReceivingRateSmallPackets) { - const size_t kPayloadSizeBytes = 100 * 1000; - const int64_t kTimeGapMs = 50; // Between each packet. - const int64_t kOneWayDelayMs = 50; - - for (int i = 1; i < 50; ++i) { - int64_t send_time_us = i * kTimeGapMs * 1000; - int64_t arrival_time_ms = send_time_us / 1000 + kOneWayDelayMs; - uint16_t sequence_number = i; - const MediaPacket media_packet(kFlowId, send_time_us, kPayloadSizeBytes, - sequence_number); - bwe_receiver_.ReceivePacket(arrival_time_ms, media_packet); - } - - const size_t kReceivingRateKbps = 8 * kPayloadSizeBytes / kTimeGapMs; - EXPECT_NEAR(bwe_receiver_.RecentKbps(), kReceivingRateKbps, - static_cast(kReceivingRateKbps) / 100.0f); -} - -TEST_F(BweReceiverTest, PacketLossNoPackets) { - EXPECT_EQ(bwe_receiver_.RecentPacketLossRatio(), 0.0f); -} - -TEST_F(BweReceiverTest, PacketLossSinglePacket) { - const MediaPacket media_packet(kFlowId, 0, 0, 0); - bwe_receiver_.ReceivePacket(0, media_packet); - EXPECT_EQ(bwe_receiver_.RecentPacketLossRatio(), 0.0f); -} - -TEST_F(BweReceiverTest, PacketLossContiguousPackets) { - const int64_t kTimeWindowMs = BweReceiver::kPacketLossTimeWindowMs; - size_t set_capacity = bwe_receiver_.GetSetCapacity(); - - for (int i = 0; i < 10; ++i) { - uint16_t sequence_number = static_cast(i); - // Sequence_number and flow_id are the only members that matter here. - const MediaPacket media_packet(kFlowId, 0, 0, sequence_number); - // Arrival time = 0, all packets will be considered. - bwe_receiver_.ReceivePacket(0, media_packet); - } - EXPECT_EQ(bwe_receiver_.RecentPacketLossRatio(), 0.0f); - - for (int i = 30; i > 20; i--) { - uint16_t sequence_number = static_cast(i); - // Sequence_number and flow_id are the only members that matter here. - const MediaPacket media_packet(kFlowId, 0, 0, sequence_number); - // Only the packets sent in this for loop will be considered. - bwe_receiver_.ReceivePacket(2 * kTimeWindowMs, media_packet); - } - EXPECT_EQ(bwe_receiver_.RecentPacketLossRatio(), 0.0f); - - // Should handle uint16_t overflow. - for (int i = 0xFFFF - 10; i < 0xFFFF + 10; ++i) { - uint16_t sequence_number = static_cast(i); - const MediaPacket media_packet(kFlowId, 0, 0, sequence_number); - // Only the packets sent in this for loop will be considered. - bwe_receiver_.ReceivePacket(4 * kTimeWindowMs, media_packet); - } - EXPECT_EQ(bwe_receiver_.RecentPacketLossRatio(), 0.0f); - - // Should handle set overflow. - for (int i = 0; i < set_capacity * 1.5; ++i) { - uint16_t sequence_number = static_cast(i); - const MediaPacket media_packet(kFlowId, 0, 0, sequence_number); - // Only the packets sent in this for loop will be considered. - bwe_receiver_.ReceivePacket(6 * kTimeWindowMs, media_packet); - } - EXPECT_EQ(bwe_receiver_.RecentPacketLossRatio(), 0.0f); -} - -// Should handle duplicates. -TEST_F(BweReceiverTest, PacketLossDuplicatedPackets) { - const int64_t kTimeWindowMs = BweReceiver::kPacketLossTimeWindowMs; - - for (int i = 0; i < 10; ++i) { - const MediaPacket media_packet(kFlowId, 0, 0, 0); - // Arrival time = 0, all packets will be considered. - bwe_receiver_.ReceivePacket(0, media_packet); - } - EXPECT_EQ(bwe_receiver_.RecentPacketLossRatio(), 0.0f); - - // Missing the element 5. - const uint16_t kSequenceNumbers[] = {1, 2, 3, 4, 6, 7, 8}; - const int kNumPackets = arraysize(kSequenceNumbers); - - // Insert each sequence number twice. - for (int i = 0; i < 2; ++i) { - for (int j = 0; j < kNumPackets; j++) { - const MediaPacket media_packet(kFlowId, 0, 0, kSequenceNumbers[j]); - // Only the packets sent in this for loop will be considered. - bwe_receiver_.ReceivePacket(2 * kTimeWindowMs, media_packet); - } - } - - EXPECT_NEAR(bwe_receiver_.RecentPacketLossRatio(), 1.0f / (kNumPackets + 1), - 0.1f / (kNumPackets + 1)); -} - -TEST_F(BweReceiverTest, PacketLossLakingPackets) { - size_t set_capacity = bwe_receiver_.GetSetCapacity(); - EXPECT_LT(set_capacity, static_cast(0xFFFF)); - - // Missing every other packet. - for (size_t i = 0; i < set_capacity; ++i) { - if ((i & 1) == 0) { // Only even sequence numbers. - uint16_t sequence_number = static_cast(i); - const MediaPacket media_packet(kFlowId, 0, 0, sequence_number); - // Arrival time = 0, all packets will be considered. - bwe_receiver_.ReceivePacket(0, media_packet); - } - } - EXPECT_NEAR(bwe_receiver_.RecentPacketLossRatio(), 0.5f, 0.01f); -} - -TEST_F(BweReceiverTest, PacketLossLakingFewPackets) { - size_t set_capacity = bwe_receiver_.GetSetCapacity(); - EXPECT_LT(set_capacity, static_cast(0xFFFF)); - - const int kPeriod = 100; - // Missing one for each kPeriod packets. - for (size_t i = 0; i < set_capacity; ++i) { - if ((i % kPeriod) != 0) { - uint16_t sequence_number = static_cast(i); - const MediaPacket media_packet(kFlowId, 0, 0, sequence_number); - // Arrival time = 0, all packets will be considered. - bwe_receiver_.ReceivePacket(0, media_packet); - } - } - EXPECT_NEAR(bwe_receiver_.RecentPacketLossRatio(), 1.0f / kPeriod, - 0.1f / kPeriod); -} - -// Packet's sequence numbers greatly apart, expect high loss. -TEST_F(BweReceiverTest, PacketLossWideGap) { - const int64_t kTimeWindowMs = BweReceiver::kPacketLossTimeWindowMs; - - const MediaPacket media_packet1(0, 0, 0, 1); - const MediaPacket media_packet2(0, 0, 0, 1000); - // Only these two packets will be considered. - bwe_receiver_.ReceivePacket(0, media_packet1); - bwe_receiver_.ReceivePacket(0, media_packet2); - EXPECT_NEAR(bwe_receiver_.RecentPacketLossRatio(), 0.998f, 0.0001f); - - const MediaPacket media_packet3(0, 0, 0, 0); - const MediaPacket media_packet4(0, 0, 0, 0x8000); - // Only these two packets will be considered. - bwe_receiver_.ReceivePacket(2 * kTimeWindowMs, media_packet3); - bwe_receiver_.ReceivePacket(2 * kTimeWindowMs, media_packet4); - EXPECT_NEAR(bwe_receiver_.RecentPacketLossRatio(), 0.99994f, 0.00001f); -} - -// Packets arriving unordered should not be counted as losted. -TEST_F(BweReceiverTest, PacketLossUnorderedPackets) { - size_t num_packets = bwe_receiver_.GetSetCapacity() / 2; - std::vector sequence_numbers; - - for (size_t i = 0; i < num_packets; ++i) { - sequence_numbers.push_back(static_cast(i + 1)); - } - - std::shuffle(sequence_numbers.begin(), sequence_numbers.end(), - std::mt19937(std::random_device()())); - - for (size_t i = 0; i < num_packets; ++i) { - const MediaPacket media_packet(kFlowId, 0, 0, sequence_numbers[i]); - // Arrival time = 0, all packets will be considered. - bwe_receiver_.ReceivePacket(0, media_packet); - } - - EXPECT_EQ(bwe_receiver_.RecentPacketLossRatio(), 0.0f); -} - -TEST_F(BweReceiverTest, RecentKbps) { - EXPECT_EQ(bwe_receiver_.RecentKbps(), 0U); - - const size_t kPacketSizeBytes = 1200; - const int kNumPackets = 100; - - double window_size_s = bwe_receiver_.BitrateWindowS(); - - // Receive packets at the same time. - for (int i = 0; i < kNumPackets; ++i) { - MediaPacket packet(kFlowId, 0L, kPacketSizeBytes, static_cast(i)); - bwe_receiver_.ReceivePacket(0, packet); - } - - EXPECT_NEAR(bwe_receiver_.RecentKbps(), - (8 * kNumPackets * kPacketSizeBytes) / (1000 * window_size_s), - 10); - - int64_t time_gap_ms = - 2 * 1000 * window_size_s; // Larger than rate_counter time window. - - MediaPacket packet(kFlowId, time_gap_ms * 1000, kPacketSizeBytes, - static_cast(kNumPackets)); - bwe_receiver_.ReceivePacket(time_gap_ms, packet); - - EXPECT_NEAR(bwe_receiver_.RecentKbps(), - (8 * kPacketSizeBytes) / (1000 * window_size_s), 10); -} - -TEST_F(BweReceiverTest, Loss) { - EXPECT_NEAR(bwe_receiver_.GlobalReceiverPacketLossRatio(), 0.0f, 0.001f); - - LossAccount loss_account = bwe_receiver_.LinkedSetPacketLossRatio(); - EXPECT_NEAR(loss_account.LossRatio(), 0.0f, 0.001f); - - // Insert packets 1-50 and 151-200; - for (int i = 1; i <= 200; ++i) { - // Packet size and timestamp do not matter here. - MediaPacket packet(kFlowId, 0L, 0UL, static_cast(i)); - bwe_receiver_.ReceivePacket(0, packet); - if (i == 50) { - i += 100; - } - } - - loss_account = bwe_receiver_.LinkedSetPacketLossRatio(); - EXPECT_NEAR(loss_account.LossRatio(), 0.5f, 0.001f); - - bwe_receiver_.RelieveSetAndUpdateLoss(); - EXPECT_EQ(bwe_receiver_.received_packets_.size(), 100U / 10); - - // No packet loss within the preserved packets. - loss_account = bwe_receiver_.LinkedSetPacketLossRatio(); - EXPECT_NEAR(loss_account.LossRatio(), 0.0f, 0.001f); - - // RelieveSetAndUpdateLoss automatically updates loss account. - EXPECT_NEAR(bwe_receiver_.GlobalReceiverPacketLossRatio(), 0.5f, 0.001f); -} - -} // namespace bwe -} // namespace testing -} // namespace webrtc diff --git a/modules/remote_bitrate_estimator/test/estimators/bbr.cc b/modules/remote_bitrate_estimator/test/estimators/bbr.cc deleted file mode 100644 index b7daa81f7a..0000000000 --- a/modules/remote_bitrate_estimator/test/estimators/bbr.cc +++ /dev/null @@ -1,582 +0,0 @@ -/* - * Copyright (c) 2017 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 "modules/remote_bitrate_estimator/test/estimators/bbr.h" - -#include -#include -#include - -#include "modules/remote_bitrate_estimator/test/estimators/congestion_window.h" -#include "modules/remote_bitrate_estimator/test/estimators/max_bandwidth_filter.h" -#include "modules/remote_bitrate_estimator/test/estimators/min_rtt_filter.h" - -namespace webrtc { -namespace testing { -namespace bwe { -namespace { -const int kFeedbackIntervalsMs = 5; -// BBR uses this value to double sending rate each round trip. Design document -// suggests using this value. -const float kHighGain = 2.885f; -// BBR uses this value to drain queues created during STARTUP in one round trip -// time. -const float kDrainGain = 1 / kHighGain; -// kStartupGrowthTarget and kMaxRoundsWithoutGrowth are chosen from -// experiments, according to the design document. -const float kStartupGrowthTarget = 1.25f; -const int kMaxRoundsWithoutGrowth = 3; -// Pacing gain values for Probe Bandwidth mode. -const float kPacingGain[] = {1.1f, 0.9f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f}; -const size_t kGainCycleLength = sizeof(kPacingGain) / sizeof(kPacingGain[0]); -// Least number of rounds PROBE_RTT should last. -const int kProbeRttDurationRounds = 1; -// The least amount of milliseconds PROBE_RTT mode should last. -const int kProbeRttDurationMs = 200; -// Gain value for congestion window for assuming that network has no queues. -const float kTargetCongestionWindowGain = 1; -// Gain value for congestion window in PROBE_BW mode. In theory it should be -// equal to 1, but in practice because of delayed acks and the way networks -// work, it is nice to have some extra room in congestion window for full link -// utilization. Value chosen by observations on different tests. -const float kCruisingCongestionWindowGain = 2; -// Pacing gain specific for Recovery mode. Chosen by experiments in simulation -// tool. -const float kRecoveryPacingGain = 0.5f; -// Congestion window gain specific for Recovery mode. Chosen by experiments in -// simulation tool. -const float kRecoveryCongestionWindowGain = 1.5f; -// Number of rounds over which average RTT is stored for Recovery mode. -const size_t kPastRttsFilterSize = 1; -// Threshold to assume average RTT has increased for a round. Chosen by -// experiments in simulation tool. -const float kRttIncreaseThreshold = 3; -// Threshold to assume average RTT has decreased for a round. Chosen by -// experiments in simulation tool. -const float kRttDecreaseThreshold = 1.5f; -// If |kCongestionWindowThreshold| of the congestion window is filled up, tell -// encoder to stop, to avoid building sender side queues. -const float kCongestionWindowThreshold = 0.69f; -// Duration we send at |kDefaultRatebps| in order to ensure BBR has data to work -// with. -const int64_t kDefaultDurationMs = 200; -const int64_t kDefaultRatebps = 300000; -// Congestion window gain for PROBE_RTT mode. -const float kProbeRttCongestionWindowGain = 0.65f; -// We need to be sure that data inflight has increased by at least -// |kTargetCongestionWindowGainForHighGain| compared to the congestion window in -// PROBE_BW's high gain phase, to make ramp-up quicker. As high gain value has -// been decreased from 1.25 to 1.1 we need to make -// |kTargetCongestionWindowGainForHighGain| slightly higher than the actual high -// gain value. -const float kTargetCongestionWindowGainForHighGain = 1.15f; -// Encoder rate gain value for PROBE_RTT mode. -const float kEncoderRateGainForProbeRtt = 0.1f; -} // namespace - -BbrBweSender::BbrBweSender(BitrateObserver* observer, Clock* clock) - : BweSender(0), - observer_(observer), - clock_(clock), - mode_(STARTUP), - max_bandwidth_filter_(new MaxBandwidthFilter()), - min_rtt_filter_(new MinRttFilter()), - congestion_window_(new CongestionWindow()), - rand_(new Random(time(NULL))), - round_count_(0), - round_trip_end_(0), - full_bandwidth_reached_(false), - cycle_start_time_ms_(0), - cycle_index_(0), - bytes_acked_(0), - probe_rtt_start_time_ms_(0), - minimum_congestion_window_start_time_ms_(0), - minimum_congestion_window_start_round_(0), - bytes_sent_(0), - last_packet_sent_sequence_number_(0), - last_packet_acked_sequence_number_(0), - last_packet_ack_time_(0), - last_packet_send_time_(0), - pacing_rate_bps_(0), - last_packet_send_time_during_high_gain_ms_(-1), - data_sent_before_high_gain_started_bytes_(-1), - data_sent_before_high_gain_ended_bytes_(-1), - first_packet_ack_time_during_high_gain_ms_(-1), - last_packet_ack_time_during_high_gain_ms_(-1), - data_acked_before_high_gain_started_bytes_(-1), - data_acked_before_high_gain_ended_bytes_(-1), - first_packet_seq_num_during_high_gain_(0), - last_packet_seq_num_during_high_gain_(0), - high_gain_over_(false), - packet_stats_(), - past_rtts_() { - // Initially enter Startup mode. - EnterStartup(); -} - -BbrBweSender::~BbrBweSender() {} - -BbrBweSender::PacketStats::PacketStats() = default; - -BbrBweSender::PacketStats::PacketStats( - uint16_t sequence_number_, - int64_t last_sent_packet_send_time_ms_, - int64_t send_time_ms_, - int64_t ack_time_ms_, - int64_t last_acked_packet_ack_time_ms_, - size_t payload_size_bytes_, - size_t data_sent_bytes_, - size_t data_sent_before_last_sent_packet_bytes_, - size_t data_acked_bytes_, - size_t data_acked_before_last_acked_packet_bytes_) - : sequence_number(sequence_number_), - last_sent_packet_send_time_ms(last_sent_packet_send_time_ms_), - send_time_ms(send_time_ms_), - ack_time_ms(ack_time_ms_), - last_acked_packet_ack_time_ms(last_acked_packet_ack_time_ms_), - payload_size_bytes(payload_size_bytes_), - data_sent_bytes(data_sent_bytes_), - data_sent_before_last_sent_packet_bytes( - data_sent_before_last_sent_packet_bytes_), - data_acked_bytes(data_acked_bytes_), - data_acked_before_last_acked_packet_bytes( - data_acked_before_last_acked_packet_bytes_) {} - -BbrBweSender::PacketStats::PacketStats(const PacketStats&) = default; - -int BbrBweSender::GetFeedbackIntervalMs() const { - return kFeedbackIntervalsMs; -} - -void BbrBweSender::CalculatePacingRate() { - pacing_rate_bps_ = - max_bandwidth_filter_->max_bandwidth_estimate_bps() * pacing_gain_; -} - -// Declare lost packets as acked. -void BbrBweSender::HandleLoss(uint64_t last_acked_packet, - uint64_t recently_acked_packet) { - for (uint16_t i = last_acked_packet + 1; - AheadOrAt(recently_acked_packet - 1, i); i++) { - congestion_window_->AckReceived(packet_stats_[i].payload_size_bytes); - observer_->OnBytesAcked(packet_stats_[i].payload_size_bytes); - } -} - -void BbrBweSender::AddToPastRtts(int64_t rtt_sample_ms) { - uint64_t last_round = 0; - if (!past_rtts_.empty()) - last_round = past_rtts_.back().round; - - // Try to add the sample to the last round. - if (last_round == round_count_ && !past_rtts_.empty()) { - past_rtts_.back().sum_of_rtts_ms += rtt_sample_ms; - past_rtts_.back().num_samples++; - } else { - // If the sample belongs to a new round, keep number of rounds in the window - // equal to |kPastRttsFilterSize|. - if (past_rtts_.size() == kPastRttsFilterSize) - past_rtts_.pop_front(); - past_rtts_.push_back( - BbrBweSender::AverageRtt(rtt_sample_ms, 1, round_count_)); - } -} - -void BbrBweSender::GiveFeedback(const FeedbackPacket& feedback) { - int64_t now_ms = clock_->TimeInMilliseconds(); - last_packet_ack_time_ = now_ms; - const BbrBweFeedback& fb = static_cast(feedback); - // feedback_vector holds values of acknowledged packets' sequence numbers. - const std::vector& feedback_vector = fb.packet_feedback_vector(); - // Go through all the packets acked, update variables/containers accordingly. - for (uint16_t sequence_number : feedback_vector) { - // Completing packet information with a recently received ack. - PacketStats* packet = &packet_stats_[sequence_number]; - bytes_acked_ += packet->payload_size_bytes; - packet->data_sent_bytes = bytes_sent_; - packet->last_sent_packet_send_time_ms = last_packet_send_time_; - packet->data_acked_bytes = bytes_acked_; - packet->ack_time_ms = now_ms; - // Logic specific to applying "bucket" to high gain, in order to have - // quicker ramp-up. We check if we started receiving acks for the packets - // sent during high gain phase. - if (packet->sequence_number == first_packet_seq_num_during_high_gain_) { - first_packet_ack_time_during_high_gain_ms_ = now_ms; - // Substracting half of the packet's size to avoid overestimation. - data_acked_before_high_gain_started_bytes_ = - bytes_acked_ - packet->payload_size_bytes / 2; - } - // If the last packet of high gain phase has been acked, high gain phase is - // over. - if (packet->sequence_number == last_packet_seq_num_during_high_gain_) { - last_packet_ack_time_during_high_gain_ms_ = now_ms; - data_acked_before_high_gain_ended_bytes_ = - bytes_acked_ - packet->payload_size_bytes / 2; - high_gain_over_ = true; - } - observer_->OnBytesAcked(packet->payload_size_bytes); - congestion_window_->AckReceived(packet->payload_size_bytes); - HandleLoss(last_packet_acked_sequence_number_, packet->sequence_number); - last_packet_acked_sequence_number_ = packet->sequence_number; - // Logic for wrapping sequence numbers. If round started with packet number - // x, it can never end on y, if x > y. That could happen when sequence - // numbers are wrapped after some point. - if (packet->sequence_number == 0) - round_trip_end_ = 0; - } - // Check if new round started for the connection. - bool new_round_started = false; - if (!feedback_vector.empty()) { - if (last_packet_acked_sequence_number_ > round_trip_end_) { - new_round_started = true; - round_count_++; - round_trip_end_ = last_packet_sent_sequence_number_; - } - } - TryEnteringProbeRtt(now_ms); - UpdateBandwidthAndMinRtt(now_ms, feedback_vector, bytes_acked_); - if (new_round_started && !full_bandwidth_reached_) { - full_bandwidth_reached_ = max_bandwidth_filter_->FullBandwidthReached( - kStartupGrowthTarget, kMaxRoundsWithoutGrowth); - } - switch (mode_) { - break; - case STARTUP: - TryExitingStartup(); - break; - case DRAIN: - TryExitingDrain(now_ms); - break; - case PROBE_BW: - TryUpdatingCyclePhase(now_ms); - break; - case PROBE_RTT: - TryExitingProbeRtt(now_ms, round_count_); - break; - case RECOVERY: - TryExitingRecovery(new_round_started); - break; - } - TryEnteringRecovery(new_round_started); // Comment this line to disable - // entering Recovery mode. - for (uint16_t f : feedback_vector) - AddToPastRtts(packet_stats_[f].ack_time_ms - packet_stats_[f].send_time_ms); - CalculatePacingRate(); - size_t cwnd = congestion_window_->GetCongestionWindow( - mode_, max_bandwidth_filter_->max_bandwidth_estimate_bps(), - min_rtt_filter_->min_rtt_ms(), congestion_window_gain_); - // Make sure we don't get stuck when pacing_rate is 0, because of simulation - // tool specifics. - if (!pacing_rate_bps_) - pacing_rate_bps_ = 100; - BWE_TEST_LOGGING_PLOT(1, "SendRate", now_ms, pacing_rate_bps_ / 1000); - int64_t rate_for_pacer_bps = pacing_rate_bps_; - int64_t rate_for_encoder_bps = pacing_rate_bps_; - if (congestion_window_->data_inflight() >= cwnd * kCongestionWindowThreshold) - rate_for_encoder_bps = 0; - // We dont completely stop sending during PROBE_RTT, so we need encoder to - // produce something, another way of doing this would be telling encoder to - // stop and send padding instead of actual data. - if (mode_ == PROBE_RTT) - rate_for_encoder_bps = rate_for_pacer_bps * kEncoderRateGainForProbeRtt; - // Send for 300 kbps for first 200 ms, so that BBR has data to work with. - if (now_ms <= kDefaultDurationMs) - observer_->OnNetworkChanged( - kDefaultRatebps, kDefaultRatebps, false, - clock_->TimeInMicroseconds() + kFeedbackIntervalsMs * 1000, cwnd); - else - observer_->OnNetworkChanged( - rate_for_encoder_bps, rate_for_pacer_bps, mode_ == PROBE_RTT, - clock_->TimeInMicroseconds() + kFeedbackIntervalsMs * 1000, cwnd); -} - -size_t BbrBweSender::TargetCongestionWindow(float gain) { - size_t target_congestion_window = - congestion_window_->GetTargetCongestionWindow( - max_bandwidth_filter_->max_bandwidth_estimate_bps(), - min_rtt_filter_->min_rtt_ms(), gain); - return target_congestion_window; -} - -absl::optional BbrBweSender::CalculateBandwidthSample( - size_t data_sent_bytes, - int64_t send_time_delta_ms, - size_t data_acked_bytes, - int64_t ack_time_delta_ms) { - absl::optional bandwidth_sample; - if (send_time_delta_ms > 0) - bandwidth_sample.emplace(data_sent_bytes * 8000 / send_time_delta_ms); - absl::optional ack_rate; - if (ack_time_delta_ms > 0) - ack_rate.emplace(data_acked_bytes * 8000 / ack_time_delta_ms); - // If send rate couldn't be calculated automaticaly set |bandwidth_sample| to - // ack_rate. - if (!bandwidth_sample) - bandwidth_sample = ack_rate; - if (bandwidth_sample && ack_rate) - bandwidth_sample.emplace(std::min(*bandwidth_sample, *ack_rate)); - return bandwidth_sample; -} - -void BbrBweSender::AddSampleForHighGain() { - if (!high_gain_over_) - return; - high_gain_over_ = false; - // Calculate data sent/acked and time elapsed only for packets sent during - // high gain phase. - size_t data_sent_bytes = data_sent_before_high_gain_ended_bytes_ - - data_sent_before_high_gain_started_bytes_; - int64_t send_time_delta_ms = last_packet_send_time_during_high_gain_ms_ - - *first_packet_send_time_during_high_gain_ms_; - size_t data_acked_bytes = data_acked_before_high_gain_ended_bytes_ - - data_acked_before_high_gain_started_bytes_; - int64_t ack_time_delta_ms = last_packet_ack_time_during_high_gain_ms_ - - first_packet_ack_time_during_high_gain_ms_; - absl::optional bandwidth_sample = CalculateBandwidthSample( - data_sent_bytes, send_time_delta_ms, data_acked_bytes, ack_time_delta_ms); - if (bandwidth_sample) - max_bandwidth_filter_->AddBandwidthSample(*bandwidth_sample, round_count_); - first_packet_send_time_during_high_gain_ms_.reset(); -} - -void BbrBweSender::UpdateBandwidthAndMinRtt( - int64_t now_ms, - const std::vector& feedback_vector, - int64_t bytes_acked) { - absl::optional min_rtt_sample_ms; - for (uint16_t f : feedback_vector) { - PacketStats packet = packet_stats_[f]; - size_t data_sent_bytes = - packet.data_sent_bytes - packet.data_sent_before_last_sent_packet_bytes; - int64_t send_time_delta_ms = - packet.last_sent_packet_send_time_ms - packet.send_time_ms; - size_t data_acked_bytes = packet.data_acked_bytes - - packet.data_acked_before_last_acked_packet_bytes; - int64_t ack_time_delta_ms = - packet.ack_time_ms - packet.last_acked_packet_ack_time_ms; - absl::optional bandwidth_sample = - CalculateBandwidthSample(data_sent_bytes, send_time_delta_ms, - data_acked_bytes, ack_time_delta_ms); - if (bandwidth_sample) - max_bandwidth_filter_->AddBandwidthSample(*bandwidth_sample, - round_count_); - // AddSampleForHighGain(); // Comment to disable bucket for high gain. - if (!min_rtt_sample_ms) - min_rtt_sample_ms.emplace(packet.ack_time_ms - packet.send_time_ms); - else - *min_rtt_sample_ms = std::min(*min_rtt_sample_ms, - packet.ack_time_ms - packet.send_time_ms); - BWE_TEST_LOGGING_PLOT(1, "MinRtt", now_ms, - packet.ack_time_ms - packet.send_time_ms); - } - // We only feed RTT samples into the min_rtt filter which were not produced - // during 1.1 gain phase, to ensure they contain no queueing delay. But if the - // rtt sample from 1.1 gain phase improves the current estimate then we should - // make it as a new best estimate. - if (pacing_gain_ <= 1.0f || !min_rtt_filter_->min_rtt_ms() || - *min_rtt_filter_->min_rtt_ms() >= *min_rtt_sample_ms) - min_rtt_filter_->AddRttSample(*min_rtt_sample_ms, now_ms); -} - -void BbrBweSender::EnterStartup() { - mode_ = STARTUP; - pacing_gain_ = kHighGain; - congestion_window_gain_ = kHighGain; -} - -void BbrBweSender::TryExitingStartup() { - if (full_bandwidth_reached_) { - mode_ = DRAIN; - pacing_gain_ = kDrainGain; - congestion_window_gain_ = kHighGain; - } -} - -void BbrBweSender::TryExitingDrain(int64_t now_ms) { - if (congestion_window_->data_inflight() <= - TargetCongestionWindow(kTargetCongestionWindowGain)) - EnterProbeBw(now_ms); -} - -// Start probing with a random gain value, which is different form 0.75, -// starting with 0.75 doesn't offer any benefits as there are no queues to be -// drained. -void BbrBweSender::EnterProbeBw(int64_t now_ms) { - mode_ = PROBE_BW; - congestion_window_gain_ = kCruisingCongestionWindowGain; - int index = rand_->Rand(kGainCycleLength - 2); - if (index == 1) - index = kGainCycleLength - 1; - pacing_gain_ = kPacingGain[index]; - cycle_start_time_ms_ = now_ms; - cycle_index_ = index; -} - -void BbrBweSender::TryUpdatingCyclePhase(int64_t now_ms) { - // Each phase should last rougly min_rtt ms time. - bool advance_cycle_phase = false; - if (min_rtt_filter_->min_rtt_ms()) - advance_cycle_phase = - now_ms - cycle_start_time_ms_ > *min_rtt_filter_->min_rtt_ms(); - // If BBR was probing and it couldn't increase data inflight sufficiently in - // one min_rtt time, continue probing. BBR design doc isn't clear about this, - // but condition helps in quicker ramp-up and performs better. - if (pacing_gain_ > 1.0 && - congestion_window_->data_inflight() < - TargetCongestionWindow(kTargetCongestionWindowGainForHighGain)) - advance_cycle_phase = false; - // If BBR has already drained queues there is no point in continuing draining - // phase. - if (pacing_gain_ < 1.0 && - congestion_window_->data_inflight() <= TargetCongestionWindow(1)) - advance_cycle_phase = true; - if (advance_cycle_phase) { - cycle_index_++; - cycle_index_ %= kGainCycleLength; - pacing_gain_ = kPacingGain[cycle_index_]; - cycle_start_time_ms_ = now_ms; - } -} - -void BbrBweSender::TryEnteringProbeRtt(int64_t now_ms) { - if (min_rtt_filter_->MinRttExpired(now_ms) && mode_ != PROBE_RTT) { - mode_ = PROBE_RTT; - pacing_gain_ = 1; - congestion_window_gain_ = kProbeRttCongestionWindowGain; - probe_rtt_start_time_ms_ = now_ms; - minimum_congestion_window_start_time_ms_.reset(); - } -} - -// |minimum_congestion_window_start_time_|'s value is set to the first moment -// when data inflight was less then -// |CongestionWindow::kMinimumCongestionWindowBytes|, we should make sure that -// BBR has been in PROBE_RTT mode for at least one round or 200ms. -void BbrBweSender::TryExitingProbeRtt(int64_t now_ms, int64_t round) { - if (!minimum_congestion_window_start_time_ms_) { - if (congestion_window_->data_inflight() <= - TargetCongestionWindow(kProbeRttCongestionWindowGain)) { - minimum_congestion_window_start_time_ms_.emplace(now_ms); - minimum_congestion_window_start_round_ = round; - } - } else { - if (now_ms - *minimum_congestion_window_start_time_ms_ >= - kProbeRttDurationMs && - round - minimum_congestion_window_start_round_ >= - kProbeRttDurationRounds) { - EnterProbeBw(now_ms); - } - } -} - -void BbrBweSender::TryEnteringRecovery(bool new_round_started) { - if (mode_ == RECOVERY || !new_round_started || !full_bandwidth_reached_ || - !min_rtt_filter_->min_rtt_ms()) - return; - uint64_t increased_rtt_round_counter = 0; - // If average RTT for past |kPastRttsFilterSize| rounds has been more than - // some multiplier of min_rtt_ms enter Recovery. - for (BbrBweSender::AverageRtt i : past_rtts_) { - if (i.sum_of_rtts_ms / (int64_t)i.num_samples >= - *min_rtt_filter_->min_rtt_ms() * kRttIncreaseThreshold) - increased_rtt_round_counter++; - } - if (increased_rtt_round_counter < kPastRttsFilterSize) - return; - mode_ = RECOVERY; - pacing_gain_ = kRecoveryPacingGain; - congestion_window_gain_ = kRecoveryCongestionWindowGain; -} - -void BbrBweSender::TryExitingRecovery(bool new_round_started) { - if (mode_ != RECOVERY || !new_round_started || !full_bandwidth_reached_) - return; - // If average RTT for the past round has decreased sufficiently exit Recovery. - if (!past_rtts_.empty()) { - BbrBweSender::AverageRtt last_round_sample = past_rtts_.back(); - if (last_round_sample.sum_of_rtts_ms / last_round_sample.num_samples <= - *min_rtt_filter_->min_rtt_ms() * kRttDecreaseThreshold) { - EnterProbeBw(clock_->TimeInMilliseconds()); - } - } -} - -int64_t BbrBweSender::TimeUntilNextProcess() { - return 50; -} - -void BbrBweSender::OnPacketsSent(const Packets& packets) { - for (Packet* packet : packets) { - if (packet->GetPacketType() == Packet::kMedia) { - MediaPacket* media_packet = static_cast(packet); - bytes_sent_ += media_packet->payload_size(); - PacketStats packet_stats = PacketStats( - media_packet->sequence_number(), 0, - media_packet->sender_timestamp_ms(), 0, last_packet_ack_time_, - media_packet->payload_size(), 0, bytes_sent_, 0, bytes_acked_); - packet_stats_[media_packet->sequence_number()] = packet_stats; - last_packet_send_time_ = media_packet->sender_timestamp_ms(); - last_packet_sent_sequence_number_ = media_packet->sequence_number(); - // If this is the first packet sent for high gain phase, save data for it. - if (!first_packet_send_time_during_high_gain_ms_ && pacing_gain_ > 1) { - first_packet_send_time_during_high_gain_ms_.emplace( - last_packet_send_time_); - data_sent_before_high_gain_started_bytes_ = - bytes_sent_ - media_packet->payload_size() / 2; - first_packet_seq_num_during_high_gain_ = - media_packet->sequence_number(); - } - // This condition ensures that |last_packet_seq_num_during_high_gain_| - // will contain a sequence number of the last packet sent during high gain - // phase. - if (pacing_gain_ > 1) { - last_packet_send_time_during_high_gain_ms_ = last_packet_send_time_; - data_sent_before_high_gain_ended_bytes_ = - bytes_sent_ - media_packet->payload_size() / 2; - last_packet_seq_num_during_high_gain_ = media_packet->sequence_number(); - } - congestion_window_->PacketSent(media_packet->payload_size()); - } - } -} - -void BbrBweSender::Process() {} - -BbrBweReceiver::BbrBweReceiver(int flow_id) - : BweReceiver(flow_id, kReceivingRateTimeWindowMs), - clock_(0), - packet_feedbacks_(), - last_feedback_ms_(0) {} - -BbrBweReceiver::~BbrBweReceiver() {} - -void BbrBweReceiver::ReceivePacket(int64_t arrival_time_ms, - const MediaPacket& media_packet) { - packet_feedbacks_.push_back(media_packet.sequence_number()); - BweReceiver::ReceivePacket(arrival_time_ms, media_packet); -} - -FeedbackPacket* BbrBweReceiver::GetFeedback(int64_t now_ms) { - last_feedback_ms_ = now_ms; - int64_t corrected_send_time_ms = 0L; - if (!received_packets_.empty()) { - PacketIdentifierNode& latest = *(received_packets_.begin()); - corrected_send_time_ms = - latest.send_time_ms + now_ms - latest.arrival_time_ms; - } - FeedbackPacket* fb = new BbrBweFeedback( - flow_id_, now_ms * 1000, corrected_send_time_ms, packet_feedbacks_); - packet_feedbacks_.clear(); - return fb; -} -} // namespace bwe -} // namespace testing -} // namespace webrtc diff --git a/modules/remote_bitrate_estimator/test/estimators/bbr.h b/modules/remote_bitrate_estimator/test/estimators/bbr.h deleted file mode 100644 index f715b96bca..0000000000 --- a/modules/remote_bitrate_estimator/test/estimators/bbr.h +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright (c) 2017 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. - * - */ - -#ifndef MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_ESTIMATORS_BBR_H_ -#define MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_ESTIMATORS_BBR_H_ - -#include -#include -#include -#include - -#include "absl/types/optional.h" -#include "modules/remote_bitrate_estimator/test/bwe.h" -#include "rtc_base/numerics/sequence_number_util.h" -#include "rtc_base/random.h" - -namespace webrtc { -namespace testing { -namespace bwe { -class MaxBandwidthFilter; -class MinRttFilter; -class CongestionWindow; -class BbrBweSender : public BweSender { - public: - explicit BbrBweSender(BitrateObserver* observer, Clock* clock); - ~BbrBweSender() override; - enum Mode { - // Startup phase. - STARTUP, - // Queue draining phase, which where created during startup. - DRAIN, - // Cruising, probing new bandwidth. - PROBE_BW, - // Temporarily limiting congestion window size in order to measure - // minimum RTT. - PROBE_RTT, - // Temporarily reducing pacing rate and congestion window, in order to - // ensure no queues are built. - RECOVERY - }; - - struct PacketStats { - PacketStats(); - PacketStats(uint16_t sequence_number_, - int64_t last_sent_packet_send_time_ms_, - int64_t send_time_ms_, - int64_t ack_time_ms_, - int64_t last_acked_packet_ack_time_ms_, - size_t payload_size_bytes_, - size_t data_sent_bytes_, - size_t data_sent_before_last_sent_packet_bytes_, - size_t data_acked_bytes_, - size_t data_acked_before_last_acked_packet_bytes_); - PacketStats(const PacketStats&); - - // Sequence number of this packet. - uint16_t sequence_number; - // Send time of the last sent packet at ack time of this packet. - int64_t last_sent_packet_send_time_ms; - // Send time of this packet. - int64_t send_time_ms; - // Ack time of this packet. - int64_t ack_time_ms; - // Ack time of the last acked packet at send time of this packet. - int64_t last_acked_packet_ack_time_ms; - // Payload size of this packet. - size_t payload_size_bytes; - // Amount of data sent before this packet was sent. - size_t data_sent_bytes; - // Amount of data sent, before last sent packet. - size_t data_sent_before_last_sent_packet_bytes; - // Amount of data acked, before this packet was acked. - size_t data_acked_bytes; - // Amount of data acked, before last acked packet. - size_t data_acked_before_last_acked_packet_bytes; - }; - struct AverageRtt { - AverageRtt() {} - AverageRtt(int64_t sum_of_rtts_ms_, int64_t num_samples_, uint64_t round_) - : sum_of_rtts_ms(sum_of_rtts_ms_), - num_samples(num_samples_), - round(round_) {} - // Sum of RTTs over the round. - int64_t sum_of_rtts_ms; - // Number of RTT samples over the round. - int64_t num_samples; - // The number of the round average RTT is recorded for. - uint64_t round; - }; - void OnPacketsSent(const Packets& packets) override; - int GetFeedbackIntervalMs() const override; - void GiveFeedback(const FeedbackPacket& feedback) override; - int64_t TimeUntilNextProcess() override; - void Process() override; - - private: - void EnterStartup(); - void UpdateBandwidthAndMinRtt(int64_t now_ms, - const std::vector& feedback_vector, - int64_t bytes_acked); - void TryExitingStartup(); - void TryExitingDrain(int64_t now_ms); - void EnterProbeBw(int64_t now_ms); - void TryUpdatingCyclePhase(int64_t now_ms); - void TryEnteringProbeRtt(int64_t now_ms); - void TryExitingProbeRtt(int64_t now_ms, int64_t round); - void TryEnteringRecovery(bool new_round_started); - void TryExitingRecovery(bool new_round_started); - size_t TargetCongestionWindow(float gain); - void CalculatePacingRate(); - - // Calculates and returns bandwidth sample as minimum between send rate and - // ack rate, returns nothing if sample cannot be calculated. - absl::optional CalculateBandwidthSample(size_t data_sent, - int64_t send_time_delta_ms, - size_t data_acked, - int64_t ack_time_delta_ms); - - // Calculate and add bandwidth sample only for packets' sent during high gain - // phase. Motivation of having a seperate bucket for high gain phase is to - // achieve quicker ramp up. Slight overestimations may happen due to window - // not being as large as usual. - void AddSampleForHighGain(); - - // Declares lost packets as acked. Implements simple logic by looking at the - // gap between sequence numbers. If there is a gap between sequence numbers we - // declare those packets as lost immediately. - void HandleLoss(uint64_t last_acked_packet, uint64_t recently_acked_packet); - void AddToPastRtts(int64_t rtt_sample_ms); - BitrateObserver* observer_; - Clock* const clock_; - Mode mode_; - std::unique_ptr max_bandwidth_filter_; - std::unique_ptr min_rtt_filter_; - std::unique_ptr congestion_window_; - std::unique_ptr rand_; - uint64_t round_count_; - uint64_t round_trip_end_; - float pacing_gain_; - float congestion_window_gain_; - - // If optimal bandwidth has been discovered and reached, (for example after - // Startup mode) set this variable to true. - bool full_bandwidth_reached_; - - // Entering time for PROBE_BW mode's cycle phase. - int64_t cycle_start_time_ms_; - - // Index number of the currently used gain value in PROBE_BW mode, from 0 to - // kGainCycleLength - 1. - int64_t cycle_index_; - size_t bytes_acked_; - - // Time we entered PROBE_RTT mode. - int64_t probe_rtt_start_time_ms_; - - // First moment of time when data inflight decreased below - // kMinimumCongestionWindow in PROBE_RTT mode. - absl::optional minimum_congestion_window_start_time_ms_; - - // First round when data inflight decreased below kMinimumCongestionWindow in - // PROBE_RTT mode. - int64_t minimum_congestion_window_start_round_; - size_t bytes_sent_; - uint16_t last_packet_sent_sequence_number_; - uint16_t last_packet_acked_sequence_number_; - int64_t last_packet_ack_time_; - int64_t last_packet_send_time_; - int64_t pacing_rate_bps_; - - // Send time of a packet sent first during high gain phase. Also serves as a - // flag, holding value means that we are already in high gain. - absl::optional first_packet_send_time_during_high_gain_ms_; - - // Send time of a packet sent last during high gain phase. - int64_t last_packet_send_time_during_high_gain_ms_; - - // Amount of data sent, before first packet was sent during high gain phase. - int64_t data_sent_before_high_gain_started_bytes_; - - // Amount of data sent, before last packet was sent during high gain phase. - int64_t data_sent_before_high_gain_ended_bytes_; - - // Ack time of a packet acked first during high gain phase. - int64_t first_packet_ack_time_during_high_gain_ms_; - - // Ack time of a packet acked last during high gain phase. - int64_t last_packet_ack_time_during_high_gain_ms_; - - // Amount of data acked, before the first packet was acked during high gain - // phase. - int64_t data_acked_before_high_gain_started_bytes_; - - // Amount of data acked, before the last packet was acked during high gain - // phase. - int64_t data_acked_before_high_gain_ended_bytes_; - - // Sequence number of the first packet sent during high gain phase. - uint16_t first_packet_seq_num_during_high_gain_; - - // Sequence number of the last packet sent during high gain phase. - uint16_t last_packet_seq_num_during_high_gain_; - bool high_gain_over_; - std::map packet_stats_; - std::list past_rtts_; -}; - -class BbrBweReceiver : public BweReceiver { - public: - explicit BbrBweReceiver(int flow_id); - ~BbrBweReceiver() override; - void ReceivePacket(int64_t arrival_time_ms, - const MediaPacket& media_packet) override; - FeedbackPacket* GetFeedback(int64_t now_ms) override; - - private: - SimulatedClock clock_; - std::vector packet_feedbacks_; - int64_t last_feedback_ms_; -}; -} // namespace bwe -} // namespace testing -} // namespace webrtc - -#endif // MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_ESTIMATORS_BBR_H_ diff --git a/modules/remote_bitrate_estimator/test/estimators/congestion_window.cc b/modules/remote_bitrate_estimator/test/estimators/congestion_window.cc deleted file mode 100644 index 9f2377fa04..0000000000 --- a/modules/remote_bitrate_estimator/test/estimators/congestion_window.cc +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2017 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 "modules/remote_bitrate_estimator/test/estimators/congestion_window.h" - -#include "modules/remote_bitrate_estimator/test/estimators/bbr.h" -#include "rtc_base/checks.h" - -namespace webrtc { -namespace testing { -namespace bwe { -namespace { -// kStartingCongestionWindowBytes is used to set congestion window when -// bandwidth delay product is equal to zero, so that we don't set window to zero -// as well. Chosen randomly by me, because this value shouldn't make any -// significant difference, as bandwidth delay product is more than zero almost -// every time. -const int kStartingCongestionWindowBytes = 6000; -} // namespace - -CongestionWindow::CongestionWindow() : data_inflight_bytes_(0) {} - -CongestionWindow::~CongestionWindow() {} - -int CongestionWindow::GetCongestionWindow(BbrBweSender::Mode mode, - int64_t bandwidth_estimate_bps, - absl::optional min_rtt_ms, - float gain) { - return GetTargetCongestionWindow(bandwidth_estimate_bps, min_rtt_ms, gain); -} - -void CongestionWindow::PacketSent(size_t sent_packet_size_bytes) { - data_inflight_bytes_ += sent_packet_size_bytes; -} - -void CongestionWindow::AckReceived(size_t received_packet_size_bytes) { - RTC_DCHECK_GE(data_inflight_bytes_ >= received_packet_size_bytes, true); - data_inflight_bytes_ -= received_packet_size_bytes; -} - -int CongestionWindow::GetTargetCongestionWindow( - int64_t bandwidth_estimate_bps, - absl::optional min_rtt_ms, - float gain) { - // If we have no rtt sample yet, return the starting congestion window size. - if (!min_rtt_ms) - return gain * kStartingCongestionWindowBytes; - int bdp = *min_rtt_ms * bandwidth_estimate_bps / 8000; - int congestion_window = bdp * gain; - // Congestion window could be zero in rare cases, when either no bandwidth - // estimate is available, or path's min_rtt value is zero. - if (!congestion_window) - congestion_window = gain * kStartingCongestionWindowBytes; - return congestion_window; -} -} // namespace bwe -} // namespace testing -} // namespace webrtc diff --git a/modules/remote_bitrate_estimator/test/estimators/congestion_window.h b/modules/remote_bitrate_estimator/test/estimators/congestion_window.h deleted file mode 100644 index f7ae4328d3..0000000000 --- a/modules/remote_bitrate_estimator/test/estimators/congestion_window.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2017 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. - * - */ - -#ifndef MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_ESTIMATORS_CONGESTION_WINDOW_H_ -#define MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_ESTIMATORS_CONGESTION_WINDOW_H_ - -#include -#include - -#include "absl/types/optional.h" -#include "modules/remote_bitrate_estimator/test/estimators/bbr.h" - -namespace webrtc { -namespace testing { -namespace bwe { -class CongestionWindow { - public: - CongestionWindow(); - ~CongestionWindow(); - int GetCongestionWindow(BbrBweSender::Mode mode, - int64_t bandwidth_estimate, - absl::optional min_rtt, - float gain); - int GetTargetCongestionWindow(int64_t bandwidth_estimate, - absl::optional min_rtt, - float gain); - // Packet sent from sender, meaning it is inflight until we receive it and we - // should add packet's size to data_inflight. - void PacketSent(size_t sent_packet_size); - - // Ack was received by sender, meaning packet is no longer inflight. - void AckReceived(size_t received_packet_size); - - size_t data_inflight() { return data_inflight_bytes_; } - - private: - size_t data_inflight_bytes_; -}; -} // namespace bwe -} // namespace testing -} // namespace webrtc - -#endif // MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_ESTIMATORS_CONGESTION_WINDOW_H_ diff --git a/modules/remote_bitrate_estimator/test/estimators/congestion_window_unittest.cc b/modules/remote_bitrate_estimator/test/estimators/congestion_window_unittest.cc deleted file mode 100644 index 9b394b7b62..0000000000 --- a/modules/remote_bitrate_estimator/test/estimators/congestion_window_unittest.cc +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2017 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 "modules/remote_bitrate_estimator/test/estimators/congestion_window.h" -#include "modules/remote_bitrate_estimator/test/estimators/bbr.h" - -#include "test/gtest.h" - -namespace webrtc { -namespace testing { -namespace bwe { -namespace { -// Same value used in CongestionWindow class. -const int64_t kStartingCongestionWindow = 6000; -} // namespace - -TEST(CongestionWindowTest, InitializationCheck) { - CongestionWindow congestion_window; - congestion_window.PacketSent(0); - EXPECT_EQ(congestion_window.data_inflight(), 0u); - congestion_window.AckReceived(0); - EXPECT_EQ(congestion_window.data_inflight(), 0u); -} - -TEST(CongestionWindowTest, DataInflight) { - CongestionWindow congestion_window; - congestion_window.PacketSent(13); - EXPECT_EQ(congestion_window.data_inflight(), 13u); - congestion_window.AckReceived(12); - EXPECT_EQ(congestion_window.data_inflight(), 1u); - congestion_window.PacketSent(10); - congestion_window.PacketSent(9); - EXPECT_EQ(congestion_window.data_inflight(), 20u); - congestion_window.AckReceived(20); - EXPECT_EQ(congestion_window.data_inflight(), 0u); -} - -TEST(CongestionWindowTest, ZeroBandwidthDelayProduct) { - CongestionWindow congestion_window; - int64_t target_congestion_window = - congestion_window.GetTargetCongestionWindow(100, 0, 2.885f); - EXPECT_EQ(target_congestion_window, 2.885f * kStartingCongestionWindow); -} - -TEST(CongestionWindowTest, CalculateCongestionWindow) { - CongestionWindow congestion_window; - int64_t cwnd = congestion_window.GetCongestionWindow(BbrBweSender::STARTUP, - 800000, 100l, 2.885f); - EXPECT_EQ(cwnd, 28850); - cwnd = congestion_window.GetCongestionWindow(BbrBweSender::STARTUP, 400000, - 200l, 2.885f); - EXPECT_EQ(cwnd, 28850); -} -} // namespace bwe -} // namespace testing -} // namespace webrtc diff --git a/modules/remote_bitrate_estimator/test/estimators/max_bandwidth_filter.cc b/modules/remote_bitrate_estimator/test/estimators/max_bandwidth_filter.cc deleted file mode 100644 index 49efcdccc9..0000000000 --- a/modules/remote_bitrate_estimator/test/estimators/max_bandwidth_filter.cc +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2017 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 "modules/remote_bitrate_estimator/test/estimators/max_bandwidth_filter.h" - -namespace webrtc { -namespace testing { -namespace bwe { - -const size_t MaxBandwidthFilter::kBandwidthWindowFilterSize; - -MaxBandwidthFilter::MaxBandwidthFilter() - : bandwidth_last_round_bytes_per_ms_(0), - max_bandwidth_estimate_bps_(0), - rounds_without_growth_(0) {} - -MaxBandwidthFilter::~MaxBandwidthFilter() {} - -// For detailed explanation about implementing bandwidth filter this way visit -// "Bbr design" doc. |sample_bps| was measured during |round|. -void MaxBandwidthFilter::AddBandwidthSample(int64_t sample_bps, int64_t round) { - if (bandwidth_samples_[0].first == 0 || - sample_bps >= bandwidth_samples_[0].first || - round - bandwidth_samples_[2].second >= - MaxBandwidthFilter::kBandwidthWindowFilterSize) - bandwidth_samples_[0] = bandwidth_samples_[1] = - bandwidth_samples_[2] = {sample_bps, round}; - if (sample_bps >= bandwidth_samples_[1].first) { - bandwidth_samples_[1] = {sample_bps, round}; - bandwidth_samples_[2] = bandwidth_samples_[1]; - } else { - if (sample_bps >= bandwidth_samples_[2].first) - bandwidth_samples_[2] = {sample_bps, round}; - } - if (round - bandwidth_samples_[0].second >= - MaxBandwidthFilter::kBandwidthWindowFilterSize) { - bandwidth_samples_[0] = bandwidth_samples_[1]; - bandwidth_samples_[1] = bandwidth_samples_[2]; - bandwidth_samples_[2] = {sample_bps, round}; - if (round - bandwidth_samples_[0].second >= - MaxBandwidthFilter::kBandwidthWindowFilterSize) { - bandwidth_samples_[0] = bandwidth_samples_[1]; - bandwidth_samples_[1] = bandwidth_samples_[2]; - } - max_bandwidth_estimate_bps_ = bandwidth_samples_[0].first; - return; - } - if (bandwidth_samples_[1].first == bandwidth_samples_[0].first && - round - bandwidth_samples_[1].second > - MaxBandwidthFilter::kBandwidthWindowFilterSize / 4) { - bandwidth_samples_[2] = bandwidth_samples_[1] = {sample_bps, round}; - max_bandwidth_estimate_bps_ = bandwidth_samples_[0].first; - return; - } - if (bandwidth_samples_[2].first == bandwidth_samples_[1].first && - round - bandwidth_samples_[2].second > - MaxBandwidthFilter::kBandwidthWindowFilterSize / 2) - bandwidth_samples_[2] = {sample_bps, round}; - max_bandwidth_estimate_bps_ = bandwidth_samples_[0].first; -} - -bool MaxBandwidthFilter::FullBandwidthReached(float growth_target, - int max_rounds_without_growth) { - // Minimal bandwidth necessary to assume that better bandwidth can still be - // found and full bandwidth is not reached. - int64_t minimal_bandwidth = - bandwidth_last_round_bytes_per_ms_ * growth_target; - if (max_bandwidth_estimate_bps_ >= minimal_bandwidth) { - bandwidth_last_round_bytes_per_ms_ = max_bandwidth_estimate_bps_; - rounds_without_growth_ = 0; - return false; - } - rounds_without_growth_++; - return rounds_without_growth_ >= max_rounds_without_growth; -} -} // namespace bwe -} // namespace testing -} // namespace webrtc diff --git a/modules/remote_bitrate_estimator/test/estimators/max_bandwidth_filter.h b/modules/remote_bitrate_estimator/test/estimators/max_bandwidth_filter.h deleted file mode 100644 index 99c80203d6..0000000000 --- a/modules/remote_bitrate_estimator/test/estimators/max_bandwidth_filter.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2017 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. - * - */ - -#ifndef MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_ESTIMATORS_MAX_BANDWIDTH_FILTER_H_ -#define MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_ESTIMATORS_MAX_BANDWIDTH_FILTER_H_ - -#include -#include -#include - -namespace webrtc { -namespace testing { -namespace bwe { -class MaxBandwidthFilter { - public: - // Number of rounds for bandwidth estimate to expire. - static const size_t kBandwidthWindowFilterSize = 10; - - MaxBandwidthFilter(); - ~MaxBandwidthFilter(); - int64_t max_bandwidth_estimate_bps() { return max_bandwidth_estimate_bps_; } - - // Adds bandwidth sample to the bandwidth filter. - void AddBandwidthSample(int64_t sample, int64_t round); - - // Checks if bandwidth has grown by certain multiplier for past x rounds, - // to decide whether or full bandwidth was reached. - bool FullBandwidthReached(float growth_target, int max_rounds_without_growth); - - private: - int64_t bandwidth_last_round_bytes_per_ms_; - int64_t max_bandwidth_estimate_bps_; - int64_t rounds_without_growth_; - std::pair bandwidth_samples_[3]; -}; -} // namespace bwe -} // namespace testing -} // namespace webrtc - -#endif // MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_ESTIMATORS_MAX_BANDWIDTH_FILTER_H_ diff --git a/modules/remote_bitrate_estimator/test/estimators/max_bandwidth_filter_unittest.cc b/modules/remote_bitrate_estimator/test/estimators/max_bandwidth_filter_unittest.cc deleted file mode 100644 index 46b6d78422..0000000000 --- a/modules/remote_bitrate_estimator/test/estimators/max_bandwidth_filter_unittest.cc +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2017 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 "modules/remote_bitrate_estimator/test/estimators/max_bandwidth_filter.h" - -#include "test/gtest.h" - -namespace webrtc { -namespace testing { -namespace bwe { -TEST(MaxBandwidthFilterTest, InitializationCheck) { - MaxBandwidthFilter max_bandwidth_filter; - EXPECT_EQ(max_bandwidth_filter.max_bandwidth_estimate_bps(), 0); -} - -TEST(MaxBandwidthFilterTest, AddOneBandwidthSample) { - MaxBandwidthFilter max_bandwidth_filter; - max_bandwidth_filter.AddBandwidthSample(13, 4); - EXPECT_EQ(max_bandwidth_filter.max_bandwidth_estimate_bps(), 13); -} - -TEST(MaxBandwidthFilterTest, AddSeveralBandwidthSamples) { - MaxBandwidthFilter max_bandwidth_filter; - max_bandwidth_filter.AddBandwidthSample(10, 5); - max_bandwidth_filter.AddBandwidthSample(13, 6); - EXPECT_EQ(max_bandwidth_filter.max_bandwidth_estimate_bps(), 13); -} - -TEST(MaxBandwidthFilterTest, FirstSampleTimeOut) { - MaxBandwidthFilter max_bandwidth_filter; - max_bandwidth_filter.AddBandwidthSample(13, 5); - max_bandwidth_filter.AddBandwidthSample(10, 15); - EXPECT_EQ(max_bandwidth_filter.max_bandwidth_estimate_bps(), 10); -} - -TEST(MaxBandwidthFilterTest, SecondSampleBecomesTheFirst) { - MaxBandwidthFilter max_bandwidth_filter; - max_bandwidth_filter.AddBandwidthSample(4, 5); - max_bandwidth_filter.AddBandwidthSample(3, 10); - max_bandwidth_filter.AddBandwidthSample(2, 15); - EXPECT_EQ(max_bandwidth_filter.max_bandwidth_estimate_bps(), 3); -} - -TEST(MaxBandwidthFilterTest, ThirdSampleBecomesTheFirst) { - MaxBandwidthFilter max_bandwidth_filter; - max_bandwidth_filter.AddBandwidthSample(4, 5); - max_bandwidth_filter.AddBandwidthSample(3, 10); - max_bandwidth_filter.AddBandwidthSample(2, 25); - EXPECT_EQ(max_bandwidth_filter.max_bandwidth_estimate_bps(), 2); -} - -TEST(MaxBandwidthFilterTest, FullBandwidthReached) { - MaxBandwidthFilter max_bandwidth_filter; - max_bandwidth_filter.AddBandwidthSample(100, 1); - EXPECT_EQ(max_bandwidth_filter.FullBandwidthReached(1.25f, 3), false); - max_bandwidth_filter.AddBandwidthSample(110, 2); - EXPECT_EQ(max_bandwidth_filter.FullBandwidthReached(1.25f, 3), false); - max_bandwidth_filter.AddBandwidthSample(120, 3); - EXPECT_EQ(max_bandwidth_filter.FullBandwidthReached(1.25f, 3), false); - max_bandwidth_filter.AddBandwidthSample(124, 4); - EXPECT_EQ(max_bandwidth_filter.FullBandwidthReached(1.25f, 3), true); -} - -TEST(MaxBandwidthFilterTest, FullBandwidthNotReached) { - MaxBandwidthFilter max_bandwidth_filter; - max_bandwidth_filter.AddBandwidthSample(100, 1); - EXPECT_EQ(max_bandwidth_filter.FullBandwidthReached(1.25f, 3), false); - max_bandwidth_filter.AddBandwidthSample(110, 2); - EXPECT_EQ(max_bandwidth_filter.FullBandwidthReached(1.25f, 3), false); - max_bandwidth_filter.AddBandwidthSample(120, 3); - EXPECT_EQ(max_bandwidth_filter.FullBandwidthReached(1.25f, 3), false); - max_bandwidth_filter.AddBandwidthSample(125, 4); - EXPECT_EQ(max_bandwidth_filter.FullBandwidthReached(1.25f, 3), false); -} -} // namespace bwe -} // namespace testing -} // namespace webrtc diff --git a/modules/remote_bitrate_estimator/test/estimators/min_rtt_filter.cc b/modules/remote_bitrate_estimator/test/estimators/min_rtt_filter.cc deleted file mode 100644 index 8f699ce169..0000000000 --- a/modules/remote_bitrate_estimator/test/estimators/min_rtt_filter.cc +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2018 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 "modules/remote_bitrate_estimator/test/estimators/min_rtt_filter.h" - -namespace webrtc { -namespace testing { -namespace bwe { - -MinRttFilter::MinRttFilter() = default; -MinRttFilter::~MinRttFilter() = default; - -} // namespace bwe -} // namespace testing -} // namespace webrtc diff --git a/modules/remote_bitrate_estimator/test/estimators/min_rtt_filter.h b/modules/remote_bitrate_estimator/test/estimators/min_rtt_filter.h deleted file mode 100644 index 4ac392b5ac..0000000000 --- a/modules/remote_bitrate_estimator/test/estimators/min_rtt_filter.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2017 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. - * - */ - -#ifndef MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_ESTIMATORS_MIN_RTT_FILTER_H_ -#define MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_ESTIMATORS_MIN_RTT_FILTER_H_ - -#include -#include - -#include "absl/types/optional.h" - -namespace webrtc { -namespace testing { -namespace bwe { - -// Average rtt for past |kRttFilterSize| packets should grow by -// |kRttIncreaseThresholdForExpiry| in order to enter PROBE_RTT mode and expire. -// old min_rtt estimate. -const float kRttIncreaseThresholdForExpiry = 2.3f; -const size_t kRttFilterSize = 25; - -class MinRttFilter { - public: - // This class implements a simple filter to ensure that PROBE_RTT is only - // entered when RTTs start to increase, instead of fixed 10 second window as - // in orginal BBR design doc, to avoid unnecessary freezes in stream. - MinRttFilter(); - ~MinRttFilter(); - - absl::optional min_rtt_ms() { return min_rtt_ms_; } - void AddRttSample(int64_t rtt_ms, int64_t now_ms) { - if (!min_rtt_ms_ || rtt_ms <= *min_rtt_ms_ || MinRttExpired(now_ms)) { - min_rtt_ms_.emplace(rtt_ms); - } - rtt_samples_.push_back(rtt_ms); - if (rtt_samples_.size() > kRttFilterSize) - rtt_samples_.pop_front(); - } - - // Checks whether or not last RTT values for past |kRttFilterSize| packets - // started to increase, meaning we have to update min_rtt estimate. - bool MinRttExpired(int64_t now_ms) { - if (rtt_samples_.size() < kRttFilterSize || !min_rtt_ms_) - return false; - int64_t sum_of_rtts_ms = 0; - for (int64_t i : rtt_samples_) - sum_of_rtts_ms += i; - if (sum_of_rtts_ms >= - *min_rtt_ms_ * kRttIncreaseThresholdForExpiry * kRttFilterSize) { - rtt_samples_.clear(); - return true; - } - return false; - } - - private: - absl::optional min_rtt_ms_; - std::list rtt_samples_; -}; -} // namespace bwe -} // namespace testing -} // namespace webrtc - -#endif // MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_ESTIMATORS_MIN_RTT_FILTER_H_ diff --git a/modules/remote_bitrate_estimator/test/estimators/min_rtt_filter_unittest.cc b/modules/remote_bitrate_estimator/test/estimators/min_rtt_filter_unittest.cc deleted file mode 100644 index 53767e0db7..0000000000 --- a/modules/remote_bitrate_estimator/test/estimators/min_rtt_filter_unittest.cc +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2017 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 "modules/remote_bitrate_estimator/test/estimators/min_rtt_filter.h" - -#include "test/gtest.h" - -namespace webrtc { -namespace testing { -namespace bwe { -TEST(MinRttFilterTest, InitializationCheck) { - MinRttFilter min_rtt_filter; - EXPECT_FALSE(min_rtt_filter.min_rtt_ms()); -} - -TEST(MinRttFilterTest, AddRttSample) { - MinRttFilter min_rtt_filter; - min_rtt_filter.AddRttSample(120, 5); - EXPECT_EQ(*min_rtt_filter.min_rtt_ms(), 120); - min_rtt_filter.AddRttSample(121, 6); - min_rtt_filter.AddRttSample(119, 7); - min_rtt_filter.AddRttSample(140, 10007); - EXPECT_EQ(*min_rtt_filter.min_rtt_ms(), 119); -} - -TEST(MinRttFilterTest, MinRttExpired) { - MinRttFilter min_rtt_filter; - for (int i = 1; i <= 25; i++) - min_rtt_filter.AddRttSample(i, i); - EXPECT_EQ(min_rtt_filter.MinRttExpired(25), true); - EXPECT_EQ(min_rtt_filter.MinRttExpired(24), false); -} -} // namespace bwe -} // namespace testing -} // namespace webrtc diff --git a/modules/remote_bitrate_estimator/test/estimators/nada.cc b/modules/remote_bitrate_estimator/test/estimators/nada.cc deleted file mode 100644 index b7f5c9a40f..0000000000 --- a/modules/remote_bitrate_estimator/test/estimators/nada.cc +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Copyright (c) 2015 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. - * - */ - -// Implementation of Network-Assisted Dynamic Adaptation's (NADA's) proposal. -// Version according to Draft Document (mentioned in references) -// http://tools.ietf.org/html/draft-zhu-rmcat-nada-06 -// From March 26, 2015. - -#include -#include -#include -#include -#include -#include - -#include "modules/remote_bitrate_estimator/test/estimators/nada.h" -#include "modules/rtp_rtcp/include/receive_statistics.h" -#include "rtc_base/arraysize.h" - -namespace webrtc { -namespace testing { -namespace bwe { - -namespace { -// Used as an upper bound for calling AcceleratedRampDown. -const float kMaxCongestionSignalMs = - 40.0f + NadaBweSender::kMinNadaBitrateKbps / 15; -} // namespace - -const int NadaBweSender::kMinNadaBitrateKbps = 50; -const int64_t NadaBweReceiver::kReceivingRateTimeWindowMs = 500; - -NadaBweReceiver::NadaBweReceiver(int flow_id) - : BweReceiver(flow_id, kReceivingRateTimeWindowMs), - clock_(0), - last_feedback_ms_(0), - recv_stats_(ReceiveStatistics::Create(&clock_)), - baseline_delay_ms_(10000), // Initialized as an upper bound. - delay_signal_ms_(0), - last_congestion_signal_ms_(0), - last_delays_index_(0), - exp_smoothed_delay_ms_(-1), - est_queuing_delay_signal_ms_(0) {} - -NadaBweReceiver::~NadaBweReceiver() {} - -void NadaBweReceiver::ReceivePacket(int64_t arrival_time_ms, - const MediaPacket& media_packet) { - const float kAlpha = 0.1f; // Used for exponential smoothing. - const int64_t kDelayLowThresholdMs = 50; // Referred as d_th. - const int64_t kDelayMaxThresholdMs = 400; // Referred as d_max. - - clock_.AdvanceTimeMilliseconds(arrival_time_ms - clock_.TimeInMilliseconds()); - recv_stats_->OnRtpPacket(media_packet.GetRtpPacket()); - // Refered as x_n. - int64_t delay_ms = arrival_time_ms - media_packet.sender_timestamp_ms(); - - // The min should be updated within the first 10 minutes. - if (clock_.TimeInMilliseconds() < 10 * 60 * 1000) { - baseline_delay_ms_ = std::min(baseline_delay_ms_, delay_ms); - } - - delay_signal_ms_ = delay_ms - baseline_delay_ms_; // Refered as d_n. - const int kMedian = arraysize(last_delays_ms_); - last_delays_ms_[(last_delays_index_++) % kMedian] = delay_signal_ms_; - int size = std::min(last_delays_index_, kMedian); - - int64_t median_filtered_delay_ms_ = MedianFilter(last_delays_ms_, size); - exp_smoothed_delay_ms_ = ExponentialSmoothingFilter( - median_filtered_delay_ms_, exp_smoothed_delay_ms_, kAlpha); - - if (exp_smoothed_delay_ms_ < kDelayLowThresholdMs) { - est_queuing_delay_signal_ms_ = exp_smoothed_delay_ms_; - } else if (exp_smoothed_delay_ms_ < kDelayMaxThresholdMs) { - est_queuing_delay_signal_ms_ = static_cast( - pow((static_cast(kDelayMaxThresholdMs - - exp_smoothed_delay_ms_)) / - (kDelayMaxThresholdMs - kDelayLowThresholdMs), - 4.0) * - kDelayLowThresholdMs); - } else { - est_queuing_delay_signal_ms_ = 0; - } - - // Log received packet information. - BweReceiver::ReceivePacket(arrival_time_ms, media_packet); -} - -FeedbackPacket* NadaBweReceiver::GetFeedback(int64_t now_ms) { - const int64_t kPacketLossPenaltyMs = 1000; // Referred as d_L. - - if (now_ms - last_feedback_ms_ < 100) { - return NULL; - } - - float loss_fraction = RecentPacketLossRatio(); - - int64_t loss_signal_ms = - static_cast(loss_fraction * kPacketLossPenaltyMs + 0.5f); - int64_t congestion_signal_ms = est_queuing_delay_signal_ms_ + loss_signal_ms; - - float derivative = 0.0f; - if (last_feedback_ms_ > 0) { - derivative = (congestion_signal_ms - last_congestion_signal_ms_) / - static_cast(now_ms - last_feedback_ms_); - } - last_feedback_ms_ = now_ms; - last_congestion_signal_ms_ = congestion_signal_ms; - - int64_t corrected_send_time_ms = 0L; - - if (!received_packets_.empty()) { - PacketIdentifierNode& latest = *(received_packets_.begin()); - corrected_send_time_ms = - latest.send_time_ms + now_ms - latest.arrival_time_ms; - } - - // Sends a tuple containing latest values of and additional information. - return new NadaFeedback(flow_id_, now_ms * 1000, exp_smoothed_delay_ms_, - est_queuing_delay_signal_ms_, congestion_signal_ms, - derivative, RecentKbps(), corrected_send_time_ms); -} - -// If size is even, the median is the average of the two middlemost numbers. -int64_t NadaBweReceiver::MedianFilter(int64_t* last_delays_ms, int size) { - std::vector array_copy(last_delays_ms, last_delays_ms + size); - std::nth_element(array_copy.begin(), array_copy.begin() + size / 2, - array_copy.end()); - if (size % 2 == 1) { - // Typically, size = 5. For odd size values, right and left are equal. - return array_copy.at(size / 2); - } - int64_t right = array_copy.at(size / 2); - std::nth_element(array_copy.begin(), array_copy.begin() + (size - 1) / 2, - array_copy.end()); - int64_t left = array_copy.at((size - 1) / 2); - return (left + right + 1) / 2; -} - -int64_t NadaBweReceiver::ExponentialSmoothingFilter(int64_t new_value, - int64_t last_smoothed_value, - float alpha) { - if (last_smoothed_value < 0) { - return new_value; // Handling initial case. - } - return static_cast(alpha * new_value + - (1.0f - alpha) * last_smoothed_value + 0.5f); -} - -// Implementation according to Cisco's proposal by default. -NadaBweSender::NadaBweSender(int kbps, BitrateObserver* observer, Clock* clock) - : BweSender(kbps), // Referred as "Reference Rate" = R_n., - clock_(clock), - observer_(observer), - original_operating_mode_(true) {} - -NadaBweSender::NadaBweSender(BitrateObserver* observer, Clock* clock) - : BweSender(kMinNadaBitrateKbps), // Referred as "Reference Rate" = R_n. - clock_(clock), - observer_(observer), - original_operating_mode_(true) {} - -NadaBweSender::~NadaBweSender() {} - -int NadaBweSender::GetFeedbackIntervalMs() const { - return 100; -} - -void NadaBweSender::GiveFeedback(const FeedbackPacket& feedback) { - const NadaFeedback& fb = static_cast(feedback); - - // Following parameters might be optimized. - const int64_t kQueuingDelayUpperBoundMs = 10; - const float kDerivativeUpperBound = - 10.0f / std::max(1, min_feedback_delay_ms_); - // In the modified version, a higher kMinUpperBound allows a higher d_hat - // upper bound for calling AcceleratedRampUp. - const float kProportionalityDelayBits = 20.0f; - - int64_t now_ms = clock_->TimeInMilliseconds(); - float delta_s = now_ms - last_feedback_ms_; - last_feedback_ms_ = now_ms; - // Update delta_0. - min_feedback_delay_ms_ = - std::min(min_feedback_delay_ms_, static_cast(delta_s)); - - // Update RTT_0. - int64_t rtt_ms = now_ms - fb.latest_send_time_ms(); - min_round_trip_time_ms_ = std::min(min_round_trip_time_ms_, rtt_ms); - - // Independent limits for AcceleratedRampUp conditions variables: - // x_n, d_tilde and x'_n in the original implementation, plus - // d_hat and receiving_rate in the modified one. - // There should be no packet losses/marking, hence x_n == d_tilde. - if (original_operating_mode_) { - // Original if conditions and rate update. - if (fb.congestion_signal() == fb.est_queuing_delay_signal_ms() && - fb.est_queuing_delay_signal_ms() < kQueuingDelayUpperBoundMs && - fb.derivative() < kDerivativeUpperBound) { - AcceleratedRampUp(fb); - } else { - GradualRateUpdate(fb, delta_s, 1.0); - } - } else { - // Modified if conditions and rate update; new ramp down mode. - if (fb.congestion_signal() == fb.est_queuing_delay_signal_ms() && - fb.est_queuing_delay_signal_ms() < kQueuingDelayUpperBoundMs && - fb.exp_smoothed_delay_ms() < - kMinNadaBitrateKbps / kProportionalityDelayBits && - fb.derivative() < kDerivativeUpperBound && - fb.receiving_rate() > kMinNadaBitrateKbps) { - AcceleratedRampUp(fb); - } else if (fb.congestion_signal() > kMaxCongestionSignalMs || - fb.exp_smoothed_delay_ms() > kMaxCongestionSignalMs) { - AcceleratedRampDown(fb); - } else { - double bitrate_reference = - (2.0 * bitrate_kbps_) / (kMaxBitrateKbps + kMinNadaBitrateKbps); - double smoothing_factor = pow(bitrate_reference, 0.75); - GradualRateUpdate(fb, delta_s, smoothing_factor); - } - } - - bitrate_kbps_ = std::min(bitrate_kbps_, kMaxBitrateKbps); - bitrate_kbps_ = std::max(bitrate_kbps_, kMinNadaBitrateKbps); - - observer_->OnNetworkChanged(1000 * bitrate_kbps_, 0, rtt_ms); -} - -int64_t NadaBweSender::TimeUntilNextProcess() { - return 100; -} - -void NadaBweSender::Process() {} - -void NadaBweSender::AcceleratedRampUp(const NadaFeedback& fb) { - const int kMaxRampUpQueuingDelayMs = 50; // Referred as T_th. - const float kGamma0 = 0.5f; // Referred as gamma_0. - - float gamma = - std::min(kGamma0, static_cast(kMaxRampUpQueuingDelayMs) / - (min_round_trip_time_ms_ + min_feedback_delay_ms_)); - - bitrate_kbps_ = static_cast((1.0f + gamma) * fb.receiving_rate() + 0.5f); -} - -void NadaBweSender::AcceleratedRampDown(const NadaFeedback& fb) { - const float kGamma0 = 0.9f; - float gamma = 3.0f * kMaxCongestionSignalMs / - (fb.congestion_signal() + fb.exp_smoothed_delay_ms()); - gamma = std::min(gamma, kGamma0); - bitrate_kbps_ = gamma * fb.receiving_rate() + 0.5f; -} - -void NadaBweSender::GradualRateUpdate(const NadaFeedback& fb, - float delta_s, - double smoothing_factor) { - const float kTauOMs = 500.0f; // Referred as tau_o. - const float kEta = 2.0f; // Referred as eta. - const float kKappa = 1.0f; // Referred as kappa. - const float kReferenceDelayMs = 10.0f; // Referred as x_ref. - const float kPriorityWeight = 1.0f; // Referred as w. - - float x_hat = fb.congestion_signal() + kEta * kTauOMs * fb.derivative(); - - float kTheta = kPriorityWeight * (kMaxBitrateKbps - kMinNadaBitrateKbps) * - kReferenceDelayMs; - - int original_increase = static_cast( - (kKappa * delta_s * - (kTheta - (bitrate_kbps_ - kMinNadaBitrateKbps) * x_hat)) / - (kTauOMs * kTauOMs) + - 0.5f); - - bitrate_kbps_ = bitrate_kbps_ + smoothing_factor * original_increase; -} - -} // namespace bwe -} // namespace testing -} // namespace webrtc diff --git a/modules/remote_bitrate_estimator/test/estimators/nada.h b/modules/remote_bitrate_estimator/test/estimators/nada.h deleted file mode 100644 index 3ba923f564..0000000000 --- a/modules/remote_bitrate_estimator/test/estimators/nada.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (c) 2015 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. - * - */ - -// Implementation of Network-Assisted Dynamic Adaptation's (NADA's) proposal -// Version according to Draft Document (mentioned in references) -// http://tools.ietf.org/html/draft-zhu-rmcat-nada-06 -// From March 26, 2015. - -#ifndef MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_ESTIMATORS_NADA_H_ -#define MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_ESTIMATORS_NADA_H_ - -#include -#include -#include - -#include "modules/include/module_common_types.h" -#include "modules/remote_bitrate_estimator/test/bwe.h" -#include "rtc_base/constructor_magic.h" - -namespace webrtc { - -class ReceiveStatistics; - -namespace testing { -namespace bwe { - -class NadaBweReceiver : public BweReceiver { - public: - explicit NadaBweReceiver(int flow_id); - ~NadaBweReceiver() override; - - void ReceivePacket(int64_t arrival_time_ms, - const MediaPacket& media_packet) override; - FeedbackPacket* GetFeedback(int64_t now_ms) override; - - static int64_t MedianFilter(int64_t* v, int size); - static int64_t ExponentialSmoothingFilter(int64_t new_value, - int64_t last_smoothed_value, - float alpha); - - static const int64_t kReceivingRateTimeWindowMs; - - private: - SimulatedClock clock_; - int64_t last_feedback_ms_; - std::unique_ptr recv_stats_; - int64_t baseline_delay_ms_; // Referred as d_f. - int64_t delay_signal_ms_; // Referred as d_n. - int64_t last_congestion_signal_ms_; - int last_delays_index_; - int64_t exp_smoothed_delay_ms_; // Referred as d_hat_n. - int64_t est_queuing_delay_signal_ms_; // Referred as d_tilde_n. - int64_t last_delays_ms_[5]; // Used for Median Filter. -}; - -class NadaBweSender : public BweSender { - public: - static const int kMinNadaBitrateKbps; - - NadaBweSender(int kbps, BitrateObserver* observer, Clock* clock); - NadaBweSender(BitrateObserver* observer, Clock* clock); - ~NadaBweSender() override; - - int GetFeedbackIntervalMs() const override; - // Updates the min_feedback_delay_ms_ and the min_round_trip_time_ms_. - void GiveFeedback(const FeedbackPacket& feedback) override; - void OnPacketsSent(const Packets& packets) override {} - int64_t TimeUntilNextProcess() override; - void Process() override; - void AcceleratedRampUp(const NadaFeedback& fb); - void AcceleratedRampDown(const NadaFeedback& fb); - void GradualRateUpdate(const NadaFeedback& fb, - float delta_s, - double smoothing_factor); - - int bitrate_kbps() const { return bitrate_kbps_; } - void set_bitrate_kbps(int bitrate_kbps) { bitrate_kbps_ = bitrate_kbps; } - bool original_operating_mode() const { return original_operating_mode_; } - void set_original_operating_mode(bool original_operating_mode) { - original_operating_mode_ = original_operating_mode; - } - int64_t NowMs() const { return clock_->TimeInMilliseconds(); } - - private: - Clock* const clock_; - BitrateObserver* const observer_; - // Referred as R_min, default initialization for bitrate R_n. - int64_t last_feedback_ms_ = 0; - // Referred as delta_0, initialized as an upper bound. - int64_t min_feedback_delay_ms_ = 200; - // Referred as RTT_0, initialized as an upper bound. - int64_t min_round_trip_time_ms_ = 100; - bool original_operating_mode_; - - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(NadaBweSender); -}; - -} // namespace bwe -} // namespace testing -} // namespace webrtc - -#endif // MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_ESTIMATORS_NADA_H_ diff --git a/modules/remote_bitrate_estimator/test/estimators/nada_unittest.cc b/modules/remote_bitrate_estimator/test/estimators/nada_unittest.cc deleted file mode 100644 index abad4ad2e3..0000000000 --- a/modules/remote_bitrate_estimator/test/estimators/nada_unittest.cc +++ /dev/null @@ -1,494 +0,0 @@ -/* - * Copyright (c) 2015 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 "modules/remote_bitrate_estimator/test/estimators/nada.h" - -#include -#include -#include -#include - -#include "modules/remote_bitrate_estimator/test/packet.h" -#include "rtc_base/arraysize.h" -#include "test/gtest.h" - -namespace webrtc { -namespace testing { -namespace bwe { - -class FilterTest : public ::testing::Test { - public: - void MedianFilterConstantArray() { - std::fill_n(raw_signal_, kNumElements, kSignalValue); - for (int i = 0; i < kNumElements; ++i) { - int size = std::min(5, i + 1); - median_filtered_[i] = - NadaBweReceiver::MedianFilter(&raw_signal_[i + 1 - size], size); - } - } - - void MedianFilterIntermittentNoise() { - const int kValue = 500; - const int kNoise = 100; - - for (int i = 0; i < kNumElements; ++i) { - raw_signal_[i] = kValue + kNoise * (i % 10 == 9 ? 1 : 0); - } - for (int i = 0; i < kNumElements; ++i) { - int size = std::min(5, i + 1); - median_filtered_[i] = - NadaBweReceiver::MedianFilter(&raw_signal_[i + 1 - size], size); - EXPECT_EQ(median_filtered_[i], kValue); - } - } - - void ExponentialSmoothingFilter(const int64_t raw_signal_[], - int num_elements, - int64_t exp_smoothed[]) { - exp_smoothed[0] = - NadaBweReceiver::ExponentialSmoothingFilter(raw_signal_[0], -1, kAlpha); - for (int i = 1; i < num_elements; ++i) { - exp_smoothed[i] = NadaBweReceiver::ExponentialSmoothingFilter( - raw_signal_[i], exp_smoothed[i - 1], kAlpha); - } - } - - void ExponentialSmoothingConstantArray(int64_t exp_smoothed[]) { - std::fill_n(raw_signal_, kNumElements, kSignalValue); - ExponentialSmoothingFilter(raw_signal_, kNumElements, exp_smoothed); - } - - protected: - static const int kNumElements = 1000; - static const int64_t kSignalValue; - static const float kAlpha; - int64_t raw_signal_[kNumElements]; - int64_t median_filtered_[kNumElements]; -}; - -const int64_t FilterTest::kSignalValue = 200; -const float FilterTest::kAlpha = 0.1f; - -class TestBitrateObserver : public BitrateObserver { - public: - TestBitrateObserver() - : last_bitrate_(0), last_fraction_loss_(0), last_rtt_(0) {} - - virtual void OnNetworkChanged(uint32_t bitrate, - uint8_t fraction_loss, - int64_t rtt) { - last_bitrate_ = bitrate; - last_fraction_loss_ = fraction_loss; - last_rtt_ = rtt; - } - uint32_t last_bitrate_; - uint8_t last_fraction_loss_; - int64_t last_rtt_; -}; - -class NadaSenderSideTest : public ::testing::Test { - public: - NadaSenderSideTest() - : observer_(), - simulated_clock_(0), - nada_sender_(&observer_, &simulated_clock_) {} - ~NadaSenderSideTest() {} - - private: - TestBitrateObserver observer_; - SimulatedClock simulated_clock_; - - protected: - NadaBweSender nada_sender_; -}; - -class NadaReceiverSideTest : public ::testing::Test { - public: - NadaReceiverSideTest() : nada_receiver_(kFlowId) {} - ~NadaReceiverSideTest() {} - - protected: - const int kFlowId = 1; // Arbitrary. - NadaBweReceiver nada_receiver_; -}; - -class NadaFbGenerator { - public: - NadaFbGenerator(); - - static NadaFeedback NotCongestedFb(size_t receiving_rate, - int64_t ref_signal_ms, - int64_t send_time_ms) { - int64_t exp_smoothed_delay_ms = ref_signal_ms; - int64_t est_queuing_delay_signal_ms = ref_signal_ms; - int64_t congestion_signal_ms = ref_signal_ms; - float derivative = 0.0f; - return NadaFeedback(kFlowId, kNowMs, exp_smoothed_delay_ms, - est_queuing_delay_signal_ms, congestion_signal_ms, - derivative, receiving_rate, send_time_ms); - } - - static NadaFeedback CongestedFb(size_t receiving_rate, int64_t send_time_ms) { - int64_t exp_smoothed_delay_ms = 1000; - int64_t est_queuing_delay_signal_ms = 800; - int64_t congestion_signal_ms = 1000; - float derivative = 1.0f; - return NadaFeedback(kFlowId, kNowMs, exp_smoothed_delay_ms, - est_queuing_delay_signal_ms, congestion_signal_ms, - derivative, receiving_rate, send_time_ms); - } - - static NadaFeedback ExtremelyCongestedFb(size_t receiving_rate, - int64_t send_time_ms) { - int64_t exp_smoothed_delay_ms = 100000; - int64_t est_queuing_delay_signal_ms = 0; - int64_t congestion_signal_ms = 100000; - float derivative = 10000.0f; - return NadaFeedback(kFlowId, kNowMs, exp_smoothed_delay_ms, - est_queuing_delay_signal_ms, congestion_signal_ms, - derivative, receiving_rate, send_time_ms); - } - - private: - // Arbitrary values, won't change these test results. - static const int kFlowId = 2; - static const int64_t kNowMs = 1000; -}; - -// Verify if AcceleratedRampUp is called and that bitrate increases. -TEST_F(NadaSenderSideTest, AcceleratedRampUp) { - const int64_t kRefSignalMs = 1; - const int64_t kOneWayDelayMs = 50; - int original_bitrate = 2 * NadaBweSender::kMinNadaBitrateKbps; - size_t receiving_rate = static_cast(original_bitrate); - int64_t send_time_ms = nada_sender_.NowMs() - kOneWayDelayMs; - - NadaFeedback not_congested_fb = NadaFbGenerator::NotCongestedFb( - receiving_rate, kRefSignalMs, send_time_ms); - - nada_sender_.set_original_operating_mode(true); - nada_sender_.set_bitrate_kbps(original_bitrate); - - // Trigger AcceleratedRampUp mode. - nada_sender_.GiveFeedback(not_congested_fb); - int bitrate_1_kbps = nada_sender_.bitrate_kbps(); - EXPECT_GT(bitrate_1_kbps, original_bitrate); - // Updates the bitrate according to the receiving rate and other constant - // parameters. - nada_sender_.AcceleratedRampUp(not_congested_fb); - EXPECT_EQ(nada_sender_.bitrate_kbps(), bitrate_1_kbps); - - nada_sender_.set_original_operating_mode(false); - nada_sender_.set_bitrate_kbps(original_bitrate); - // Trigger AcceleratedRampUp mode. - nada_sender_.GiveFeedback(not_congested_fb); - bitrate_1_kbps = nada_sender_.bitrate_kbps(); - EXPECT_GT(bitrate_1_kbps, original_bitrate); - nada_sender_.AcceleratedRampUp(not_congested_fb); - EXPECT_EQ(nada_sender_.bitrate_kbps(), bitrate_1_kbps); -} - -// Verify if AcceleratedRampDown is called and if bitrate decreases. -TEST_F(NadaSenderSideTest, AcceleratedRampDown) { - const int64_t kOneWayDelayMs = 50; - int original_bitrate = 3 * NadaBweSender::kMinNadaBitrateKbps; - size_t receiving_rate = static_cast(original_bitrate); - int64_t send_time_ms = nada_sender_.NowMs() - kOneWayDelayMs; - - NadaFeedback congested_fb = - NadaFbGenerator::CongestedFb(receiving_rate, send_time_ms); - - nada_sender_.set_original_operating_mode(false); - nada_sender_.set_bitrate_kbps(original_bitrate); - nada_sender_.GiveFeedback(congested_fb); // Trigger AcceleratedRampDown mode. - int bitrate_1_kbps = nada_sender_.bitrate_kbps(); - EXPECT_LE(bitrate_1_kbps, original_bitrate * 0.9f + 0.5f); - EXPECT_LT(bitrate_1_kbps, original_bitrate); - - // Updates the bitrate according to the receiving rate and other constant - // parameters. - nada_sender_.AcceleratedRampDown(congested_fb); - int bitrate_2_kbps = - std::max(nada_sender_.bitrate_kbps(), NadaBweSender::kMinNadaBitrateKbps); - EXPECT_EQ(bitrate_2_kbps, bitrate_1_kbps); -} - -TEST_F(NadaSenderSideTest, GradualRateUpdate) { - const int64_t kDeltaSMs = 20; - const int64_t kRefSignalMs = 20; - const int64_t kOneWayDelayMs = 50; - int original_bitrate = 5 * NadaBweSender::kMinNadaBitrateKbps; - size_t receiving_rate = static_cast(original_bitrate); - int64_t send_time_ms = nada_sender_.NowMs() - kOneWayDelayMs; - - NadaFeedback congested_fb = - NadaFbGenerator::CongestedFb(receiving_rate, send_time_ms); - NadaFeedback not_congested_fb = NadaFbGenerator::NotCongestedFb( - original_bitrate, kRefSignalMs, send_time_ms); - - nada_sender_.set_bitrate_kbps(original_bitrate); - double smoothing_factor = 0.0; - nada_sender_.GradualRateUpdate(congested_fb, kDeltaSMs, smoothing_factor); - EXPECT_EQ(nada_sender_.bitrate_kbps(), original_bitrate); - - smoothing_factor = 1.0; - nada_sender_.GradualRateUpdate(congested_fb, kDeltaSMs, smoothing_factor); - EXPECT_LT(nada_sender_.bitrate_kbps(), original_bitrate); - - nada_sender_.set_bitrate_kbps(original_bitrate); - nada_sender_.GradualRateUpdate(not_congested_fb, kDeltaSMs, smoothing_factor); - EXPECT_GT(nada_sender_.bitrate_kbps(), original_bitrate); -} - -// Sending bitrate should decrease and reach its Min bound. -TEST_F(NadaSenderSideTest, VeryLowBandwith) { - const int64_t kOneWayDelayMs = 50; - - size_t receiving_rate = - static_cast(NadaBweSender::kMinNadaBitrateKbps); - int64_t send_time_ms = nada_sender_.NowMs() - kOneWayDelayMs; - - NadaFeedback extremely_congested_fb = - NadaFbGenerator::ExtremelyCongestedFb(receiving_rate, send_time_ms); - NadaFeedback congested_fb = - NadaFbGenerator::CongestedFb(receiving_rate, send_time_ms); - - nada_sender_.set_bitrate_kbps(5 * NadaBweSender::kMinNadaBitrateKbps); - nada_sender_.set_original_operating_mode(true); - for (int i = 0; i < 100; ++i) { - // Trigger GradualRateUpdate mode. - nada_sender_.GiveFeedback(extremely_congested_fb); - } - // The original implementation doesn't allow the bitrate to stay at kMin, - // even if the congestion signal is very high. - EXPECT_GE(nada_sender_.bitrate_kbps(), NadaBweSender::kMinNadaBitrateKbps); - - nada_sender_.set_original_operating_mode(false); - nada_sender_.set_bitrate_kbps(5 * NadaBweSender::kMinNadaBitrateKbps); - - for (int i = 0; i < 1000; ++i) { - int previous_bitrate = nada_sender_.bitrate_kbps(); - // Trigger AcceleratedRampDown mode. - nada_sender_.GiveFeedback(congested_fb); - EXPECT_LE(nada_sender_.bitrate_kbps(), previous_bitrate); - } - EXPECT_EQ(nada_sender_.bitrate_kbps(), NadaBweSender::kMinNadaBitrateKbps); -} - -// Sending bitrate should increase and reach its Max bound. -TEST_F(NadaSenderSideTest, VeryHighBandwith) { - const int64_t kOneWayDelayMs = 50; - const size_t kRecentReceivingRate = static_cast(kMaxBitrateKbps); - const int64_t kRefSignalMs = 1; - int64_t send_time_ms = nada_sender_.NowMs() - kOneWayDelayMs; - - NadaFeedback not_congested_fb = NadaFbGenerator::NotCongestedFb( - kRecentReceivingRate, kRefSignalMs, send_time_ms); - - nada_sender_.set_original_operating_mode(true); - for (int i = 0; i < 100; ++i) { - int previous_bitrate = nada_sender_.bitrate_kbps(); - nada_sender_.GiveFeedback(not_congested_fb); - EXPECT_GE(nada_sender_.bitrate_kbps(), previous_bitrate); - } - EXPECT_EQ(nada_sender_.bitrate_kbps(), kMaxBitrateKbps); - - nada_sender_.set_original_operating_mode(false); - nada_sender_.set_bitrate_kbps(NadaBweSender::kMinNadaBitrateKbps); - - for (int i = 0; i < 100; ++i) { - int previous_bitrate = nada_sender_.bitrate_kbps(); - nada_sender_.GiveFeedback(not_congested_fb); - EXPECT_GE(nada_sender_.bitrate_kbps(), previous_bitrate); - } - EXPECT_EQ(nada_sender_.bitrate_kbps(), kMaxBitrateKbps); -} - -TEST_F(NadaReceiverSideTest, FeedbackInitialCases) { - std::unique_ptr nada_feedback( - static_cast(nada_receiver_.GetFeedback(0))); - EXPECT_EQ(nada_feedback, nullptr); - - nada_feedback.reset( - static_cast(nada_receiver_.GetFeedback(100))); - EXPECT_EQ(nada_feedback->exp_smoothed_delay_ms(), -1); - EXPECT_EQ(nada_feedback->est_queuing_delay_signal_ms(), 0L); - EXPECT_EQ(nada_feedback->congestion_signal(), 0L); - EXPECT_EQ(nada_feedback->derivative(), 0.0f); - EXPECT_EQ(nada_feedback->receiving_rate(), 0.0f); -} - -TEST_F(NadaReceiverSideTest, FeedbackEmptyQueues) { - const int64_t kTimeGapMs = 50; // Between each packet. - const int64_t kOneWayDelayMs = 50; - - // No added latency, delay = kOneWayDelayMs. - for (int i = 1; i < 10; ++i) { - int64_t send_time_us = i * kTimeGapMs * 1000; - int64_t arrival_time_ms = send_time_us / 1000 + kOneWayDelayMs; - uint16_t sequence_number = static_cast(i); - // Payload sizes are not important here. - const MediaPacket media_packet(kFlowId, send_time_us, 0, sequence_number); - nada_receiver_.ReceivePacket(arrival_time_ms, media_packet); - } - - // Baseline delay will be equal kOneWayDelayMs. - std::unique_ptr nada_feedback( - static_cast(nada_receiver_.GetFeedback(500))); - EXPECT_EQ(nada_feedback->exp_smoothed_delay_ms(), 0L); - EXPECT_EQ(nada_feedback->est_queuing_delay_signal_ms(), 0L); - EXPECT_EQ(nada_feedback->congestion_signal(), 0L); - EXPECT_EQ(nada_feedback->derivative(), 0.0f); -} - -TEST_F(NadaReceiverSideTest, FeedbackIncreasingDelay) { - // Since packets are 100ms apart, each one corresponds to a feedback. - const int64_t kTimeGapMs = 100; // Between each packet. - - // Raw delays are = [10 20 30 40 50 60 70 80] ms. - // Baseline delay will be 50 ms. - // Delay signals should be: [0 10 20 30 40 50 60 70] ms. - const int64_t kMedianFilteredDelaysMs[] = {0, 5, 10, 15, 20, 30, 40, 50}; - const int kNumPackets = arraysize(kMedianFilteredDelaysMs); - const float kAlpha = 0.1f; // Used for exponential smoothing. - - int64_t exp_smoothed_delays_ms[kNumPackets]; - exp_smoothed_delays_ms[0] = kMedianFilteredDelaysMs[0]; - - for (int i = 1; i < kNumPackets; ++i) { - exp_smoothed_delays_ms[i] = static_cast( - kAlpha * kMedianFilteredDelaysMs[i] + - (1.0f - kAlpha) * exp_smoothed_delays_ms[i - 1] + 0.5f); - } - - for (int i = 0; i < kNumPackets; ++i) { - int64_t send_time_us = (i + 1) * kTimeGapMs * 1000; - int64_t arrival_time_ms = send_time_us / 1000 + 10 * (i + 1); - uint16_t sequence_number = static_cast(i + 1); - // Payload sizes are not important here. - const MediaPacket media_packet(kFlowId, send_time_us, 0, sequence_number); - nada_receiver_.ReceivePacket(arrival_time_ms, media_packet); - - std::unique_ptr nada_feedback(static_cast( - nada_receiver_.GetFeedback(arrival_time_ms))); - EXPECT_EQ(nada_feedback->exp_smoothed_delay_ms(), - exp_smoothed_delays_ms[i]); - // Since delay signals are lower than 50ms, they will not be non-linearly - // warped. - EXPECT_EQ(nada_feedback->est_queuing_delay_signal_ms(), - exp_smoothed_delays_ms[i]); - // Zero loss, congestion signal = queuing_delay - EXPECT_EQ(nada_feedback->congestion_signal(), exp_smoothed_delays_ms[i]); - if (i == 0) { - EXPECT_NEAR(nada_feedback->derivative(), - static_cast(exp_smoothed_delays_ms[i]) / kTimeGapMs, - 0.005f); - } else { - EXPECT_NEAR(nada_feedback->derivative(), - static_cast(exp_smoothed_delays_ms[i] - - exp_smoothed_delays_ms[i - 1]) / - kTimeGapMs, - 0.005f); - } - } -} - -int64_t Warp(int64_t input) { - const int64_t kMinThreshold = 50; // Referred as d_th. - const int64_t kMaxThreshold = 400; // Referred as d_max. - if (input < kMinThreshold) { - return input; - } else if (input < kMaxThreshold) { - return static_cast( - pow((static_cast(kMaxThreshold - input)) / - (kMaxThreshold - kMinThreshold), - 4.0) * - kMinThreshold); - } else { - return 0L; - } -} - -TEST_F(NadaReceiverSideTest, FeedbackWarpedDelay) { - // Since packets are 100ms apart, each one corresponds to a feedback. - const int64_t kTimeGapMs = 100; // Between each packet. - - // Raw delays are = [50 250 450 650 850 1050 1250 1450] ms. - // Baseline delay will be 50 ms. - // Delay signals should be: [0 200 400 600 800 1000 1200 1400] ms. - const int64_t kMedianFilteredDelaysMs[] = {0, 100, 200, 300, - 400, 600, 800, 1000}; - const int kNumPackets = arraysize(kMedianFilteredDelaysMs); - const float kAlpha = 0.1f; // Used for exponential smoothing. - - int64_t exp_smoothed_delays_ms[kNumPackets]; - exp_smoothed_delays_ms[0] = kMedianFilteredDelaysMs[0]; - - for (int i = 1; i < kNumPackets; ++i) { - exp_smoothed_delays_ms[i] = static_cast( - kAlpha * kMedianFilteredDelaysMs[i] + - (1.0f - kAlpha) * exp_smoothed_delays_ms[i - 1] + 0.5f); - } - - for (int i = 0; i < kNumPackets; ++i) { - int64_t send_time_us = (i + 1) * kTimeGapMs * 1000; - int64_t arrival_time_ms = send_time_us / 1000 + 50 + 200 * i; - uint16_t sequence_number = static_cast(i + 1); - // Payload sizes are not important here. - const MediaPacket media_packet(kFlowId, send_time_us, 0, sequence_number); - nada_receiver_.ReceivePacket(arrival_time_ms, media_packet); - - std::unique_ptr nada_feedback(static_cast( - nada_receiver_.GetFeedback(arrival_time_ms))); - EXPECT_EQ(nada_feedback->exp_smoothed_delay_ms(), - exp_smoothed_delays_ms[i]); - // Delays can be non-linearly warped. - EXPECT_EQ(nada_feedback->est_queuing_delay_signal_ms(), - Warp(exp_smoothed_delays_ms[i])); - // Zero loss, congestion signal = queuing_delay - EXPECT_EQ(nada_feedback->congestion_signal(), - Warp(exp_smoothed_delays_ms[i])); - } -} - -TEST_F(FilterTest, MedianConstantArray) { - MedianFilterConstantArray(); - for (int i = 0; i < kNumElements; ++i) { - EXPECT_EQ(median_filtered_[i], raw_signal_[i]); - } -} - -TEST_F(FilterTest, MedianIntermittentNoise) { - MedianFilterIntermittentNoise(); -} - -TEST_F(FilterTest, ExponentialSmoothingConstantArray) { - int64_t exp_smoothed[kNumElements]; - ExponentialSmoothingConstantArray(exp_smoothed); - for (int i = 0; i < kNumElements; ++i) { - EXPECT_EQ(exp_smoothed[i], kSignalValue); - } -} - -TEST_F(FilterTest, ExponentialSmoothingInitialPertubation) { - const int64_t kSignal[] = {90000, 0, 0, 0, 0, 0}; - const int kNumElements = arraysize(kSignal); - int64_t exp_smoothed[kNumElements]; - ExponentialSmoothingFilter(kSignal, kNumElements, exp_smoothed); - for (int i = 1; i < kNumElements; ++i) { - EXPECT_EQ( - exp_smoothed[i], - static_cast(exp_smoothed[i - 1] * (1.0f - kAlpha) + 0.5f)); - } -} - -} // namespace bwe -} // namespace testing -} // namespace webrtc diff --git a/modules/remote_bitrate_estimator/test/estimators/remb.cc b/modules/remote_bitrate_estimator/test/estimators/remb.cc deleted file mode 100644 index 3af91c4d90..0000000000 --- a/modules/remote_bitrate_estimator/test/estimators/remb.cc +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2015 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 -#include -#include -#include - -#include "modules/bitrate_controller/include/bitrate_controller.h" -#include "modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.h" -#include "modules/remote_bitrate_estimator/test/bwe_test_logging.h" -#include "modules/remote_bitrate_estimator/test/estimators/remb.h" -#include "modules/rtp_rtcp/include/receive_statistics.h" -#include "modules/rtp_rtcp/source/rtcp_packet/report_block.h" -#include "rtc_base/strings/string_builder.h" -#include "rtc_base/system/unused.h" -#include "test/gtest.h" - -namespace webrtc { -namespace testing { -namespace bwe { - -RembBweSender::RembBweSender(int kbps, BitrateObserver* observer, Clock* clock) - : bitrate_controller_( - BitrateController::CreateBitrateController(clock, - observer, - &event_log_)), - feedback_observer_(bitrate_controller_.get()), - clock_(clock) { - assert(kbps >= kMinBitrateKbps); - assert(kbps <= kMaxBitrateKbps); - bitrate_controller_->SetStartBitrate(1000 * kbps); - bitrate_controller_->SetMinMaxBitrate(1000 * kMinBitrateKbps, - 1000 * kMaxBitrateKbps); -} - -RembBweSender::~RembBweSender() {} - -void RembBweSender::GiveFeedback(const FeedbackPacket& feedback) { - const RembFeedback& remb_feedback = - static_cast(feedback); - feedback_observer_->OnReceivedEstimatedBitrate(remb_feedback.estimated_bps()); - ReportBlockList report_blocks; - report_blocks.push_back(remb_feedback.report_block()); - feedback_observer_->OnReceivedRtcpReceiverReport( - report_blocks, 0, clock_->TimeInMilliseconds()); - bitrate_controller_->Process(); -} - -int64_t RembBweSender::TimeUntilNextProcess() { - return bitrate_controller_->TimeUntilNextProcess(); -} - -void RembBweSender::Process() { - bitrate_controller_->Process(); -} - -int RembBweSender::GetFeedbackIntervalMs() const { - return 100; -} - -RembReceiver::RembReceiver(int flow_id, bool plot) - : BweReceiver(flow_id), - estimate_log_prefix_(), - plot_estimate_(plot), - clock_(0), - recv_stats_(ReceiveStatistics::Create(&clock_)), - latest_estimate_bps_(-1), - last_feedback_ms_(-1), - estimator_(new RemoteBitrateEstimatorAbsSendTime(this, &clock_)) { - rtc::StringBuilder ss; - ss << "Estimate_" << flow_id_ << "#1"; - estimate_log_prefix_ = ss.str(); - // Default RTT in RemoteRateControl is 200 ms ; 50 ms is more realistic. - estimator_->OnRttUpdate(50, 50); - estimator_->SetMinBitrate(kRemoteBitrateEstimatorMinBitrateBps); -} - -RembReceiver::~RembReceiver() {} - -void RembReceiver::ReceivePacket(int64_t arrival_time_ms, - const MediaPacket& media_packet) { - recv_stats_->OnRtpPacket(media_packet.GetRtpPacket()); - - latest_estimate_bps_ = -1; - - int64_t step_ms = std::max(estimator_->TimeUntilNextProcess(), 0); - while ((clock_.TimeInMilliseconds() + step_ms) < arrival_time_ms) { - clock_.AdvanceTimeMilliseconds(step_ms); - estimator_->Process(); - step_ms = std::max(estimator_->TimeUntilNextProcess(), 0); - } - estimator_->IncomingPacket(arrival_time_ms, media_packet.payload_size(), - media_packet.header()); - clock_.AdvanceTimeMilliseconds(arrival_time_ms - clock_.TimeInMilliseconds()); - ASSERT_TRUE(arrival_time_ms == clock_.TimeInMilliseconds()); - - // Log received packet information. - BweReceiver::ReceivePacket(arrival_time_ms, media_packet); -} - -FeedbackPacket* RembReceiver::GetFeedback(int64_t now_ms) { - BWE_TEST_LOGGING_CONTEXT("Remb"); - uint32_t estimated_bps = 0; - RembFeedback* feedback = NULL; - if (LatestEstimate(&estimated_bps)) { - auto report_blocks = recv_stats_->RtcpReportBlocks(1); - if (!report_blocks.empty()) { - const rtcp::ReportBlock& stat = report_blocks.front(); - latest_report_block_.fraction_lost = stat.fraction_lost(); - latest_report_block_.packets_lost = stat.cumulative_lost(); - latest_report_block_.extended_highest_sequence_number = - stat.extended_high_seq_num(); - latest_report_block_.jitter = stat.jitter(); - } - - feedback = new RembFeedback(flow_id_, now_ms * 1000, last_feedback_ms_, - estimated_bps, latest_report_block_); - last_feedback_ms_ = now_ms; - - double estimated_kbps = static_cast(estimated_bps) / 1000.0; - RTC_UNUSED(estimated_kbps); - if (plot_estimate_) { - BWE_TEST_LOGGING_PLOT(0, estimate_log_prefix_, - clock_.TimeInMilliseconds(), estimated_kbps); - } - } - return feedback; -} - -void RembReceiver::OnReceiveBitrateChanged(const std::vector& ssrcs, - uint32_t bitrate) {} - -bool RembReceiver::LatestEstimate(uint32_t* estimate_bps) { - if (latest_estimate_bps_ < 0) { - std::vector ssrcs; - uint32_t bps = 0; - if (!estimator_->LatestEstimate(&ssrcs, &bps)) { - return false; - } - latest_estimate_bps_ = bps; - } - *estimate_bps = latest_estimate_bps_; - return true; -} - -} // namespace bwe -} // namespace testing -} // namespace webrtc diff --git a/modules/remote_bitrate_estimator/test/estimators/remb.h b/modules/remote_bitrate_estimator/test/estimators/remb.h deleted file mode 100644 index df16fec848..0000000000 --- a/modules/remote_bitrate_estimator/test/estimators/remb.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2015 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. - */ - -#ifndef MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_ESTIMATORS_REMB_H_ -#define MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_ESTIMATORS_REMB_H_ - -#include -#include -#include - -#include "logging/rtc_event_log/mock/mock_rtc_event_log.h" -#include "modules/remote_bitrate_estimator/test/bwe.h" -#include "rtc_base/constructor_magic.h" - -namespace webrtc { - -class BitrateObserver; -class BitrateController; -class ReceiveStatistics; -class StreamStatistician; - -namespace testing { -namespace bwe { - -class RembBweSender : public BweSender { - public: - RembBweSender(int kbps, BitrateObserver* observer, Clock* clock); - virtual ~RembBweSender(); - - int GetFeedbackIntervalMs() const override; - void GiveFeedback(const FeedbackPacket& feedback) override; - void OnPacketsSent(const Packets& packets) override {} - int64_t TimeUntilNextProcess() override; - void Process() override; - - protected: - std::unique_ptr bitrate_controller_; - RtcpBandwidthObserver* feedback_observer_; - - private: - Clock* clock_; - ::testing::NiceMock event_log_; - - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RembBweSender); -}; - -class RembReceiver : public BweReceiver, public RemoteBitrateObserver { - public: - static const uint32_t kRemoteBitrateEstimatorMinBitrateBps = 30000; - - RembReceiver(int flow_id, bool plot); - ~RembReceiver() override; - - void ReceivePacket(int64_t arrival_time_ms, - const MediaPacket& media_packet) override; - FeedbackPacket* GetFeedback(int64_t now_ms) override; - // Implements RemoteBitrateObserver. - void OnReceiveBitrateChanged(const std::vector& ssrcs, - uint32_t bitrate) override; - - private: - bool LatestEstimate(uint32_t* estimate_bps); - - std::string estimate_log_prefix_; - bool plot_estimate_ = false; - SimulatedClock clock_; - std::unique_ptr recv_stats_; - int64_t latest_estimate_bps_; - int64_t last_feedback_ms_; - std::unique_ptr estimator_; - RTCPReportBlock latest_report_block_; - - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RembReceiver); -}; - -} // namespace bwe -} // namespace testing -} // namespace webrtc - -#endif // MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_ESTIMATORS_REMB_H_ diff --git a/modules/remote_bitrate_estimator/test/estimators/send_side.cc b/modules/remote_bitrate_estimator/test/estimators/send_side.cc deleted file mode 100644 index bd701cfffb..0000000000 --- a/modules/remote_bitrate_estimator/test/estimators/send_side.cc +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (c) 2015 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 "modules/remote_bitrate_estimator/test/estimators/send_side.h" - -#include -#include -#include - -#include "absl/memory/memory.h" -#include "api/rtp_headers.h" -#include "api/transport/network_types.h" -#include "modules/congestion_controller/goog_cc/delay_based_bwe.h" -#include "modules/remote_bitrate_estimator/test/bwe_test_logging.h" -#include "rtc_base/logging.h" - -namespace webrtc { -namespace testing { -namespace bwe { - -const int kFeedbackIntervalMs = 50; - -SendSideBweSender::SendSideBweSender(int kbps, - BitrateObserver* observer, - Clock* clock) - : bitrate_controller_( - BitrateController::CreateBitrateController(clock, - observer, - &event_log_)), - acknowledged_bitrate_estimator_( - absl::make_unique( - &field_trial_config_)), - probe_bitrate_estimator_(new ProbeBitrateEstimator(nullptr)), - bwe_(new DelayBasedBwe(&field_trial_config_, nullptr, nullptr)), - feedback_observer_(bitrate_controller_.get()), - clock_(clock), - send_time_history_(10000), - has_received_ack_(false), - last_acked_seq_num_(0), - last_log_time_ms_(0) { - assert(kbps >= kMinBitrateKbps); - assert(kbps <= kMaxBitrateKbps); - bitrate_controller_->SetStartBitrate(1000 * kbps); - bitrate_controller_->SetMinMaxBitrate(1000 * kMinBitrateKbps, - 1000 * kMaxBitrateKbps); - bwe_->SetMinBitrate(DataRate::kbps(kMinBitrateKbps)); -} - -SendSideBweSender::~SendSideBweSender() {} - -int SendSideBweSender::GetFeedbackIntervalMs() const { - return kFeedbackIntervalMs; -} - -void SendSideBweSender::GiveFeedback(const FeedbackPacket& feedback) { - const SendSideBweFeedback& fb = - static_cast(feedback); - if (fb.packet_feedback_vector().empty()) - return; - std::vector packet_feedback_vector( - fb.packet_feedback_vector()); - for (PacketFeedback& packet_feedback : packet_feedback_vector) { - if (!send_time_history_.GetFeedback(&packet_feedback, true)) { - int64_t now_ms = clock_->TimeInMilliseconds(); - if (now_ms - last_log_time_ms_ > 5000) { - RTC_LOG(LS_WARNING) << "Ack arrived too late."; - last_log_time_ms_ = now_ms; - } - } - } - - int64_t rtt_ms = - clock_->TimeInMilliseconds() - feedback.latest_send_time_ms(); - bwe_->OnRttUpdate(TimeDelta::ms(rtt_ms)); - BWE_TEST_LOGGING_PLOT(1, "RTT", clock_->TimeInMilliseconds(), rtt_ms); - - std::sort(packet_feedback_vector.begin(), packet_feedback_vector.end(), - PacketFeedbackComparator()); - acknowledged_bitrate_estimator_->IncomingPacketFeedbackVector( - packet_feedback_vector); - for (PacketFeedback& packet : packet_feedback_vector) { - if (packet.send_time_ms != PacketFeedback::kNoSendTime && - packet.pacing_info.probe_cluster_id != PacedPacketInfo::kNotAProbe) - probe_bitrate_estimator_->HandleProbeAndEstimateBitrate(packet); - } - DelayBasedBwe::Result result = bwe_->IncomingPacketFeedbackVector( - packet_feedback_vector, acknowledged_bitrate_estimator_->bitrate(), - probe_bitrate_estimator_->FetchAndResetLastEstimatedBitrate(), - absl::nullopt, false, Timestamp::ms(clock_->TimeInMilliseconds())); - if (result.updated) - bitrate_controller_->OnDelayBasedBweResult(result); - - if (has_received_ack_) { - int expected_packets = fb.packet_feedback_vector().back().sequence_number - - last_acked_seq_num_; - // Assuming no reordering for now. - if (expected_packets > 0) { - int lost_packets = expected_packets - - static_cast(fb.packet_feedback_vector().size()); - report_block_.fraction_lost = (lost_packets << 8) / expected_packets; - report_block_.packets_lost += lost_packets; - uint32_t unwrapped = seq_num_unwrapper_.Unwrap( - packet_feedback_vector.back().sequence_number); - report_block_.extended_highest_sequence_number = - std::max(unwrapped, report_block_.extended_highest_sequence_number); - ReportBlockList report_blocks; - report_blocks.push_back(report_block_); - feedback_observer_->OnReceivedRtcpReceiverReport( - report_blocks, rtt_ms, clock_->TimeInMilliseconds()); - } - bitrate_controller_->Process(); - - last_acked_seq_num_ = LatestSequenceNumber( - packet_feedback_vector.back().sequence_number, last_acked_seq_num_); - } else { - last_acked_seq_num_ = packet_feedback_vector.back().sequence_number; - has_received_ack_ = true; - } -} - -void SendSideBweSender::OnPacketsSent(const Packets& packets) { - for (Packet* packet : packets) { - if (packet->GetPacketType() == Packet::kMedia) { - MediaPacket* media_packet = static_cast(packet); - // TODO(philipel): Add probe_cluster_id to Packet class in order - // to create tests for probing using cluster ids. - PacketFeedback packet_feedback( - clock_->TimeInMilliseconds(), media_packet->header().sequenceNumber, - media_packet->payload_size(), 0, 0, PacedPacketInfo()); - send_time_history_.AddAndRemoveOld(packet_feedback, - clock_->TimeInMilliseconds()); - send_time_history_.OnSentPacket(media_packet->header().sequenceNumber, - media_packet->sender_timestamp_ms()); - } - } -} - -void SendSideBweSender::OnReceiveBitrateChanged( - const std::vector& ssrcs, - uint32_t bitrate) { - feedback_observer_->OnReceivedEstimatedBitrate(bitrate); -} - -int64_t SendSideBweSender::TimeUntilNextProcess() { - return bitrate_controller_->TimeUntilNextProcess(); -} - -void SendSideBweSender::Process() { - bitrate_controller_->Process(); -} - -SendSideBweReceiver::SendSideBweReceiver(int flow_id) - : BweReceiver(flow_id), last_feedback_ms_(0) {} - -SendSideBweReceiver::~SendSideBweReceiver() {} - -void SendSideBweReceiver::ReceivePacket(int64_t arrival_time_ms, - const MediaPacket& media_packet) { - packet_feedback_vector_.push_back( - PacketFeedback(-1, arrival_time_ms, media_packet.sender_timestamp_ms(), - media_packet.header().sequenceNumber, - media_packet.payload_size(), 0, 0, PacedPacketInfo())); - - // Log received packet information. - BweReceiver::ReceivePacket(arrival_time_ms, media_packet); -} - -FeedbackPacket* SendSideBweReceiver::GetFeedback(int64_t now_ms) { - if (now_ms - last_feedback_ms_ < kFeedbackIntervalMs) - return NULL; - last_feedback_ms_ = now_ms; - int64_t corrected_send_time_ms = - packet_feedback_vector_.back().send_time_ms + now_ms - - packet_feedback_vector_.back().arrival_time_ms; - FeedbackPacket* fb = new SendSideBweFeedback( - flow_id_, now_ms * 1000, corrected_send_time_ms, packet_feedback_vector_); - packet_feedback_vector_.clear(); - return fb; -} - -} // namespace bwe -} // namespace testing -} // namespace webrtc diff --git a/modules/remote_bitrate_estimator/test/estimators/send_side.h b/modules/remote_bitrate_estimator/test/estimators/send_side.h deleted file mode 100644 index 4d7cb18759..0000000000 --- a/modules/remote_bitrate_estimator/test/estimators/send_side.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2015 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. - */ - -#ifndef MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_ESTIMATORS_SEND_SIDE_H_ -#define MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_ESTIMATORS_SEND_SIDE_H_ - -#include -#include -#include - -#include "api/transport/field_trial_based_config.h" -#include "logging/rtc_event_log/mock/mock_rtc_event_log.h" -#include "modules/bitrate_controller/include/bitrate_controller.h" -#include "modules/congestion_controller/goog_cc/acknowledged_bitrate_estimator.h" -#include "modules/congestion_controller/goog_cc/delay_based_bwe.h" -#include "modules/congestion_controller/rtp/send_time_history.h" -#include "modules/include/module_common_types_public.h" -#include "modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h" -#include "modules/remote_bitrate_estimator/test/bwe.h" -#include "modules/remote_bitrate_estimator/test/packet.h" -#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" -#include "rtc_base/constructor_magic.h" -#include "system_wrappers/include/clock.h" -#include "test/gmock.h" - -namespace webrtc { -namespace testing { -namespace bwe { - -class SendSideBweSender : public BweSender, public RemoteBitrateObserver { - public: - SendSideBweSender(int kbps, BitrateObserver* observer, Clock* clock); - virtual ~SendSideBweSender(); - - int GetFeedbackIntervalMs() const override; - void GiveFeedback(const FeedbackPacket& feedback) override; - void OnPacketsSent(const Packets& packets) override; - void OnReceiveBitrateChanged(const std::vector& ssrcs, - uint32_t bitrate) override; - int64_t TimeUntilNextProcess() override; - void Process() override; - - private: - FieldTrialBasedConfig field_trial_config_; - - protected: - std::unique_ptr bitrate_controller_; - std::unique_ptr acknowledged_bitrate_estimator_; - std::unique_ptr probe_bitrate_estimator_; - std::unique_ptr bwe_; - RtcpBandwidthObserver* feedback_observer_; - - private: - Clock* const clock_; - RTCPReportBlock report_block_; - SendTimeHistory send_time_history_; - bool has_received_ack_; - uint16_t last_acked_seq_num_; - int64_t last_log_time_ms_; - SequenceNumberUnwrapper seq_num_unwrapper_; - ::testing::NiceMock event_log_; - - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(SendSideBweSender); -}; - -class SendSideBweReceiver : public BweReceiver { - public: - explicit SendSideBweReceiver(int flow_id); - ~SendSideBweReceiver() override; - - void ReceivePacket(int64_t arrival_time_ms, - const MediaPacket& media_packet) override; - FeedbackPacket* GetFeedback(int64_t now_ms) override; - - private: - int64_t last_feedback_ms_; - std::vector packet_feedback_vector_; -}; - -} // namespace bwe -} // namespace testing -} // namespace webrtc - -#endif // MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_ESTIMATORS_SEND_SIDE_H_ diff --git a/modules/remote_bitrate_estimator/test/estimators/tcp.cc b/modules/remote_bitrate_estimator/test/estimators/tcp.cc deleted file mode 100644 index 96c97ed5b5..0000000000 --- a/modules/remote_bitrate_estimator/test/estimators/tcp.cc +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2015 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 - -#include "api/rtp_headers.h" -#include "modules/remote_bitrate_estimator/test/estimators/tcp.h" - -namespace webrtc { -namespace testing { -namespace bwe { - -TcpBweReceiver::TcpBweReceiver(int flow_id) - : BweReceiver(flow_id), last_feedback_ms_(0), latest_owd_ms_(0) {} - -TcpBweReceiver::~TcpBweReceiver() {} - -void TcpBweReceiver::ReceivePacket(int64_t arrival_time_ms, - const MediaPacket& media_packet) { - latest_owd_ms_ = arrival_time_ms - media_packet.sender_timestamp_ms() / 1000; - acks_.push_back(media_packet.header().sequenceNumber); - - // Log received packet information. - BweReceiver::ReceivePacket(arrival_time_ms, media_packet); -} - -FeedbackPacket* TcpBweReceiver::GetFeedback(int64_t now_ms) { - int64_t corrected_send_time_ms = now_ms - latest_owd_ms_; - FeedbackPacket* fb = - new TcpFeedback(flow_id_, now_ms * 1000, corrected_send_time_ms, acks_); - last_feedback_ms_ = now_ms; - acks_.clear(); - return fb; -} - -} // namespace bwe -} // namespace testing -} // namespace webrtc diff --git a/modules/remote_bitrate_estimator/test/estimators/tcp.h b/modules/remote_bitrate_estimator/test/estimators/tcp.h deleted file mode 100644 index abdc0718cf..0000000000 --- a/modules/remote_bitrate_estimator/test/estimators/tcp.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2015 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. - */ - -#ifndef MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_ESTIMATORS_TCP_H_ -#define MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_ESTIMATORS_TCP_H_ - -#include -#include - -#include "modules/remote_bitrate_estimator/test/bwe.h" -#include "modules/remote_bitrate_estimator/test/packet.h" - -namespace webrtc { -namespace testing { -namespace bwe { -class TcpBweReceiver : public BweReceiver { - public: - explicit TcpBweReceiver(int flow_id); - ~TcpBweReceiver() override; - - void ReceivePacket(int64_t arrival_time_ms, - const MediaPacket& media_packet) override; - FeedbackPacket* GetFeedback(int64_t now_ms) override; - - private: - int64_t last_feedback_ms_; - int64_t latest_owd_ms_; - std::vector acks_; -}; -} // namespace bwe -} // namespace testing -} // namespace webrtc -#endif // MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_ESTIMATORS_TCP_H_ diff --git a/modules/remote_bitrate_estimator/test/metric_recorder.cc b/modules/remote_bitrate_estimator/test/metric_recorder.cc deleted file mode 100644 index 2346ece37e..0000000000 --- a/modules/remote_bitrate_estimator/test/metric_recorder.cc +++ /dev/null @@ -1,453 +0,0 @@ -/* - * Copyright (c) 2015 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 "modules/remote_bitrate_estimator/test/metric_recorder.h" - -#include - -#include - -#include "modules/remote_bitrate_estimator/test/packet_sender.h" -#include "rtc_base/strings/string_builder.h" -#include "rtc_base/system/unused.h" - -namespace webrtc { -namespace testing { -namespace bwe { - -namespace { -// Holder mean, Manhattan distance for p=1, EuclidianNorm/sqrt(n) for p=2. -template -double NormLp(T sum, size_t size, double p) { - return pow(sum / size, 1.0 / p); -} -} // namespace - -const double kP = 1.0; // Used for Norm Lp. - -LinkShare::LinkShare(ChokeFilter* choke_filter) - : choke_filter_(choke_filter), running_flows_(choke_filter->flow_ids()) {} - -LinkShare::~LinkShare() = default; - -void LinkShare::PauseFlow(int flow_id) { - running_flows_.erase(flow_id); -} - -void LinkShare::ResumeFlow(int flow_id) { - running_flows_.insert(flow_id); -} - -uint32_t LinkShare::TotalAvailableKbps() { - return choke_filter_->capacity_kbps(); -} - -uint32_t LinkShare::AvailablePerFlowKbps(int flow_id) { - uint32_t available_capacity_per_flow_kbps = 0; - if (running_flows_.find(flow_id) != running_flows_.end()) { - available_capacity_per_flow_kbps = - TotalAvailableKbps() / static_cast(running_flows_.size()); - } - return available_capacity_per_flow_kbps; -} - -MetricRecorder::MetricRecorder(const std::string algorithm_name, - int flow_id, - PacketSender* packet_sender, - LinkShare* link_share) - : algorithm_name_(algorithm_name), - flow_id_(flow_id), - link_share_(link_share), - now_ms_(0), - sum_delays_ms_(0), - delay_histogram_ms_(), - sum_delays_square_ms2_(0), - sum_throughput_bytes_(0), - last_unweighted_estimate_error_(0), - optimal_throughput_bits_(0), - last_available_bitrate_per_flow_kbps_(0), - start_computing_metrics_ms_(0), - started_computing_metrics_(false), - num_packets_received_(0) { - std::fill_n(sum_lp_weighted_estimate_error_, 2, 0); - if (packet_sender != nullptr) - packet_sender->set_metric_recorder(this); -} - -MetricRecorder::~MetricRecorder() = default; - -void MetricRecorder::SetPlotInformation( - const std::vector& prefixes, - bool plot_delay, - bool plot_loss) { - assert(prefixes.size() == kNumMetrics); - for (size_t i = 0; i < kNumMetrics; ++i) { - plot_information_[i].prefix = prefixes[i]; - } - plot_information_[kThroughput].plot_interval_ms = 100; - plot_information_[kSendingEstimate].plot_interval_ms = 100; - plot_information_[kDelay].plot_interval_ms = 100; - plot_information_[kLoss].plot_interval_ms = 500; - plot_information_[kObjective].plot_interval_ms = 1000; - plot_information_[kTotalAvailable].plot_interval_ms = 1000; - plot_information_[kAvailablePerFlow].plot_interval_ms = 1000; - - for (int i = kThroughput; i < kNumMetrics; ++i) { - plot_information_[i].last_plot_ms = 0; - switch (i) { - case kSendingEstimate: - case kObjective: - case kAvailablePerFlow: - plot_information_[i].plot = false; - break; - case kLoss: - plot_information_[i].plot = plot_loss; - break; - case kDelay: - plot_information_[i].plot = plot_delay; - break; - default: - plot_information_[i].plot = true; - } - } -} - -void MetricRecorder::PlotAllDynamics() { - for (int i = kThroughput; i < kNumMetrics; ++i) { - if (plot_information_[i].plot && - now_ms_ - plot_information_[i].last_plot_ms >= - plot_information_[i].plot_interval_ms) { - PlotDynamics(i); - } - } -} - -void MetricRecorder::PlotDynamics(int metric) { - if (metric == kTotalAvailable) { - BWE_TEST_LOGGING_PLOT_WITH_NAME_AND_SSRC( - 0, plot_information_[kTotalAvailable].prefix, now_ms_, - GetTotalAvailableKbps(), flow_id_, "Available"); - } else if (metric == kAvailablePerFlow) { - BWE_TEST_LOGGING_PLOT_WITH_NAME_AND_SSRC( - 0, plot_information_[kAvailablePerFlow].prefix, now_ms_, - GetAvailablePerFlowKbps(), flow_id_, "Available_per_flow"); - } else { - PlotLine(metric, plot_information_[metric].prefix, - plot_information_[metric].time_ms, - plot_information_[metric].value); - } - plot_information_[metric].last_plot_ms = now_ms_; -} - -template -void MetricRecorder::PlotLine(int windows_id, - const std::string& prefix, - int64_t time_ms, - T y) { - BWE_TEST_LOGGING_PLOT_WITH_NAME_AND_SSRC(windows_id, prefix, time_ms, - static_cast(y), flow_id_, - algorithm_name_); -} - -void MetricRecorder::UpdateTimeMs(int64_t time_ms) { - now_ms_ = std::max(now_ms_, time_ms); -} - -void MetricRecorder::UpdateThroughput(int64_t bitrate_kbps, - size_t payload_size) { - // Total throughput should be computed before updating the time. - PushThroughputBytes(payload_size, now_ms_); - plot_information_[kThroughput].Update(now_ms_, bitrate_kbps); -} - -void MetricRecorder::UpdateSendingEstimateKbps(int64_t bitrate_kbps) { - plot_information_[kSendingEstimate].Update(now_ms_, bitrate_kbps); -} - -void MetricRecorder::UpdateDelayMs(int64_t delay_ms) { - PushDelayMs(delay_ms, now_ms_); - plot_information_[kDelay].Update(now_ms_, delay_ms); -} - -void MetricRecorder::UpdateLoss(float loss_ratio) { - plot_information_[kLoss].Update(now_ms_, loss_ratio); -} - -void MetricRecorder::UpdateObjective() { - plot_information_[kObjective].Update(now_ms_, ObjectiveFunction()); -} - -uint32_t MetricRecorder::GetTotalAvailableKbps() { - if (link_share_ == nullptr) - return 0; - return link_share_->TotalAvailableKbps(); -} - -uint32_t MetricRecorder::GetAvailablePerFlowKbps() { - if (link_share_ == nullptr) - return 0; - return link_share_->AvailablePerFlowKbps(flow_id_); -} - -uint32_t MetricRecorder::GetSendingEstimateKbps() { - return static_cast(plot_information_[kSendingEstimate].value); -} - -void MetricRecorder::PushDelayMs(int64_t delay_ms, int64_t arrival_time_ms) { - if (ShouldRecord(arrival_time_ms)) { - sum_delays_ms_ += delay_ms; - sum_delays_square_ms2_ += delay_ms * delay_ms; - if (delay_histogram_ms_.find(delay_ms) == delay_histogram_ms_.end()) { - delay_histogram_ms_[delay_ms] = 0; - } - ++delay_histogram_ms_[delay_ms]; - } -} - -void MetricRecorder::UpdateEstimateError(int64_t new_value) { - int64_t lp_value = pow(static_cast(std::abs(new_value)), kP); - if (new_value < 0) { - sum_lp_weighted_estimate_error_[0] += lp_value; - } else { - sum_lp_weighted_estimate_error_[1] += lp_value; - } -} - -void MetricRecorder::PushThroughputBytes(size_t payload_size, - int64_t arrival_time_ms) { - if (ShouldRecord(arrival_time_ms)) { - ++num_packets_received_; - sum_throughput_bytes_ += payload_size; - - int64_t current_available_per_flow_kbps = - static_cast(GetAvailablePerFlowKbps()); - - int64_t current_bitrate_diff_kbps = - static_cast(GetSendingEstimateKbps()) - - current_available_per_flow_kbps; - - int64_t weighted_estimate_error = - (((current_bitrate_diff_kbps + last_unweighted_estimate_error_) * - (arrival_time_ms - plot_information_[kThroughput].time_ms)) / - 2); - - UpdateEstimateError(weighted_estimate_error); - - optimal_throughput_bits_ += - ((current_available_per_flow_kbps + - last_available_bitrate_per_flow_kbps_) * - (arrival_time_ms - plot_information_[kThroughput].time_ms)) / - 2; - - last_available_bitrate_per_flow_kbps_ = current_available_per_flow_kbps; - } -} - -bool MetricRecorder::ShouldRecord(int64_t arrival_time_ms) { - if (arrival_time_ms >= start_computing_metrics_ms_) { - if (!started_computing_metrics_) { - start_computing_metrics_ms_ = arrival_time_ms; - now_ms_ = arrival_time_ms; - started_computing_metrics_ = true; - } - return true; - } else { - return false; - } -} - -void MetricRecorder::PlotThroughputHistogram( - const std::string& title, - const std::string& bwe_name, - size_t num_flows, - int64_t extra_offset_ms, - const std::string optimum_id) const { - double optimal_bitrate_per_flow_kbps = static_cast( - optimal_throughput_bits_ / RunDurationMs(extra_offset_ms)); - - double neg_error = Renormalize( - NormLp(sum_lp_weighted_estimate_error_[0], num_packets_received_, kP)); - double pos_error = Renormalize( - NormLp(sum_lp_weighted_estimate_error_[1], num_packets_received_, kP)); - - double average_bitrate_kbps = AverageBitrateKbps(extra_offset_ms); - - // Prevent the error to be too close to zero (plotting issue). - double extra_error = average_bitrate_kbps / 500; - - std::string optimum_title = - optimum_id.empty() ? "optimal_bitrate" : "optimal_bitrates#" + optimum_id; - - BWE_TEST_LOGGING_LABEL(4, title, "average_bitrate_(kbps)", num_flows); - BWE_TEST_LOGGING_LIMITERRORBAR( - 4, bwe_name, average_bitrate_kbps, - average_bitrate_kbps - neg_error - extra_error, - average_bitrate_kbps + pos_error + extra_error, "estimate_error", - optimal_bitrate_per_flow_kbps, optimum_title, flow_id_); - - BWE_TEST_LOGGING_LOG1( - "RESULTS >>> " + bwe_name + " Channel utilization : ", "%lf %%", - 100.0 * static_cast(average_bitrate_kbps) / - optimal_bitrate_per_flow_kbps); - - RTC_UNUSED(pos_error); - RTC_UNUSED(neg_error); - RTC_UNUSED(extra_error); - RTC_UNUSED(optimal_bitrate_per_flow_kbps); -} - -void MetricRecorder::PlotThroughputHistogram(const std::string& title, - const std::string& bwe_name, - size_t num_flows, - int64_t extra_offset_ms) const { - PlotThroughputHistogram(title, bwe_name, num_flows, extra_offset_ms, ""); -} - -void MetricRecorder::PlotDelayHistogram(const std::string& title, - const std::string& bwe_name, - size_t num_flows, - int64_t one_way_path_delay_ms) const { - double average_delay_ms = - static_cast(sum_delays_ms_) / num_packets_received_; - int64_t percentile_5_ms = NthDelayPercentile(5); - int64_t percentile_95_ms = NthDelayPercentile(95); - - BWE_TEST_LOGGING_LABEL(5, title, "average_delay_(ms)", num_flows); - BWE_TEST_LOGGING_ERRORBAR(5, bwe_name, average_delay_ms, percentile_5_ms, - percentile_95_ms, "5th and 95th percentiles", - flow_id_); - - // Log added latency, disregard baseline path delay. - BWE_TEST_LOGGING_LOG1("RESULTS >>> " + bwe_name + " Delay average : ", - "%lf ms", average_delay_ms - one_way_path_delay_ms); - BWE_TEST_LOGGING_LOG1( - "RESULTS >>> " + bwe_name + " Delay 5th percentile : ", "%" PRId64 " ms", - percentile_5_ms - one_way_path_delay_ms); - BWE_TEST_LOGGING_LOG1( - "RESULTS >>> " + bwe_name + " Delay 95th percentile : ", "%" PRId64 " ms", - percentile_95_ms - one_way_path_delay_ms); - - RTC_UNUSED(average_delay_ms); - RTC_UNUSED(percentile_5_ms); - RTC_UNUSED(percentile_95_ms); -} - -void MetricRecorder::PlotLossHistogram(const std::string& title, - const std::string& bwe_name, - size_t num_flows, - float global_loss_ratio) const { - BWE_TEST_LOGGING_LABEL(6, title, "packet_loss_ratio_(%)", num_flows); - BWE_TEST_LOGGING_BAR(6, bwe_name, 100.0f * global_loss_ratio, flow_id_); - - BWE_TEST_LOGGING_LOG1("RESULTS >>> " + bwe_name + " Loss Ratio : ", "%f %%", - 100.0f * global_loss_ratio); -} - -void MetricRecorder::PlotObjectiveHistogram(const std::string& title, - const std::string& bwe_name, - size_t num_flows) const { - BWE_TEST_LOGGING_LABEL(7, title, "objective_function", num_flows); - BWE_TEST_LOGGING_BAR(7, bwe_name, ObjectiveFunction(), flow_id_); -} - -void MetricRecorder::PlotZero() { - for (int i = kThroughput; i <= kLoss; ++i) { - if (plot_information_[i].plot) { - rtc::StringBuilder prefix; - // TODO(terelius): Since this does not use the BWE_TEST_LOGGING macros, - // it hasn't been kept up to date with the plot format. Remove or fix? - prefix << "Receiver_" << flow_id_ << "_" + plot_information_[i].prefix; - PlotLine(i, prefix.str(), now_ms_, 0); - plot_information_[i].last_plot_ms = now_ms_; - } - } -} - -void MetricRecorder::PauseFlow() { - PlotZero(); - link_share_->PauseFlow(flow_id_); -} - -void MetricRecorder::ResumeFlow(int64_t paused_time_ms) { - UpdateTimeMs(now_ms_ + paused_time_ms); - PlotZero(); - link_share_->ResumeFlow(flow_id_); -} - -double MetricRecorder::AverageBitrateKbps(int64_t extra_offset_ms) const { - int64_t duration_ms = RunDurationMs(extra_offset_ms); - if (duration_ms == 0) - return 0.0; - return static_cast(8 * sum_throughput_bytes_ / duration_ms); -} - -int64_t MetricRecorder::RunDurationMs(int64_t extra_offset_ms) const { - return now_ms_ - start_computing_metrics_ms_ - extra_offset_ms; -} - -double MetricRecorder::DelayStdDev() const { - if (num_packets_received_ == 0) { - return 0.0; - } - double mean = static_cast(sum_delays_ms_) / num_packets_received_; - double mean2 = - static_cast(sum_delays_square_ms2_) / num_packets_received_; - return sqrt(mean2 - pow(mean, 2.0)); -} - -// Since delay values are bounded in a subset of [0, 5000] ms, -// this function's execution time is O(1), independend of num_packets_received_. -int64_t MetricRecorder::NthDelayPercentile(int n) const { - if (num_packets_received_ == 0) { - return 0; - } - size_t num_packets_remaining = (n * num_packets_received_) / 100; - for (auto hist : delay_histogram_ms_) { - if (num_packets_remaining <= hist.second) - return static_cast(hist.first); - num_packets_remaining -= hist.second; - } - - assert(false); - return -1; -} - -// The weighted_estimate_error_ was weighted based on time windows. -// This function scales back the result before plotting. -double MetricRecorder::Renormalize(double x) const { - return (x * num_packets_received_) / now_ms_; -} - -inline double U(int64_t x, double alpha) { - if (alpha == 1.0) { - return log(static_cast(x)); - } - return pow(static_cast(x), 1.0 - alpha) / (1.0 - alpha); -} - -inline double U(size_t x, double alpha) { - return U(static_cast(x), alpha); -} - -// TODO(magalhaesc): Update ObjectiveFunction. -double MetricRecorder::ObjectiveFunction() const { - const double kDelta = 0.15; // Delay penalty factor. - const double kAlpha = 1.0; - const double kBeta = 1.0; - - double throughput_metric = U(sum_throughput_bytes_, kAlpha); - double delay_penalty = kDelta * U(sum_delays_ms_, kBeta); - - return throughput_metric - delay_penalty; -} - -} // namespace bwe -} // namespace testing -} // namespace webrtc diff --git a/modules/remote_bitrate_estimator/test/metric_recorder.h b/modules/remote_bitrate_estimator/test/metric_recorder.h deleted file mode 100644 index d0ba4e3163..0000000000 --- a/modules/remote_bitrate_estimator/test/metric_recorder.h +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (c) 2015 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. - */ - -#ifndef MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_METRIC_RECORDER_H_ -#define MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_METRIC_RECORDER_H_ - -#include -#include -#include -#include - -#include "rtc_base/gtest_prod_util.h" - -namespace webrtc { -namespace testing { -namespace bwe { - -class ChokeFilter; -class PacketSender; - -class LinkShare { - public: - explicit LinkShare(ChokeFilter* choke_filter); - ~LinkShare(); - - void PauseFlow(int flow_id); // Increases available capacity per flow. - void ResumeFlow(int flow_id); // Decreases available capacity per flow. - - uint32_t TotalAvailableKbps(); - // If the given flow is paused, its output is zero. - uint32_t AvailablePerFlowKbps(int flow_id); - - private: - ChokeFilter* choke_filter_; - std::set running_flows_; -}; - -struct PlotInformation { - PlotInformation() - : prefix(), - last_plot_ms(0), - time_ms(0), - value(0.0), - plot_interval_ms(0) {} - template - void Update(int64_t now_ms, T new_value) { - time_ms = now_ms; - value = static_cast(new_value); - } - std::string prefix; - bool plot; - int64_t last_plot_ms; - int64_t time_ms; - double value; - int64_t plot_interval_ms; -}; - -class MetricRecorder { - public: - MetricRecorder(const std::string algorithm_name, - int flow_id, - PacketSender* packet_sender, - LinkShare* link_share); - ~MetricRecorder(); - - void SetPlotInformation(const std::vector& prefixes, - bool plot_delay, - bool plot_loss); - - template - void PlotLine(int windows_id, - const std::string& prefix, - int64_t time_ms, - T y); - - void PlotDynamics(int metric); - void PlotAllDynamics(); - - void UpdateTimeMs(int64_t time_ms); - void UpdateThroughput(int64_t bitrate_kbps, size_t payload_size); - void UpdateSendingEstimateKbps(int64_t bitrate_kbps); - void UpdateDelayMs(int64_t delay_ms); - void UpdateLoss(float loss_ratio); - void UpdateObjective(); - - void PlotThroughputHistogram(const std::string& title, - const std::string& bwe_name, - size_t num_flows, - int64_t extra_offset_ms, - const std::string optimum_id) const; - - void PlotThroughputHistogram(const std::string& title, - const std::string& bwe_name, - size_t num_flows, - int64_t extra_offset_ms) const; - - void PlotDelayHistogram(const std::string& title, - const std::string& bwe_name, - size_t num_flows, - int64_t one_way_path_delay_ms) const; - - void PlotLossHistogram(const std::string& title, - const std::string& bwe_name, - size_t num_flows, - float global_loss_ratio) const; - - void PlotObjectiveHistogram(const std::string& title, - const std::string& bwe_name, - size_t num_flows) const; - - void set_start_computing_metrics_ms(int64_t start_computing_metrics_ms) { - start_computing_metrics_ms_ = start_computing_metrics_ms; - } - - void set_plot_available_capacity(bool plot) { - plot_information_[kTotalAvailable].plot = plot; - } - - void PauseFlow(); // Plot zero. - void ResumeFlow(int64_t paused_time_ms); // Plot zero. - void PlotZero(); - - private: - FRIEND_TEST_ALL_PREFIXES(MetricRecorderTest, NoPackets); - FRIEND_TEST_ALL_PREFIXES(MetricRecorderTest, RegularPackets); - FRIEND_TEST_ALL_PREFIXES(MetricRecorderTest, VariableDelayPackets); - - uint32_t GetTotalAvailableKbps(); - uint32_t GetAvailablePerFlowKbps(); - uint32_t GetSendingEstimateKbps(); - double ObjectiveFunction() const; - - double Renormalize(double x) const; - bool ShouldRecord(int64_t arrival_time_ms); - - void PushDelayMs(int64_t delay_ms, int64_t arrival_time_ms); - void PushThroughputBytes(size_t throughput_bytes, int64_t arrival_time_ms); - - void UpdateEstimateError(int64_t new_value); - double DelayStdDev() const; - int64_t NthDelayPercentile(int n) const; - double AverageBitrateKbps(int64_t extra_offset_ms) const; - int64_t RunDurationMs(int64_t extra_offset_ms) const; - - enum Metrics { - kThroughput = 0, - kSendingEstimate, - kDelay, - kLoss, - kObjective, - kTotalAvailable, - kAvailablePerFlow, - kNumMetrics - }; - - std::string algorithm_name_; - int flow_id_; - LinkShare* link_share_; - - int64_t now_ms_; - - PlotInformation plot_information_[kNumMetrics]; - - int64_t sum_delays_ms_; - // delay_histogram_ms_[i] counts how many packets have delay = i ms. - std::map delay_histogram_ms_; - int64_t sum_delays_square_ms2_; // Used to compute standard deviation. - size_t sum_throughput_bytes_; - // ((Receiving rate - available bitrate per flow) * time window)^p. - // 0 for negative values, 1 for positive values. - int64_t sum_lp_weighted_estimate_error_[2]; - int64_t last_unweighted_estimate_error_; - int64_t optimal_throughput_bits_; - int64_t last_available_bitrate_per_flow_kbps_; - int64_t start_computing_metrics_ms_; - bool started_computing_metrics_; - size_t num_packets_received_; -}; - -} // namespace bwe -} // namespace testing -} // namespace webrtc -#endif // MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_METRIC_RECORDER_H_ diff --git a/modules/remote_bitrate_estimator/test/metric_recorder_unittest.cc b/modules/remote_bitrate_estimator/test/metric_recorder_unittest.cc deleted file mode 100644 index 670b9bc00b..0000000000 --- a/modules/remote_bitrate_estimator/test/metric_recorder_unittest.cc +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) 2015 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 "modules/remote_bitrate_estimator/test/metric_recorder.h" - -#include -#include -#include -#include -#include - -#include "test/gtest.h" - -namespace webrtc { -namespace testing { -namespace bwe { - -class MetricRecorderTest : public ::testing::Test { - public: - MetricRecorderTest() : metric_recorder_("Test", 0, nullptr, nullptr) {} - - ~MetricRecorderTest() {} - - protected: - MetricRecorder metric_recorder_; -}; - -TEST_F(MetricRecorderTest, NoPackets) { - EXPECT_EQ(metric_recorder_.AverageBitrateKbps(0), 0); - EXPECT_EQ(metric_recorder_.DelayStdDev(), 0.0); - EXPECT_EQ(metric_recorder_.NthDelayPercentile(0), 0); - EXPECT_EQ(metric_recorder_.NthDelayPercentile(5), 0); - EXPECT_EQ(metric_recorder_.NthDelayPercentile(95), 0); - EXPECT_EQ(metric_recorder_.NthDelayPercentile(100), 0); -} - -TEST_F(MetricRecorderTest, RegularPackets) { - const size_t kPayloadSizeBytes = 1200; - const int64_t kDelayMs = 20; - const int64_t kInterpacketGapMs = 5; - const int kNumPackets = 1000; - - for (int i = 0; i < kNumPackets; ++i) { - int64_t arrival_time_ms = kInterpacketGapMs * i + kDelayMs; - metric_recorder_.UpdateTimeMs(arrival_time_ms); - metric_recorder_.PushDelayMs(kDelayMs, arrival_time_ms); - metric_recorder_.PushThroughputBytes(kPayloadSizeBytes, arrival_time_ms); - } - - EXPECT_NEAR( - metric_recorder_.AverageBitrateKbps(0), - static_cast(kPayloadSizeBytes * 8) / (kInterpacketGapMs), 10); - - EXPECT_EQ(metric_recorder_.DelayStdDev(), 0.0); - - EXPECT_EQ(metric_recorder_.NthDelayPercentile(0), kDelayMs); - EXPECT_EQ(metric_recorder_.NthDelayPercentile(5), kDelayMs); - EXPECT_EQ(metric_recorder_.NthDelayPercentile(95), kDelayMs); - EXPECT_EQ(metric_recorder_.NthDelayPercentile(100), kDelayMs); -} - -TEST_F(MetricRecorderTest, VariableDelayPackets) { - const size_t kPayloadSizeBytes = 1200; - const int64_t kInterpacketGapMs = 2000; - const int kNumPackets = 1000; - - std::vector delays_ms; - delays_ms.reserve(kNumPackets); - for (int i = 0; i < kNumPackets; ++i) { - delays_ms.push_back(static_cast(i + 1)); - } - // Order of packets should not matter here. - std::shuffle(delays_ms.begin(), delays_ms.end(), - std::mt19937(std::random_device()())); - - int first_received_ms = delays_ms[0]; - int64_t last_received_ms = 0; - for (int i = 0; i < kNumPackets; ++i) { - int64_t arrival_time_ms = kInterpacketGapMs * i + delays_ms[i]; - last_received_ms = std::max(last_received_ms, arrival_time_ms); - metric_recorder_.UpdateTimeMs(arrival_time_ms); - metric_recorder_.PushDelayMs(delays_ms[i], arrival_time_ms); - metric_recorder_.PushThroughputBytes(kPayloadSizeBytes, arrival_time_ms); - } - - size_t received_bits = kPayloadSizeBytes * 8 * kNumPackets; - EXPECT_NEAR(metric_recorder_.AverageBitrateKbps(0), - static_cast(received_bits) / - ((last_received_ms - first_received_ms)), - 10); - - double expected_x = (kNumPackets + 1) / 2.0; - double expected_x2 = ((kNumPackets + 1) * (2 * kNumPackets + 1)) / 6.0; - double var = expected_x2 - pow(expected_x, 2.0); - EXPECT_NEAR(metric_recorder_.DelayStdDev(), sqrt(var), kNumPackets / 1000.0); - - EXPECT_EQ(metric_recorder_.NthDelayPercentile(0), 1); - EXPECT_EQ(metric_recorder_.NthDelayPercentile(5), (5 * kNumPackets) / 100); - EXPECT_EQ(metric_recorder_.NthDelayPercentile(95), (95 * kNumPackets) / 100); - EXPECT_EQ(metric_recorder_.NthDelayPercentile(100), kNumPackets); -} - -} // namespace bwe -} // namespace testing -} // namespace webrtc diff --git a/modules/remote_bitrate_estimator/test/packet.cc b/modules/remote_bitrate_estimator/test/packet.cc deleted file mode 100644 index d318f09b45..0000000000 --- a/modules/remote_bitrate_estimator/test/packet.cc +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2018 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 "modules/remote_bitrate_estimator/test/packet.h" - -#include -#include - -namespace webrtc { -namespace testing { -namespace bwe { - -Packet::Packet() - : flow_id_(0), - creation_time_us_(-1), - send_time_us_(-1), - sender_timestamp_us_(-1), - payload_size_(0) {} - -Packet::Packet(int flow_id, int64_t send_time_us, size_t payload_size) - : flow_id_(flow_id), - creation_time_us_(send_time_us), - send_time_us_(send_time_us), - sender_timestamp_us_(send_time_us), - payload_size_(payload_size) {} - -Packet::~Packet() {} - -bool Packet::operator<(const Packet& rhs) const { - return send_time_us_ < rhs.send_time_us_; -} - -void Packet::set_send_time_us(int64_t send_time_us) { - assert(send_time_us >= 0); - send_time_us_ = send_time_us; -} - -int Packet::flow_id() const { - return flow_id_; -} - -int64_t Packet::send_time_us() const { - return send_time_us_; -} - -int64_t Packet::sender_timestamp_us() const { - return sender_timestamp_us_; -} - -size_t Packet::payload_size() const { - return payload_size_; -} - -void Packet::set_sender_timestamp_us(int64_t sender_timestamp_us) { - sender_timestamp_us_ = sender_timestamp_us; -} - -int64_t Packet::creation_time_ms() const { - return (creation_time_us_ + 500) / 1000; -} - -int64_t Packet::sender_timestamp_ms() const { - return (sender_timestamp_us_ + 500) / 1000; -} - -int64_t Packet::send_time_ms() const { - return (send_time_us_ + 500) / 1000; -} - -Packet::Type MediaPacket::GetPacketType() const { - return kMedia; -} - -Packet::Type FeedbackPacket::GetPacketType() const { - return kFeedback; -} - -BbrBweFeedback::~BbrBweFeedback() = default; - -SendSideBweFeedback::~SendSideBweFeedback() = default; - -TcpFeedback::TcpFeedback(int flow_id, - int64_t send_time_us, - int64_t latest_send_time_ms, - const std::vector& acked_packets) - : FeedbackPacket(flow_id, send_time_us, latest_send_time_ms), - acked_packets_(acked_packets) {} - -TcpFeedback::~TcpFeedback() = default; - -} // namespace bwe -} // namespace testing -} // namespace webrtc diff --git a/modules/remote_bitrate_estimator/test/packet.h b/modules/remote_bitrate_estimator/test/packet.h deleted file mode 100644 index 5a8c6467f3..0000000000 --- a/modules/remote_bitrate_estimator/test/packet.h +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright (c) 2015 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. - */ - -#ifndef MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_PACKET_H_ -#define MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_PACKET_H_ - -#include -#include -#include -#include -#include - -#include "api/rtp_headers.h" -#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" -#include "modules/rtp_rtcp/source/rtp_packet_received.h" - -namespace webrtc { -namespace testing { -namespace bwe { - -class Packet { - public: - enum Type { kMedia, kFeedback }; - - Packet(); - Packet(int flow_id, int64_t send_time_us, size_t payload_size); - virtual ~Packet(); - - virtual bool operator<(const Packet& rhs) const; - - virtual int flow_id() const; - virtual void set_send_time_us(int64_t send_time_us); - virtual int64_t send_time_us() const; - virtual int64_t sender_timestamp_us() const; - virtual size_t payload_size() const; - virtual Packet::Type GetPacketType() const = 0; - virtual void set_sender_timestamp_us(int64_t sender_timestamp_us); - virtual int64_t creation_time_ms() const; - virtual int64_t sender_timestamp_ms() const; - virtual int64_t send_time_ms() const; - - protected: - int flow_id_; - int64_t creation_time_us_; // Time when the packet was created. - int64_t send_time_us_; // Time the packet left last processor touching it. - int64_t sender_timestamp_us_; // Time the packet left the Sender. - size_t payload_size_; // Size of the (non-existent, simulated) payload. -}; - -class MediaPacket : public Packet { - public: - MediaPacket(); - MediaPacket(int flow_id, - int64_t send_time_us, - size_t payload_size, - uint16_t sequence_number); - MediaPacket(int flow_id, - int64_t send_time_us, - size_t payload_size, - const RTPHeader& header); - MediaPacket(int64_t send_time_us, uint16_t sequence_number); - - ~MediaPacket() override {} - - int64_t GetAbsSendTimeInMs() const { - int64_t timestamp = header_.extension.absoluteSendTime - << kAbsSendTimeInterArrivalUpshift; - return 1000.0 * timestamp / static_cast(1 << kInterArrivalShift); - } - void SetAbsSendTimeMs(int64_t abs_send_time_ms); - const RTPHeader& header() const { return header_; } - Packet::Type GetPacketType() const override; - uint16_t sequence_number() const { return header_.sequenceNumber; } - RtpPacketReceived GetRtpPacket() const; - - private: - static const int kAbsSendTimeFraction = 18; - static const int kAbsSendTimeInterArrivalUpshift = 8; - static const int kInterArrivalShift = - kAbsSendTimeFraction + kAbsSendTimeInterArrivalUpshift; - - RTPHeader header_; -}; - -class FeedbackPacket : public Packet { - public: - FeedbackPacket(int flow_id, - int64_t this_send_time_us, - int64_t latest_send_time_ms) - : Packet(flow_id, this_send_time_us, 0), - latest_send_time_ms_(latest_send_time_ms) {} - ~FeedbackPacket() override {} - - Packet::Type GetPacketType() const override; - int64_t latest_send_time_ms() const { return latest_send_time_ms_; } - - private: - int64_t latest_send_time_ms_; // Time stamp for the latest sent FbPacket. -}; - -class BbrBweFeedback : public FeedbackPacket { - public: - BbrBweFeedback(int flow_id, - int64_t send_time_us, - int64_t latest_send_time_ms, - const std::vector& packet_feedback_vector); - ~BbrBweFeedback() override; - - const std::vector& packet_feedback_vector() const { - return packet_feedback_vector_; - } - - private: - const std::vector packet_feedback_vector_; -}; - -class RembFeedback : public FeedbackPacket { - public: - RembFeedback(int flow_id, - int64_t send_time_us, - int64_t latest_send_time_ms, - uint32_t estimated_bps, - RTCPReportBlock report_block); - ~RembFeedback() override {} - - uint32_t estimated_bps() const { return estimated_bps_; } - RTCPReportBlock report_block() const { return report_block_; } - - private: - const uint32_t estimated_bps_; - const RTCPReportBlock report_block_; -}; - -class SendSideBweFeedback : public FeedbackPacket { - public: - typedef std::map ArrivalTimesMap; - SendSideBweFeedback( - int flow_id, - int64_t send_time_us, - int64_t latest_send_time_ms, - const std::vector& packet_feedback_vector); - ~SendSideBweFeedback() override; - - const std::vector& packet_feedback_vector() const { - return packet_feedback_vector_; - } - - private: - const std::vector packet_feedback_vector_; -}; - -class NadaFeedback : public FeedbackPacket { - public: - NadaFeedback(int flow_id, - int64_t this_send_time_us, - int64_t exp_smoothed_delay_ms, - int64_t est_queuing_delay_signal_ms, - int64_t congestion_signal, - float derivative, - float receiving_rate, - int64_t latest_send_time_ms) - : FeedbackPacket(flow_id, this_send_time_us, latest_send_time_ms), - exp_smoothed_delay_ms_(exp_smoothed_delay_ms), - est_queuing_delay_signal_ms_(est_queuing_delay_signal_ms), - congestion_signal_(congestion_signal), - derivative_(derivative), - receiving_rate_(receiving_rate) {} - ~NadaFeedback() override {} - - int64_t exp_smoothed_delay_ms() const { return exp_smoothed_delay_ms_; } - int64_t est_queuing_delay_signal_ms() const { - return est_queuing_delay_signal_ms_; - } - int64_t congestion_signal() const { return congestion_signal_; } - float derivative() const { return derivative_; } - float receiving_rate() const { return receiving_rate_; } - - private: - int64_t exp_smoothed_delay_ms_; // Referred as d_hat_n. - int64_t est_queuing_delay_signal_ms_; // Referred as d_tilde_n. - int64_t congestion_signal_; // Referred as x_n. - float derivative_; // Referred as x'_n. - float receiving_rate_; // Referred as R_r. -}; - -class TcpFeedback : public FeedbackPacket { - public: - TcpFeedback(int flow_id, - int64_t send_time_us, - int64_t latest_send_time_ms, - const std::vector& acked_packets); - ~TcpFeedback() override; - - const std::vector& acked_packets() const { return acked_packets_; } - - private: - const std::vector acked_packets_; -}; - -typedef std::list Packets; -typedef std::list::iterator PacketsIt; -typedef std::list::const_iterator PacketsConstIt; - -} // namespace bwe -} // namespace testing -} // namespace webrtc -#endif // MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_PACKET_H_ diff --git a/modules/remote_bitrate_estimator/test/packet_receiver.cc b/modules/remote_bitrate_estimator/test/packet_receiver.cc deleted file mode 100644 index abd1b5f78a..0000000000 --- a/modules/remote_bitrate_estimator/test/packet_receiver.cc +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (c) 2015 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 "modules/remote_bitrate_estimator/test/packet_receiver.h" - -#include -#include - -#include "modules/remote_bitrate_estimator/test/bwe.h" -#include "modules/remote_bitrate_estimator/test/bwe_test_framework.h" -#include "modules/remote_bitrate_estimator/test/bwe_test_logging.h" - -namespace webrtc { -namespace testing { -namespace bwe { - -PacketReceiver::PacketReceiver(PacketProcessorListener* listener, - int flow_id, - BandwidthEstimatorType bwe_type, - bool plot_delay, - bool plot_bwe, - MetricRecorder* metric_recorder) - : PacketProcessor(listener, flow_id, kReceiver), - bwe_receiver_(CreateBweReceiver(bwe_type, flow_id, plot_bwe)), - metric_recorder_(metric_recorder), - plot_delay_(plot_delay), - last_delay_plot_ms_(0), - // #2 aligns the plot with the right axis. - delay_prefix_("Delay_ms#2"), - bwe_type_(bwe_type) { - if (metric_recorder_ != nullptr) { - // Setup the prefix std::strings used when logging. - std::vector prefixes; - - // Metric recorder plots them in separated figures, - // alignment will take place with the #1 left axis. - prefixes.push_back("MetricRecorderThroughput_kbps#1"); - prefixes.push_back("Sending_Estimate_kbps#1"); - prefixes.push_back("Delay_ms_#1"); - prefixes.push_back("Packet_Loss_#1"); - prefixes.push_back("Objective_function_#1"); - - // Plot Total/PerFlow Available capacity together with throughputs. - prefixes.push_back("Capacity_kbps#1"); // Total Available. - prefixes.push_back("PerFlowCapacity_kbps#1"); // Available per flow. - - bool plot_loss = plot_delay; // Plot loss if delay is plotted. - metric_recorder_->SetPlotInformation(prefixes, plot_delay, plot_loss); - } -} - -PacketReceiver::PacketReceiver(PacketProcessorListener* listener, - int flow_id, - BandwidthEstimatorType bwe_type, - bool plot_delay, - bool plot_bwe) - : PacketReceiver(listener, - flow_id, - bwe_type, - plot_delay, - plot_bwe, - nullptr) {} - -PacketReceiver::~PacketReceiver() {} - -void PacketReceiver::RunFor(int64_t time_ms, Packets* in_out) { - Packets feedback; - for (auto it = in_out->begin(); it != in_out->end();) { - // PacketReceivers are only associated with a single stream, and therefore - // should only process a single flow id. - // TODO(holmer): Break this out into a Demuxer which implements both - // PacketProcessorListener and PacketProcessor. - BWE_TEST_LOGGING_CONTEXT("Receiver"); - if ((*it)->GetPacketType() == Packet::kMedia && - (*it)->flow_id() == *flow_ids().begin()) { - BWE_TEST_LOGGING_CONTEXT(*flow_ids().begin()); - const MediaPacket* media_packet = static_cast(*it); - // We're treating the send time (from previous filter) as the arrival - // time once packet reaches the estimator. - int64_t arrival_time_ms = media_packet->send_time_ms(); - int64_t send_time_ms = media_packet->creation_time_ms(); - delay_stats_.Push(arrival_time_ms - send_time_ms); - - if (metric_recorder_ != nullptr) { - metric_recorder_->UpdateTimeMs(arrival_time_ms); - UpdateMetrics(arrival_time_ms, send_time_ms, - media_packet->payload_size()); - metric_recorder_->PlotAllDynamics(); - } else if (plot_delay_) { - PlotDelay(arrival_time_ms, send_time_ms); - } - - bwe_receiver_->ReceivePacket(arrival_time_ms, *media_packet); - FeedbackPacket* fb = bwe_receiver_->GetFeedback(arrival_time_ms); - if (fb) - feedback.push_back(fb); - delete media_packet; - it = in_out->erase(it); - } else { - ++it; - } - } - // Insert feedback packets to be sent back to the sender. - in_out->merge(feedback, DereferencingComparator); -} - -void PacketReceiver::UpdateMetrics(int64_t arrival_time_ms, - int64_t send_time_ms, - size_t payload_size) { - metric_recorder_->UpdateThroughput(bwe_receiver_->RecentKbps(), payload_size); - metric_recorder_->UpdateDelayMs(arrival_time_ms - send_time_ms); - metric_recorder_->UpdateLoss(bwe_receiver_->RecentPacketLossRatio()); - metric_recorder_->UpdateObjective(); -} - -void PacketReceiver::PlotDelay(int64_t arrival_time_ms, int64_t send_time_ms) { - const int64_t kDelayPlotIntervalMs = 100; - if (arrival_time_ms >= last_delay_plot_ms_ + kDelayPlotIntervalMs) { - BWE_TEST_LOGGING_PLOT_WITH_NAME(0, delay_prefix_, arrival_time_ms, - arrival_time_ms - send_time_ms, - bwe_names[bwe_type_]); - last_delay_plot_ms_ = arrival_time_ms; - } -} - -float PacketReceiver::GlobalPacketLoss() { - return bwe_receiver_->GlobalReceiverPacketLossRatio(); -} - -Stats PacketReceiver::GetDelayStats() const { - return delay_stats_; -} -} // namespace bwe -} // namespace testing -} // namespace webrtc diff --git a/modules/remote_bitrate_estimator/test/packet_receiver.h b/modules/remote_bitrate_estimator/test/packet_receiver.h deleted file mode 100644 index 848119e6d5..0000000000 --- a/modules/remote_bitrate_estimator/test/packet_receiver.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2015 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. - */ - -#ifndef MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_PACKET_RECEIVER_H_ -#define MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_PACKET_RECEIVER_H_ - -#include -#include -#include -#include - -#include "modules/remote_bitrate_estimator/test/bwe.h" -#include "modules/remote_bitrate_estimator/test/bwe_test_framework.h" -#include "modules/remote_bitrate_estimator/test/metric_recorder.h" -#include "modules/remote_bitrate_estimator/test/packet.h" -#include "rtc_base/constructor_magic.h" - -namespace webrtc { -namespace testing { -namespace bwe { - -class PacketReceiver : public PacketProcessor { - public: - PacketReceiver(PacketProcessorListener* listener, - int flow_id, - BandwidthEstimatorType bwe_type, - bool plot_delay, - bool plot_bwe); - PacketReceiver(PacketProcessorListener* listener, - int flow_id, - BandwidthEstimatorType bwe_type, - bool plot_delay, - bool plot_bwe, - MetricRecorder* metric_recorder); - ~PacketReceiver() override; - - // Implements PacketProcessor. - void RunFor(int64_t time_ms, Packets* in_out) override; - - void LogStats(); - - Stats GetDelayStats() const; - - float GlobalPacketLoss(); - - protected: - void UpdateMetrics(int64_t arrival_time_ms, - int64_t send_time_ms, - size_t payload_size); - - Stats delay_stats_; - std::unique_ptr bwe_receiver_; - - private: - void PlotDelay(int64_t arrival_time_ms, int64_t send_time_ms); - MetricRecorder* metric_recorder_; - bool plot_delay_; // Used in case there isn't a metric recorder. - int64_t last_delay_plot_ms_; - std::string delay_prefix_; - BandwidthEstimatorType bwe_type_; - - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(PacketReceiver); -}; -} // namespace bwe -} // namespace testing -} // namespace webrtc -#endif // MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_PACKET_RECEIVER_H_ diff --git a/modules/remote_bitrate_estimator/test/packet_sender.cc b/modules/remote_bitrate_estimator/test/packet_sender.cc deleted file mode 100644 index f7cb716cd6..0000000000 --- a/modules/remote_bitrate_estimator/test/packet_sender.cc +++ /dev/null @@ -1,533 +0,0 @@ -/* - * Copyright (c) 2015 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 "modules/remote_bitrate_estimator/test/packet_sender.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "modules/include/module_common_types_public.h" -#include "modules/pacing/pacer.h" -#include "modules/remote_bitrate_estimator/test/bbr_paced_sender.h" -#include "modules/remote_bitrate_estimator/test/bwe.h" -#include "modules/remote_bitrate_estimator/test/bwe_test_logging.h" -#include "modules/remote_bitrate_estimator/test/metric_recorder.h" -#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" -#include "rtc_base/checks.h" - -namespace webrtc { -namespace testing { -namespace bwe { -namespace { -const float kPaceMultiplier = 2.5f; -} - -uint32_t PacketSender::TargetBitrateKbps() { - return 0; -} - -void PacketSender::Pause() { - running_ = false; - if (metric_recorder_ != nullptr) { - metric_recorder_->PauseFlow(); - } -} - -void PacketSender::Resume(int64_t paused_time_ms) { - running_ = true; - if (metric_recorder_ != nullptr) { - metric_recorder_->ResumeFlow(paused_time_ms); - } -} - -void PacketSender::set_metric_recorder(MetricRecorder* metric_recorder) { - metric_recorder_ = metric_recorder; -} - -void PacketSender::RecordBitrate() { - if (metric_recorder_ != nullptr) { - BWE_TEST_LOGGING_CONTEXT("Sender"); - BWE_TEST_LOGGING_CONTEXT(*flow_ids().begin()); - metric_recorder_->UpdateTimeMs(clock_.TimeInMilliseconds()); - metric_recorder_->UpdateSendingEstimateKbps(TargetBitrateKbps()); - } -} - -std::list GetFeedbackPackets(Packets* in_out, - int64_t end_time_ms, - int flow_id) { - std::list fb_packets; - for (auto it = in_out->begin(); it != in_out->end();) { - if ((*it)->send_time_us() > 1000 * end_time_ms) - break; - if ((*it)->GetPacketType() == Packet::kFeedback && - flow_id == (*it)->flow_id()) { - fb_packets.push_back(static_cast(*it)); - it = in_out->erase(it); - } else { - ++it; - } - } - return fb_packets; -} - -VideoSender::VideoSender(PacketProcessorListener* listener, - VideoSource* source, - BandwidthEstimatorType estimator_type) - : PacketSender(listener, source->flow_id()), - source_(source), - bwe_(CreateBweSender(estimator_type, - source_->bits_per_second() / 1000, - this, - &clock_)), - previous_sending_bitrate_(0) { - modules_.push_back(bwe_.get()); -} - -VideoSender::~VideoSender() {} - -void VideoSender::Pause() { - previous_sending_bitrate_ = TargetBitrateKbps(); - PacketSender::Pause(); -} - -void VideoSender::Resume(int64_t paused_time_ms) { - source_->SetBitrateBps(previous_sending_bitrate_); - PacketSender::Resume(paused_time_ms); -} - -void VideoSender::RunFor(int64_t time_ms, Packets* in_out) { - std::list feedbacks = GetFeedbackPackets( - in_out, clock_.TimeInMilliseconds() + time_ms, source_->flow_id()); - ProcessFeedbackAndGeneratePackets(time_ms, &feedbacks, in_out); -} - -VideoSource* VideoSender::source() const { - return source_; -} - -void VideoSender::ProcessFeedbackAndGeneratePackets( - int64_t time_ms, - std::list* feedbacks, - Packets* packets) { - do { - // Make sure to at least run Process() below every 100 ms. - int64_t time_to_run_ms = std::min(time_ms, 100); - if (!feedbacks->empty()) { - int64_t time_until_feedback_ms = - feedbacks->front()->send_time_ms() - clock_.TimeInMilliseconds(); - time_to_run_ms = - std::max(std::min(time_ms, time_until_feedback_ms), 0); - } - - if (!running_) { - source_->SetBitrateBps(0); - } - - Packets generated; - source_->RunFor(time_to_run_ms, &generated); - bwe_->OnPacketsSent(generated); - packets->merge(generated, DereferencingComparator); - - clock_.AdvanceTimeMilliseconds(time_to_run_ms); - - if (!feedbacks->empty()) { - bwe_->GiveFeedback(*feedbacks->front()); - delete feedbacks->front(); - feedbacks->pop_front(); - } - - bwe_->Process(); - - time_ms -= time_to_run_ms; - } while (time_ms > 0); - assert(feedbacks->empty()); -} - -int VideoSender::GetFeedbackIntervalMs() const { - return bwe_->GetFeedbackIntervalMs(); -} - -void VideoSender::OnNetworkChanged(uint32_t target_bitrate_bps, - uint8_t fraction_lost, - int64_t rtt) { - source_->SetBitrateBps(target_bitrate_bps); - RecordBitrate(); -} - -uint32_t VideoSender::TargetBitrateKbps() { - return (source_->bits_per_second() + 500) / 1000; -} - -PacedVideoSender::PacedVideoSender(PacketProcessorListener* listener, - VideoSource* source, - BandwidthEstimatorType estimator) - : VideoSender(listener, source, estimator), - pacer_( - estimator == kBbrEstimator - ? static_cast(new BbrPacedSender(&clock_, this, nullptr)) - : static_cast(new PacedSender(&clock_, this, nullptr))) { - modules_.push_back(pacer_.get()); - pacer_->SetPacingRates(source->bits_per_second() * kPaceMultiplier, 0); -} - -PacedVideoSender::~PacedVideoSender() { - for (Packet* packet : pacer_queue_) - delete packet; - for (Packet* packet : queue_) - delete packet; -} - -void PacedVideoSender::RunFor(int64_t time_ms, Packets* in_out) { - int64_t end_time_ms = clock_.TimeInMilliseconds() + time_ms; - // Run process periodically to allow the packets to be paced out. - std::list feedbacks = - GetFeedbackPackets(in_out, end_time_ms, source_->flow_id()); - int64_t last_run_time_ms = -1; - BWE_TEST_LOGGING_CONTEXT("Sender"); - BWE_TEST_LOGGING_CONTEXT(source_->flow_id()); - do { - int64_t time_until_process_ms = TimeUntilNextProcess(modules_); - int64_t time_until_feedback_ms = time_ms; - if (!feedbacks.empty()) - time_until_feedback_ms = std::max( - feedbacks.front()->send_time_ms() - clock_.TimeInMilliseconds(), 0); - - int64_t time_until_next_event_ms = - std::min(time_until_feedback_ms, time_until_process_ms); - - time_until_next_event_ms = - std::min(source_->GetTimeUntilNextFrameMs(), time_until_next_event_ms); - - // Never run for longer than we have been asked for. - if (clock_.TimeInMilliseconds() + time_until_next_event_ms > end_time_ms) - time_until_next_event_ms = end_time_ms - clock_.TimeInMilliseconds(); - - // Make sure we don't get stuck if an event doesn't trigger. This typically - // happens if the prober wants to probe, but there's no packet to send. - if (time_until_next_event_ms == 0 && last_run_time_ms == 0) - time_until_next_event_ms = 1; - last_run_time_ms = time_until_next_event_ms; - - Packets generated_packets; - source_->RunFor(time_until_next_event_ms, &generated_packets); - if (!generated_packets.empty()) { - for (Packet* packet : generated_packets) { - MediaPacket* media_packet = static_cast(packet); - pacer_->InsertPacket( - PacedSender::kNormalPriority, media_packet->header().ssrc, - media_packet->header().sequenceNumber, media_packet->send_time_ms(), - media_packet->payload_size(), false); - pacer_queue_size_in_bytes_ += media_packet->payload_size(); - pacer_queue_.push_back(packet); - assert(pacer_queue_.size() < 10000); - } - } - - clock_.AdvanceTimeMilliseconds(time_until_next_event_ms); - - if (time_until_next_event_ms == time_until_feedback_ms) { - if (!feedbacks.empty()) { - bwe_->GiveFeedback(*feedbacks.front()); - delete feedbacks.front(); - feedbacks.pop_front(); - } - bwe_->Process(); - } - - if (time_until_next_event_ms == time_until_process_ms) { - CallProcess(modules_); - } - } while (clock_.TimeInMilliseconds() < end_time_ms); - QueuePackets(in_out, end_time_ms * 1000); -} - -int64_t PacedVideoSender::TimeUntilNextProcess( - const std::list& modules) { - int64_t time_until_next_process_ms = 10; - for (Module* module : modules) { - int64_t next_process_ms = module->TimeUntilNextProcess(); - if (next_process_ms < time_until_next_process_ms) - time_until_next_process_ms = next_process_ms; - } - if (time_until_next_process_ms < 0) - time_until_next_process_ms = 0; - return time_until_next_process_ms; -} - -void PacedVideoSender::CallProcess(const std::list& modules) { - for (Module* module : modules) { - if (module->TimeUntilNextProcess() <= 0) { - module->Process(); - } - } -} - -void PacedVideoSender::QueuePackets(Packets* batch, - int64_t end_of_batch_time_us) { - queue_.merge(*batch, DereferencingComparator); - if (queue_.empty()) { - return; - } - Packets::iterator it = queue_.begin(); - for (; it != queue_.end(); ++it) { - if ((*it)->send_time_us() > end_of_batch_time_us) { - break; - } - } - Packets to_transfer; - to_transfer.splice(to_transfer.begin(), queue_, queue_.begin(), it); - bwe_->OnPacketsSent(to_transfer); - batch->merge(to_transfer, DereferencingComparator); -} - -RtpPacketSendResult PacedVideoSender::TimeToSendPacket( - uint32_t ssrc, - uint16_t sequence_number, - int64_t capture_time_ms, - bool retransmission, - const PacedPacketInfo& pacing_info) { - for (Packets::iterator it = pacer_queue_.begin(); it != pacer_queue_.end(); - ++it) { - MediaPacket* media_packet = static_cast(*it); - if (media_packet->header().sequenceNumber == sequence_number) { - int64_t pace_out_time_ms = clock_.TimeInMilliseconds(); - - // Make sure a packet is never paced out earlier than when it was put into - // the pacer. - RTC_CHECK_GE(pace_out_time_ms, media_packet->send_time_ms()); - media_packet->SetAbsSendTimeMs(pace_out_time_ms); - media_packet->set_send_time_us(1000 * pace_out_time_ms); - media_packet->set_sender_timestamp_us(1000 * pace_out_time_ms); - queue_.push_back(media_packet); - pacer_queue_size_in_bytes_ -= media_packet->payload_size(); - pacer_queue_.erase(it); - return RtpPacketSendResult::kSuccess; - } - } - return RtpPacketSendResult::kTransportUnavailable; -} - -size_t PacedVideoSender::TimeToSendPadding(size_t bytes, - const PacedPacketInfo& pacing_info) { - return 0; -} - -void PacedVideoSender::OnNetworkChanged(uint32_t target_bitrate_bps, - uint8_t fraction_lost, - int64_t rtt) { - VideoSender::OnNetworkChanged(target_bitrate_bps, fraction_lost, rtt); - pacer_->SetPacingRates(target_bitrate_bps * kPaceMultiplier, 0); -} - -void PacedVideoSender::OnNetworkChanged(uint32_t bitrate_for_encoder_bps, - uint32_t bitrate_for_pacer_bps, - bool in_probe_rtt, - int64_t target_set_time, - uint64_t congestion_window) { - VideoSender::OnNetworkChanged(bitrate_for_encoder_bps, 0u, 0u); - pacer_->SetEstimatedBitrateAndCongestionWindow( - bitrate_for_pacer_bps, in_probe_rtt, congestion_window); -} - -size_t PacedVideoSender::pacer_queue_size_in_bytes() { - return pacer_queue_size_in_bytes_; -} - -void PacedVideoSender::OnBytesAcked(size_t bytes) { - pacer_->OnBytesAcked(bytes); -} - -const int kNoLimit = std::numeric_limits::max(); -const int kPacketSizeBytes = 1200; - -TcpSender::TcpSender(PacketProcessorListener* listener, - int flow_id, - int64_t offset_ms) - : TcpSender(listener, flow_id, offset_ms, kNoLimit) {} - -TcpSender::TcpSender(PacketProcessorListener* listener, - int flow_id, - int64_t offset_ms, - int send_limit_bytes) - : PacketSender(listener, flow_id), - cwnd_(10), - ssthresh_(kNoLimit), - ack_received_(false), - last_acked_seq_num_(0), - next_sequence_number_(0), - offset_ms_(offset_ms), - last_reduction_time_ms_(-1), - last_rtt_ms_(0), - total_sent_bytes_(0), - send_limit_bytes_(send_limit_bytes), - last_generated_packets_ms_(0), - num_recent_sent_packets_(0), - bitrate_kbps_(0) {} - -TcpSender::~TcpSender() = default; - -void TcpSender::RunFor(int64_t time_ms, Packets* in_out) { - if (clock_.TimeInMilliseconds() + time_ms < offset_ms_) { - clock_.AdvanceTimeMilliseconds(time_ms); - if (running_) { - Pause(); - } - return; - } - - if (!running_ && total_sent_bytes_ == 0) { - Resume(offset_ms_); - } - - int64_t start_time_ms = clock_.TimeInMilliseconds(); - - std::list feedbacks = GetFeedbackPackets( - in_out, clock_.TimeInMilliseconds() + time_ms, *flow_ids().begin()); - // The number of packets which are sent in during time_ms depends on the - // number of packets in_flight_ and the max number of packets in flight - // (cwnd_). Therefore SendPackets() isn't directly dependent on time_ms. - for (FeedbackPacket* fb : feedbacks) { - clock_.AdvanceTimeMilliseconds(fb->send_time_ms() - - clock_.TimeInMilliseconds()); - last_rtt_ms_ = fb->send_time_ms() - fb->latest_send_time_ms(); - UpdateCongestionControl(fb); - SendPackets(in_out); - } - - for (auto it = in_flight_.begin(); it != in_flight_.end();) { - if (it->time_ms < clock_.TimeInMilliseconds() - 1000) - in_flight_.erase(it++); - else - ++it; - } - - clock_.AdvanceTimeMilliseconds(time_ms - - (clock_.TimeInMilliseconds() - start_time_ms)); - SendPackets(in_out); -} - -int TcpSender::GetFeedbackIntervalMs() const { - return 10; -} - -void TcpSender::SendPackets(Packets* in_out) { - int cwnd = std::ceil(cwnd_); - int packets_to_send = std::max(cwnd - static_cast(in_flight_.size()), 0); - int timed_out = TriggerTimeouts(); - if (timed_out > 0) { - HandleLoss(); - } - if (packets_to_send > 0) { - Packets generated = GeneratePackets(packets_to_send); - for (Packet* packet : generated) - in_flight_.insert(InFlight(*static_cast(packet))); - - in_out->merge(generated, DereferencingComparator); - } -} - -void TcpSender::UpdateCongestionControl(const FeedbackPacket* fb) { - const TcpFeedback* tcp_fb = static_cast(fb); - RTC_DCHECK(!tcp_fb->acked_packets().empty()); - ack_received_ = true; - - uint16_t expected = tcp_fb->acked_packets().back() - last_acked_seq_num_; - uint16_t missing = - expected - static_cast(tcp_fb->acked_packets().size()); - - for (uint16_t ack_seq_num : tcp_fb->acked_packets()) - in_flight_.erase(InFlight(ack_seq_num, clock_.TimeInMilliseconds())); - - if (missing > 0) { - HandleLoss(); - } else if (cwnd_ <= ssthresh_) { - cwnd_ += tcp_fb->acked_packets().size(); - } else { - cwnd_ += 1.0f / cwnd_; - } - - last_acked_seq_num_ = - LatestSequenceNumber(tcp_fb->acked_packets().back(), last_acked_seq_num_); -} - -int TcpSender::TriggerTimeouts() { - int timed_out = 0; - for (auto it = in_flight_.begin(); it != in_flight_.end();) { - if (it->time_ms < clock_.TimeInMilliseconds() - 1000) { - in_flight_.erase(it++); - ++timed_out; - } else { - ++it; - } - } - return timed_out; -} - -void TcpSender::HandleLoss() { - if (clock_.TimeInMilliseconds() - last_reduction_time_ms_ < last_rtt_ms_) - return; - last_reduction_time_ms_ = clock_.TimeInMilliseconds(); - ssthresh_ = std::max(static_cast(in_flight_.size() / 2), 2); - cwnd_ = ssthresh_; -} - -Packets TcpSender::GeneratePackets(size_t num_packets) { - Packets generated; - - UpdateSendBitrateEstimate(num_packets); - - for (size_t i = 0; i < num_packets; ++i) { - if ((total_sent_bytes_ + kPacketSizeBytes) > send_limit_bytes_) { - if (running_) { - Pause(); - } - break; - } - generated.push_back( - new MediaPacket(*flow_ids().begin(), 1000 * clock_.TimeInMilliseconds(), - kPacketSizeBytes, next_sequence_number_++)); - generated.back()->set_sender_timestamp_us(1000 * - clock_.TimeInMilliseconds()); - - total_sent_bytes_ += kPacketSizeBytes; - } - - return generated; -} - -void TcpSender::UpdateSendBitrateEstimate(size_t num_packets) { - const int kTimeWindowMs = 500; - num_recent_sent_packets_ += num_packets; - - int64_t delta_ms = clock_.TimeInMilliseconds() - last_generated_packets_ms_; - if (delta_ms >= kTimeWindowMs) { - bitrate_kbps_ = - static_cast(8 * num_recent_sent_packets_ * kPacketSizeBytes) / - delta_ms; - last_generated_packets_ms_ = clock_.TimeInMilliseconds(); - num_recent_sent_packets_ = 0; - } - - RecordBitrate(); -} - -uint32_t TcpSender::TargetBitrateKbps() { - return bitrate_kbps_; -} - -} // namespace bwe -} // namespace testing -} // namespace webrtc diff --git a/modules/remote_bitrate_estimator/test/packet_sender.h b/modules/remote_bitrate_estimator/test/packet_sender.h deleted file mode 100644 index 085ceab381..0000000000 --- a/modules/remote_bitrate_estimator/test/packet_sender.h +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (c) 2015 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. - */ - -#ifndef MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_PACKET_SENDER_H_ -#define MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_PACKET_SENDER_H_ - -#include -#include -#include -#include -#include - -#include "modules/include/module.h" -#include "modules/remote_bitrate_estimator/test/bwe.h" -#include "modules/remote_bitrate_estimator/test/bwe_test_framework.h" -#include "rtc_base/constructor_magic.h" - -namespace webrtc { -namespace testing { -namespace bwe { - -class MetricRecorder; - -class PacketSender : public PacketProcessor { - public: - PacketSender(PacketProcessorListener* listener, int flow_id) - : PacketProcessor(listener, flow_id, kSender), - running_(true), - // For Packet::send_time_us() to be comparable with timestamps from - // clock_, the clock of the PacketSender and the Source must be aligned. - // We assume that both start at time 0. - clock_(0), - metric_recorder_(nullptr) {} - ~PacketSender() override {} - // Call GiveFeedback() with the returned interval in milliseconds, provided - // there is a new estimate available. - // Note that changing the feedback interval affects the timing of when the - // output of the estimators is sampled and therefore the baseline files may - // have to be regenerated. - virtual int GetFeedbackIntervalMs() const = 0; - void SetSenderTimestamps(Packets* in_out); - - virtual uint32_t TargetBitrateKbps(); - - virtual void Pause(); - virtual void Resume(int64_t paused_time_ms); - - void set_metric_recorder(MetricRecorder* metric_recorder); - virtual void RecordBitrate(); - - protected: - bool running_; // Initialized by default as true. - SimulatedClock clock_; - - private: - MetricRecorder* metric_recorder_; -}; - -class VideoSender : public PacketSender, public BitrateObserver { - public: - VideoSender(PacketProcessorListener* listener, - VideoSource* source, - BandwidthEstimatorType estimator); - ~VideoSender() override; - - int GetFeedbackIntervalMs() const override; - void RunFor(int64_t time_ms, Packets* in_out) override; - - virtual VideoSource* source() const; - - uint32_t TargetBitrateKbps() override; - - // Implements BitrateObserver. - void OnNetworkChanged(uint32_t target_bitrate_bps, - uint8_t fraction_lost, - int64_t rtt) override; - void Pause() override; - void Resume(int64_t paused_time_ms) override; - - protected: - void ProcessFeedbackAndGeneratePackets(int64_t time_ms, - std::list* feedbacks, - Packets* generated); - - VideoSource* source_; - std::unique_ptr bwe_; - int64_t start_of_run_ms_; - std::list modules_; - - private: - uint32_t previous_sending_bitrate_; - RTC_DISALLOW_COPY_AND_ASSIGN(VideoSender); -}; - -class PacedVideoSender : public VideoSender, public PacedSender::PacketSender { - public: - PacedVideoSender(PacketProcessorListener* listener, - VideoSource* source, - BandwidthEstimatorType estimator); - ~PacedVideoSender() override; - - void RunFor(int64_t time_ms, Packets* in_out) override; - - // Implements PacedSender::Callback. - RtpPacketSendResult TimeToSendPacket( - uint32_t ssrc, - uint16_t sequence_number, - int64_t capture_time_ms, - bool retransmission, - const PacedPacketInfo& pacing_info) override; - size_t TimeToSendPadding(size_t bytes, - const PacedPacketInfo& pacing_info) override; - - // Implements BitrateObserver. - void OnNetworkChanged(uint32_t target_bitrate_bps, - uint8_t fraction_lost, - int64_t rtt) override; - - void OnNetworkChanged(uint32_t bitrate_for_encoder_bps, - uint32_t bitrate_for_pacer_bps, - bool in_probe_rtt, - int64_t rtt, - uint64_t congestion_window) override; - size_t pacer_queue_size_in_bytes() override; - void OnBytesAcked(size_t bytes) override; - - private: - int64_t TimeUntilNextProcess(const std::list& modules); - void CallProcess(const std::list& modules); - void QueuePackets(Packets* batch, int64_t end_of_batch_time_us); - - size_t pacer_queue_size_in_bytes_ = 0; - std::unique_ptr pacer_; - Packets queue_; - Packets pacer_queue_; - - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(PacedVideoSender); -}; - -class TcpSender : public PacketSender { - public: - TcpSender(PacketProcessorListener* listener, int flow_id, int64_t offset_ms); - TcpSender(PacketProcessorListener* listener, - int flow_id, - int64_t offset_ms, - int send_limit_bytes); - ~TcpSender() override; - - void RunFor(int64_t time_ms, Packets* in_out) override; - int GetFeedbackIntervalMs() const override; - - uint32_t TargetBitrateKbps() override; - - private: - struct InFlight { - public: - explicit InFlight(const MediaPacket& packet) - : sequence_number(packet.header().sequenceNumber), - time_ms(packet.send_time_ms()) {} - - InFlight(uint16_t seq_num, int64_t now_ms) - : sequence_number(seq_num), time_ms(now_ms) {} - - bool operator<(const InFlight& rhs) const { - return sequence_number < rhs.sequence_number; - } - - uint16_t sequence_number; // Sequence number of a packet in flight, or a - // packet which has just been acked. - int64_t time_ms; // Time of when the packet left the sender, or when the - // ack was received. - }; - - void SendPackets(Packets* in_out); - void UpdateCongestionControl(const FeedbackPacket* fb); - int TriggerTimeouts(); - void HandleLoss(); - Packets GeneratePackets(size_t num_packets); - void UpdateSendBitrateEstimate(size_t num_packets); - - float cwnd_; - int ssthresh_; - std::set in_flight_; - bool ack_received_; - uint16_t last_acked_seq_num_; - uint16_t next_sequence_number_; - int64_t offset_ms_; - int64_t last_reduction_time_ms_; - int64_t last_rtt_ms_; - int total_sent_bytes_; - int send_limit_bytes_; // Initialized by default as kNoLimit. - int64_t last_generated_packets_ms_; - size_t num_recent_sent_packets_; - uint32_t bitrate_kbps_; -}; -} // namespace bwe -} // namespace testing -} // namespace webrtc -#endif // MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_PACKET_SENDER_H_ diff --git a/modules/remote_bitrate_estimator/test/plot_bars.sh b/modules/remote_bitrate_estimator/test/plot_bars.sh deleted file mode 100755 index 9f7fb16203..0000000000 --- a/modules/remote_bitrate_estimator/test/plot_bars.sh +++ /dev/null @@ -1,286 +0,0 @@ -#!/bin/bash - -# Copyright (c) 2013 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. - -# To set up in e.g. Eclipse, run a separate shell and pipe the output from the -# test into this script. -# -# In Eclipse, that amounts to creating a Run Configuration which starts -# "/bin/bash" with the arguments "-c [trunk_path]/out/Debug/modules_unittests -# --gtest_filter=*BweTest* | [trunk_path]/webrtc/modules/ -# remote_bitrate_estimator/test/plot_bars.sh - -# This script supports multiple figures (windows), the figure is specified as an -# identifier at the first argument after the PLOT command. Each figure has a -# single y axis and a dual y axis mode. If any line specifies an axis by ending -# with "#" two y axis will be used, the first will be -# assumed to represent bitrate (in kbps) and the second will be assumed to -# represent time deltas (in ms). - -log=$( "1" )); then - tcp_flow=true - box_width=$(echo "(1.0-$tcp_space/2)/$num_flows" | bc -l) - echo "set xtics font 'Verdana,16'" - x_labels="(" - delimiter="" - abscissa=$(echo $x_start + 0.5 + 0.5*$box_width | bc) - for label in "${split_label_1[@]}" ; do - x_labels+="$delimiter'$label' $abscissa" - abscissa=$(echo $abscissa + $box_width | bc) - delimiter=", " - done - abscissa=$(echo $abscissa + $tcp_space | bc) - IFS='x' read -ra split_label_2 <<< "$x_label_2" - for label in "${split_label_2[@]}" ; do - x_labels+="$delimiter'$label' $abscissa" - abscissa=$(echo $abscissa + $box_width | bc) - done - x_labels="$x_labels)" - else - box_width=$(echo 1.0/$num_flows | bc -l) - fi - - echo "set boxwidth $box_width" - - # Plots can be directly exported to image files. - file_name=$(echo "$labels" | grep "^LABEL.$figure" | cut -f 5 | head -n 1) - - y_max=0 # Used to scale the plot properly. - - # Scale all latency plots with the same vertical scale. - delay_figure=5 - if (( $figure==$delay_figure )) ; then - y_max=400 - else # Take y_max = 1.1 * highest plot value. - - # Since only the optimal bitrate for the first flow is being ploted, - # consider only this one for scalling purposes. - data_sets=$(echo "$bars" | grep "LIMITERRORBAR.$figure" | cut -f 3 | \ - sed 's/_/\t/g' | cut -f 1 | sort | uniq) - - if (( ${#data_sets[@]} > "0" )); then - for set in $data_sets ; do - y=$(echo "$bars" | grep "LIMITERRORBAR.$figure.$set" | cut -f 8 | \ - head -n 1) - if (( $(bc <<< "$y > $y_max") == 1 )); then - y_max=$y - fi - done - fi - - data_sets=$(echo "$bars" | grep "ERRORBAR.$figure" | cut -f 3 | \ - sort | uniq) - if (( ${#data_sets[@]} > "0" )); then - for set in $data_sets ; do - y=$(echo "$bars" | grep "ERRORBAR.$figure.$set" | cut -f 6 | \ - head -n 1) - if (( $(bc <<< "$y > $y_max") == 1 )) ; then - y_max=$y - fi - done - fi - - data_sets=$(echo "$bars" | grep "BAR.$figure" | cut -f 3 | sort | uniq) - - for set in $data_sets ; do - y=$(echo "$bars" | grep "BAR.$figure.$set" | cut -f 4 | head -n 1) - if (( $(bc <<< "$y > $y_max") == 1 )) ; then - y_max=$y - fi - done - - y_max=$(echo $y_max*1.1 | bc) - fi - - - echo "set ylabel \"$y_label\"" - echo "set yrange[0:$y_max]" - - echo "set multiplot" - - # Plot bars. - data_sets=$(echo "$bars" | grep "BAR.$figure" | cut -f 3 | sort | uniq) - - echo "set xtics $x_labels" - echo "plot '-' using 1:4:2 with boxes lc variable notitle" - - echo - - color=11 # Green. - x_bar=$(echo $x_start + 0.5 + 0.5*$box_width | bc) - for set in $data_sets ; do - echo -n "$x_bar $color " - echo "$bars" | grep "BAR.$figure.$set" | cut -f 3,4 - - # Add extra space if TCP flows are being plotted. - if $tcp_flow && \ - (( $(bc <<< "$x_bar < $x_start + 1.5 - 0.5*$tcp_space") == 1 )) && \ - (( $(bc <<< "$x_bar + $box_width > $x_start + 1.5 + 0.5*$tcp_space") \ - == 1 )); then - x_bar=$(echo $x_bar + $tcp_space | bc) - fi - - x_bar=$(echo $x_bar + $box_width | bc) - - if (( $(bc <<< "$x_bar > 2.5") == 1 )) ; then - color=12 # Blue. - fi - # Different bar color for TCP flows: - if $tcp_flow && \ - (( $(bc <<< "(100*$x_bar)%100 < 50") == 1 )) - then - color=18 # Gray. - fi - done - echo "e" - - # Plot Baseline bars, e.g. one-way path delay on latency plots. - data_sets=$(echo "$log" | grep "BASELINE.$figure" | cut -f 3 | sort | uniq) - - if (( ${#data_sets} > "0" )); then - echo "set xtics $x_labels" - echo "plot '-' using 1:4:2 with boxes lc variable notitle" - - echo - - color=18 # Gray. - x_bar=$(echo $x_start + 0.5 + 0.5*$box_width | bc) - for set in $data_sets ; do - echo -n "$x_bar $color " - echo "$log" | grep "BASELINE.$figure.$set" | cut -f 3,4 - - # Add extra space if TCP flows are being plotted. - if $tcp_flow && \ - (( $(bc <<< "$x_bar < $x_start + 1.5 - 0.5*$tcp_space") == 1 )) && \ - (( $(bc <<< "$x_bar + $box_width > $x_start + 1.5 \ - + 0.5*$tcp_space") == 1 )); then - x_bar=$(echo $x_bar + $tcp_space | bc) - fi - - x_bar=$(echo $x_bar + $box_width | bc) - - done - echo "e" - fi - - # Plot vertical error lines, e.g. y +- sigma. - data_sets=$(echo "$bars" | grep "ERRORBAR.$figure" | cut -f 3 | sort | uniq) - - if (( ${#data_sets} > "0" )); then - - echo "set key left" - error_title=$(echo "$bars" | grep "ERRORBAR.$figure" | cut -f 7 | \ - head -n 1 | sed 's/_/ /g') - - echo "set xtics $x_labels" - echo "plot '-' using 1:3:4:5 title '$error_title' with yerr" - - x_error_line=$(echo $x_start + 0.5 + 0.5*$box_width | bc) - for set in $data_sets ; do - echo -n "$x_error_line " - echo "$bars" | grep "ERRORBAR.$figure.$set" | cut -f 3,4,5,6 - - # Add extra space if TCP flows are being plotted. - if $tcp_flow && \ - (( $(bc <<< "$x_error_line < $x_start + 1.5 - 0.5*$tcp_space") == 1 \ - )) && (( $(bc <<< "$x_error_line + $box_width > $x_start + 1.5 \ - + 0.5*$tcp_space") == 1 )); then - x_error_line=$(echo $x_error_line + $tcp_space | bc) - fi - - x_error_line=$(echo $x_error_line + $box_width | bc) - done - echo "e" - fi - - # Plot horizontal dashed lines, e.g. y = optimal bitrate. - data_sets=$(echo "$bars" | grep "LIMITERRORBAR.$figure" | cut -f 3 \ - | sort | uniq) - if (( ${#data_sets} > "0" )); then - - echo "set style line 1 lt 1 lw 3 pt 3 ps 0 linecolor rgb 'black'" - - limit_titles=$(echo "$bars" | grep "LIMITERRORBAR.$figure" | cut -f 9 \ - | sort | uniq) - - for title in $limit_titles ; do - y_max=$(echo "$bars" | grep "LIMITERRORBAR.$figure" | grep "$title" \ - | cut -f 8 | head -n 1) - - retouched_title=$(echo "$title" | sed 's/#/\t/g' | cut -f 1 \ - | sed 's/_/ /g') - - echo "set key right top" - echo "set xtics $x_labels" - echo "plot $y_max lt 7 lw 1 linecolor rgb 'black' \ - title '$retouched_title'" - done - - fi - - echo "unset multiplot" - done -} - -gen_gnuplot_bar_input | gnuplot -persist diff --git a/modules/remote_bitrate_estimator/test/plot_dynamics.py b/modules/remote_bitrate_estimator/test/plot_dynamics.py deleted file mode 100755 index e5180634cb..0000000000 --- a/modules/remote_bitrate_estimator/test/plot_dynamics.py +++ /dev/null @@ -1,182 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2015 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. - -# This script is used to plot simulation dynamics. The expected format is -# PLOT :@