From 07bc7344595e9cb3a3039eaffcb7a3ec2ca72928 Mon Sep 17 00:00:00 2001 From: "andresp@webrtc.org" Date: Fri, 21 Mar 2014 16:51:01 +0000 Subject: [PATCH] Refactor in BitrateController module. - Move condition of 0 bps as max meaning 1gbps from SendSideBandwidthEstimation to BitrateController. - Remove condition on bitrate=0 meaning bandwidth estimation off as that could only happen when no observers existed and in which case the estimation would be ignored. - Add MaybeTriggerOnNetworkChanged which only runs rate allocation if any of the dependent variables has changed thus allowing to remove many of the bool returns that try to indicate if the estimation has changed which would not be aware if the observers have changed. - SendSideBandwidthEstimation now has a UpdateBitrate and has clear code paths to which calls update bitrate. - Changes in enforce_min_bitrate so the 10kbps min is set from the BitrateController and not from the outside this keep valid as observers are changed. R=henrik.lundin@webrtc.org, stefan@webrtc.org BUG=3065 Review URL: https://webrtc-codereview.appspot.com/10189004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@5752 4adac7df-926f-26a2-2b94-8c16560cd09d --- .../bitrate_controller_impl.cc | 84 ++++-- .../bitrate_controller_impl.h | 10 +- .../bitrate_controller_unittest.cc | 44 ++-- .../include/bitrate_controller.h | 4 - .../send_side_bandwidth_estimation.cc | 241 ++++++++---------- .../send_side_bandwidth_estimation.h | 41 +-- webrtc/video_engine/vie_encoder.cc | 1 - 7 files changed, 204 insertions(+), 221 deletions(-) diff --git a/webrtc/modules/bitrate_controller/bitrate_controller_impl.cc b/webrtc/modules/bitrate_controller/bitrate_controller_impl.cc index 381040646..d777536b9 100644 --- a/webrtc/modules/bitrate_controller/bitrate_controller_impl.cc +++ b/webrtc/modules/bitrate_controller/bitrate_controller_impl.cc @@ -132,22 +132,39 @@ void BitrateControllerImpl::SetBitrateObserver( // Add new settings. bitrate_observers_.push_back(BitrateObserverConfiguration(observer, new BitrateConfiguration(start_bitrate, min_bitrate, max_bitrate))); + bitrate_observers_modified_ = true; + + // TODO(andresp): This is a ugly way to set start bitrate. + // + // Only change start bitrate if we have exactly one observer. By definition + // you can only have one start bitrate, once we have our first estimate we + // will adapt from there. + if (bitrate_observers_.size() == 1) { + bandwidth_estimation_.SetSendBitrate(start_bitrate); + } } + + UpdateMinMaxBitrate(); +} + +void BitrateControllerImpl::UpdateMinMaxBitrate() { uint32_t sum_start_bitrate = 0; uint32_t sum_min_bitrate = 0; uint32_t sum_max_bitrate = 0; - - // Summarize all configurations. + BitrateObserverConfList::iterator it; for (it = bitrate_observers_.begin(); it != bitrate_observers_.end(); ++it) { sum_start_bitrate += it->second->start_bitrate_; sum_min_bitrate += it->second->min_bitrate_; sum_max_bitrate += it->second->max_bitrate_; } - // Only change start bitrate if we have exactly one observer. By definition - // you can only have one start bitrate, once we have our first estimate we - // will adapt from there. - if (bitrate_observers_.size() == 1) { - bandwidth_estimation_.SetSendBitrate(sum_start_bitrate); + if (sum_max_bitrate == 0) { + // No max configured use 1Gbit/s. + sum_max_bitrate = 1000000000; + } + if (enforce_min_bitrate_ == false) { + // If not enforcing min bitrate, allow the bandwidth estimation to + // go as low as 10 kbps. + sum_min_bitrate = std::min(sum_min_bitrate, 10000u); } bandwidth_estimation_.SetMinMaxBitrate(sum_min_bitrate, sum_max_bitrate); @@ -160,30 +177,20 @@ void BitrateControllerImpl::RemoveBitrateObserver(BitrateObserver* observer) { if (it != bitrate_observers_.end()) { delete it->second; bitrate_observers_.erase(it); + bitrate_observers_modified_ = true; } } void BitrateControllerImpl::EnforceMinBitrate(bool enforce_min_bitrate) { CriticalSectionScoped cs(critsect_); enforce_min_bitrate_ = enforce_min_bitrate; -} - -void BitrateControllerImpl::SetBweMinBitrate(uint32_t min_bitrate) { - CriticalSectionScoped cs(critsect_); - bandwidth_estimation_.SetMinBitrate(min_bitrate); + UpdateMinMaxBitrate(); } void BitrateControllerImpl::OnReceivedEstimatedBitrate(const uint32_t bitrate) { - uint32_t new_bitrate = 0; - uint8_t fraction_lost = 0; - uint16_t rtt = 0; CriticalSectionScoped cs(critsect_); - if (bandwidth_estimation_.UpdateBandwidthEstimate(bitrate, - &new_bitrate, - &fraction_lost, - &rtt)) { - OnNetworkChanged(new_bitrate, fraction_lost, rtt); - } + bandwidth_estimation_.UpdateReceiverEstimate(bitrate); + MaybeTriggerOnNetworkChanged(); } void BitrateControllerImpl::OnReceivedRtcpReceiverReport( @@ -191,12 +198,27 @@ void BitrateControllerImpl::OnReceivedRtcpReceiverReport( const uint32_t rtt, const int number_of_packets, const uint32_t now_ms) { - uint32_t new_bitrate = 0; - uint8_t loss = fraction_loss; CriticalSectionScoped cs(critsect_); - if (bandwidth_estimation_.UpdatePacketLoss(number_of_packets, rtt, now_ms, - &loss, &new_bitrate)) { - OnNetworkChanged(new_bitrate, loss, rtt); + bandwidth_estimation_.UpdateReceiverBlock( + fraction_loss, rtt, number_of_packets, now_ms); + MaybeTriggerOnNetworkChanged(); +} + +void BitrateControllerImpl::MaybeTriggerOnNetworkChanged() { + uint32_t bitrate; + uint8_t fraction_loss; + 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_ || + last_enforce_min_bitrate_ != enforce_min_bitrate_) { + last_bitrate_ = bitrate; + last_fraction_loss_ = fraction_loss; + last_rtt_ = rtt; + last_enforce_min_bitrate_ = enforce_min_bitrate_; + bitrate_observers_modified_ = false; + OnNetworkChanged(bitrate, fraction_loss, rtt); } } @@ -289,7 +311,15 @@ void BitrateControllerImpl::LowRateAllocation(uint32_t bitrate, bool BitrateControllerImpl::AvailableBandwidth(uint32_t* bandwidth) const { CriticalSectionScoped cs(critsect_); - return bandwidth_estimation_.AvailableBandwidth(bandwidth); + uint32_t bitrate; + uint8_t fraction_loss; + uint32_t rtt; + bandwidth_estimation_.CurrentEstimate(&bitrate, &fraction_loss, &rtt); + if (bitrate) { + *bandwidth = bitrate; + return true; + } + return false; } } // namespace webrtc diff --git a/webrtc/modules/bitrate_controller/bitrate_controller_impl.h b/webrtc/modules/bitrate_controller/bitrate_controller_impl.h index 4e4099702..f9d2354ca 100644 --- a/webrtc/modules/bitrate_controller/bitrate_controller_impl.h +++ b/webrtc/modules/bitrate_controller/bitrate_controller_impl.h @@ -45,8 +45,6 @@ class BitrateControllerImpl : public BitrateController { virtual void EnforceMinBitrate(bool enforce_min_bitrate) OVERRIDE; - virtual void SetBweMinBitrate(uint32_t min_bitrate) OVERRIDE; - private: class RtcpBandwidthObserverImpl; @@ -75,6 +73,7 @@ class BitrateControllerImpl : public BitrateController { BitrateObserverConfiguration; typedef std::list BitrateObserverConfList; + void UpdateMinMaxBitrate() EXCLUSIVE_LOCKS_REQUIRED(*critsect_); // Called by BitrateObserver's direct from the RTCP module. void OnReceivedEstimatedBitrate(const uint32_t bitrate); @@ -84,6 +83,8 @@ class BitrateControllerImpl : public BitrateController { const int number_of_packets, const uint32_t now_ms); + void MaybeTriggerOnNetworkChanged() EXCLUSIVE_LOCKS_REQUIRED(*critsect_); + void OnNetworkChanged(const uint32_t bitrate, const uint8_t fraction_loss, // 0 - 255. const uint32_t rtt) @@ -110,6 +111,11 @@ class BitrateControllerImpl : public BitrateController { 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_); + uint8_t last_fraction_loss_ GUARDED_BY(*critsect_); + uint32_t last_rtt_ GUARDED_BY(*critsect_); + bool last_enforce_min_bitrate_ GUARDED_BY(*critsect_); + bool bitrate_observers_modified_ GUARDED_BY(*critsect_); }; } // namespace webrtc #endif // WEBRTC_MODULES_BITRATE_CONTROLLER_BITRATE_CONTROLLER_IMPL_H_ diff --git a/webrtc/modules/bitrate_controller/bitrate_controller_unittest.cc b/webrtc/modules/bitrate_controller/bitrate_controller_unittest.cc index 30f85a81c..c53928b23 100644 --- a/webrtc/modules/bitrate_controller/bitrate_controller_unittest.cc +++ b/webrtc/modules/bitrate_controller/bitrate_controller_unittest.cc @@ -92,9 +92,9 @@ TEST_F(BitrateControllerTest, OneBitrateObserverOneRtcpObserver) { webrtc::ReportBlockList report_blocks; report_blocks.push_back(CreateReportBlock(1, 2, 0, 1)); bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 1); - EXPECT_EQ(0u, bitrate_observer.last_bitrate_); + EXPECT_EQ(200000u, bitrate_observer.last_bitrate_); EXPECT_EQ(0, bitrate_observer.last_fraction_loss_); - EXPECT_EQ(0u, bitrate_observer.last_rtt_); + EXPECT_EQ(50u, bitrate_observer.last_rtt_); // Test bitrate increase 8% per second. report_blocks.clear(); @@ -161,9 +161,9 @@ TEST_F(BitrateControllerTest, OneBitrateObserverTwoRtcpObservers) { bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 1); second_bandwidth_observer->OnReceivedRtcpReceiverReport( report_blocks, 100, 1); - EXPECT_EQ(0u, bitrate_observer.last_bitrate_); + EXPECT_EQ(200000u, bitrate_observer.last_bitrate_); EXPECT_EQ(0, bitrate_observer.last_fraction_loss_); - EXPECT_EQ(0u, bitrate_observer.last_rtt_); + EXPECT_EQ(100u, bitrate_observer.last_rtt_); // Test bitrate increase 8% per second. report_blocks.clear(); @@ -323,11 +323,6 @@ TEST_F(BitrateControllerTest, TwoBitrateObserversOneRtcpObserver) { webrtc::ReportBlockList report_blocks; report_blocks.push_back(CreateReportBlock(1, 2, 0, 1)); bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 1); - - // 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(100000u, bitrate_observer_1.last_bitrate_); EXPECT_EQ(0, bitrate_observer_1.last_fraction_loss_); EXPECT_EQ(50u, bitrate_observer_1.last_rtt_); @@ -336,21 +331,22 @@ TEST_F(BitrateControllerTest, TwoBitrateObserversOneRtcpObserver) { 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, 41)); - bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 2001); + 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, 61)); - bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 3001); + report_blocks.push_back(CreateReportBlock(1, 2, 0, 41)); + bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 2001); EXPECT_EQ(126000u, bitrate_observer_1.last_bitrate_); EXPECT_EQ(226000u, bitrate_observer_2.last_bitrate_); report_blocks.clear(); - report_blocks.push_back(CreateReportBlock(1, 2, 0, 81)); - bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 4001); + report_blocks.push_back(CreateReportBlock(1, 2, 0, 61)); + bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 3001); EXPECT_EQ(140580u, bitrate_observer_1.last_bitrate_); EXPECT_EQ(240580u, bitrate_observer_2.last_bitrate_); @@ -434,8 +430,12 @@ TEST_F(BitrateControllerTestNoEnforceMin, OneBitrateObserver) { EXPECT_EQ(150000u, bitrate_observer_1.last_bitrate_); // Low REMB. - bandwidth_observer_->OnReceivedEstimatedBitrate(1000); - EXPECT_EQ(1000u, bitrate_observer_1.last_bitrate_); + bandwidth_observer_->OnReceivedEstimatedBitrate(10000); + EXPECT_EQ(10000u, bitrate_observer_1.last_bitrate_); + + // Keeps at least 10 kbps. + bandwidth_observer_->OnReceivedEstimatedBitrate(9000); + EXPECT_EQ(10000u, bitrate_observer_1.last_bitrate_); controller_->RemoveBitrateObserver(&bitrate_observer_1); } @@ -469,9 +469,15 @@ TEST_F(BitrateControllerTestNoEnforceMin, ThreeBitrateObservers) { EXPECT_EQ(200000u, bitrate_observer_3.last_bitrate_); // Remainder. // Low REMB. - bandwidth_observer_->OnReceivedEstimatedBitrate(1000); + bandwidth_observer_->OnReceivedEstimatedBitrate(10000); // Verify that the first observer gets all the rate, and the rest get zero. - EXPECT_EQ(1000u, bitrate_observer_1.last_bitrate_); + EXPECT_EQ(10000u, bitrate_observer_1.last_bitrate_); + EXPECT_EQ(0u, bitrate_observer_2.last_bitrate_); + EXPECT_EQ(0u, bitrate_observer_3.last_bitrate_); + + // Verify it keeps an estimate of at least 10kbps. + bandwidth_observer_->OnReceivedEstimatedBitrate(9000); + EXPECT_EQ(10000u, bitrate_observer_1.last_bitrate_); EXPECT_EQ(0u, bitrate_observer_2.last_bitrate_); EXPECT_EQ(0u, bitrate_observer_3.last_bitrate_); diff --git a/webrtc/modules/bitrate_controller/include/bitrate_controller.h b/webrtc/modules/bitrate_controller/include/bitrate_controller.h index 3117bfd6f..0f7436765 100644 --- a/webrtc/modules/bitrate_controller/include/bitrate_controller.h +++ b/webrtc/modules/bitrate_controller/include/bitrate_controller.h @@ -73,10 +73,6 @@ class BitrateController { // Changes the mode that was set in the constructor. virtual void EnforceMinBitrate(bool enforce_min_bitrate) = 0; - - // Changes the minimum configured bitrate of the send-side bandwidth - // estimator. - virtual void SetBweMinBitrate(uint32_t min_bitrate) = 0; }; } // namespace webrtc #endif // WEBRTC_MODULES_BITRATE_CONTROLLER_INCLUDE_BITRATE_CONTROLLER_H_ diff --git a/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc b/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc index a089590bd..52eec8fe2 100644 --- a/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc +++ b/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc @@ -10,11 +10,41 @@ #include "webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h" -#include // sqrt() +#include #include "webrtc/system_wrappers/interface/trace.h" namespace webrtc { +namespace { +enum { kBweIncreaseIntervalMs = 1000 }; +enum { kBweDecreaseIntervalMs = 300 }; +enum { kLimitNumPackets = 20 }; +enum { kAvgPacketSizeBytes = 1000 }; + +// Calculate the rate that TCP-Friendly Rate Control (TFRC) would apply. +// The formula in RFC 3448, Section 3.1, is used. +uint32_t CalcTfrcBps(uint16_t rtt, uint8_t loss) { + if (rtt == 0 || loss == 0) { + // Input variables out of range. + return 0; + } + double R = static_cast(rtt) / 1000; // RTT in seconds. + int b = 1; // Number of packets acknowledged by a single TCP acknowledgement: + // recommended = 1. + double t_RTO = 4.0 * R; // TCP retransmission timeout value in seconds + // recommended = 4*R. + double p = static_cast(loss) / 255; // Packet loss rate in [0, 1). + double s = static_cast(kAvgPacketSizeBytes); + + // Calculate send rate in bytes/second. + double X = + s / (R * std::sqrt(2 * b * p / 3) + + (t_RTO * (3 * std::sqrt(3 * b * p / 8) * p * (1 + 32 * p * p)))); + + // Convert to bits/second. + return (static_cast(X * 8)); +} +} SendSideBandwidthEstimation::SendSideBandwidthEstimation() : accumulate_lost_packets_Q8_(0), @@ -30,190 +60,121 @@ SendSideBandwidthEstimation::SendSideBandwidthEstimation() SendSideBandwidthEstimation::~SendSideBandwidthEstimation() {} -void SendSideBandwidthEstimation::SetSendBitrate(const uint32_t bitrate) { +void SendSideBandwidthEstimation::SetSendBitrate(uint32_t bitrate) { bitrate_ = bitrate; } -void SendSideBandwidthEstimation::SetMinMaxBitrate(const uint32_t min_bitrate, - const uint32_t max_bitrate) { +void SendSideBandwidthEstimation::SetMinMaxBitrate(uint32_t min_bitrate, + uint32_t max_bitrate) { min_bitrate_configured_ = min_bitrate; - if (max_bitrate == 0) { - // no max configured use 1Gbit/s - max_bitrate_configured_ = 1000000000; - } else { - max_bitrate_configured_ = max_bitrate; - } + max_bitrate_configured_ = max_bitrate; } void SendSideBandwidthEstimation::SetMinBitrate(uint32_t min_bitrate) { min_bitrate_configured_ = min_bitrate; } -bool SendSideBandwidthEstimation::UpdateBandwidthEstimate( - const uint32_t bandwidth, - uint32_t* new_bitrate, - uint8_t* fraction_lost, - uint16_t* rtt) { - *new_bitrate = 0; - bwe_incoming_ = bandwidth; - - if (bitrate_ == 0) { - // SendSideBandwidthEstimation off - return false; - } - if (bwe_incoming_ > 0 && bitrate_ > bwe_incoming_) { - bitrate_ = bwe_incoming_; - *new_bitrate = bitrate_; - *fraction_lost = last_fraction_loss_; - *rtt = last_round_trip_time_; - return true; - } - return false; +void SendSideBandwidthEstimation::CurrentEstimate(uint32_t* bitrate, + uint8_t* loss, + uint32_t* rtt) const { + *bitrate = bitrate_; + *loss = last_fraction_loss_; + *rtt = last_round_trip_time_; } -bool SendSideBandwidthEstimation::UpdatePacketLoss( - const int number_of_packets, - const uint32_t rtt, - const uint32_t now_ms, - uint8_t* loss, - uint32_t* new_bitrate) { - if (bitrate_ == 0) { - // SendSideBandwidthEstimation off - return false; - } +void SendSideBandwidthEstimation::UpdateReceiverEstimate(uint32_t bandwidth) { + bwe_incoming_ = bandwidth; + CapBitrateToThresholds(); +} + +void SendSideBandwidthEstimation::UpdateReceiverBlock(uint8_t fraction_loss, + uint32_t rtt, + int number_of_packets, + uint32_t now_ms) { // Update RTT. last_round_trip_time_ = rtt; // Check sequence number diff and weight loss report if (number_of_packets > 0) { // Calculate number of lost packets. - const int num_lost_packets_Q8 = *loss * number_of_packets; + const int num_lost_packets_Q8 = fraction_loss * number_of_packets; // Accumulate reports. accumulate_lost_packets_Q8_ += num_lost_packets_Q8; accumulate_expected_packets_ += number_of_packets; // Report loss if the total report is based on sufficiently many packets. if (accumulate_expected_packets_ >= kLimitNumPackets) { - *loss = accumulate_lost_packets_Q8_ / accumulate_expected_packets_; + last_fraction_loss_ = + accumulate_lost_packets_Q8_ / accumulate_expected_packets_; - // Reset accumulators + // Reset accumulators. accumulate_lost_packets_Q8_ = 0; accumulate_expected_packets_ = 0; } else { - // Report zero loss until we have enough data to estimate - // the loss rate. - return false; + // Early return without updating estimate. + return; } } - // Keep for next time. - last_fraction_loss_ = *loss; - uint32_t bitrate = 0; - if (!ShapeSimple(*loss, rtt, now_ms, &bitrate)) { - // No change. - return false; - } - bitrate_ = bitrate; - *new_bitrate = bitrate; - return true; + UpdateEstimate(now_ms); } -bool SendSideBandwidthEstimation::AvailableBandwidth( - uint32_t* bandwidth) const { - if (bitrate_ == 0) { - return false; - } - *bandwidth = bitrate_; - return true; -} +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; -/* - * Calculate the rate that TCP-Friendly Rate Control (TFRC) would apply. - * The formula in RFC 3448, Section 3.1, is used. - */ -uint32_t SendSideBandwidthEstimation::CalcTFRCbps(uint16_t rtt, uint8_t loss) { - if (rtt == 0 || loss == 0) { - // input variables out of range - return 0; - } - double R = static_cast(rtt) / 1000; // RTT in seconds - int b = 1; // number of packets acknowledged by a single TCP acknowledgement; - // recommended = 1 - double t_RTO = 4.0 * R; // TCP retransmission timeout value in seconds - // recommended = 4*R - double p = static_cast(loss) / 255; // packet loss rate in [0, 1) - double s = static_cast(kAvgPacketSizeBytes); + // Increase rate by 8%. + bitrate_ = static_cast(bitrate_ * 1.08 + 0.5); - // calculate send rate in bytes/second - double X = s / (R * sqrt(2 * b * p / 3) + - (t_RTO * (3 * sqrt(3 * b * p / 8) * p * (1 + 32 * p * p)))); - - return (static_cast(X * 8)); // bits/second -} - -bool SendSideBandwidthEstimation::ShapeSimple(const uint8_t loss, - const uint32_t rtt, - const uint32_t now_ms, - uint32_t* bitrate) { - uint32_t new_bitrate = 0; - - // Limit the rate increases to once a kBWEIncreaseIntervalMs. - if (loss <= 5) { - if ((now_ms - time_last_increase_) < kBWEIncreaseIntervalMs) { - return false; + // 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; } - time_last_increase_ = now_ms; - } - // Limit the rate decreases to once a kBWEDecreaseIntervalMs + rtt. - if (loss > 26) { - if ((now_ms - time_last_decrease_) < kBWEDecreaseIntervalMs + rtt) { - return false; - } - time_last_decrease_ = now_ms; - } - if (loss > 5 && loss <= 26) { - // 2% - 10% - new_bitrate = bitrate_; - } else if (loss > 26) { - // 26/256 ~= 10% - // reduce rate: newRate = rate * (1 - 0.5*lossRate) - // packetLoss = 256*lossRate - new_bitrate = static_cast((bitrate_ * - static_cast(512 - loss)) / 512.0); - // Calculate what rate TFRC would apply in this situation - // scale loss to Q0 (back to [0, 255]) - uint32_t tfrc_bitrate = CalcTFRCbps(rtt, loss); - if (tfrc_bitrate > new_bitrate) { - // do not reduce further if rate is below TFRC rate - new_bitrate = tfrc_bitrate; - } + } else if (last_fraction_loss_ <= 26) { + // Loss between 2% - 10%: Do nothing. + } else { - // increase rate by 8% - new_bitrate = static_cast(bitrate_ * 1.08 + 0.5); + // 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; - // 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) - new_bitrate += 1000; + // 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_)); + } } - CapBitrateToThresholds(&new_bitrate); - *bitrate = new_bitrate; - return true; + + CapBitrateToThresholds(); } -void SendSideBandwidthEstimation::CapBitrateToThresholds( - uint32_t* new_bitrate) { - if (bwe_incoming_ > 0 && *new_bitrate > bwe_incoming_) { - *new_bitrate = bwe_incoming_; +void SendSideBandwidthEstimation::CapBitrateToThresholds() { + if (bwe_incoming_ > 0 && bitrate_ > bwe_incoming_) { + bitrate_ = bwe_incoming_; } - if (*new_bitrate > max_bitrate_configured_) { - *new_bitrate = max_bitrate_configured_; + if (bitrate_ > max_bitrate_configured_) { + bitrate_ = max_bitrate_configured_; } - if (*new_bitrate < min_bitrate_configured_) { - WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, -1, + if (bitrate_ < min_bitrate_configured_) { + WEBRTC_TRACE(kTraceWarning, + kTraceRtpRtcp, + -1, "The configured min bitrate (%u kbps) is greater than the " "estimated available bandwidth (%u kbps).\n", - min_bitrate_configured_ / 1000, *new_bitrate / 1000); - *new_bitrate = min_bitrate_configured_; + min_bitrate_configured_ / 1000, + bitrate_ / 1000); + bitrate_ = min_bitrate_configured_; } } diff --git a/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h b/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h index 79b9e2daa..9ba3a6807 100644 --- a/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h +++ b/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h @@ -22,39 +22,24 @@ class SendSideBandwidthEstimation { SendSideBandwidthEstimation(); virtual ~SendSideBandwidthEstimation(); - // Call when we receive a RTCP message with TMMBR or REMB - // Return true if new_bitrate is valid. - bool UpdateBandwidthEstimate(const uint32_t bandwidth, - uint32_t* new_bitrate, - uint8_t* fraction_lost, - uint16_t* rtt); + void CurrentEstimate(uint32_t* bitrate, uint8_t* loss, uint32_t* rtt) const; - // Call when we receive a RTCP message with a ReceiveBlock - // Return true if new_bitrate is valid. - bool UpdatePacketLoss(const int number_of_packets, - const uint32_t rtt, - const uint32_t now_ms, - uint8_t* loss, - uint32_t* new_bitrate); + // Call when we receive a RTCP message with TMMBR or REMB. + void UpdateReceiverEstimate(uint32_t bandwidth); - // Return false if no bandwidth estimate is available - bool AvailableBandwidth(uint32_t* bandwidth) const; - void SetSendBitrate(const uint32_t bitrate); - void SetMinMaxBitrate(const uint32_t min_bitrate, const uint32_t max_bitrate); + // Call when we receive a RTCP message with a ReceiveBlock. + void UpdateReceiverBlock(uint8_t fraction_loss, + uint32_t rtt, + int number_of_packets, + uint32_t now_ms); + + void SetSendBitrate(uint32_t bitrate); + void SetMinMaxBitrate(uint32_t min_bitrate, uint32_t max_bitrate); void SetMinBitrate(uint32_t min_bitrate); private: - bool ShapeSimple(const uint8_t loss, const uint32_t rtt, - const uint32_t now_ms, uint32_t* bitrate); - - void CapBitrateToThresholds(uint32_t* bitrate); - - uint32_t CalcTFRCbps(uint16_t rtt, uint8_t loss); - - enum { kBWEIncreaseIntervalMs = 1000 }; - enum { kBWEDecreaseIntervalMs = 300 }; - enum { kLimitNumPackets = 20 }; - enum { kAvgPacketSizeBytes = 1000 }; + void UpdateEstimate(uint32_t now_ms); + void CapBitrateToThresholds(); // incoming filters int accumulate_lost_packets_Q8_; diff --git a/webrtc/video_engine/vie_encoder.cc b/webrtc/video_engine/vie_encoder.cc index fd619a0ce..620972b04 100644 --- a/webrtc/video_engine/vie_encoder.cc +++ b/webrtc/video_engine/vie_encoder.cc @@ -1159,7 +1159,6 @@ int ViEEncoder::StopDebugRecording() { void ViEEncoder::SuspendBelowMinBitrate() { vcm_.SuspendBelowMinBitrate(); bitrate_controller_->EnforceMinBitrate(false); - bitrate_controller_->SetBweMinBitrate(10000); } void ViEEncoder::RegisterPreEncodeCallback(