Add API to allow deducting bitrate from incoming estimates before the capacity is distributed among outgoing video streams. For example, this can be used to reserve space for audio streams.

BUG=
R=stefan@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/10499004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@5791 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/modules/bitrate_controller/bitrate_controller_impl.cc b/webrtc/modules/bitrate_controller/bitrate_controller_impl.cc
index d777536..212ac19 100644
--- a/webrtc/modules/bitrate_controller/bitrate_controller_impl.cc
+++ b/webrtc/modules/bitrate_controller/bitrate_controller_impl.cc
@@ -84,11 +84,19 @@
 
 BitrateControllerImpl::BitrateControllerImpl(bool enforce_min_bitrate)
     : critsect_(CriticalSectionWrapper::CreateCriticalSection()),
-      enforce_min_bitrate_(enforce_min_bitrate) {}
+      bandwidth_estimation_(),
+      bitrate_observers_(),
+      enforce_min_bitrate_(enforce_min_bitrate),
+      last_bitrate_(0),
+      last_fraction_loss_(0),
+      last_rtt_(0),
+      last_enforce_min_bitrate_(!enforce_min_bitrate_),
+      bitrate_observers_modified_(false),
+      last_reserved_bitrate_bps_(0),
+      reserved_bitrate_bps_(0) {}
 
 BitrateControllerImpl::~BitrateControllerImpl() {
-  BitrateObserverConfList::iterator it =
-      bitrate_observers_.begin();
+  BitrateObserverConfList::iterator it = bitrate_observers_.begin();
   while (it != bitrate_observers_.end()) {
     delete it->second;
     bitrate_observers_.erase(it);
@@ -187,6 +195,12 @@
   UpdateMinMaxBitrate();
 }
 
+void BitrateControllerImpl::SetReservedBitrate(uint32_t reserved_bitrate_bps) {
+  CriticalSectionScoped cs(critsect_);
+  reserved_bitrate_bps_ = reserved_bitrate_bps;
+  MaybeTriggerOnNetworkChanged();
+}
+
 void BitrateControllerImpl::OnReceivedEstimatedBitrate(const uint32_t bitrate) {
   CriticalSectionScoped cs(critsect_);
   bandwidth_estimation_.UpdateReceiverEstimate(bitrate);
@@ -209,10 +223,12 @@
   uint8_t fraction_loss;
   uint32_t rtt;
   bandwidth_estimation_.CurrentEstimate(&bitrate, &fraction_loss, &rtt);
+  bitrate -= std::min(bitrate, reserved_bitrate_bps_);
 
   if (bitrate_observers_modified_ || bitrate != last_bitrate_ ||
       fraction_loss != last_fraction_loss_ || rtt != last_rtt_ ||
-      last_enforce_min_bitrate_ != enforce_min_bitrate_) {
+      last_enforce_min_bitrate_ != enforce_min_bitrate_ ||
+      last_reserved_bitrate_bps_ != reserved_bitrate_bps_) {
     last_bitrate_ = bitrate;
     last_fraction_loss_ = fraction_loss;
     last_rtt_ = rtt;
@@ -316,7 +332,7 @@
   uint32_t rtt;
   bandwidth_estimation_.CurrentEstimate(&bitrate, &fraction_loss, &rtt);
   if (bitrate) {
-    *bandwidth = bitrate;
+    *bandwidth = bitrate - std::min(bitrate, reserved_bitrate_bps_);
     return true;
   }
   return false;
diff --git a/webrtc/modules/bitrate_controller/bitrate_controller_impl.h b/webrtc/modules/bitrate_controller/bitrate_controller_impl.h
index f9d2354..02b41f2 100644
--- a/webrtc/modules/bitrate_controller/bitrate_controller_impl.h
+++ b/webrtc/modules/bitrate_controller/bitrate_controller_impl.h
@@ -44,6 +44,7 @@
   virtual void RemoveBitrateObserver(BitrateObserver* observer) OVERRIDE;
 
   virtual void EnforceMinBitrate(bool enforce_min_bitrate) OVERRIDE;
+  virtual void SetReservedBitrate(uint32_t reserved_bitrate_bps) OVERRIDE;
 
  private:
   class RtcpBandwidthObserverImpl;
@@ -116,6 +117,10 @@
   uint32_t last_rtt_ GUARDED_BY(*critsect_);
   bool last_enforce_min_bitrate_ GUARDED_BY(*critsect_);
   bool bitrate_observers_modified_ GUARDED_BY(*critsect_);
+  uint32_t last_reserved_bitrate_bps_ GUARDED_BY(*critsect_);
+  uint32_t reserved_bitrate_bps_ GUARDED_BY(*critsect_);
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(BitrateControllerImpl);
 };
 }  // 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 c53928b..2bc1dac 100644
--- a/webrtc/modules/bitrate_controller/bitrate_controller_unittest.cc
+++ b/webrtc/modules/bitrate_controller/bitrate_controller_unittest.cc
@@ -412,6 +412,61 @@
   controller_->RemoveBitrateObserver(&bitrate_observer_2);
 }
 
