diff --git a/resources/voice_engine/audio_dtx16.wav.sha1 b/resources/voice_engine/audio_dtx16.wav.sha1 new file mode 100644 index 0000000000..6a552c2953 --- /dev/null +++ b/resources/voice_engine/audio_dtx16.wav.sha1 @@ -0,0 +1 @@ +cafd7151d6b7b4313d0bd2a128a31fc83bca7aa3 \ No newline at end of file diff --git a/webrtc/BUILD.gn b/webrtc/BUILD.gn index e057ebe415..a4cc0eed0d 100644 --- a/webrtc/BUILD.gn +++ b/webrtc/BUILD.gn @@ -496,6 +496,7 @@ if (rtc_include_tests) { configs += [ ":rtc_unittests_config" ] deps = [ + "audio:audio_perf_tests", "call:call_perf_tests", "modules/audio_coding:audio_coding_perf_tests", "modules/audio_processing:audio_processing_perf_tests", diff --git a/webrtc/audio/BUILD.gn b/webrtc/audio/BUILD.gn index 5296f1fa82..4fc7337691 100644 --- a/webrtc/audio/BUILD.gn +++ b/webrtc/audio/BUILD.gn @@ -113,6 +113,8 @@ if (rtc_include_tests) { "../test:fake_audio_device", "../test:test_common", "../test:test_main", + "//testing/gmock", + "//testing/gtest", "//third_party/gflags", ] if (is_android) { @@ -122,6 +124,7 @@ if (rtc_include_tests) { data = [ "../../resources/voice_engine/audio_tiny16.wav", "../../resources/voice_engine/audio_tiny48.wav", + "../../resources/voice_engine/audio_dtx16.wav", ] if (!build_with_chromium && is_clang) { @@ -130,4 +133,40 @@ if (rtc_include_tests) { } } } + + rtc_source_set("audio_perf_tests") { + testonly = true + + # Skip restricting visibility on mobile platforms since the tests on those + # gets additional generated targets which would require many lines here to + # cover (which would be confusing to read and hard to maintain). + if (!is_android && !is_ios) { + visibility = [ "//webrtc:webrtc_perf_tests" ] + } + sources = [ + "test/audio_bwe_integration_test.cc", + "test/audio_bwe_integration_test.h", + ] + deps = [ + "../base:rtc_base_approved", + "../common_audio", + "../system_wrappers", + "../test:fake_audio_device", + "../test:field_trial", + "../test:test_common", + "../test:test_main", + "//testing/gmock", + "//testing/gtest", + "//third_party/gflags", + ] + + data = [ + "//resources/voice_engine/audio_dtx16.wav", + ] + + if (!build_with_chromium && is_clang) { + # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163). + suppressed_configs += [ "//build/config/clang:find_bad_constructs" ] + } + } } diff --git a/webrtc/audio/test/audio_bwe_integration_test.cc b/webrtc/audio/test/audio_bwe_integration_test.cc new file mode 100644 index 0000000000..d3f7f0bba7 --- /dev/null +++ b/webrtc/audio/test/audio_bwe_integration_test.cc @@ -0,0 +1,151 @@ +/* + * 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 "webrtc/audio/test/audio_bwe_integration_test.h" + +#include "webrtc/common_audio/wav_file.h" +#include "webrtc/rtc_base/ptr_util.h" +#include "webrtc/system_wrappers/include/sleep.h" +#include "webrtc/test/field_trial.h" +#include "webrtc/test/gtest.h" +#include "webrtc/test/testsupport/fileutils.h" + +namespace webrtc { +namespace test { + +namespace { +// Wait a second between stopping sending and stopping receiving audio. +constexpr int kExtraProcessTimeMs = 1000; +} // namespace + +AudioBweTest::AudioBweTest() : EndToEndTest(CallTest::kDefaultTimeoutMs) {} + +size_t AudioBweTest::GetNumVideoStreams() const { + return 0; +} +size_t AudioBweTest::GetNumAudioStreams() const { + return 1; +} +size_t AudioBweTest::GetNumFlexfecStreams() const { + return 0; +} + +std::unique_ptr +AudioBweTest::CreateCapturer() { + return test::FakeAudioDevice::CreateWavFileReader(AudioInputFile()); +} + +void AudioBweTest::OnFakeAudioDevicesCreated( + test::FakeAudioDevice* send_audio_device, + test::FakeAudioDevice* recv_audio_device) { + send_audio_device_ = send_audio_device; +} + +test::PacketTransport* AudioBweTest::CreateSendTransport(Call* sender_call) { + return new test::PacketTransport( + sender_call, this, test::PacketTransport::kSender, + test::CallTest::payload_type_map_, GetNetworkPipeConfig()); +} + +test::PacketTransport* AudioBweTest::CreateReceiveTransport() { + return new test::PacketTransport( + nullptr, this, test::PacketTransport::kReceiver, + test::CallTest::payload_type_map_, GetNetworkPipeConfig()); +} + +void AudioBweTest::PerformTest() { + send_audio_device_->WaitForRecordingEnd(); + SleepMs(GetNetworkPipeConfig().queue_delay_ms + kExtraProcessTimeMs); +} + +class StatsPollTask : public rtc::QueuedTask { + public: + explicit StatsPollTask(Call* sender_call) : sender_call_(sender_call) {} + + private: + bool Run() override { + RTC_CHECK(sender_call_); + Call::Stats call_stats = sender_call_->GetStats(); + EXPECT_GT(call_stats.send_bandwidth_bps, 25000); + rtc::TaskQueue::Current()->PostDelayedTask( + std::unique_ptr(this), 100); + return false; + } + Call* sender_call_; +}; + +class NoBandwidthDropAfterDtx : public AudioBweTest { + public: + NoBandwidthDropAfterDtx() + : sender_call_(nullptr), stats_poller_("stats poller task queue") {} + + void ModifyAudioConfigs( + AudioSendStream::Config* send_config, + std::vector* receive_configs) override { + send_config->send_codec_spec = + rtc::Optional( + {test::CallTest::kAudioSendPayloadType, + {"OPUS", + 48000, + 2, + {{"ptime", "60"}, {"usedtx", "1"}, {"stereo", "1"}}}}); + + send_config->min_bitrate_bps = 6000; + send_config->max_bitrate_bps = 100000; + send_config->rtp.extensions.push_back( + RtpExtension(RtpExtension::kTransportSequenceNumberUri, + kTransportSequenceNumberExtensionId)); + for (AudioReceiveStream::Config& recv_config : *receive_configs) { + recv_config.rtp.transport_cc = true; + recv_config.rtp.extensions = send_config->rtp.extensions; + recv_config.rtp.remote_ssrc = send_config->rtp.ssrc; + } + } + + std::string AudioInputFile() override { + return test::ResourcePath("voice_engine/audio_dtx16", "wav"); + } + + FakeNetworkPipe::Config GetNetworkPipeConfig() override { + FakeNetworkPipe::Config pipe_config; + pipe_config.link_capacity_kbps = 50; + pipe_config.queue_length_packets = 1500; + pipe_config.queue_delay_ms = 300; + return pipe_config; + } + + void OnCallsCreated(Call* sender_call, Call* receiver_call) override { + sender_call_ = sender_call; + } + + void PerformTest() override { + stats_poller_.PostDelayedTask( + std::unique_ptr(new StatsPollTask(sender_call_)), 100); + sender_call_->OnTransportOverheadChanged(webrtc::MediaType::AUDIO, 0); + AudioBweTest::PerformTest(); + } + + private: + Call* sender_call_; + rtc::TaskQueue stats_poller_; +}; + +using AudioBweIntegrationTest = CallTest; + +TEST_F(AudioBweIntegrationTest, NoBandwidthDropAfterDtx) { + webrtc::test::ScopedFieldTrials override_field_trials( + "WebRTC-Audio-SendSideBwe/Enabled/" + "WebRTC-SendSideBwe-WithOverhead/Enabled/"); + NoBandwidthDropAfterDtx test; + RunBaseTest(&test); +} + +} // namespace test +} // namespace webrtc diff --git a/webrtc/audio/test/audio_bwe_integration_test.h b/webrtc/audio/test/audio_bwe_integration_test.h new file mode 100644 index 0000000000..769603aca9 --- /dev/null +++ b/webrtc/audio/test/audio_bwe_integration_test.h @@ -0,0 +1,53 @@ +/* + * 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 WEBRTC_AUDIO_TEST_AUDIO_BWE_INTEGRATION_TEST_H_ +#define WEBRTC_AUDIO_TEST_AUDIO_BWE_INTEGRATION_TEST_H_ + +#include +#include + +#include "webrtc/test/call_test.h" +#include "webrtc/test/fake_audio_device.h" + +namespace webrtc { +namespace test { + +class AudioBweTest : public test::EndToEndTest { + public: + AudioBweTest(); + + protected: + virtual std::string AudioInputFile() = 0; + + virtual FakeNetworkPipe::Config GetNetworkPipeConfig() = 0; + + size_t GetNumVideoStreams() const override; + size_t GetNumAudioStreams() const override; + size_t GetNumFlexfecStreams() const override; + + std::unique_ptr CreateCapturer() override; + + void OnFakeAudioDevicesCreated( + test::FakeAudioDevice* send_audio_device, + test::FakeAudioDevice* recv_audio_device) override; + + test::PacketTransport* CreateSendTransport(Call* sender_call) override; + test::PacketTransport* CreateReceiveTransport() override; + + void PerformTest() override; + + private: + test::FakeAudioDevice* send_audio_device_; +}; + +} // namespace test +} // namespace webrtc + +#endif // WEBRTC_AUDIO_TEST_AUDIO_BWE_INTEGRATION_TEST_H_ diff --git a/webrtc/modules/congestion_controller/BUILD.gn b/webrtc/modules/congestion_controller/BUILD.gn index dbfd56b445..c3ee11fd54 100644 --- a/webrtc/modules/congestion_controller/BUILD.gn +++ b/webrtc/modules/congestion_controller/BUILD.gn @@ -10,8 +10,10 @@ import("../../webrtc.gni") rtc_static_library("congestion_controller") { sources = [ - "acknowledge_bitrate_estimator.cc", - "acknowledge_bitrate_estimator.h", + "acknowledged_bitrate_estimator.cc", + "acknowledged_bitrate_estimator.h", + "bitrate_estimator.cc", + "bitrate_estimator.h", "congestion_controller.cc", "delay_based_bwe.cc", "delay_based_bwe.h", @@ -73,6 +75,7 @@ if (rtc_include_tests) { visibility = [ "..:modules_unittests" ] } sources = [ + "acknowledged_bitrate_estimator_unittest.cc", "congestion_controller_unittest.cc", "congestion_controller_unittests_helper.cc", "congestion_controller_unittests_helper.h", @@ -90,6 +93,7 @@ if (rtc_include_tests) { ":mock_congestion_controller", "../../base:rtc_base", "../../base:rtc_base_approved", + "../../base:rtc_base_tests_utils", "../../system_wrappers:system_wrappers", "../../test:field_trial", "../../test:test_support", diff --git a/webrtc/modules/congestion_controller/acknowledged_bitrate_estimator.cc b/webrtc/modules/congestion_controller/acknowledged_bitrate_estimator.cc new file mode 100644 index 0000000000..b150734df1 --- /dev/null +++ b/webrtc/modules/congestion_controller/acknowledged_bitrate_estimator.cc @@ -0,0 +1,63 @@ +/* + * 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 "webrtc/modules/congestion_controller/acknowledged_bitrate_estimator.h" + +#include + +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" +#include "webrtc/rtc_base/ptr_util.h" + +namespace webrtc { + +namespace { +bool IsInSendTimeHistory(const PacketFeedback& packet) { + return packet.send_time_ms >= 0; +} +} // namespace + +AcknowledgedBitrateEstimator::AcknowledgedBitrateEstimator() + : AcknowledgedBitrateEstimator(rtc::MakeUnique()) {} + +AcknowledgedBitrateEstimator::AcknowledgedBitrateEstimator( + std::unique_ptr bitrate_estimator) + : bitrate_estimator_(std::move(bitrate_estimator)) {} + +void AcknowledgedBitrateEstimator::IncomingPacketFeedbackVector( + const std::vector& packet_feedback_vector) { + RTC_DCHECK(std::is_sorted(packet_feedback_vector.begin(), + packet_feedback_vector.end(), + PacketFeedbackComparator())); + for (const auto& packet : packet_feedback_vector) { + if (IsInSendTimeHistory(packet)) { + MaybeExpectFastRateChange(packet.send_time_ms); + bitrate_estimator_->Update(packet.arrival_time_ms, packet.payload_size); + } + } +} + +rtc::Optional AcknowledgedBitrateEstimator::bitrate_bps() const { + return bitrate_estimator_->bitrate_bps(); +} + +void AcknowledgedBitrateEstimator::SetAlrEndedTimeMs( + int64_t alr_ended_time_ms) { + alr_ended_time_ms_.emplace(alr_ended_time_ms); +} + +void AcknowledgedBitrateEstimator::MaybeExpectFastRateChange( + int64_t packet_send_time_ms) { + if (alr_ended_time_ms_ && packet_send_time_ms > *alr_ended_time_ms_) { + bitrate_estimator_->ExpectFastRateChange(); + alr_ended_time_ms_.reset(); + } +} + +} // namespace webrtc diff --git a/webrtc/modules/congestion_controller/acknowledged_bitrate_estimator.h b/webrtc/modules/congestion_controller/acknowledged_bitrate_estimator.h new file mode 100644 index 0000000000..bab5d93ce5 --- /dev/null +++ b/webrtc/modules/congestion_controller/acknowledged_bitrate_estimator.h @@ -0,0 +1,44 @@ +/* + * 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 WEBRTC_MODULES_CONGESTION_CONTROLLER_ACKNOWLEDGED_BITRATE_ESTIMATOR_H_ +#define WEBRTC_MODULES_CONGESTION_CONTROLLER_ACKNOWLEDGED_BITRATE_ESTIMATOR_H_ + +#include +#include + +#include "webrtc/modules/congestion_controller/bitrate_estimator.h" +#include "webrtc/rtc_base/optional.h" + +namespace webrtc { + +struct PacketFeedback; + +class AcknowledgedBitrateEstimator { + public: + explicit AcknowledgedBitrateEstimator( + std::unique_ptr bitrate_estimator); + + AcknowledgedBitrateEstimator(); + + void IncomingPacketFeedbackVector( + const std::vector& packet_feedback_vector); + rtc::Optional bitrate_bps() const; + void SetAlrEndedTimeMs(int64_t alr_ended_time_ms); + + private: + void MaybeExpectFastRateChange(int64_t packet_arrival_time_ms); + rtc::Optional alr_ended_time_ms_; + std::unique_ptr bitrate_estimator_; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_CONGESTION_CONTROLLER_ACKNOWLEDGED_BITRATE_ESTIMATOR_H_ diff --git a/webrtc/modules/congestion_controller/acknowledged_bitrate_estimator_unittest.cc b/webrtc/modules/congestion_controller/acknowledged_bitrate_estimator_unittest.cc new file mode 100644 index 0000000000..70ce0c1d01 --- /dev/null +++ b/webrtc/modules/congestion_controller/acknowledged_bitrate_estimator_unittest.cc @@ -0,0 +1,134 @@ +/* + * 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 "webrtc/modules/congestion_controller/acknowledged_bitrate_estimator.h" + +#include + +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" +#include "webrtc/rtc_base/fakeclock.h" +#include "webrtc/rtc_base/ptr_util.h" +#include "webrtc/test/gmock.h" +#include "webrtc/test/gtest.h" + +using testing::_; +using testing::NiceMock; +using testing::InSequence; +using testing::Return; + +namespace webrtc { + +namespace { + +constexpr int64_t kFirstArrivalTimeMs = 10; +constexpr int64_t kFirstSendTimeMs = 10; +constexpr uint16_t kSequenceNumber = 1; +constexpr size_t kPayloadSize = 10; + +class MockBitrateEstimator : public BitrateEstimator { + public: + MOCK_METHOD2(Update, void(int64_t now_ms, int bytes)); + MOCK_CONST_METHOD0(bitrate_bps, rtc::Optional()); + MOCK_METHOD0(ExpectFastRateChange, void()); +}; + +struct AcknowledgedBitrateEstimatorTestStates { + std::unique_ptr acknowledged_bitrate_estimator; + MockBitrateEstimator* mock_bitrate_estimator; +}; + +AcknowledgedBitrateEstimatorTestStates CreateTestStates() { + AcknowledgedBitrateEstimatorTestStates states; + auto mock_bitrate_estimator = rtc::MakeUnique(); + states.mock_bitrate_estimator = mock_bitrate_estimator.get(); + states.acknowledged_bitrate_estimator = + rtc::MakeUnique( + std::move(mock_bitrate_estimator)); + return states; +} + +std::vector CreateFeedbackVector() { + std::vector packet_feedback_vector; + const PacedPacketInfo pacing_info; + packet_feedback_vector.push_back( + PacketFeedback(kFirstArrivalTimeMs, kFirstSendTimeMs, kSequenceNumber, + kPayloadSize, pacing_info)); + packet_feedback_vector.push_back( + PacketFeedback(kFirstArrivalTimeMs + 10, kFirstSendTimeMs + 10, + kSequenceNumber, kPayloadSize + 10, pacing_info)); + return packet_feedback_vector; +} + +} // anonymous namespace + +TEST(TestAcknowledgedBitrateEstimator, DontAddPacketsWhichAreNotInSendHistory) { + auto states = CreateTestStates(); + std::vector packet_feedback_vector; + packet_feedback_vector.push_back( + PacketFeedback(kFirstArrivalTimeMs, kSequenceNumber)); + EXPECT_CALL(*states.mock_bitrate_estimator, Update(_, _)).Times(0); + states.acknowledged_bitrate_estimator->IncomingPacketFeedbackVector( + packet_feedback_vector); +} + +TEST(TestAcknowledgedBitrateEstimator, UpdateBandwith) { + auto states = CreateTestStates(); + auto packet_feedback_vector = CreateFeedbackVector(); + { + InSequence dummy; + EXPECT_CALL( + *states.mock_bitrate_estimator, + Update(packet_feedback_vector[0].arrival_time_ms, + static_cast(packet_feedback_vector[0].payload_size))) + .Times(1); + EXPECT_CALL( + *states.mock_bitrate_estimator, + Update(packet_feedback_vector[1].arrival_time_ms, + static_cast(packet_feedback_vector[1].payload_size))) + .Times(1); + } + states.acknowledged_bitrate_estimator->IncomingPacketFeedbackVector( + packet_feedback_vector); +} + +TEST(TestAcknowledgedBitrateEstimator, ExpectFastRateChangeWhenLeftAlr) { + auto states = CreateTestStates(); + auto packet_feedback_vector = CreateFeedbackVector(); + { + InSequence dummy; + EXPECT_CALL( + *states.mock_bitrate_estimator, + Update(packet_feedback_vector[0].arrival_time_ms, + static_cast(packet_feedback_vector[0].payload_size))) + .Times(1); + EXPECT_CALL(*states.mock_bitrate_estimator, ExpectFastRateChange()) + .Times(1); + EXPECT_CALL( + *states.mock_bitrate_estimator, + Update(packet_feedback_vector[1].arrival_time_ms, + static_cast(packet_feedback_vector[1].payload_size))) + .Times(1); + } + states.acknowledged_bitrate_estimator->SetAlrEndedTimeMs(kFirstArrivalTimeMs + + 1); + states.acknowledged_bitrate_estimator->IncomingPacketFeedbackVector( + packet_feedback_vector); +} + +TEST(TestAcknowledgedBitrateEstimator, ReturnBitrate) { + auto states = CreateTestStates(); + rtc::Optional return_value(42); + EXPECT_CALL(*states.mock_bitrate_estimator, bitrate_bps()) + .Times(1) + .WillOnce(Return(return_value)); + EXPECT_EQ(return_value, states.acknowledged_bitrate_estimator->bitrate_bps()); +} + +} // namespace webrtc*/ diff --git a/webrtc/modules/congestion_controller/acknowledge_bitrate_estimator.cc b/webrtc/modules/congestion_controller/bitrate_estimator.cc similarity index 75% rename from webrtc/modules/congestion_controller/acknowledge_bitrate_estimator.cc rename to webrtc/modules/congestion_controller/bitrate_estimator.cc index 3fa3ac9995..1627bf84be 100644 --- a/webrtc/modules/congestion_controller/acknowledge_bitrate_estimator.cc +++ b/webrtc/modules/congestion_controller/bitrate_estimator.cc @@ -8,7 +8,7 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "webrtc/modules/congestion_controller/acknowledge_bitrate_estimator.h" +#include "webrtc/modules/congestion_controller/bitrate_estimator.h" #include @@ -20,32 +20,18 @@ namespace webrtc { namespace { constexpr int kInitialRateWindowMs = 500; constexpr int kRateWindowMs = 150; - -bool IsInSendTimeHistory(const PacketFeedback& packet) { - return packet.send_time_ms >= 0; -} - } // namespace -AcknowledgedBitrateEstimator::AcknowledgedBitrateEstimator() +BitrateEstimator::BitrateEstimator() : sum_(0), current_win_ms_(0), prev_time_ms_(-1), bitrate_estimate_(-1.0f), bitrate_estimate_var_(50.0f) {} -void AcknowledgedBitrateEstimator::IncomingPacketFeedbackVector( - const std::vector& packet_feedback_vector) { - RTC_DCHECK(std::is_sorted(packet_feedback_vector.begin(), - packet_feedback_vector.end(), - PacketFeedbackComparator())); - for (const auto& packet : packet_feedback_vector) { - if (IsInSendTimeHistory(packet)) - Update(packet.arrival_time_ms, packet.payload_size); - } -} +BitrateEstimator::~BitrateEstimator() = default; -void AcknowledgedBitrateEstimator::Update(int64_t now_ms, int bytes) { +void BitrateEstimator::Update(int64_t now_ms, int bytes) { int rate_window_ms = kRateWindowMs; // We use a larger window at the beginning to get a more stable sample that // we can use to initialize the estimate. @@ -78,9 +64,9 @@ void AcknowledgedBitrateEstimator::Update(int64_t now_ms, int bytes) { bitrate_estimate_ * 1000); } -float AcknowledgedBitrateEstimator::UpdateWindow(int64_t now_ms, - int bytes, - int rate_window_ms) { +float BitrateEstimator::UpdateWindow(int64_t now_ms, + int bytes, + int rate_window_ms) { // Reset if time moves backwards. if (now_ms < prev_time_ms_) { prev_time_ms_ = -1; @@ -106,10 +92,16 @@ float AcknowledgedBitrateEstimator::UpdateWindow(int64_t now_ms, return bitrate_sample; } -rtc::Optional AcknowledgedBitrateEstimator::bitrate_bps() const { +rtc::Optional BitrateEstimator::bitrate_bps() const { if (bitrate_estimate_ < 0.f) return rtc::Optional(); return rtc::Optional(bitrate_estimate_ * 1000); } +void BitrateEstimator::ExpectFastRateChange() { + // By setting the bitrate-estimate variance to a higher value we allow the + // bitrate to change fast for the next few samples. + bitrate_estimate_var_ += 200; +} + } // namespace webrtc diff --git a/webrtc/modules/congestion_controller/acknowledge_bitrate_estimator.h b/webrtc/modules/congestion_controller/bitrate_estimator.h similarity index 67% rename from webrtc/modules/congestion_controller/acknowledge_bitrate_estimator.h rename to webrtc/modules/congestion_controller/bitrate_estimator.h index 0bc2dacf03..f27d0630ef 100644 --- a/webrtc/modules/congestion_controller/acknowledge_bitrate_estimator.h +++ b/webrtc/modules/congestion_controller/bitrate_estimator.h @@ -8,8 +8,8 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_MODULES_CONGESTION_CONTROLLER_ACKNOWLEDGE_BITRATE_ESTIMATOR_H_ -#define WEBRTC_MODULES_CONGESTION_CONTROLLER_ACKNOWLEDGE_BITRATE_ESTIMATOR_H_ +#ifndef WEBRTC_MODULES_CONGESTION_CONTROLLER_BITRATE_ESTIMATOR_H_ +#define WEBRTC_MODULES_CONGESTION_CONTROLLER_BITRATE_ESTIMATOR_H_ #include @@ -17,25 +17,23 @@ namespace webrtc { -struct PacketFeedback; - // Computes a bayesian estimate of the throughput given acks containing // the arrival time and payload size. Samples which are far from the current // estimate or are based on few packets are given a smaller weight, as they // are considered to be more likely to have been caused by, e.g., delay spikes // unrelated to congestion. -class AcknowledgedBitrateEstimator { +class BitrateEstimator { public: - AcknowledgedBitrateEstimator(); + BitrateEstimator(); + virtual ~BitrateEstimator(); + virtual void Update(int64_t now_ms, int bytes); - void IncomingPacketFeedbackVector( - const std::vector& packet_feedback_vector); - rtc::Optional bitrate_bps() const; + virtual rtc::Optional bitrate_bps() const; + + virtual void ExpectFastRateChange(); private: - void Update(int64_t now_ms, int bytes); float UpdateWindow(int64_t now_ms, int bytes, int rate_window_ms); - int sum_; int64_t current_win_ms_; int64_t prev_time_ms_; @@ -45,4 +43,4 @@ class AcknowledgedBitrateEstimator { } // namespace webrtc -#endif // WEBRTC_MODULES_CONGESTION_CONTROLLER_ACKNOWLEDGE_BITRATE_ESTIMATOR_H_ +#endif // WEBRTC_MODULES_CONGESTION_CONTROLLER_BITRATE_ESTIMATOR_H_ diff --git a/webrtc/modules/congestion_controller/delay_based_bwe_unittest_helper.h b/webrtc/modules/congestion_controller/delay_based_bwe_unittest_helper.h index 4e9c21ceb2..2210a2e95e 100644 --- a/webrtc/modules/congestion_controller/delay_based_bwe_unittest_helper.h +++ b/webrtc/modules/congestion_controller/delay_based_bwe_unittest_helper.h @@ -17,7 +17,7 @@ #include #include -#include "webrtc/modules/congestion_controller/acknowledge_bitrate_estimator.h" +#include "webrtc/modules/congestion_controller/acknowledged_bitrate_estimator.h" #include "webrtc/modules/congestion_controller/delay_based_bwe.h" #include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h" #include "webrtc/rtc_base/constructormagic.h" diff --git a/webrtc/modules/congestion_controller/include/send_side_congestion_controller.h b/webrtc/modules/congestion_controller/include/send_side_congestion_controller.h index 7a8f362c31..6bebf238ff 100644 --- a/webrtc/modules/congestion_controller/include/send_side_congestion_controller.h +++ b/webrtc/modules/congestion_controller/include/send_side_congestion_controller.h @@ -154,6 +154,7 @@ class SendSideCongestionController : public CallStatsObserver, rtc::CriticalSection bwe_lock_; int min_bitrate_bps_ GUARDED_BY(bwe_lock_); std::unique_ptr delay_based_bwe_ GUARDED_BY(bwe_lock_); + bool was_in_alr_; rtc::RaceChecker worker_race_; diff --git a/webrtc/modules/congestion_controller/send_side_congestion_controller.cc b/webrtc/modules/congestion_controller/send_side_congestion_controller.cc index 60e692ccdf..5328161e08 100644 --- a/webrtc/modules/congestion_controller/send_side_congestion_controller.cc +++ b/webrtc/modules/congestion_controller/send_side_congestion_controller.cc @@ -15,14 +15,16 @@ #include #include "webrtc/modules/bitrate_controller/include/bitrate_controller.h" -#include "webrtc/modules/congestion_controller/acknowledge_bitrate_estimator.h" +#include "webrtc/modules/congestion_controller/acknowledged_bitrate_estimator.h" #include "webrtc/modules/congestion_controller/probe_controller.h" +#include "webrtc/modules/pacing/alr_detector.h" #include "webrtc/modules/remote_bitrate_estimator/include/bwe_defines.h" #include "webrtc/rtc_base/checks.h" #include "webrtc/rtc_base/logging.h" #include "webrtc/rtc_base/ptr_util.h" #include "webrtc/rtc_base/rate_limiter.h" #include "webrtc/rtc_base/socket.h" +#include "webrtc/rtc_base/timeutils.h" namespace webrtc { namespace { @@ -99,7 +101,8 @@ SendSideCongestionController::SendSideCongestionController( last_reported_rtt_(0), network_state_(kNetworkUp), min_bitrate_bps_(congestion_controller::GetMinBitrateBps()), - delay_based_bwe_(new DelayBasedBwe(event_log_, clock_)) { + delay_based_bwe_(new DelayBasedBwe(event_log_, clock_)), + was_in_alr_(0) { delay_based_bwe_->SetMinBitrate(min_bitrate_bps_); } @@ -277,6 +280,14 @@ void SendSideCongestionController::OnTransportFeedback( std::vector feedback_vector = ReceivedPacketFeedbackVector( transport_feedback_adapter_.GetTransportFeedbackVector()); SortPacketFeedbackVector(&feedback_vector); + + bool currently_in_alr = + pacer_->GetApplicationLimitedRegionStartTime().has_value(); + if (!currently_in_alr && was_in_alr_) { + acknowledged_bitrate_estimator_->SetAlrEndedTimeMs(rtc::TimeMillis()); + } + was_in_alr_ = currently_in_alr; + acknowledged_bitrate_estimator_->IncomingPacketFeedbackVector( feedback_vector); DelayBasedBwe::Result result; diff --git a/webrtc/modules/pacing/alr_detector.h b/webrtc/modules/pacing/alr_detector.h index 11eeceaa98..7e630970e6 100644 --- a/webrtc/modules/pacing/alr_detector.h +++ b/webrtc/modules/pacing/alr_detector.h @@ -27,7 +27,6 @@ namespace webrtc { // AlrDetector provides a signal that can be utilized to adjust // estimate bandwidth. // Note: This class is not thread-safe. - class AlrDetector { public: AlrDetector(); @@ -57,8 +56,8 @@ class AlrDetector { // kAlrEndUsagePercent. NOTE: This is intentionally conservative at the moment // until BW adjustments of application limited region is fine tuned. static constexpr int kDefaultAlrBandwidthUsagePercent = 65; - static constexpr int kDefaultAlrStartBudgetLevelPercent = 20; - static constexpr int kDefaultAlrStopBudgetLevelPercent = -20; + static constexpr int kDefaultAlrStartBudgetLevelPercent = 80; + static constexpr int kDefaultAlrStopBudgetLevelPercent = 50; static const char* kScreenshareProbingBweExperimentName; void UpdateBudgetWithElapsedTime(int64_t delta_time_ms); diff --git a/webrtc/modules/pacing/alr_detector_unittest.cc b/webrtc/modules/pacing/alr_detector_unittest.cc index e1a78103df..9f1998b617 100644 --- a/webrtc/modules/pacing/alr_detector_unittest.cc +++ b/webrtc/modules/pacing/alr_detector_unittest.cc @@ -86,7 +86,7 @@ TEST_F(AlrDetectorTest, AlrDetection) { // Verify that we ALR starts when bitrate drops below 20%. SimulateOutgoingTrafficIn(&alr_detector_) - .ForTimeMs(1000) + .ForTimeMs(1500) .AtPercentOfEstimatedBitrate(20); EXPECT_TRUE(alr_detector_.GetApplicationLimitedRegionStartTime()); @@ -109,7 +109,7 @@ TEST_F(AlrDetectorTest, ShortSpike) { // Verify that we stay in ALR region even after a short bitrate spike. SimulateOutgoingTrafficIn(&alr_detector_) - .ForTimeMs(200) + .ForTimeMs(100) .AtPercentOfEstimatedBitrate(150); EXPECT_TRUE(alr_detector_.GetApplicationLimitedRegionStartTime()); diff --git a/webrtc/modules/remote_bitrate_estimator/test/estimators/send_side.h b/webrtc/modules/remote_bitrate_estimator/test/estimators/send_side.h index d2aa8de930..ed6a7cdee8 100644 --- a/webrtc/modules/remote_bitrate_estimator/test/estimators/send_side.h +++ b/webrtc/modules/remote_bitrate_estimator/test/estimators/send_side.h @@ -15,7 +15,7 @@ #include #include "webrtc/logging/rtc_event_log/mock/mock_rtc_event_log.h" -#include "webrtc/modules/congestion_controller/acknowledge_bitrate_estimator.h" +#include "webrtc/modules/congestion_controller/acknowledged_bitrate_estimator.h" #include "webrtc/modules/remote_bitrate_estimator/include/send_time_history.h" #include "webrtc/modules/remote_bitrate_estimator/test/bwe.h"