diff --git a/webrtc/modules/bitrate_controller/bitrate_controller_impl.cc b/webrtc/modules/bitrate_controller/bitrate_controller_impl.cc index d777536b9..e31aafb77 100644 --- a/webrtc/modules/bitrate_controller/bitrate_controller_impl.cc +++ b/webrtc/modules/bitrate_controller/bitrate_controller_impl.cc @@ -78,13 +78,22 @@ class BitrateControllerImpl::RtcpBandwidthObserverImpl }; BitrateController* BitrateController::CreateBitrateController( + Clock* clock, bool enforce_min_bitrate) { - return new BitrateControllerImpl(enforce_min_bitrate); + return new BitrateControllerImpl(clock, enforce_min_bitrate); } -BitrateControllerImpl::BitrateControllerImpl(bool enforce_min_bitrate) - : critsect_(CriticalSectionWrapper::CreateCriticalSection()), - enforce_min_bitrate_(enforce_min_bitrate) {} +BitrateControllerImpl::BitrateControllerImpl(Clock* clock, + bool enforce_min_bitrate) + : clock_(clock), + last_bitrate_update_ms_(clock_->TimeInMilliseconds()), + critsect_(CriticalSectionWrapper::CreateCriticalSection()), + enforce_min_bitrate_(enforce_min_bitrate), + last_bitrate_bps_(0), + last_fraction_loss_(0), + last_rtt_ms_(0), + last_enforce_min_bitrate_(enforce_min_bitrate_), + bitrate_observers_modified_(false) {} BitrateControllerImpl::~BitrateControllerImpl() { BitrateObserverConfList::iterator it = @@ -193,6 +202,26 @@ void BitrateControllerImpl::OnReceivedEstimatedBitrate(const uint32_t bitrate) { MaybeTriggerOnNetworkChanged(); } +int32_t BitrateControllerImpl::TimeUntilNextProcess() { + enum { kBitrateControllerUpdateIntervalMs = 25 }; + CriticalSectionScoped cs(critsect_); + int time_since_update_ms = + clock_->TimeInMilliseconds() - last_bitrate_update_ms_; + return std::max(0, kBitrateControllerUpdateIntervalMs - time_since_update_ms); +} + +int32_t BitrateControllerImpl::Process() { + if (TimeUntilNextProcess() > 0) + return 0; + { + CriticalSectionScoped cs(critsect_); + bandwidth_estimation_.UpdateEstimate(clock_->TimeInMilliseconds()); + MaybeTriggerOnNetworkChanged(); + } + last_bitrate_update_ms_ = clock_->TimeInMilliseconds(); + return 0; +} + void BitrateControllerImpl::OnReceivedRtcpReceiverReport( const uint8_t fraction_loss, const uint32_t rtt, @@ -210,12 +239,12 @@ void BitrateControllerImpl::MaybeTriggerOnNetworkChanged() { uint32_t rtt; bandwidth_estimation_.CurrentEstimate(&bitrate, &fraction_loss, &rtt); - if (bitrate_observers_modified_ || bitrate != last_bitrate_ || - fraction_loss != last_fraction_loss_ || rtt != last_rtt_ || + if (bitrate_observers_modified_ || bitrate != last_bitrate_bps_ || + fraction_loss != last_fraction_loss_ || rtt != last_rtt_ms_ || last_enforce_min_bitrate_ != enforce_min_bitrate_) { - last_bitrate_ = bitrate; + last_bitrate_bps_ = bitrate; last_fraction_loss_ = fraction_loss; - last_rtt_ = rtt; + last_rtt_ms_ = rtt; last_enforce_min_bitrate_ = enforce_min_bitrate_; bitrate_observers_modified_ = false; OnNetworkChanged(bitrate, fraction_loss, rtt); diff --git a/webrtc/modules/bitrate_controller/bitrate_controller_impl.h b/webrtc/modules/bitrate_controller/bitrate_controller_impl.h index f9d2354ca..df7d28edc 100644 --- a/webrtc/modules/bitrate_controller/bitrate_controller_impl.h +++ b/webrtc/modules/bitrate_controller/bitrate_controller_impl.h @@ -29,7 +29,7 @@ namespace webrtc { class BitrateControllerImpl : public BitrateController { public: - explicit BitrateControllerImpl(bool enforce_min_bitrate); + BitrateControllerImpl(Clock* clock, bool enforce_min_bitrate); virtual ~BitrateControllerImpl(); virtual bool AvailableBandwidth(uint32_t* bandwidth) const OVERRIDE; @@ -45,6 +45,9 @@ class BitrateControllerImpl : public BitrateController { virtual void EnforceMinBitrate(bool enforce_min_bitrate) OVERRIDE; + virtual int32_t TimeUntilNextProcess() OVERRIDE; + virtual int32_t Process() OVERRIDE; + private: class RtcpBandwidthObserverImpl; @@ -107,13 +110,17 @@ class BitrateControllerImpl : public BitrateController { BitrateObserverConfList::iterator FindObserverConfigurationPair( const BitrateObserver* observer) EXCLUSIVE_LOCKS_REQUIRED(*critsect_); + // Used by process thread. + Clock* clock_; + uint32_t last_bitrate_update_ms_; + CriticalSectionWrapper* critsect_; SendSideBandwidthEstimation bandwidth_estimation_ GUARDED_BY(*critsect_); BitrateObserverConfList bitrate_observers_ GUARDED_BY(*critsect_); bool enforce_min_bitrate_ GUARDED_BY(*critsect_); - uint32_t last_bitrate_ GUARDED_BY(*critsect_); + uint32_t last_bitrate_bps_ GUARDED_BY(*critsect_); uint8_t last_fraction_loss_ GUARDED_BY(*critsect_); - uint32_t last_rtt_ GUARDED_BY(*critsect_); + uint32_t last_rtt_ms_ GUARDED_BY(*critsect_); bool last_enforce_min_bitrate_ GUARDED_BY(*critsect_); bool bitrate_observers_modified_ GUARDED_BY(*critsect_); }; diff --git a/webrtc/modules/bitrate_controller/bitrate_controller_unittest.cc b/webrtc/modules/bitrate_controller/bitrate_controller_unittest.cc index c53928b23..edfe34377 100644 --- a/webrtc/modules/bitrate_controller/bitrate_controller_unittest.cc +++ b/webrtc/modules/bitrate_controller/bitrate_controller_unittest.cc @@ -57,12 +57,12 @@ class TestBitrateObserver: public BitrateObserver { class BitrateControllerTest : public ::testing::Test { protected: - BitrateControllerTest() : enforce_min_bitrate_(true) {} + BitrateControllerTest() : clock_(0), enforce_min_bitrate_(true) {} ~BitrateControllerTest() {} virtual void SetUp() { - controller_ = - BitrateController::CreateBitrateController(enforce_min_bitrate_); + controller_ = BitrateController::CreateBitrateController( + &clock_, enforce_min_bitrate_); bandwidth_observer_ = controller_->CreateRtcpBandwidthObserver(); } @@ -70,6 +70,8 @@ class BitrateControllerTest : public ::testing::Test { delete bandwidth_observer_; delete controller_; } + + webrtc::SimulatedClock clock_; bool enforce_min_bitrate_; BitrateController* controller_; RtcpBandwidthObserver* bandwidth_observer_; @@ -87,52 +89,50 @@ TEST_F(BitrateControllerTest, OneBitrateObserverOneRtcpObserver) { // Receive a high remb, test bitrate inc. bandwidth_observer_->OnReceivedEstimatedBitrate(400000); + EXPECT_EQ(200000u, bitrate_observer.last_bitrate_); + EXPECT_EQ(0, bitrate_observer.last_fraction_loss_); + EXPECT_EQ(0u, bitrate_observer.last_rtt_); - // Test start bitrate. + // Test bitrate increase 8% per second. webrtc::ReportBlockList report_blocks; report_blocks.push_back(CreateReportBlock(1, 2, 0, 1)); bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 1); - EXPECT_EQ(200000u, bitrate_observer.last_bitrate_); + EXPECT_EQ(217000u, bitrate_observer.last_bitrate_); EXPECT_EQ(0, bitrate_observer.last_fraction_loss_); EXPECT_EQ(50u, bitrate_observer.last_rtt_); - // Test bitrate increase 8% per second. report_blocks.clear(); report_blocks.push_back(CreateReportBlock(1, 2, 0, 21)); bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 1001); - EXPECT_EQ(217000u, bitrate_observer.last_bitrate_); + EXPECT_EQ(235360u, bitrate_observer.last_bitrate_); EXPECT_EQ(0, bitrate_observer.last_fraction_loss_); EXPECT_EQ(50u, bitrate_observer.last_rtt_); report_blocks.clear(); report_blocks.push_back(CreateReportBlock(1, 2, 0, 41)); bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 2001); - EXPECT_EQ(235360u, bitrate_observer.last_bitrate_); + EXPECT_EQ(255189u, bitrate_observer.last_bitrate_); report_blocks.clear(); report_blocks.push_back(CreateReportBlock(1, 2, 0, 61)); bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 3001); - EXPECT_EQ(255189u, bitrate_observer.last_bitrate_); + EXPECT_EQ(276604u, bitrate_observer.last_bitrate_); report_blocks.clear(); report_blocks.push_back(CreateReportBlock(1, 2, 0, 801)); bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 4001); - EXPECT_EQ(276604u, bitrate_observer.last_bitrate_); + EXPECT_EQ(299732u, bitrate_observer.last_bitrate_); + // Reach max cap. report_blocks.clear(); report_blocks.push_back(CreateReportBlock(1, 2, 0, 101)); bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 5001); - EXPECT_EQ(299732u, bitrate_observer.last_bitrate_); - - report_blocks.clear(); - report_blocks.push_back(CreateReportBlock(1, 2, 0, 121)); - bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 6001); - EXPECT_EQ(300000u, bitrate_observer.last_bitrate_); // Max cap. + EXPECT_EQ(300000u, bitrate_observer.last_bitrate_); report_blocks.clear(); report_blocks.push_back(CreateReportBlock(1, 2, 0, 141)); bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 7001); - EXPECT_EQ(300000u, bitrate_observer.last_bitrate_); // Max cap. + EXPECT_EQ(300000u, bitrate_observer.last_bitrate_); // Test that a low REMB trigger immediately. bandwidth_observer_->OnReceivedEstimatedBitrate(250000); @@ -154,6 +154,9 @@ TEST_F(BitrateControllerTest, OneBitrateObserverTwoRtcpObservers) { // Receive a high remb, test bitrate inc. bandwidth_observer_->OnReceivedEstimatedBitrate(400000); + EXPECT_EQ(200000u, bitrate_observer.last_bitrate_); + EXPECT_EQ(0, bitrate_observer.last_fraction_loss_); + EXPECT_EQ(0u, bitrate_observer.last_rtt_); // Test start bitrate. webrtc::ReportBlockList report_blocks; @@ -161,7 +164,7 @@ TEST_F(BitrateControllerTest, OneBitrateObserverTwoRtcpObservers) { bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 1); second_bandwidth_observer->OnReceivedRtcpReceiverReport( report_blocks, 100, 1); - EXPECT_EQ(200000u, bitrate_observer.last_bitrate_); + EXPECT_EQ(217000u, bitrate_observer.last_bitrate_); EXPECT_EQ(0, bitrate_observer.last_fraction_loss_); EXPECT_EQ(100u, bitrate_observer.last_rtt_); @@ -171,7 +174,7 @@ TEST_F(BitrateControllerTest, OneBitrateObserverTwoRtcpObservers) { bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 501); second_bandwidth_observer->OnReceivedRtcpReceiverReport(report_blocks, 100, 1001); - EXPECT_EQ(217000u, bitrate_observer.last_bitrate_); + EXPECT_EQ(235360u, bitrate_observer.last_bitrate_); EXPECT_EQ(0, bitrate_observer.last_fraction_loss_); EXPECT_EQ(100u, bitrate_observer.last_rtt_); @@ -180,50 +183,45 @@ TEST_F(BitrateControllerTest, OneBitrateObserverTwoRtcpObservers) { report_blocks.push_back(CreateReportBlock(1, 2, 0, 31)); second_bandwidth_observer->OnReceivedRtcpReceiverReport(report_blocks, 100, 1501); - EXPECT_EQ(217000u, bitrate_observer.last_bitrate_); + EXPECT_EQ(235360u, bitrate_observer.last_bitrate_); report_blocks.clear(); report_blocks.push_back(CreateReportBlock(1, 2, 0, 41)); bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 2001); - EXPECT_EQ(235360u, bitrate_observer.last_bitrate_); + EXPECT_EQ(255189u, bitrate_observer.last_bitrate_); // Second report should not change estimate. report_blocks.clear(); report_blocks.push_back(CreateReportBlock(1, 2, 0, 41)); second_bandwidth_observer->OnReceivedRtcpReceiverReport(report_blocks, 100, 2001); - EXPECT_EQ(235360u, bitrate_observer.last_bitrate_); + EXPECT_EQ(255189u, bitrate_observer.last_bitrate_); // Reports from only one bandwidth observer is ok. report_blocks.clear(); report_blocks.push_back(CreateReportBlock(1, 2, 0, 61)); second_bandwidth_observer->OnReceivedRtcpReceiverReport(report_blocks, 50, 3001); - EXPECT_EQ(255189u, bitrate_observer.last_bitrate_); + EXPECT_EQ(276604u, bitrate_observer.last_bitrate_); report_blocks.clear(); report_blocks.push_back(CreateReportBlock(1, 2, 0, 81)); second_bandwidth_observer->OnReceivedRtcpReceiverReport(report_blocks, 50, 4001); - EXPECT_EQ(276604u, bitrate_observer.last_bitrate_); - - report_blocks.clear(); - report_blocks.push_back(CreateReportBlock(1, 2, 0, 101)); - second_bandwidth_observer->OnReceivedRtcpReceiverReport(report_blocks, 50, - 5001); EXPECT_EQ(299732u, bitrate_observer.last_bitrate_); + // Reach max cap. report_blocks.clear(); report_blocks.push_back(CreateReportBlock(1, 2, 0, 121)); - second_bandwidth_observer->OnReceivedRtcpReceiverReport(report_blocks, 50, - 6001); - EXPECT_EQ(300000u, bitrate_observer.last_bitrate_); // Max cap. + second_bandwidth_observer->OnReceivedRtcpReceiverReport( + report_blocks, 50, 5001); + EXPECT_EQ(300000u, bitrate_observer.last_bitrate_); report_blocks.clear(); report_blocks.push_back(CreateReportBlock(1, 2, 0, 141)); - second_bandwidth_observer->OnReceivedRtcpReceiverReport(report_blocks, 50, - 7001); - EXPECT_EQ(300000u, bitrate_observer.last_bitrate_); // Max cap. + second_bandwidth_observer->OnReceivedRtcpReceiverReport( + report_blocks, 50, 6001); + EXPECT_EQ(300000u, bitrate_observer.last_bitrate_); // Test that a low REMB trigger immediately. // We don't care which bandwidth observer that delivers the REMB. @@ -232,8 +230,9 @@ TEST_F(BitrateControllerTest, OneBitrateObserverTwoRtcpObservers) { EXPECT_EQ(0, bitrate_observer.last_fraction_loss_); EXPECT_EQ(50u, bitrate_observer.last_rtt_); + // Min cap. bandwidth_observer_->OnReceivedEstimatedBitrate(1000); - EXPECT_EQ(100000u, bitrate_observer.last_bitrate_); // Min cap. + EXPECT_EQ(100000u, bitrate_observer.last_bitrate_); controller_->RemoveBitrateObserver(&bitrate_observer); delete second_bandwidth_observer; } @@ -317,27 +316,24 @@ TEST_F(BitrateControllerTest, TwoBitrateObserversOneRtcpObserver) { controller_->SetBitrateObserver(&bitrate_observer_1, 200000, 100000, 300000); // Receive a high remb, test bitrate inc. - bandwidth_observer_->OnReceivedEstimatedBitrate(400000); - // Test too low start bitrate, hence lower than sum of min. + bandwidth_observer_->OnReceivedEstimatedBitrate(400000); + EXPECT_EQ(100000u, bitrate_observer_1.last_bitrate_); + EXPECT_EQ(0, bitrate_observer_1.last_fraction_loss_); + EXPECT_EQ(0u, bitrate_observer_1.last_rtt_); + + // Test bitrate increase 8% per second, distributed equally. webrtc::ReportBlockList report_blocks; report_blocks.push_back(CreateReportBlock(1, 2, 0, 1)); - bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 1); - EXPECT_EQ(100000u, bitrate_observer_1.last_bitrate_); + bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 1001); + EXPECT_EQ(112500u, bitrate_observer_1.last_bitrate_); EXPECT_EQ(0, bitrate_observer_1.last_fraction_loss_); EXPECT_EQ(50u, bitrate_observer_1.last_rtt_); - EXPECT_EQ(200000u, bitrate_observer_2.last_bitrate_); + EXPECT_EQ(212500u, bitrate_observer_2.last_bitrate_); EXPECT_EQ(0, bitrate_observer_2.last_fraction_loss_); EXPECT_EQ(50u, bitrate_observer_2.last_rtt_); - // Test bitrate increase 8% per second, distributed equally. - report_blocks.clear(); - report_blocks.push_back(CreateReportBlock(1, 2, 0, 21)); - bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 1001); - EXPECT_EQ(112500u, bitrate_observer_1.last_bitrate_); - EXPECT_EQ(212500u, bitrate_observer_2.last_bitrate_); - report_blocks.clear(); report_blocks.push_back(CreateReportBlock(1, 2, 0, 41)); bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 2001); diff --git a/webrtc/modules/bitrate_controller/include/bitrate_controller.h b/webrtc/modules/bitrate_controller/include/bitrate_controller.h index 0f7436765..1d90cb987 100644 --- a/webrtc/modules/bitrate_controller/include/bitrate_controller.h +++ b/webrtc/modules/bitrate_controller/include/bitrate_controller.h @@ -15,6 +15,7 @@ #ifndef WEBRTC_MODULES_BITRATE_CONTROLLER_INCLUDE_BITRATE_CONTROLLER_H_ #define WEBRTC_MODULES_BITRATE_CONTROLLER_INCLUDE_BITRATE_CONTROLLER_H_ +#include "webrtc/modules/interface/module.h" #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" namespace webrtc { @@ -35,7 +36,7 @@ class BitrateObserver { virtual ~BitrateObserver() {} }; -class BitrateController { +class BitrateController : public Module { /* * This class collects feedback from all streams sent to a peer (via * RTCPBandwidthObservers). It does one aggregated send side bandwidth @@ -48,7 +49,8 @@ class BitrateController { // When true, the bitrate will never be set lower than the minimum bitrate(s). // When false, the bitrate observers will be allocated rates up to their // respective minimum bitrate, satisfying one observer after the other. - static BitrateController* CreateBitrateController(bool enforce_min_bitrate); + static BitrateController* CreateBitrateController(Clock* clock, + bool enforce_min_bitrate); virtual ~BitrateController() {} virtual RtcpBandwidthObserver* CreateRtcpBandwidthObserver() = 0; diff --git a/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc b/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc index 52eec8fe2..036e04fc6 100644 --- a/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc +++ b/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc @@ -52,16 +52,20 @@ SendSideBandwidthEstimation::SendSideBandwidthEstimation() bitrate_(0), min_bitrate_configured_(0), max_bitrate_configured_(0), + time_last_receiver_block_ms_(0), last_fraction_loss_(0), - last_round_trip_time_(0), + last_round_trip_time_ms_(0), bwe_incoming_(0), - time_last_increase_(0), - time_last_decrease_(0) {} + time_last_decrease_ms_(0) {} SendSideBandwidthEstimation::~SendSideBandwidthEstimation() {} void SendSideBandwidthEstimation::SetSendBitrate(uint32_t bitrate) { bitrate_ = bitrate; + + // Clear last sent bitrate history so the new value can be used directly + // and not capped. + min_bitrate_history_.clear(); } void SendSideBandwidthEstimation::SetMinMaxBitrate(uint32_t min_bitrate, @@ -79,7 +83,7 @@ void SendSideBandwidthEstimation::CurrentEstimate(uint32_t* bitrate, uint32_t* rtt) const { *bitrate = bitrate_; *loss = last_fraction_loss_; - *rtt = last_round_trip_time_; + *rtt = last_round_trip_time_ms_; } void SendSideBandwidthEstimation::UpdateReceiverEstimate(uint32_t bandwidth) { @@ -92,7 +96,7 @@ void SendSideBandwidthEstimation::UpdateReceiverBlock(uint8_t fraction_loss, int number_of_packets, uint32_t now_ms) { // Update RTT. - last_round_trip_time_ = rtt; + last_round_trip_time_ms_ = rtt; // Check sequence number diff and weight loss report if (number_of_packets > 0) { @@ -115,50 +119,82 @@ void SendSideBandwidthEstimation::UpdateReceiverBlock(uint8_t fraction_loss, return; } } + time_last_receiver_block_ms_ = now_ms; UpdateEstimate(now_ms); } void SendSideBandwidthEstimation::UpdateEstimate(uint32_t now_ms) { - if (last_fraction_loss_ <= 5) { - // Loss < 2%: Limit the rate increases to once a kBweIncreaseIntervalMs. - if ((now_ms - time_last_increase_) >= kBweIncreaseIntervalMs) { - time_last_increase_ = now_ms; + UpdateMinHistory(now_ms); - // Increase rate by 8%. - bitrate_ = static_cast(bitrate_ * 1.08 + 0.5); + // Only start updating bitrate when receiving receiver blocks. + if (time_last_receiver_block_ms_ != 0) { + if (last_fraction_loss_ <= 5) { + // Loss < 2%: Increase rate by 8% of the min bitrate in the last + // kBweIncreaseIntervalMs. + // Note that by remembering the bitrate over the last second one can + // rampup up one second faster than if only allowed to start ramping + // at 8% per second rate now. E.g.: + // If sending a constant 100kbps it can rampup immediatly to 108kbps + // whenever a receiver report is received with lower packet loss. + // If instead one would do: bitrate_ *= 1.08^(delta time), it would + // take over one second since the lower packet loss to achieve 108kbps. + bitrate_ = static_cast( + min_bitrate_history_.front().second * 1.08 + 0.5); // Add 1 kbps extra, just to make sure that we do not get stuck // (gives a little extra increase at low rates, negligible at higher // rates). bitrate_ += 1000; - } - } else if (last_fraction_loss_ <= 26) { - // Loss between 2% - 10%: Do nothing. + } else if (last_fraction_loss_ <= 26) { + // Loss between 2% - 10%: Do nothing. - } else { - // Loss > 10%: Limit the rate decreases to once a kBweDecreaseIntervalMs + - // rtt. - if ((now_ms - time_last_decrease_) >= - static_cast(kBweDecreaseIntervalMs + last_round_trip_time_)) { - time_last_decrease_ = now_ms; + } else { + // Loss > 10%: Limit the rate decreases to once a kBweDecreaseIntervalMs + + // rtt. + if ((now_ms - time_last_decrease_ms_) >= + static_cast(kBweDecreaseIntervalMs + + last_round_trip_time_ms_)) { + time_last_decrease_ms_ = now_ms; - // Reduce rate: - // newRate = rate * (1 - 0.5*lossRate); - // where packetLoss = 256*lossRate; - bitrate_ = static_cast( - (bitrate_ * static_cast(512 - last_fraction_loss_)) / 512.0); + // Reduce rate: + // newRate = rate * (1 - 0.5*lossRate); + // where packetLoss = 256*lossRate; + bitrate_ = static_cast( + (bitrate_ * static_cast(512 - last_fraction_loss_)) / + 512.0); - // Calculate what rate TFRC would apply in this situation and to not - // reduce further than it. - bitrate_ = std::max( - bitrate_, CalcTfrcBps(last_round_trip_time_, last_fraction_loss_)); + // Calculate what rate TFRC would apply in this situation and to not + // reduce further than it. + bitrate_ = std::max( + bitrate_, + CalcTfrcBps(last_round_trip_time_ms_, last_fraction_loss_)); + } } } - CapBitrateToThresholds(); } +void SendSideBandwidthEstimation::UpdateMinHistory(uint32_t now_ms) { + // Remove old data points from history. + // Since history precision is in ms, add one so it is able to increase + // bitrate if it is off by as little as 0.5ms. + while (!min_bitrate_history_.empty() && + now_ms - min_bitrate_history_.front().first + 1 > + kBweIncreaseIntervalMs) { + min_bitrate_history_.pop_front(); + } + + // Typical minimum sliding-window algorithm: Pop values higher than current + // bitrate before pushing it. + while (!min_bitrate_history_.empty() && + bitrate_ <= min_bitrate_history_.back().second) { + min_bitrate_history_.pop_back(); + } + + min_bitrate_history_.push_back(std::make_pair(now_ms, bitrate_)); +} + void SendSideBandwidthEstimation::CapBitrateToThresholds() { if (bwe_incoming_ > 0 && bitrate_ > bwe_incoming_) { bitrate_ = bwe_incoming_; diff --git a/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h b/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h index 9ba3a6807..eb675d1ca 100644 --- a/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h +++ b/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h @@ -13,6 +13,8 @@ #ifndef WEBRTC_MODULES_BITRATE_CONTROLLER_SEND_SIDE_BANDWIDTH_ESTIMATION_H_ #define WEBRTC_MODULES_BITRATE_CONTROLLER_SEND_SIDE_BANDWIDTH_ESTIMATION_H_ +#include + #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" @@ -24,6 +26,9 @@ class SendSideBandwidthEstimation { void CurrentEstimate(uint32_t* bitrate, uint8_t* loss, uint32_t* rtt) const; + // Call periodically to update estimate. + void UpdateEstimate(uint32_t now_ms); + // Call when we receive a RTCP message with TMMBR or REMB. void UpdateReceiverEstimate(uint32_t bandwidth); @@ -38,9 +43,15 @@ class SendSideBandwidthEstimation { void SetMinBitrate(uint32_t min_bitrate); private: - void UpdateEstimate(uint32_t now_ms); void CapBitrateToThresholds(); + // Updates history of min bitrates. + // After this method returns min_bitrate_history_.front().second contains the + // min bitrate used during last kBweIncreaseIntervalMs. + void UpdateMinHistory(uint32_t now_ms); + + std::deque > min_bitrate_history_; + // incoming filters int accumulate_lost_packets_Q8_; int accumulate_expected_packets_; @@ -49,12 +60,12 @@ class SendSideBandwidthEstimation { uint32_t min_bitrate_configured_; uint32_t max_bitrate_configured_; + uint32_t time_last_receiver_block_ms_; uint8_t last_fraction_loss_; - uint16_t last_round_trip_time_; + uint16_t last_round_trip_time_ms_; uint32_t bwe_incoming_; - uint32_t time_last_increase_; - uint32_t time_last_decrease_; + uint32_t time_last_decrease_ms_; }; } // namespace webrtc #endif // WEBRTC_MODULES_BITRATE_CONTROLLER_SEND_SIDE_BANDWIDTH_ESTIMATION_H_ diff --git a/webrtc/video/video_send_stream_tests.cc b/webrtc/video/video_send_stream_tests.cc index 517225868..656bfab3e 100644 --- a/webrtc/video/video_send_stream_tests.cc +++ b/webrtc/video/video_send_stream_tests.cc @@ -1123,9 +1123,12 @@ TEST_F(VideoSendStreamTest, ProducesStats) { // indicate that it should be lowered significantly. The test then observes that // the bitrate observed is sinking well below the min-transmit-bitrate threshold // to verify that the min-transmit bitrate respects incoming REMB. +// +// Note that the test starts at "high" bitrate and does not ramp up to "higher" +// bitrate since no receiver block or remb is sent in the initial phase. TEST_F(VideoSendStreamTest, MinTransmitBitrateRespectsRemb) { static const int kMinTransmitBitrateBps = 400000; - static const int kHighBitrateBps = 200000; + static const int kHighBitrateBps = 150000; static const int kRembBitrateBps = 80000; static const int kRembRespectedBitrateBps = 100000; class BitrateObserver: public test::RtpRtcpObserver, public PacketReceiver { diff --git a/webrtc/video_engine/vie_channel_group.cc b/webrtc/video_engine/vie_channel_group.cc index 9ce52a220..7cfb44596 100644 --- a/webrtc/video_engine/vie_channel_group.cc +++ b/webrtc/video_engine/vie_channel_group.cc @@ -160,10 +160,13 @@ class WrappingBitrateEstimator : public RemoteBitrateEstimator { }; } // namespace -ChannelGroup::ChannelGroup(int engine_id, ProcessThread* process_thread, +ChannelGroup::ChannelGroup(int engine_id, + ProcessThread* process_thread, const Config* config) : remb_(new VieRemb()), - bitrate_controller_(BitrateController::CreateBitrateController(true)), + bitrate_controller_( + BitrateController::CreateBitrateController(Clock::GetRealTimeClock(), + true)), call_stats_(new CallStats()), encoder_state_feedback_(new EncoderStateFeedback()), config_(config), @@ -175,16 +178,21 @@ ChannelGroup::ChannelGroup(int engine_id, ProcessThread* process_thread, } assert(config_); // Must have a valid config pointer here. remote_bitrate_estimator_.reset( - new WrappingBitrateEstimator(engine_id, remb_.get(), - Clock::GetRealTimeClock(), process_thread, + new WrappingBitrateEstimator(engine_id, + remb_.get(), + Clock::GetRealTimeClock(), + process_thread, *config_)), - call_stats_->RegisterStatsObserver(remote_bitrate_estimator_.get()); + call_stats_->RegisterStatsObserver(remote_bitrate_estimator_.get()); + process_thread->RegisterModule(call_stats_.get()); + process_thread->RegisterModule(bitrate_controller_.get()); } ChannelGroup::~ChannelGroup() { - call_stats_->DeregisterStatsObserver(remote_bitrate_estimator_.get()); + process_thread_->DeRegisterModule(bitrate_controller_.get()); process_thread_->DeRegisterModule(call_stats_.get()); + call_stats_->DeregisterStatsObserver(remote_bitrate_estimator_.get()); assert(channels_.empty()); assert(!remb_->InUse()); }