+TEST_F(BitrateControllerTest, SetReservedBitrate) {
+  TestBitrateObserver bitrate_observer;
+  controller_->SetBitrateObserver(&bitrate_observer, 200000, 100000, 300000);
+
+  // Receive successively lower REMBs, verify the reserved bitrate is deducted.
+
+  controller_->SetReservedBitrate(0);
+  bandwidth_observer_->OnReceivedEstimatedBitrate(400000);
+  EXPECT_EQ(200000u, bitrate_observer.last_bitrate_);
+  controller_->SetReservedBitrate(50000);
+  bandwidth_observer_->OnReceivedEstimatedBitrate(400000);
+  EXPECT_EQ(150000u, bitrate_observer.last_bitrate_);
+
+  controller_->SetReservedBitrate(0);
+  bandwidth_observer_->OnReceivedEstimatedBitrate(250000);
+  EXPECT_EQ(200000u, bitrate_observer.last_bitrate_);
+  controller_->SetReservedBitrate(50000);
+  bandwidth_observer_->OnReceivedEstimatedBitrate(250000);
+  EXPECT_EQ(150000u, bitrate_observer.last_bitrate_);
+
+  controller_->SetReservedBitrate(0);
+  bandwidth_observer_->OnReceivedEstimatedBitrate(200000);
+  EXPECT_EQ(200000u, bitrate_observer.last_bitrate_);
+  controller_->SetReservedBitrate(30000);
+  bandwidth_observer_->OnReceivedEstimatedBitrate(200000);
+  EXPECT_EQ(170000u, bitrate_observer.last_bitrate_);
+
+  controller_->SetReservedBitrate(0);
+  bandwidth_observer_->OnReceivedEstimatedBitrate(160000);
+  EXPECT_EQ(160000u, bitrate_observer.last_bitrate_);
+  controller_->SetReservedBitrate(30000);
+  bandwidth_observer_->OnReceivedEstimatedBitrate(160000);
+  EXPECT_EQ(130000u, bitrate_observer.last_bitrate_);
+
+  controller_->SetReservedBitrate(0);
+  bandwidth_observer_->OnReceivedEstimatedBitrate(120000);
+  EXPECT_EQ(120000u, bitrate_observer.last_bitrate_);
+  controller_->SetReservedBitrate(10000);
+  bandwidth_observer_->OnReceivedEstimatedBitrate(120000);
+  EXPECT_EQ(110000u, bitrate_observer.last_bitrate_);
+
+  controller_->SetReservedBitrate(0);
+  bandwidth_observer_->OnReceivedEstimatedBitrate(120000);
+  EXPECT_EQ(120000u, bitrate_observer.last_bitrate_);
+  controller_->SetReservedBitrate(50000);
+  bandwidth_observer_->OnReceivedEstimatedBitrate(120000);
+  EXPECT_EQ(100000u, bitrate_observer.last_bitrate_);
+
+  controller_->SetReservedBitrate(10000);
+  bandwidth_observer_->OnReceivedEstimatedBitrate(0);
+  EXPECT_EQ(100000u, bitrate_observer.last_bitrate_);
+
+  controller_->RemoveBitrateObserver(&bitrate_observer);
+}
+
 class BitrateControllerTestNoEnforceMin : public BitrateControllerTest {
  protected:
   BitrateControllerTestNoEnforceMin() : BitrateControllerTest() {
@@ -440,6 +495,26 @@
   controller_->RemoveBitrateObserver(&bitrate_observer_1);
 }
 
+TEST_F(BitrateControllerTestNoEnforceMin, SetReservedBitrate) {
+  TestBitrateObserver bitrate_observer_1;
+  controller_->SetBitrateObserver(&bitrate_observer_1, 200000, 100000, 400000);
+  controller_->SetReservedBitrate(10000);
+
+  // High REMB.
+  bandwidth_observer_->OnReceivedEstimatedBitrate(150000);
+  EXPECT_EQ(140000u, bitrate_observer_1.last_bitrate_);
+
+  // Low REMB.
+  bandwidth_observer_->OnReceivedEstimatedBitrate(15000);
+  EXPECT_EQ(5000u, bitrate_observer_1.last_bitrate_);
+
+  // Keeps at least 10 kbps.
+  bandwidth_observer_->OnReceivedEstimatedBitrate(9000);
+  EXPECT_EQ(0u, bitrate_observer_1.last_bitrate_);
+
+  controller_->RemoveBitrateObserver(&bitrate_observer_1);
+}
+
 TEST_F(BitrateControllerTestNoEnforceMin, ThreeBitrateObservers) {
   TestBitrateObserver bitrate_observer_1;
   TestBitrateObserver bitrate_observer_2;
diff --git a/webrtc/modules/bitrate_controller/include/bitrate_controller.h b/webrtc/modules/bitrate_controller/include/bitrate_controller.h
index 0f74367..b25852d 100644
--- a/webrtc/modules/bitrate_controller/include/bitrate_controller.h
+++ b/webrtc/modules/bitrate_controller/include/bitrate_controller.h
@@ -73,6 +73,8 @@
 
   // Changes the mode that was set in the constructor.
   virtual void EnforceMinBitrate(bool enforce_min_bitrate) = 0;
+
+  virtual void SetReservedBitrate(uint32_t reserved_bitrate_bps) = 0;
 };
 }  // namespace webrtc
 #endif  // WEBRTC_MODULES_BITRATE_CONTROLLER_INCLUDE_BITRATE_CONTROLLER_H_