aboutsummaryrefslogtreecommitdiff
path: root/webrtc/modules/bitrate_controller
diff options
context:
space:
mode:
Diffstat (limited to 'webrtc/modules/bitrate_controller')
-rw-r--r--webrtc/modules/bitrate_controller/bitrate_controller_impl.cc45
-rw-r--r--webrtc/modules/bitrate_controller/bitrate_controller_impl.h13
-rw-r--r--webrtc/modules/bitrate_controller/bitrate_controller_unittest.cc90
-rw-r--r--webrtc/modules/bitrate_controller/include/bitrate_controller.h6
-rw-r--r--webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc100
-rw-r--r--webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h19
6 files changed, 177 insertions, 96 deletions
diff --git a/webrtc/modules/bitrate_controller/bitrate_controller_impl.cc b/webrtc/modules/bitrate_controller/bitrate_controller_impl.cc
index d777536b96..e31aafb77d 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 f9d2354ca1..df7d28edc5 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 c53928b239..edfe343775 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.
+ // 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 too low start bitrate, hence lower than sum of min.
+ // 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 0f74367658..1d90cb9876 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 52eec8fe2d..036e04fc64 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,48 +119,80 @@ 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;
-
- // Increase rate by 8%.
- bitrate_ = static_cast<uint32_t>(bitrate_ * 1.08 + 0.5);
+ UpdateMinHistory(now_ms);
+
+ // 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<uint32_t>(
+ 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<uint32_t>(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<uint32_t>(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<uint32_t>(
+ (bitrate_ * static_cast<double>(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_ms_, last_fraction_loss_));
+ }
+ }
+ }
+ CapBitrateToThresholds();
+}
- // Reduce rate:
- // newRate = rate * (1 - 0.5*lossRate);
- // where packetLoss = 256*lossRate;
- bitrate_ = static_cast<uint32_t>(
- (bitrate_ * static_cast<double>(512 - last_fraction_loss_)) / 512.0);
+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();
+ }
- // 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_));
- }
+ // 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();
}
- CapBitrateToThresholds();
+ min_bitrate_history_.push_back(std::make_pair(now_ms, bitrate_));
}
void SendSideBandwidthEstimation::CapBitrateToThresholds() {
diff --git a/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h b/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h
index 9ba3a68078..eb675d1ca6 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 <deque>
+
#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<std::pair<uint32_t, uint32_t> > 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_