Adds support for sending first set of packets at increasingly higher bitrates to probe the link and faster ramp up to a high bitrate.

Also wires up a finch experiment to control this.

R=mflodman@webrtc.org

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@7505 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/modules/bitrate_controller/bitrate_controller_unittest.cc b/webrtc/modules/bitrate_controller/bitrate_controller_unittest.cc
index 8523d50..fddab9d 100644
--- a/webrtc/modules/bitrate_controller/bitrate_controller_unittest.cc
+++ b/webrtc/modules/bitrate_controller/bitrate_controller_unittest.cc
@@ -83,6 +83,27 @@
   controller_->RemoveBitrateObserver(&bitrate_observer);
 }
 
+TEST_F(BitrateControllerTest, InitialRemb) {
+  TestBitrateObserver bitrate_observer;
+  controller_->SetBitrateObserver(&bitrate_observer, 200000, 100000, 1500000);
+  const uint32_t kRemb = 1000000u;
+  const uint32_t kSecondRemb = kRemb + 500000u;
+
+  // Initial REMB applies immediately.
+  bandwidth_observer_->OnReceivedEstimatedBitrate(kRemb);
+  webrtc::ReportBlockList report_blocks;
+  report_blocks.push_back(CreateReportBlock(1, 2, 0, 1));
+  bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 1);
+  report_blocks.clear();
+  EXPECT_EQ(kRemb, bitrate_observer.last_bitrate_);
+
+  // Second REMB doesn't apply immediately.
+  bandwidth_observer_->OnReceivedEstimatedBitrate(kRemb + 500000);
+  report_blocks.push_back(CreateReportBlock(1, 2, 0, 21));
+  bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 2001);
+  EXPECT_LT(bitrate_observer.last_bitrate_, kSecondRemb);
+}
+
 TEST_F(BitrateControllerTest, UpdatingBitrateObserver) {
   TestBitrateObserver bitrate_observer;
   controller_->SetBitrateObserver(&bitrate_observer, 200000, 100000, 1500000);
@@ -105,51 +126,65 @@
   TestBitrateObserver bitrate_observer;
   controller_->SetBitrateObserver(&bitrate_observer, 200000, 100000, 300000);
 
-  // Receive a high remb, test bitrate inc.
-  bandwidth_observer_->OnReceivedEstimatedBitrate(400000);
+  // First REMB applies immediately.
+  int64_t time_ms = 1001;
+  webrtc::ReportBlockList report_blocks;
+  report_blocks.push_back(CreateReportBlock(1, 2, 0, 1));
+  bandwidth_observer_->OnReceivedEstimatedBitrate(200000);
   EXPECT_EQ(200000u, bitrate_observer.last_bitrate_);
   EXPECT_EQ(0, bitrate_observer.last_fraction_loss_);
   EXPECT_EQ(0u, bitrate_observer.last_rtt_);
+  bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
+  report_blocks.clear();
+  time_ms += 2000;
+
+  // Receive a high remb, test bitrate inc.
+  bandwidth_observer_->OnReceivedEstimatedBitrate(400000);
 
   // 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);
+  report_blocks.push_back(CreateReportBlock(1, 2, 0, 21));
+  bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
   EXPECT_EQ(217000u, 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, 21));
-  bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 1001);
-  EXPECT_EQ(235360u, bitrate_observer.last_bitrate_);
-  EXPECT_EQ(0, bitrate_observer.last_fraction_loss_);
-  EXPECT_EQ(50u, bitrate_observer.last_rtt_);
+  time_ms += 1000;
 
   report_blocks.clear();
   report_blocks.push_back(CreateReportBlock(1, 2, 0, 41));
-  bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 2001);
-  EXPECT_EQ(255189u, bitrate_observer.last_bitrate_);
+  bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
+  EXPECT_EQ(235360u, bitrate_observer.last_bitrate_);
+  EXPECT_EQ(0, bitrate_observer.last_fraction_loss_);
+  EXPECT_EQ(50u, bitrate_observer.last_rtt_);
+  time_ms += 1000;
 
   report_blocks.clear();
   report_blocks.push_back(CreateReportBlock(1, 2, 0, 61));
-  bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 3001);
+  bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
+  EXPECT_EQ(255189u, bitrate_observer.last_bitrate_);
+  time_ms += 1000;
+
+  report_blocks.clear();
+  report_blocks.push_back(CreateReportBlock(1, 2, 0, 81));
+  bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
   EXPECT_EQ(276604u, bitrate_observer.last_bitrate_);
+  time_ms += 1000;
 
   report_blocks.clear();
   report_blocks.push_back(CreateReportBlock(1, 2, 0, 801));
-  bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 4001);
+  bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
   EXPECT_EQ(299732u, bitrate_observer.last_bitrate_);
+  time_ms += 1000;
 
   // Reach max cap.
   report_blocks.clear();
   report_blocks.push_back(CreateReportBlock(1, 2, 0, 101));
-  bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 5001);
+  bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
   EXPECT_EQ(300000u, bitrate_observer.last_bitrate_);
+  time_ms += 1000;
 
   report_blocks.clear();
   report_blocks.push_back(CreateReportBlock(1, 2, 0, 141));
-  bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 7001);
+  bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
   EXPECT_EQ(300000u, bitrate_observer.last_bitrate_);
 
   // Test that a low REMB trigger immediately.
@@ -167,78 +202,86 @@
   TestBitrateObserver bitrate_observer;
   controller_->SetBitrateObserver(&bitrate_observer, 200000, 100000, 300000);
 
+  // REMBs during the first 2 seconds apply immediately.
+  int64_t time_ms = 1;
+  webrtc::ReportBlockList report_blocks;
+  report_blocks.push_back(CreateReportBlock(1, 2, 0, 1));
+  bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
+  report_blocks.clear();
+  time_ms += 500;
+
   RtcpBandwidthObserver* second_bandwidth_observer =
       controller_->CreateRtcpBandwidthObserver();
 
-  // 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;
-  report_blocks.push_back(CreateReportBlock(1, 2, 0, 1));
-  bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 1);
+  report_blocks.push_back(CreateReportBlock(1, 2, 0, 21));
   second_bandwidth_observer->OnReceivedRtcpReceiverReport(
       report_blocks, 100, 1);
   EXPECT_EQ(217000u, bitrate_observer.last_bitrate_);
   EXPECT_EQ(0, bitrate_observer.last_fraction_loss_);
   EXPECT_EQ(100u, bitrate_observer.last_rtt_);
+  time_ms += 500;
 
   // Test bitrate increase 8% per second.
   report_blocks.clear();
   report_blocks.push_back(CreateReportBlock(1, 2, 0, 21));
-  bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 501);
-  second_bandwidth_observer->OnReceivedRtcpReceiverReport(report_blocks, 100,
-                                                          1001);
+  bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
+  time_ms += 500;
+  second_bandwidth_observer->OnReceivedRtcpReceiverReport(
+      report_blocks, 100, time_ms);
   EXPECT_EQ(235360u, bitrate_observer.last_bitrate_);
   EXPECT_EQ(0, bitrate_observer.last_fraction_loss_);
   EXPECT_EQ(100u, bitrate_observer.last_rtt_);
+  time_ms += 500;
 
   // Extra report should not change estimate.
   report_blocks.clear();
   report_blocks.push_back(CreateReportBlock(1, 2, 0, 31));
-  second_bandwidth_observer->OnReceivedRtcpReceiverReport(report_blocks, 100,
-                                                          1501);
+  second_bandwidth_observer->OnReceivedRtcpReceiverReport(
+      report_blocks, 100, time_ms);
   EXPECT_EQ(235360u, bitrate_observer.last_bitrate_);
+  time_ms += 500;
 
   report_blocks.clear();
   report_blocks.push_back(CreateReportBlock(1, 2, 0, 41));
-  bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 2001);
+  bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
   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);
+  second_bandwidth_observer->OnReceivedRtcpReceiverReport(
+      report_blocks, 100, time_ms);
   EXPECT_EQ(255189u, bitrate_observer.last_bitrate_);
+  time_ms += 1000;
 
   // 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);
+  second_bandwidth_observer->OnReceivedRtcpReceiverReport(
+      report_blocks, 50, time_ms);
   EXPECT_EQ(276604u, bitrate_observer.last_bitrate_);
+  time_ms += 1000;
 
   report_blocks.clear();
   report_blocks.push_back(CreateReportBlock(1, 2, 0, 81));
-  second_bandwidth_observer->OnReceivedRtcpReceiverReport(report_blocks, 50,
-                                                          4001);
+  second_bandwidth_observer->OnReceivedRtcpReceiverReport(
+      report_blocks, 50, time_ms);
   EXPECT_EQ(299732u, bitrate_observer.last_bitrate_);
+  time_ms += 1000;
 
   // Reach max cap.
   report_blocks.clear();
   report_blocks.push_back(CreateReportBlock(1, 2, 0, 121));
   second_bandwidth_observer->OnReceivedRtcpReceiverReport(
-      report_blocks, 50, 5001);
+      report_blocks, 50, time_ms);
   EXPECT_EQ(300000u, bitrate_observer.last_bitrate_);
+  time_ms += 1000;
 
   report_blocks.clear();
   report_blocks.push_back(CreateReportBlock(1, 2, 0, 141));
   second_bandwidth_observer->OnReceivedRtcpReceiverReport(
-      report_blocks, 50, 6001);
+      report_blocks, 50, time_ms);
   EXPECT_EQ(300000u, bitrate_observer.last_bitrate_);
 
   // Test that a low REMB trigger immediately.
@@ -264,11 +307,18 @@
   controller_->SetBitrateObserver(&bitrate_observer, kStartBitrate, kMinBitrate,
                                   kMaxBitrate);
 
+  // REMBs during the first 2 seconds apply immediately.
+  int64_t time_ms = 1001;
+  webrtc::ReportBlockList report_blocks;
+  report_blocks.push_back(CreateReportBlock(1, 2, 0, sequence_number[0]));
+  bandwidth_observer_->OnReceivedEstimatedBitrate(kStartBitrate);
+  bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
+  report_blocks.clear();
+  time_ms += 2000;
+
   // Receive a high REMB, test bitrate increase.
   bandwidth_observer_->OnReceivedEstimatedBitrate(400000);
 
-  webrtc::ReportBlockList report_blocks;
-  int64_t time_ms = 1001;
   uint32_t last_bitrate = 0;
   // Ramp up to max bitrate.
   for (int i = 0; i < 6; ++i) {
@@ -333,20 +383,29 @@
   controller_->SetBitrateObserver(&bitrate_observer_2, 200000, 200000, 300000);
   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);
+  // REMBs during the first 2 seconds apply immediately.
+  int64_t time_ms = 1001;
+  webrtc::ReportBlockList report_blocks;
+  report_blocks.push_back(CreateReportBlock(1, 2, 0, 1));
+  bandwidth_observer_->OnReceivedEstimatedBitrate(200000);
   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_);
+  bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
+  report_blocks.clear();
+  time_ms += 2000;
+
+  // Receive a high remb, test bitrate inc.
+  // Test too low start bitrate, hence lower than sum of min.
+  bandwidth_observer_->OnReceivedEstimatedBitrate(400000);
 
   // 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, 1001);
+  report_blocks.push_back(CreateReportBlock(1, 2, 0, 21));
+  bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
   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_);
+  time_ms += 1000;
 
   EXPECT_EQ(212500u, bitrate_observer_2.last_bitrate_);
   EXPECT_EQ(0, bitrate_observer_2.last_fraction_loss_);
@@ -354,59 +413,67 @@
 
   report_blocks.clear();
   report_blocks.push_back(CreateReportBlock(1, 2, 0, 41));
-  bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 2001);
+  bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
   EXPECT_EQ(126000u, bitrate_observer_1.last_bitrate_);
   EXPECT_EQ(226000u, bitrate_observer_2.last_bitrate_);
+  time_ms += 1000;
 
   report_blocks.clear();
   report_blocks.push_back(CreateReportBlock(1, 2, 0, 61));
-  bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 3001);
+  bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
   EXPECT_EQ(140580u, bitrate_observer_1.last_bitrate_);
   EXPECT_EQ(240580u, bitrate_observer_2.last_bitrate_);
+  time_ms += 1000;
 
   // Check that the bitrate sum honor our REMB.
   report_blocks.clear();
   report_blocks.push_back(CreateReportBlock(1, 2, 0, 101));
-  bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 5001);
+  bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
   EXPECT_EQ(150000u, bitrate_observer_1.last_bitrate_);
   EXPECT_EQ(250000u, bitrate_observer_2.last_bitrate_);
+  time_ms += 1000;
 
   // Remove REMB cap, higher than sum of max.
   bandwidth_observer_->OnReceivedEstimatedBitrate(700000);
 
   report_blocks.clear();
   report_blocks.push_back(CreateReportBlock(1, 2, 0, 121));
-  bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 6001);
+  bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
   EXPECT_EQ(166500u, bitrate_observer_1.last_bitrate_);
   EXPECT_EQ(266500u, bitrate_observer_2.last_bitrate_);
+  time_ms += 1000;
 
   report_blocks.clear();
   report_blocks.push_back(CreateReportBlock(1, 2, 0, 141));
-  bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 7001);
+  bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
   EXPECT_EQ(184320u, bitrate_observer_1.last_bitrate_);
   EXPECT_EQ(284320u, bitrate_observer_2.last_bitrate_);
+  time_ms += 1000;
 
   report_blocks.clear();
   report_blocks.push_back(CreateReportBlock(1, 2, 0, 161));
-  bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 8001);
+  bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
   EXPECT_EQ(207130u, bitrate_observer_1.last_bitrate_);
   EXPECT_EQ(300000u, bitrate_observer_2.last_bitrate_);  // Max cap.
+  time_ms += 1000;
 
   report_blocks.clear();
   report_blocks.push_back(CreateReportBlock(1, 2, 0, 181));
-  bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 9001);
+  bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
   EXPECT_EQ(248700u, bitrate_observer_1.last_bitrate_);
   EXPECT_EQ(300000u, bitrate_observer_2.last_bitrate_);
+  time_ms += 1000;
 
   report_blocks.clear();
   report_blocks.push_back(CreateReportBlock(1, 2, 0, 201));
-  bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 10001);
+  bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
   EXPECT_EQ(293596u, bitrate_observer_1.last_bitrate_);
   EXPECT_EQ(300000u, bitrate_observer_2.last_bitrate_);
+  time_ms += 1000;
 
   report_blocks.clear();
   report_blocks.push_back(CreateReportBlock(1, 2, 0, 221));
-  bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, 11001);
+  bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms);
   EXPECT_EQ(300000u, bitrate_observer_1.last_bitrate_);  // Max cap.
   EXPECT_EQ(300000u, bitrate_observer_2.last_bitrate_);
 
diff --git a/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc b/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc
index 5da23f0..406322a 100644
--- a/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc
+++ b/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc
@@ -56,7 +56,9 @@
       last_fraction_loss_(0),
       last_round_trip_time_ms_(0),
       bwe_incoming_(0),
-      time_last_decrease_ms_(0) {}
+      time_last_decrease_ms_(0),
+      first_report_time_ms_(-1) {
+}
 
 SendSideBandwidthEstimation::~SendSideBandwidthEstimation() {}
 
@@ -88,13 +90,15 @@
 
 void SendSideBandwidthEstimation::UpdateReceiverEstimate(uint32_t bandwidth) {
   bwe_incoming_ = bandwidth;
-  CapBitrateToThresholds();
+  bitrate_ = CapBitrateToThresholds(bitrate_);
 }
 
 void SendSideBandwidthEstimation::UpdateReceiverBlock(uint8_t fraction_loss,
                                                       uint32_t rtt,
                                                       int number_of_packets,
                                                       uint32_t now_ms) {
+  if (first_report_time_ms_ == -1)
+    first_report_time_ms_ = now_ms;
   // Update RTT.
   last_round_trip_time_ms_ = rtt;
 
@@ -124,8 +128,16 @@
 }
 
 void SendSideBandwidthEstimation::UpdateEstimate(uint32_t now_ms) {
+  // We trust the REMB during the first 2 seconds if we haven't had any
+  // packet loss reported, to allow startup bitrate probing.
+  if (last_fraction_loss_ == 0 && now_ms - first_report_time_ms_ < 2000 &&
+      bwe_incoming_ > bitrate_) {
+    bitrate_ = CapBitrateToThresholds(bwe_incoming_);
+    min_bitrate_history_.clear();
+    min_bitrate_history_.push_back(std::make_pair(now_ms, bitrate_));
+    return;
+  }
   UpdateMinHistory(now_ms);
-
   // Only start updating bitrate when receiving receiver blocks.
   if (time_last_receiver_block_ms_ != 0) {
     if (last_fraction_loss_ <= 5) {
@@ -172,7 +184,7 @@
       }
     }
   }
-  CapBitrateToThresholds();
+  bitrate_ = CapBitrateToThresholds(bitrate_);
 }
 
 void SendSideBandwidthEstimation::UpdateMinHistory(uint32_t now_ms) {
@@ -195,19 +207,20 @@
   min_bitrate_history_.push_back(std::make_pair(now_ms, bitrate_));
 }
 
-void SendSideBandwidthEstimation::CapBitrateToThresholds() {
-  if (bwe_incoming_ > 0 && bitrate_ > bwe_incoming_) {
-    bitrate_ = bwe_incoming_;
+uint32_t SendSideBandwidthEstimation::CapBitrateToThresholds(uint32_t bitrate) {
+  if (bwe_incoming_ > 0 && bitrate > bwe_incoming_) {
+    bitrate = bwe_incoming_;
   }
-  if (bitrate_ > max_bitrate_configured_) {
-    bitrate_ = max_bitrate_configured_;
+  if (bitrate > max_bitrate_configured_) {
+    bitrate = max_bitrate_configured_;
   }
-  if (bitrate_ < min_bitrate_configured_) {
-    LOG(LS_WARNING) << "Estimated available bandwidth " << bitrate_ / 1000
+  if (bitrate < min_bitrate_configured_) {
+    LOG(LS_WARNING) << "Estimated available bandwidth " << bitrate / 1000
                     << " kbps is below configured min bitrate "
                     << min_bitrate_configured_ / 1000 << " kbps.";
-    bitrate_ = min_bitrate_configured_;
+    bitrate = min_bitrate_configured_;
   }
+  return bitrate;
 }
 
 }  // namespace webrtc
diff --git a/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h b/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h
index eb675d1..6b32385 100644
--- a/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h
+++ b/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h
@@ -43,7 +43,9 @@
   void SetMinBitrate(uint32_t min_bitrate);
 
  private:
-  void CapBitrateToThresholds();
+  // Returns the input bitrate capped to the thresholds defined by the max,
+  // min and incoming bandwidth.
+  uint32_t CapBitrateToThresholds(uint32_t bitrate);
 
   // Updates history of min bitrates.
   // After this method returns min_bitrate_history_.front().second contains the
@@ -66,6 +68,7 @@
 
   uint32_t bwe_incoming_;
   uint32_t time_last_decrease_ms_;
+  int64_t first_report_time_ms_;
 };
 }  // namespace webrtc
 #endif  // WEBRTC_MODULES_BITRATE_CONTROLLER_SEND_SIDE_BANDWIDTH_ESTIMATION_H_
diff --git a/webrtc/modules/modules.gyp b/webrtc/modules/modules.gyp
index 082b887..b0c5bb5 100644
--- a/webrtc/modules/modules.gyp
+++ b/webrtc/modules/modules.gyp
@@ -180,6 +180,7 @@
             'desktop_capture/win/cursor_unittest_resources.rc',
             'media_file/source/media_file_unittest.cc',
             'module_common_types_unittest.cc',
+            'pacing/bitrate_prober_unittest.cc',
             'pacing/paced_sender_unittest.cc',
             'remote_bitrate_estimator/bwe_simulations.cc',
             'remote_bitrate_estimator/include/mock/mock_remote_bitrate_observer.h',
diff --git a/webrtc/modules/pacing/BUILD.gn b/webrtc/modules/pacing/BUILD.gn
index 58a73ae..aa44b0d 100644
--- a/webrtc/modules/pacing/BUILD.gn
+++ b/webrtc/modules/pacing/BUILD.gn
@@ -9,6 +9,8 @@
 source_set("pacing") {
   sources = [
     "include/paced_sender.h",
+    "bitrate_prober.cc",
+    "bitrate_prober.h",
     "paced_sender.cc",
   ]
 
diff --git a/webrtc/modules/pacing/bitrate_prober.cc b/webrtc/modules/pacing/bitrate_prober.cc
new file mode 100644
index 0000000..04e71c5
--- /dev/null
+++ b/webrtc/modules/pacing/bitrate_prober.cc
@@ -0,0 +1,120 @@
+/*
+ *  Copyright (c) 2014 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/pacing/bitrate_prober.h"
+
+#include <assert.h>
+#include <limits>
+#include <sstream>
+
+#include "webrtc/system_wrappers/interface/logging.h"
+
+namespace webrtc {
+
+namespace {
+int ComputeDeltaFromBitrate(size_t packet_size, int bitrate_bps) {
+  assert(bitrate_bps > 0);
+  // Compute the time delta needed to send packet_size bytes at bitrate_bps
+  // bps. Result is in milliseconds.
+  return static_cast<int>(1000ll * static_cast<int64_t>(packet_size) * 8ll /
+      bitrate_bps);
+}
+}  // namespace
+
+BitrateProber::BitrateProber()
+    : probing_state_(kDisabled),
+      packet_size_last_send_(0),
+      time_last_send_ms_(-1) {
+}
+
+void BitrateProber::SetEnabled(bool enable) {
+  if (enable) {
+    if (probing_state_ == kDisabled) {
+      probing_state_ = kAllowedToProbe;
+      LOG(LS_INFO) << "Initial bandwidth probing enabled";
+    }
+  } else {
+    probing_state_ = kDisabled;
+    LOG(LS_INFO) << "Initial bandwidth probing disabled";
+  }
+}
+
+bool BitrateProber::IsProbing() const {
+  return probing_state_ == kProbing;
+}
+
+void BitrateProber::MaybeInitializeProbe(int bitrate_bps) {
+  if (probing_state_ != kAllowedToProbe)
+    return;
+  probe_bitrates_.clear();
+  // Max number of packets used for probing.
+  const int kMaxProbeLength = 15;
+  const int kMaxNumProbes = 3;
+  const int kPacketsPerProbe = kMaxProbeLength / kMaxNumProbes;
+  const float kProbeBitrateMultipliers[kMaxNumProbes] = {2.5, 4, 6};
+  int bitrates_bps[kMaxNumProbes];
+  std::stringstream bitrate_log;
+  bitrate_log << "Start probing for bandwidth, bitrates:";
+  for (int i = 0; i < kMaxNumProbes; ++i) {
+    bitrates_bps[i] = kProbeBitrateMultipliers[i] * bitrate_bps;
+    bitrate_log << " " << bitrates_bps[i];
+    for (int j = 0; j < kPacketsPerProbe; ++j)
+      probe_bitrates_.push_back(bitrates_bps[i]);
+  }
+  bitrate_log << ", num packets: " << probe_bitrates_.size();
+  LOG(LS_INFO) << bitrate_log.str().c_str();
+  probing_state_ = kProbing;
+}
+
+int BitrateProber::TimeUntilNextProbe(int64_t now_ms) {
+  if (probing_state_ != kDisabled && probe_bitrates_.empty()) {
+    probing_state_ = kWait;
+  }
+  if (probe_bitrates_.empty()) {
+    // No probe started, or waiting for next probe.
+    return std::numeric_limits<int>::max();
+  }
+  int64_t elapsed_time_ms = now_ms - time_last_send_ms_;
+  // We will send the first probe packet immediately if no packet has been
+  // sent before.
+  int time_until_probe_ms = 0;
+  if (packet_size_last_send_ > 0 && probing_state_ == kProbing) {
+    int next_delta_ms = ComputeDeltaFromBitrate(packet_size_last_send_,
+                                                probe_bitrates_.front());
+    time_until_probe_ms = next_delta_ms - elapsed_time_ms;
+    // There is no point in trying to probe with less than 1 ms between packets
+    // as it essentially means trying to probe at infinite bandwidth.
+    const int kMinProbeDeltaMs = 1;
+    // If we have waited more than 3 ms for a new packet to probe with we will
+    // consider this probing session over.
+    const int kMaxProbeDelayMs = 3;
+    if (next_delta_ms < kMinProbeDeltaMs ||
+        time_until_probe_ms < -kMaxProbeDelayMs) {
+      // We currently disable probing after the first probe, as we only want
+      // to probe at the beginning of a connection. We should set this to
+      // kWait if we later want to probe periodically.
+      probing_state_ = kWait;
+      LOG(LS_INFO) << "Next delta too small, stop probing.";
+      time_until_probe_ms = 0;
+    }
+  }
+  return time_until_probe_ms;
+}
+
+void BitrateProber::PacketSent(int64_t now_ms, size_t packet_size) {
+  assert(packet_size > 0);
+  packet_size_last_send_ = packet_size;
+  time_last_send_ms_ = now_ms;
+  if (probing_state_ != kProbing)
+    return;
+  if (!probe_bitrates_.empty())
+    probe_bitrates_.pop_front();
+}
+}  // namespace webrtc
diff --git a/webrtc/modules/pacing/bitrate_prober.h b/webrtc/modules/pacing/bitrate_prober.h
new file mode 100644
index 0000000..04a8580
--- /dev/null
+++ b/webrtc/modules/pacing/bitrate_prober.h
@@ -0,0 +1,57 @@
+/*
+ *  Copyright (c) 2014 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_PACING_BITRATE_PROBER_H_
+#define WEBRTC_MODULES_PACING_BITRATE_PROBER_H_
+
+#include <cstddef>
+#include <list>
+
+#include "webrtc/typedefs.h"
+
+namespace webrtc {
+
+// Note that this class isn't thread-safe by itself and therefore relies
+// on being protected by the caller.
+class BitrateProber {
+ public:
+  BitrateProber();
+
+  void SetEnabled(bool enable);
+
+  // Returns true if the prober is in a probing session, i.e., it currently
+  // wants packets to be sent out according to the time returned by
+  // TimeUntilNextProbe().
+  bool IsProbing() const;
+
+  // Initializes a new probing session if the prober is allowed to probe.
+  void MaybeInitializeProbe(int bitrate_bps);
+
+  // Returns the number of milliseconds until the next packet should be sent to
+  // get accurate probing.
+  int TimeUntilNextProbe(int64_t now_ms);
+
+  // Called to report to the prober that a packet has been sent, which helps the
+  // prober know when to move to the next packet in a probe.
+  void PacketSent(int64_t now_ms, size_t packet_size);
+
+ private:
+  enum ProbingState { kDisabled, kAllowedToProbe, kProbing, kWait };
+
+  ProbingState probing_state_;
+  // Probe bitrate per packet. These are used to compute the delta relative to
+  // the previous probe packet based on the size and time when that packet was
+  // sent.
+  std::list<int> probe_bitrates_;
+  size_t packet_size_last_send_;
+  int64_t time_last_send_ms_;
+};
+}  // namespace webrtc
+#endif  // WEBRTC_MODULES_PACING_BITRATE_PROBER_H_
diff --git a/webrtc/modules/pacing/bitrate_prober_unittest.cc b/webrtc/modules/pacing/bitrate_prober_unittest.cc
new file mode 100644
index 0000000..15b1cc5
--- /dev/null
+++ b/webrtc/modules/pacing/bitrate_prober_unittest.cc
@@ -0,0 +1,57 @@
+/*
+ *  Copyright (c) 2014 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 <limits>
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webrtc/modules/pacing/bitrate_prober.h"
+
+namespace webrtc {
+
+TEST(BitrateProberTest, VerifyStatesAndTimeBetweenProbes) {
+  BitrateProber prober;
+  EXPECT_FALSE(prober.IsProbing());
+  int64_t now_ms = 0;
+  EXPECT_EQ(std::numeric_limits<int>::max(), prober.TimeUntilNextProbe(now_ms));
+
+  prober.SetEnabled(true);
+  EXPECT_FALSE(prober.IsProbing());
+
+  prober.MaybeInitializeProbe(300000);
+  EXPECT_TRUE(prober.IsProbing());
+
+  EXPECT_EQ(0, prober.TimeUntilNextProbe(now_ms));
+  prober.PacketSent(now_ms, 1000);
+
+  for (int i = 0; i < 4; ++i) {
+    EXPECT_EQ(10, prober.TimeUntilNextProbe(now_ms));
+    now_ms += 5;
+    EXPECT_EQ(5, prober.TimeUntilNextProbe(now_ms));
+    now_ms += 5;
+    EXPECT_EQ(0, prober.TimeUntilNextProbe(now_ms));
+    prober.PacketSent(now_ms, 1000);
+  }
+  for (int i = 0; i < 5; ++i) {
+    EXPECT_EQ(6, prober.TimeUntilNextProbe(now_ms));
+    now_ms += 6;
+    EXPECT_EQ(0, prober.TimeUntilNextProbe(now_ms));
+    prober.PacketSent(now_ms, 1000);
+  }
+  for (int i = 0; i < 5; ++i) {
+    EXPECT_EQ(4, prober.TimeUntilNextProbe(now_ms));
+    now_ms += 4;
+    EXPECT_EQ(0, prober.TimeUntilNextProbe(now_ms));
+    prober.PacketSent(now_ms, 1000);
+  }
+
+  EXPECT_EQ(std::numeric_limits<int>::max(), prober.TimeUntilNextProbe(now_ms));
+  EXPECT_FALSE(prober.IsProbing());
+}
+}  // namespace webrtc
diff --git a/webrtc/modules/pacing/include/mock/mock_paced_sender.h b/webrtc/modules/pacing/include/mock/mock_paced_sender.h
index 6600a92..0c9e354 100644
--- a/webrtc/modules/pacing/include/mock/mock_paced_sender.h
+++ b/webrtc/modules/pacing/include/mock/mock_paced_sender.h
@@ -22,7 +22,7 @@
 
 class MockPacedSender : public PacedSender {
  public:
-  MockPacedSender() : PacedSender(Clock::GetRealTimeClock(), NULL, 0, 0) {}
+  MockPacedSender() : PacedSender(Clock::GetRealTimeClock(), NULL, 0, 0, 0) {}
   MOCK_METHOD6(SendPacket, bool(Priority priority,
                                 uint32_t ssrc,
                                 uint16_t sequence_number,
diff --git a/webrtc/modules/pacing/include/paced_sender.h b/webrtc/modules/pacing/include/paced_sender.h
index 14a3a3d..d303446 100644
--- a/webrtc/modules/pacing/include/paced_sender.h
+++ b/webrtc/modules/pacing/include/paced_sender.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef WEBRTC_MODULES_PACED_SENDER_H_
-#define WEBRTC_MODULES_PACED_SENDER_H_
+#ifndef WEBRTC_MODULES_PACING_INCLUDE_PACED_SENDER_H_
+#define WEBRTC_MODULES_PACING_INCLUDE_PACED_SENDER_H_
 
 #include <list>
 #include <set>
@@ -20,6 +20,7 @@
 #include "webrtc/typedefs.h"
 
 namespace webrtc {
+class BitrateProber;
 class Clock;
 class CriticalSectionWrapper;
 
@@ -67,7 +68,10 @@
   // overshoots from the encoder.
   static const float kDefaultPaceMultiplier;
 
-  PacedSender(Clock* clock, Callback* callback, int max_bitrate_kbps,
+  PacedSender(Clock* clock,
+              Callback* callback,
+              int bitrate_kbps,
+              int max_bitrate_kbps,
               int min_bitrate_kbps);
 
   virtual ~PacedSender();
@@ -83,9 +87,14 @@
   // Resume sending packets.
   void Resume();
 
-  // Set target bitrates for the pacer. Padding packets will be utilized to
-  // reach |min_bitrate| unless enough media packets are available.
-  void UpdateBitrate(int max_bitrate_kbps, int min_bitrate_kbps);
+  // Set target bitrates for the pacer.
+  // We will pace out bursts of packets at a bitrate of |max_bitrate_kbps|.
+  // |bitrate_kbps| is our estimate of what we are allowed to send on average.
+  // Padding packets will be utilized to reach |min_bitrate| unless enough media
+  // packets are available.
+  void UpdateBitrate(int bitrate_kbps,
+                     int max_bitrate_kbps,
+                     int min_bitrate_kbps);
 
   // Returns true if we send the packet now, else it will add the packet
   // information to the queue and call TimeToSendPacket when it's time to send.
@@ -103,6 +112,8 @@
   // Returns the time since the oldest queued packet was enqueued.
   virtual int QueueInMs() const;
 
+  virtual size_t QueueSizePackets() const;
+
   // Returns the number of milliseconds until the module want a worker thread
   // to call Process.
   virtual int32_t TimeUntilNextProcess() OVERRIDE;
@@ -110,10 +121,13 @@
   // Process any pending packets in the queue(s).
   virtual int32_t Process() OVERRIDE;
 
+ protected:
+  virtual bool ProbingExperimentIsEnabled() const;
+
  private:
   // Return true if next packet in line should be transmitted.
   // Return packet list that contains the next packet.
-  bool ShouldSendNextPacket(paced_sender::PacketList** packet_list)
+  bool ShouldSendNextPacket(paced_sender::PacketList** packet_list, bool probe)
       EXCLUSIVE_LOCKS_REQUIRED(critsect_);
 
   // Local helper function to GetNextPacket.
@@ -146,8 +160,12 @@
   scoped_ptr<paced_sender::IntervalBudget> padding_budget_
       GUARDED_BY(critsect_);
 
+  scoped_ptr<BitrateProber> prober_ GUARDED_BY(critsect_);
+  int bitrate_bps_ GUARDED_BY(critsect_);
+
   int64_t time_last_update_us_ GUARDED_BY(critsect_);
-  int64_t time_last_send_us_ GUARDED_BY(critsect_);
+  // Only accessed via process thread.
+  int64_t time_last_media_send_us_;
   int64_t capture_time_ms_last_queued_ GUARDED_BY(critsect_);
   int64_t capture_time_ms_last_sent_ GUARDED_BY(critsect_);
 
@@ -159,4 +177,4 @@
       GUARDED_BY(critsect_);
 };
 }  // namespace webrtc
-#endif  // WEBRTC_MODULES_PACED_SENDER_H_
+#endif  // WEBRTC_MODULES_PACING_INCLUDE_PACED_SENDER_H_
diff --git a/webrtc/modules/pacing/paced_sender.cc b/webrtc/modules/pacing/paced_sender.cc
index 6204a9a..64b3eb1 100644
--- a/webrtc/modules/pacing/paced_sender.cc
+++ b/webrtc/modules/pacing/paced_sender.cc
@@ -16,8 +16,11 @@
 #include <set>
 
 #include "webrtc/modules/interface/module_common_types.h"
+#include "webrtc/modules/pacing/bitrate_prober.h"
 #include "webrtc/system_wrappers/interface/clock.h"
 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
+#include "webrtc/system_wrappers/interface/field_trial.h"
+#include "webrtc/system_wrappers/interface/logging.h"
 #include "webrtc/system_wrappers/interface/trace_event.h"
 
 namespace {
@@ -71,6 +74,17 @@
     return packet_list_.front();
   }
 
+  size_t size() const {
+    size_t sum = 0;
+    for (std::map<uint32_t, std::set<uint16_t> >::const_iterator it =
+             sequence_number_set_.begin();
+         it != sequence_number_set_.end();
+         ++it) {
+      sum += it->second.size();
+    }
+    return sum;
+  }
+
   void pop_front() {
     Packet& packet = packet_list_.front();
     uint16_t sequence_number = packet.sequence_number;
@@ -131,6 +145,7 @@
 
 PacedSender::PacedSender(Clock* clock,
                          Callback* callback,
+                         int bitrate_kbps,
                          int max_bitrate_kbps,
                          int min_bitrate_kbps)
     : clock_(clock),
@@ -141,7 +156,10 @@
       max_queue_length_ms_(kDefaultMaxQueueLengthMs),
       media_budget_(new paced_sender::IntervalBudget(max_bitrate_kbps)),
       padding_budget_(new paced_sender::IntervalBudget(min_bitrate_kbps)),
+      prober_(new BitrateProber()),
+      bitrate_bps_(1000 * bitrate_kbps),
       time_last_update_us_(clock->TimeInMicroseconds()),
+      time_last_media_send_us_(-1),
       capture_time_ms_last_queued_(0),
       capture_time_ms_last_sent_(0),
       high_priority_packets_(new paced_sender::PacketList),
@@ -172,11 +190,13 @@
   return enabled_;
 }
 
-void PacedSender::UpdateBitrate(int max_bitrate_kbps,
+void PacedSender::UpdateBitrate(int bitrate_kbps,
+                                int max_bitrate_kbps,
                                 int min_bitrate_kbps) {
   CriticalSectionScoped cs(critsect_.get());
   media_budget_->set_target_rate_kbps(max_bitrate_kbps);
   padding_budget_->set_target_rate_kbps(min_bitrate_kbps);
+  bitrate_bps_ = 1000 * bitrate_kbps;
 }
 
 bool PacedSender::SendPacket(Priority priority, uint32_t ssrc,
@@ -187,6 +207,12 @@
   if (!enabled_) {
     return true;  // We can send now.
   }
+  // Enable probing if the probing experiment is enabled.
+  if (!prober_->IsProbing() && ProbingExperimentIsEnabled()) {
+    prober_->SetEnabled(true);
+  }
+  prober_->MaybeInitializeProbe(bitrate_bps_);
+
   if (capture_time_ms < 0) {
     capture_time_ms = clock_->TimeInMilliseconds();
   }
@@ -244,12 +270,19 @@
   return now_ms - oldest_packet_enqueue_time;
 }
 
+size_t PacedSender::QueueSizePackets() const {
+  CriticalSectionScoped cs(critsect_.get());
+  return low_priority_packets_->size() + normal_priority_packets_->size() +
+         high_priority_packets_->size();
+}
+
 int32_t PacedSender::TimeUntilNextProcess() {
   CriticalSectionScoped cs(critsect_.get());
-  int64_t elapsed_time_ms = (clock_->TimeInMicroseconds() -
-      time_last_update_us_ + 500) / 1000;
-  if (elapsed_time_ms <= 0) {
-    return kMinPacketLimitMs;
+  int64_t elapsed_time_us = clock_->TimeInMicroseconds() - time_last_update_us_;
+  int elapsed_time_ms = static_cast<int>((elapsed_time_us + 500) / 1000);
+  if (prober_->IsProbing()) {
+    int next_probe = prober_->TimeUntilNextProbe(clock_->TimeInMilliseconds());
+    return next_probe;
   }
   if (elapsed_time_ms >= kMinPacketLimitMs) {
     return 0;
@@ -271,12 +304,15 @@
       UpdateBytesPerInterval(delta_time_ms);
     }
     paced_sender::PacketList* packet_list;
-    while (ShouldSendNextPacket(&packet_list)) {
+    while (ShouldSendNextPacket(&packet_list, prober_->IsProbing())) {
       if (!SendPacketFromList(packet_list))
         return 0;
+      // Send one packet per Process() call when probing, so that we have
+      // better control over the delta between packets.
+      if (prober_->IsProbing())
+        return 0;
     }
-    if (high_priority_packets_->empty() &&
-        normal_priority_packets_->empty() &&
+    if (high_priority_packets_->empty() && normal_priority_packets_->empty() &&
         low_priority_packets_->empty() &&
         padding_budget_->bytes_remaining() > 0) {
       int padding_needed = padding_budget_->bytes_remaining();
@@ -325,12 +361,13 @@
   padding_budget_->IncreaseBudget(delta_time_ms);
 }
 
-bool PacedSender::ShouldSendNextPacket(paced_sender::PacketList** packet_list) {
+bool PacedSender::ShouldSendNextPacket(paced_sender::PacketList** packet_list,
+                                       bool probe) {
   *packet_list = NULL;
-  if (media_budget_->bytes_remaining() <= 0) {
+  if (!probe && media_budget_->bytes_remaining() <= 0) {
     // All bytes consumed for this interval.
     // Check if we have not sent in a too long time.
-    if (clock_->TimeInMicroseconds() - time_last_send_us_ >
+    if (clock_->TimeInMicroseconds() - time_last_media_send_us_ >
         kMaxQueueTimeWithoutSendingUs) {
       if (!high_priority_packets_->empty()) {
         *packet_list = high_priority_packets_.get();
@@ -383,9 +420,14 @@
 }
 
 void PacedSender::UpdateMediaBytesSent(int num_bytes) {
-  time_last_send_us_ = clock_->TimeInMicroseconds();
+  prober_->PacketSent(clock_->TimeInMilliseconds(), num_bytes);
+  time_last_media_send_us_ = clock_->TimeInMicroseconds();
   media_budget_->UseBudget(num_bytes);
   padding_budget_->UseBudget(num_bytes);
 }
 
+bool PacedSender::ProbingExperimentIsEnabled() const {
+  return webrtc::field_trial::FindFullName("WebRTC-BitrateProbing") ==
+         "Enabled";
+}
 }  // namespace webrtc
diff --git a/webrtc/modules/pacing/paced_sender_unittest.cc b/webrtc/modules/pacing/paced_sender_unittest.cc
index 14dcdbc..f8028a9 100644
--- a/webrtc/modules/pacing/paced_sender_unittest.cc
+++ b/webrtc/modules/pacing/paced_sender_unittest.cc
@@ -8,9 +8,10 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#include <list>
+
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
-
 #include "webrtc/modules/pacing/include/paced_sender.h"
 #include "webrtc/system_wrappers/interface/clock.h"
 
@@ -26,8 +27,10 @@
 class MockPacedSenderCallback : public PacedSender::Callback {
  public:
   MOCK_METHOD4(TimeToSendPacket,
-      bool(uint32_t ssrc, uint16_t sequence_number, int64_t capture_time_ms,
-           bool retransmission));
+               bool(uint32_t ssrc,
+                    uint16_t sequence_number,
+                    int64_t capture_time_ms,
+                    bool retransmission));
   MOCK_METHOD1(TimeToSendPadding,
       int(int bytes));
 };
@@ -36,8 +39,10 @@
  public:
   PacedSenderPadding() : padding_sent_(0) {}
 
-  bool TimeToSendPacket(uint32_t ssrc, uint16_t sequence_number,
-                        int64_t capture_time_ms, bool retransmission) {
+  bool TimeToSendPacket(uint32_t ssrc,
+                        uint16_t sequence_number,
+                        int64_t capture_time_ms,
+                        bool retransmission) {
     return true;
   }
 
@@ -54,24 +59,67 @@
   int padding_sent_;
 };
 
+class PacedSenderProbing : public PacedSender::Callback {
+ public:
+  PacedSenderProbing(const std::list<int>& expected_deltas, Clock* clock)
+      : prev_packet_time_ms_(-1),
+        expected_deltas_(expected_deltas),
+        packets_sent_(0),
+        clock_(clock) {}
+
+  bool TimeToSendPacket(uint32_t ssrc,
+                        uint16_t sequence_number,
+                        int64_t capture_time_ms,
+                        bool retransmission) {
+    ++packets_sent_;
+    EXPECT_FALSE(expected_deltas_.empty());
+    if (expected_deltas_.empty())
+      return false;
+    int64_t now_ms = clock_->TimeInMilliseconds();
+    if (prev_packet_time_ms_ >= 0) {
+      EXPECT_EQ(expected_deltas_.front(), now_ms - prev_packet_time_ms_);
+      expected_deltas_.pop_front();
+    }
+    prev_packet_time_ms_ = now_ms;
+    return true;
+  }
+
+  int TimeToSendPadding(int bytes) {
+    EXPECT_TRUE(false);
+    return bytes;
+  }
+
+  int packets_sent() const { return packets_sent_; }
+
+ private:
+  int64_t prev_packet_time_ms_;
+  std::list<int> expected_deltas_;
+  int packets_sent_;
+  Clock* clock_;
+};
+
 class PacedSenderTest : public ::testing::Test {
  protected:
   PacedSenderTest() : clock_(123456) {
     srand(0);
     // Need to initialize PacedSender after we initialize clock.
-    send_bucket_.reset(
-        new PacedSender(
-            &clock_, &callback_, kPaceMultiplier * kTargetBitrate, 0));
+    send_bucket_.reset(new PacedSender(&clock_,
+                                       &callback_,
+                                       kTargetBitrate,
+                                       kPaceMultiplier * kTargetBitrate,
+                                       0));
   }
 
   void SendAndExpectPacket(PacedSender::Priority priority,
-                           uint32_t ssrc, uint16_t sequence_number,
-                           int64_t capture_time_ms, int size,
+                           uint32_t ssrc,
+                           uint16_t sequence_number,
+                           int64_t capture_time_ms,
+                           int size,
                            bool retransmission) {
     EXPECT_FALSE(send_bucket_->SendPacket(priority, ssrc,
         sequence_number, capture_time_ms, size, retransmission));
-    EXPECT_CALL(callback_, TimeToSendPacket(
-        ssrc, sequence_number, capture_time_ms, false))
+    EXPECT_CALL(callback_,
+                TimeToSendPacket(ssrc, sequence_number, capture_time_ms, false))
         .Times(1)
         .WillRepeatedly(Return(true));
   }
@@ -85,12 +133,24 @@
   uint32_t ssrc = 12345;
   uint16_t sequence_number = 1234;
   // Due to the multiplicative factor we can send 3 packets not 2 packets.
-  SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
-                      clock_.TimeInMilliseconds(), 250, false);
-  SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
-                      clock_.TimeInMilliseconds(), 250, false);
-  SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
-                      clock_.TimeInMilliseconds(), 250, false);
+  SendAndExpectPacket(PacedSender::kNormalPriority,
+                      ssrc,
+                      sequence_number++,
+                      clock_.TimeInMilliseconds(),
+                      250,
+                      false);
+  SendAndExpectPacket(PacedSender::kNormalPriority,
+                      ssrc,
+                      sequence_number++,
+                      clock_.TimeInMilliseconds(),
+                      250,
+                      false);
+  SendAndExpectPacket(PacedSender::kNormalPriority,
+                      ssrc,
+                      sequence_number++,
+                      clock_.TimeInMilliseconds(),
+                      250,
+                      false);
   int64_t queued_packet_timestamp = clock_.TimeInMilliseconds();
   EXPECT_FALSE(send_bucket_->SendPacket(PacedSender::kNormalPriority, ssrc,
       sequence_number, queued_packet_timestamp, 250, false));
@@ -101,16 +161,25 @@
   EXPECT_EQ(1, send_bucket_->TimeUntilNextProcess());
   clock_.AdvanceTimeMilliseconds(1);
   EXPECT_EQ(0, send_bucket_->TimeUntilNextProcess());
-  EXPECT_CALL(callback_, TimeToSendPacket(
-      ssrc, sequence_number++, queued_packet_timestamp, false))
+  EXPECT_CALL(
+      callback_,
+      TimeToSendPacket(ssrc, sequence_number++, queued_packet_timestamp, false))
       .Times(1)
       .WillRepeatedly(Return(true));
   send_bucket_->Process();
   sequence_number++;
-  SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
-                      clock_.TimeInMilliseconds(), 250, false);
-  SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
-                      clock_.TimeInMilliseconds(), 250, false);
+  SendAndExpectPacket(PacedSender::kNormalPriority,
+                      ssrc,
+                      sequence_number++,
+                      clock_.TimeInMilliseconds(),
+                      250,
+                      false);
+  SendAndExpectPacket(PacedSender::kNormalPriority,
+                      ssrc,
+                      sequence_number++,
+                      clock_.TimeInMilliseconds(),
+                      250,
+                      false);
   EXPECT_FALSE(send_bucket_->SendPacket(PacedSender::kNormalPriority, ssrc,
       sequence_number++, clock_.TimeInMilliseconds(), 250, false));
   send_bucket_->Process();
@@ -122,8 +191,12 @@
 
   // Due to the multiplicative factor we can send 3 packets not 2 packets.
   for (int i = 0; i < 3; ++i) {
-    SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
-                        clock_.TimeInMilliseconds(), 250, false);
+    SendAndExpectPacket(PacedSender::kNormalPriority,
+                        ssrc,
+                        sequence_number++,
+                        clock_.TimeInMilliseconds(),
+                        250,
+                        false);
   }
   for (int j = 0; j < 30; ++j) {
     EXPECT_FALSE(send_bucket_->SendPacket(PacedSender::kNormalPriority, ssrc,
@@ -134,8 +207,7 @@
   for (int k = 0; k < 10; ++k) {
     EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess());
     clock_.AdvanceTimeMilliseconds(5);
-    EXPECT_CALL(callback_,
-        TimeToSendPacket(ssrc, _, _, false))
+    EXPECT_CALL(callback_, TimeToSendPacket(ssrc, _, _, false))
         .Times(3)
         .WillRepeatedly(Return(true));
     EXPECT_EQ(0, send_bucket_->TimeUntilNextProcess());
@@ -145,12 +217,24 @@
   clock_.AdvanceTimeMilliseconds(5);
   EXPECT_EQ(0, send_bucket_->TimeUntilNextProcess());
   EXPECT_EQ(0, send_bucket_->Process());
-  SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
-                      clock_.TimeInMilliseconds(), 250, false);
-  SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
-                      clock_.TimeInMilliseconds(), 250, false);
-  SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
-                      clock_.TimeInMilliseconds(), 250, false);
+  SendAndExpectPacket(PacedSender::kNormalPriority,
+                      ssrc,
+                      sequence_number++,
+                      clock_.TimeInMilliseconds(),
+                      250,
+                      false);
+  SendAndExpectPacket(PacedSender::kNormalPriority,
+                      ssrc,
+                      sequence_number++,
+                      clock_.TimeInMilliseconds(),
+                      250,
+                      false);
+  SendAndExpectPacket(PacedSender::kNormalPriority,
+                      ssrc,
+                      sequence_number++,
+                      clock_.TimeInMilliseconds(),
+                      250,
+                      false);
   EXPECT_FALSE(send_bucket_->SendPacket(PacedSender::kNormalPriority, ssrc,
       sequence_number, clock_.TimeInMilliseconds(), 250, false));
   send_bucket_->Process();
@@ -163,8 +247,12 @@
 
   // Due to the multiplicative factor we can send 3 packets not 2 packets.
   for (int i = 0; i < 3; ++i) {
-    SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
-                        clock_.TimeInMilliseconds(), 250, false);
+    SendAndExpectPacket(PacedSender::kNormalPriority,
+                        ssrc,
+                        sequence_number++,
+                        clock_.TimeInMilliseconds(),
+                        250,
+                        false);
   }
   queued_sequence_number = sequence_number;
 
@@ -182,9 +270,8 @@
     clock_.AdvanceTimeMilliseconds(5);
 
     for (int i = 0; i < 3; ++i) {
-      EXPECT_CALL(callback_, TimeToSendPacket(ssrc, queued_sequence_number++,
-                                              _,
-                                              false))
+      EXPECT_CALL(callback_,
+                  TimeToSendPacket(ssrc, queued_sequence_number++, _, false))
           .Times(1)
           .WillRepeatedly(Return(true));
    }
@@ -195,12 +282,24 @@
   clock_.AdvanceTimeMilliseconds(5);
   EXPECT_EQ(0, send_bucket_->TimeUntilNextProcess());
   EXPECT_EQ(0, send_bucket_->Process());
-  SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
-                      clock_.TimeInMilliseconds(), 250, false);
-  SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
-                      clock_.TimeInMilliseconds(), 250, false);
-  SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
-                      clock_.TimeInMilliseconds(), 250, false);
+  SendAndExpectPacket(PacedSender::kNormalPriority,
+                      ssrc,
+                      sequence_number++,
+                      clock_.TimeInMilliseconds(),
+                      250,
+                      false);
+  SendAndExpectPacket(PacedSender::kNormalPriority,
+                      ssrc,
+                      sequence_number++,
+                      clock_.TimeInMilliseconds(),
+                      250,
+                      false);
+  SendAndExpectPacket(PacedSender::kNormalPriority,
+                      ssrc,
+                      sequence_number++,
+                      clock_.TimeInMilliseconds(),
+                      250,
+                      false);
   EXPECT_FALSE(send_bucket_->SendPacket(PacedSender::kNormalPriority, ssrc,
       sequence_number++, clock_.TimeInMilliseconds(), 250, false));
   send_bucket_->Process();
@@ -233,14 +332,27 @@
   uint32_t ssrc = 12345;
   uint16_t sequence_number = 1234;
 
-  send_bucket_->UpdateBitrate(kPaceMultiplier * kTargetBitrate, kTargetBitrate);
+  send_bucket_->UpdateBitrate(
+      kTargetBitrate, kPaceMultiplier * kTargetBitrate, kTargetBitrate);
   // Due to the multiplicative factor we can send 3 packets not 2 packets.
-  SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
-                      clock_.TimeInMilliseconds(), 250, false);
-  SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
-                      clock_.TimeInMilliseconds(), 250, false);
-  SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
-                      clock_.TimeInMilliseconds(), 250, false);
+  SendAndExpectPacket(PacedSender::kNormalPriority,
+                      ssrc,
+                      sequence_number++,
+                      clock_.TimeInMilliseconds(),
+                      250,
+                      false);
+  SendAndExpectPacket(PacedSender::kNormalPriority,
+                      ssrc,
+                      sequence_number++,
+                      clock_.TimeInMilliseconds(),
+                      250,
+                      false);
+  SendAndExpectPacket(PacedSender::kNormalPriority,
+                      ssrc,
+                      sequence_number++,
+                      clock_.TimeInMilliseconds(),
+                      250,
+                      false);
   // No padding is expected since we have sent too much already.
   EXPECT_CALL(callback_, TimeToSendPadding(_)).Times(0);
   EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess());
@@ -259,7 +371,8 @@
 
 TEST_F(PacedSenderTest, NoPaddingWhenDisabled) {
   send_bucket_->SetStatus(false);
-  send_bucket_->UpdateBitrate(kPaceMultiplier * kTargetBitrate, kTargetBitrate);
+  send_bucket_->UpdateBitrate(
+      kTargetBitrate, kPaceMultiplier * kTargetBitrate, kTargetBitrate);
   // No padding is expected since the pacer is disabled.
   EXPECT_CALL(callback_, TimeToSendPadding(_)).Times(0);
   EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess());
@@ -279,11 +392,16 @@
   int64_t capture_time_ms = 56789;
   const int kTimeStep = 5;
   const int64_t kBitrateWindow = 100;
-  send_bucket_->UpdateBitrate(kPaceMultiplier * kTargetBitrate, kTargetBitrate);
+  send_bucket_->UpdateBitrate(
+      kTargetBitrate, kPaceMultiplier * kTargetBitrate, kTargetBitrate);
   int64_t start_time = clock_.TimeInMilliseconds();
   while (clock_.TimeInMilliseconds() - start_time < kBitrateWindow) {
-    SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
-                        capture_time_ms, 250, false);
+    SendAndExpectPacket(PacedSender::kNormalPriority,
+                        ssrc,
+                        sequence_number++,
+                        capture_time_ms,
+                        250,
+                        false);
     clock_.AdvanceTimeMilliseconds(kTimeStep);
     EXPECT_CALL(callback_, TimeToSendPadding(250)).Times(1).
         WillOnce(Return(250));
@@ -298,9 +416,10 @@
   const int kTimeStep = 5;
   const int64_t kBitrateWindow = 10000;
   PacedSenderPadding callback;
-  send_bucket_.reset(
-      new PacedSender(&clock_, &callback, kPaceMultiplier * kTargetBitrate, 0));
-  send_bucket_->UpdateBitrate(kPaceMultiplier * kTargetBitrate, kTargetBitrate);
+  send_bucket_.reset(new PacedSender(
+      &clock_, &callback, kTargetBitrate, kPaceMultiplier * kTargetBitrate, 0));
+  send_bucket_->UpdateBitrate(
+      kTargetBitrate, kPaceMultiplier * kTargetBitrate, kTargetBitrate);
   int64_t start_time = clock_.TimeInMilliseconds();
   int media_bytes = 0;
   while (clock_.TimeInMilliseconds() - start_time < kBitrateWindow) {
@@ -324,12 +443,24 @@
   int64_t capture_time_ms_low_priority = 1234567;
 
   // Due to the multiplicative factor we can send 3 packets not 2 packets.
-  SendAndExpectPacket(PacedSender::kLowPriority, ssrc, sequence_number++,
-                      capture_time_ms, 250, false);
-  SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
-                      capture_time_ms, 250, false);
-  SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
-                      capture_time_ms, 250, false);
+  SendAndExpectPacket(PacedSender::kLowPriority,
+                      ssrc,
+                      sequence_number++,
+                      capture_time_ms,
+                      250,
+                      false);
+  SendAndExpectPacket(PacedSender::kNormalPriority,
+                      ssrc,
+                      sequence_number++,
+                      capture_time_ms,
+                      250,
+                      false);
+  SendAndExpectPacket(PacedSender::kNormalPriority,
+                      ssrc,
+                      sequence_number++,
+                      capture_time_ms,
+                      250,
+                      false);
   send_bucket_->Process();
 
   // Expect normal and low priority to be queued and high to pass through.
@@ -354,8 +485,9 @@
   EXPECT_EQ(0, send_bucket_->TimeUntilNextProcess());
   EXPECT_EQ(0, send_bucket_->Process());
 
-  EXPECT_CALL(callback_, TimeToSendPacket(
-      ssrc_low_priority, _, capture_time_ms_low_priority, false))
+  EXPECT_CALL(callback_,
+              TimeToSendPacket(
+                  ssrc_low_priority, _, capture_time_ms_low_priority, false))
       .Times(1)
       .WillRepeatedly(Return(true));
 
@@ -374,12 +506,24 @@
   EXPECT_EQ(0, send_bucket_->QueueInMs());
 
   // Due to the multiplicative factor we can send 3 packets not 2 packets.
-  SendAndExpectPacket(PacedSender::kLowPriority, ssrc, sequence_number++,
-                      capture_time_ms, 250, false);
-  SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
-                      capture_time_ms, 250, false);
-  SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
-                      capture_time_ms, 250, false);
+  SendAndExpectPacket(PacedSender::kLowPriority,
+                      ssrc,
+                      sequence_number++,
+                      capture_time_ms,
+                      250,
+                      false);
+  SendAndExpectPacket(PacedSender::kNormalPriority,
+                      ssrc,
+                      sequence_number++,
+                      capture_time_ms,
+                      250,
+                      false);
+  SendAndExpectPacket(PacedSender::kNormalPriority,
+                      ssrc,
+                      sequence_number++,
+                      capture_time_ms,
+                      250,
+                      false);
   send_bucket_->Process();
 
   send_bucket_->Pause();
@@ -423,8 +567,7 @@
   EXPECT_EQ(0, send_bucket_->TimeUntilNextProcess());
   EXPECT_EQ(0, send_bucket_->Process());
 
-  EXPECT_CALL(
-      callback_, TimeToSendPacket(_, _, second_capture_time_ms, false))
+  EXPECT_CALL(callback_, TimeToSendPacket(_, _, second_capture_time_ms, false))
       .Times(1)
       .WillRepeatedly(Return(true));
   EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess());
@@ -457,8 +600,8 @@
   EXPECT_EQ(clock_.TimeInMilliseconds() - capture_time_ms,
             send_bucket_->QueueInMs());
   // Fails to send first packet so only one call.
-  EXPECT_CALL(callback_, TimeToSendPacket(
-      ssrc, sequence_number, capture_time_ms, false))
+  EXPECT_CALL(callback_,
+              TimeToSendPacket(ssrc, sequence_number, capture_time_ms, false))
       .Times(1)
       .WillOnce(Return(false));
   clock_.AdvanceTimeMilliseconds(10000);
@@ -469,12 +612,13 @@
             send_bucket_->QueueInMs());
 
   // Fails to send second packet.
-  EXPECT_CALL(callback_, TimeToSendPacket(
-      ssrc, sequence_number, capture_time_ms, false))
+  EXPECT_CALL(callback_,
+              TimeToSendPacket(ssrc, sequence_number, capture_time_ms, false))
       .Times(1)
       .WillOnce(Return(true));
-  EXPECT_CALL(callback_, TimeToSendPacket(
-      ssrc, sequence_number + 1, capture_time_ms + 1, false))
+  EXPECT_CALL(
+      callback_,
+      TimeToSendPacket(ssrc, sequence_number + 1, capture_time_ms + 1, false))
       .Times(1)
       .WillOnce(Return(false));
   clock_.AdvanceTimeMilliseconds(10000);
@@ -485,8 +629,9 @@
             send_bucket_->QueueInMs());
 
   // Send second packet and queue becomes empty.
-  EXPECT_CALL(callback_, TimeToSendPacket(
-      ssrc, sequence_number + 1, capture_time_ms + 1, false))
+  EXPECT_CALL(
+      callback_,
+      TimeToSendPacket(ssrc, sequence_number + 1, capture_time_ms + 1, false))
       .Times(1)
       .WillOnce(Return(true));
   clock_.AdvanceTimeMilliseconds(10000);
@@ -499,7 +644,7 @@
   uint16_t sequence_number = 1234;
   EXPECT_EQ(0, send_bucket_->QueueInMs());
 
-  send_bucket_->UpdateBitrate(kPaceMultiplier * 30, 0);
+  send_bucket_->UpdateBitrate(30, kPaceMultiplier * 30, 0);
   for (int i = 0; i < 30; ++i) {
     SendAndExpectPacket(PacedSender::kNormalPriority,
                         ssrc,
@@ -529,7 +674,7 @@
   uint16_t sequence_number = 1234;
   EXPECT_EQ(0, send_bucket_->QueueInMs());
 
-  send_bucket_->UpdateBitrate(kPaceMultiplier * 30, 0);
+  send_bucket_->UpdateBitrate(30, kPaceMultiplier * 30, 0);
   SendAndExpectPacket(PacedSender::kNormalPriority,
                       ssrc,
                       sequence_number,
@@ -542,5 +687,56 @@
   send_bucket_->Process();
   EXPECT_EQ(0, send_bucket_->QueueInMs());
 }
+
+class ProbingPacedSender : public PacedSender {
+ public:
+  ProbingPacedSender(Clock* clock,
+                     Callback* callback,
+                     int bitrate_kbps,
+                     int max_bitrate_kbps,
+                     int min_bitrate_kbps)
+      : PacedSender(clock,
+                    callback,
+                    bitrate_kbps,
+                    max_bitrate_kbps,
+                    min_bitrate_kbps) {}
+
+  virtual bool ProbingExperimentIsEnabled() const OVERRIDE { return true; }
+};
+
+TEST_F(PacedSenderTest, ProbingWithInitialFrame) {
+  const int kNumPackets = 15;
+  const int kPacketSize = 1200;
+  const int kInitialBitrateKbps = 300;
+  uint32_t ssrc = 12346;
+  uint16_t sequence_number = 1234;
+  const int expected_deltas[kNumPackets - 1] = {
+      12, 12, 12, 12, 8, 8, 8, 8, 8, 5, 5, 5, 5, 5};
+  std::list<int> expected_deltas_list(expected_deltas,
+                                      expected_deltas + kNumPackets - 1);
+  PacedSenderProbing callback(expected_deltas_list, &clock_);
+  send_bucket_.reset(
+      new ProbingPacedSender(&clock_,
+                             &callback,
+                             kInitialBitrateKbps,
+                             kPaceMultiplier * kInitialBitrateKbps,
+                             0));
+  for (int i = 0; i < kNumPackets; ++i) {
+    EXPECT_FALSE(send_bucket_->SendPacket(PacedSender::kNormalPriority,
+                                          ssrc,
+                                          sequence_number++,
+                                          clock_.TimeInMilliseconds(),
+                                          kPacketSize,
+                                          false));
+  }
+  while (callback.packets_sent() < kNumPackets) {
+    int time_until_process = send_bucket_->TimeUntilNextProcess();
+    if (time_until_process <= 0) {
+      send_bucket_->Process();
+    } else {
+      clock_.AdvanceTimeMilliseconds(time_until_process);
+    }
+  }
+}
 }  // namespace test
 }  // namespace webrtc
diff --git a/webrtc/modules/pacing/pacing.gypi b/webrtc/modules/pacing/pacing.gypi
index 07b4338..3668450 100644
--- a/webrtc/modules/pacing/pacing.gypi
+++ b/webrtc/modules/pacing/pacing.gypi
@@ -16,6 +16,8 @@
       ],
       'sources': [
         'include/paced_sender.h',
+        'bitrate_prober.cc',
+        'bitrate_prober.h',
         'paced_sender.cc',
       ],
     },
diff --git a/webrtc/modules/remote_bitrate_estimator/bwe_simulations.cc b/webrtc/modules/remote_bitrate_estimator/bwe_simulations.cc
index 142de87..f47984c 100644
--- a/webrtc/modules/remote_bitrate_estimator/bwe_simulations.cc
+++ b/webrtc/modules/remote_bitrate_estimator/bwe_simulations.cc
@@ -98,7 +98,7 @@
 
 TEST_P(BweSimulation, PacerChoke1000kbps500kbps1000kbps) {
   VerboseLogging(true);
-  AdaptiveVideoSender source(0, NULL, 30, 300, 0, 0);
+  PeriodicKeyFrameSender source(0, NULL, 30, 300, 0, 0, 1000);
   PacedVideoSender sender(this, 300, &source);
   ChokeFilter filter(this);
   RateCounterFilter counter(this, "receiver_input");
@@ -111,9 +111,20 @@
   RunFor(60 * 1000);
 }
 
+TEST_P(BweSimulation, PacerChoke10000kbps) {
+  VerboseLogging(true);
+  PeriodicKeyFrameSender source(0, NULL, 30, 300, 0, 0, 0);
+  PacedVideoSender sender(this, 300, &source);
+  ChokeFilter filter(this);
+  RateCounterFilter counter(this, "receiver_input");
+  filter.SetCapacity(10000);
+  filter.SetMaxDelay(500);
+  RunFor(60 * 1000);
+}
+
 TEST_P(BweSimulation, PacerChoke200kbps30kbps200kbps) {
   VerboseLogging(true);
-  AdaptiveVideoSender source(0, NULL, 30, 300, 0, 0);
+  PeriodicKeyFrameSender source(0, NULL, 30, 300, 0, 0, 1000);
   PacedVideoSender sender(this, 300, &source);
   ChokeFilter filter(this);
   RateCounterFilter counter(this, "receiver_input");
@@ -151,6 +162,18 @@
   RunFor(300 * 1000);
 }
 
+TEST_P(BweSimulation, PacerGoogleWifiTrace3Mbps) {
+  VerboseLogging(true);
+  PeriodicKeyFrameSender source(0, NULL, 30, 300, 0, 0, 1000);
+  PacedVideoSender sender(this, 300, &source);
+  RateCounterFilter counter1(this, "sender_output");
+  TraceBasedDeliveryFilter filter(this, "link_capacity");
+  filter.SetMaxDelay(500);
+  RateCounterFilter counter2(this, "receiver_input");
+  ASSERT_TRUE(filter.Init(test::ResourcePath("google-wifi-3mbps", "rx")));
+  RunFor(300 * 1000);
+}
+
 class MultiFlowBweSimulation : public BweSimulation {
  public:
   MultiFlowBweSimulation() : BweSimulation() {}
diff --git a/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.cc b/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.cc
index 194db4d..f7a7197 100644
--- a/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.cc
+++ b/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.cc
@@ -155,6 +155,7 @@
 }
 
 void Packet::SetAbsSendTimeMs(int64_t abs_send_time_ms) {
+  header_.extension.hasAbsoluteSendTime = true;
   header_.extension.absoluteSendTime = ((static_cast<int64_t>(abs_send_time_ms *
     (1 << 18)) + 500) / 1000) & 0x00fffffful;
 }
@@ -543,8 +544,11 @@
 
 }
 
-VideoSender::VideoSender(int flow_id, PacketProcessorListener* listener,
-                         float fps, uint32_t kbps, uint32_t ssrc,
+VideoSender::VideoSender(int flow_id,
+                         PacketProcessorListener* listener,
+                         float fps,
+                         uint32_t kbps,
+                         uint32_t ssrc,
                          float first_frame_offset)
     : PacketSender(listener, FlowIds(1, flow_id)),
       kMaxPayloadSizeBytes(1200),
@@ -566,6 +570,15 @@
   return (bytes_per_second_ * 8) / 1000;
 }
 
+uint32_t VideoSender::NextFrameSize() {
+  return frame_size_bytes_;
+}
+
+uint32_t VideoSender::NextPacketSize(uint32_t frame_size,
+                                     uint32_t remaining_payload) {
+  return std::min(kMaxPayloadSizeBytes, remaining_payload);
+}
+
 void VideoSender::RunFor(int64_t time_ms, Packets* in_out) {
   assert(in_out);
   now_ms_ += time_ms;
@@ -580,10 +593,12 @@
     // one packet, we will see a number of equally sized packets followed by
     // one smaller at the tail.
     int64_t send_time_us = next_frame_ms_ * 1000.0;
-    uint32_t payload_size = frame_size_bytes_;
+    uint32_t frame_size = NextFrameSize();
+    uint32_t payload_size = frame_size;
+
     while (payload_size > 0) {
       ++prototype_header_.sequenceNumber;
-      uint32_t size = std::min(kMaxPayloadSizeBytes, payload_size);
+      uint32_t size = NextPacketSize(frame_size, payload_size);
       new_packets.push_back(Packet(flow_ids()[0], send_time_us, size,
                                    prototype_header_));
       new_packets.back().SetAbsSendTimeMs(next_frame_ms_);
@@ -601,13 +616,69 @@
                                          uint32_t kbps,
                                          uint32_t ssrc,
                                          float first_frame_offset)
-    : VideoSender(flow_id, listener, fps, kbps, ssrc, first_frame_offset) {}
+    : VideoSender(flow_id, listener, fps, kbps, ssrc, first_frame_offset) {
+}
 
 void AdaptiveVideoSender::GiveFeedback(const PacketSender::Feedback& feedback) {
-  bytes_per_second_ = feedback.estimated_bps / 8;
+  bytes_per_second_ = std::min(feedback.estimated_bps / 8, 2500000u / 8);
   frame_size_bytes_ = (bytes_per_second_ * frame_period_ms_ + 500) / 1000;
 }
 
+PeriodicKeyFrameSender::PeriodicKeyFrameSender(
+    int flow_id,
+    PacketProcessorListener* listener,
+    float fps,
+    uint32_t kbps,
+    uint32_t ssrc,
+    float first_frame_offset,
+    int key_frame_interval)
+    : AdaptiveVideoSender(flow_id,
+                          listener,
+                          fps,
+                          kbps,
+                          ssrc,
+                          first_frame_offset),
+      key_frame_interval_(key_frame_interval),
+      frame_counter_(0),
+      compensation_bytes_(0),
+      compensation_per_frame_(0) {
+}
+
+uint32_t PeriodicKeyFrameSender::NextFrameSize() {
+  uint32_t payload_size = frame_size_bytes_;
+  if (frame_counter_ == 0) {
+    payload_size = kMaxPayloadSizeBytes * 12;
+    compensation_bytes_ = 4 * frame_size_bytes_;
+    compensation_per_frame_ = compensation_bytes_ / 30;
+  } else if (key_frame_interval_ > 0 &&
+             (frame_counter_ % key_frame_interval_ == 0)) {
+    payload_size *= 5;
+    compensation_bytes_ = payload_size - frame_size_bytes_;
+    compensation_per_frame_ = compensation_bytes_ / 30;
+  } else if (compensation_bytes_ > 0) {
+    if (compensation_per_frame_ > static_cast<int>(payload_size)) {
+      // Skip this frame.
+      compensation_bytes_ -= payload_size;
+      payload_size = 0;
+    } else {
+      payload_size -= compensation_per_frame_;
+      compensation_bytes_ -= compensation_per_frame_;
+    }
+  }
+  if (compensation_bytes_ < 0)
+    compensation_bytes_ = 0;
+  ++frame_counter_;
+  return payload_size;
+}
+
+uint32_t PeriodicKeyFrameSender::NextPacketSize(uint32_t frame_size,
+                                                uint32_t remaining_payload) {
+  uint32_t fragments =
+      (frame_size + (kMaxPayloadSizeBytes - 1)) / kMaxPayloadSizeBytes;
+  uint32_t avg_size = (frame_size + fragments - 1) / fragments;
+  return std::min(avg_size, remaining_payload);
+}
+
 PacedVideoSender::PacedVideoSender(PacketProcessorListener* listener,
                                    uint32_t kbps,
                                    AdaptiveVideoSender* source)
@@ -617,22 +688,40 @@
     : PacketSender(listener, source->flow_ids()),
       clock_(0),
       start_of_run_ms_(0),
-      pacer_(&clock_, this, PacedSender::kDefaultPaceMultiplier * kbps, 0),
-      source_(source) {}
+      pacer_(&clock_, this, kbps, PacedSender::kDefaultPaceMultiplier* kbps, 0),
+      source_(source) {
+}
 
 void PacedVideoSender::RunFor(int64_t time_ms, Packets* in_out) {
   start_of_run_ms_ = clock_.TimeInMilliseconds();
   Packets generated_packets;
   source_->RunFor(time_ms, &generated_packets);
-  Packets::iterator it = generated_packets.begin();
   // Run process periodically to allow the packets to be paced out.
-  const int kProcessIntervalMs = 10;
-  for (int64_t current_time = 0; current_time < time_ms;
-       current_time += kProcessIntervalMs) {
-    int64_t end_of_interval_us =
-        1000 * (clock_.TimeInMilliseconds() + kProcessIntervalMs);
-    while (it != generated_packets.end() &&
-           end_of_interval_us >= it->send_time_us()) {
+  int64_t end_time_ms = clock_.TimeInMilliseconds() + time_ms;
+  Packets::iterator it = generated_packets.begin();
+  while (clock_.TimeInMilliseconds() <= end_time_ms) {
+    int time_until_process_ms = pacer_.TimeUntilNextProcess();
+    if (time_until_process_ms < 0)
+      time_until_process_ms = 0;
+    int time_until_packet_ms = time_ms;
+    if (it != generated_packets.end())
+      time_until_packet_ms =
+          (it->send_time_us() + 500) / 1000 - clock_.TimeInMilliseconds();
+    assert(time_until_packet_ms >= 0);
+    int time_until_next_event_ms = time_until_packet_ms;
+    if (time_until_process_ms < time_until_packet_ms &&
+        pacer_.QueueSizePackets() > 0)
+      time_until_next_event_ms = time_until_process_ms;
+
+    if (clock_.TimeInMilliseconds() + time_until_next_event_ms > end_time_ms) {
+      clock_.AdvanceTimeMilliseconds(end_time_ms - clock_.TimeInMilliseconds());
+      break;
+    }
+    clock_.AdvanceTimeMilliseconds(time_until_next_event_ms);
+    if (time_until_process_ms < time_until_packet_ms) {
+      // Time to process.
+      pacer_.Process();
+    } else {
       // Time to send next packet to pacer.
       pacer_.SendPacket(PacedSender::kNormalPriority,
                         it->header().ssrc,
@@ -641,16 +730,14 @@
                         it->payload_size(),
                         false);
       pacer_queue_.push_back(*it);
-      const size_t kMaxPacerQueueSize = 1000;
+      const size_t kMaxPacerQueueSize = 10000;
       if (pacer_queue_.size() > kMaxPacerQueueSize) {
         pacer_queue_.pop_front();
       }
       ++it;
     }
-    clock_.AdvanceTimeMilliseconds(kProcessIntervalMs);
-    pacer_.Process();
   }
-  QueuePackets(in_out, (start_of_run_ms_ + time_ms) * 1000);
+  QueuePackets(in_out, end_time_ms * 1000);
 }
 
 void PacedVideoSender::QueuePackets(Packets* batch,
@@ -673,7 +760,9 @@
 void PacedVideoSender::GiveFeedback(const PacketSender::Feedback& feedback) {
   source_->GiveFeedback(feedback);
   pacer_.UpdateBitrate(
-      PacedSender::kDefaultPaceMultiplier * feedback.estimated_bps / 1000, 0);
+      feedback.estimated_bps / 1000,
+      PacedSender::kDefaultPaceMultiplier * feedback.estimated_bps / 1000,
+      0);
 }
 
 bool PacedVideoSender::TimeToSendPacket(uint32_t ssrc,
@@ -686,7 +775,7 @@
       int64_t pace_out_time_ms = clock_.TimeInMilliseconds();
       // Make sure a packet is never paced out earlier than when it was put into
       // the pacer.
-      assert(1000 * pace_out_time_ms >= it->send_time_us());
+      assert(pace_out_time_ms >= (it->send_time_us() + 500) / 1000);
       it->SetAbsSendTimeMs(pace_out_time_ms);
       it->set_send_time_us(1000 * pace_out_time_ms);
       queue_.push_back(*it);
diff --git a/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.h b/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.h
index 0ab3b5f..6098197 100644
--- a/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.h
+++ b/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.h
@@ -387,8 +387,12 @@
 
 class VideoSender : public PacketSender {
  public:
-  VideoSender(int flow_id, PacketProcessorListener* listener, float fps,
-              uint32_t kbps, uint32_t ssrc, float first_frame_offset);
+  VideoSender(int flow_id,
+              PacketProcessorListener* listener,
+              float fps,
+              uint32_t kbps,
+              uint32_t ssrc,
+              float first_frame_offset);
   virtual ~VideoSender() {}
 
   uint32_t max_payload_size_bytes() const { return kMaxPayloadSizeBytes; }
@@ -399,6 +403,10 @@
   virtual void RunFor(int64_t time_ms, Packets* in_out) OVERRIDE;
 
  protected:
+  virtual uint32_t NextFrameSize();
+  virtual uint32_t NextPacketSize(uint32_t frame_size,
+                                  uint32_t remaining_payload);
+
   const uint32_t kMaxPayloadSizeBytes;
   const uint32_t kTimestampBase;
   const double frame_period_ms_;
@@ -427,6 +435,30 @@
   DISALLOW_IMPLICIT_CONSTRUCTORS(AdaptiveVideoSender);
 };
 
+class PeriodicKeyFrameSender : public AdaptiveVideoSender {
+ public:
+  PeriodicKeyFrameSender(int flow_id,
+                         PacketProcessorListener* listener,
+                         float fps,
+                         uint32_t kbps,
+                         uint32_t ssrc,
+                         float first_frame_offset,
+                         int key_frame_interval);
+  virtual ~PeriodicKeyFrameSender() {}
+
+ protected:
+  virtual uint32_t NextFrameSize() OVERRIDE;
+  virtual uint32_t NextPacketSize(uint32_t frame_size,
+                                  uint32_t remaining_payload) OVERRIDE;
+
+ private:
+  int key_frame_interval_;
+  uint32_t frame_counter_;
+  int compensation_bytes_;
+  int compensation_per_frame_;
+  DISALLOW_IMPLICIT_CONSTRUCTORS(PeriodicKeyFrameSender);
+};
+
 class PacedVideoSender : public PacketSender, public PacedSender::Callback {
  public:
   PacedVideoSender(PacketProcessorListener* listener,
@@ -445,12 +477,28 @@
   virtual int TimeToSendPadding(int bytes) OVERRIDE;
 
  private:
+  class ProbingPacedSender : public PacedSender {
+   public:
+    ProbingPacedSender(Clock* clock,
+                       Callback* callback,
+                       int bitrate_kbps,
+                       int max_bitrate_kbps,
+                       int min_bitrate_kbps)
+        : PacedSender(clock,
+                      callback,
+                      bitrate_kbps,
+                      max_bitrate_kbps,
+                      min_bitrate_kbps) {}
+
+    virtual bool ProbingExperimentIsEnabled() const OVERRIDE { return true; }
+  };
+
   void QueuePackets(Packets* batch, int64_t end_of_batch_time_us);
 
   static const int64_t kInitialTimeMs = 0;
   SimulatedClock clock_;
   int64_t start_of_run_ms_;
-  PacedSender pacer_;
+  ProbingPacedSender pacer_;
   Packets pacer_queue_;
   Packets queue_;
   AdaptiveVideoSender* source_;
diff --git a/webrtc/modules/video_coding/main/interface/video_coding_defines.h b/webrtc/modules/video_coding/main/interface/video_coding_defines.h
index c5f93cb..0919c892 100644
--- a/webrtc/modules/video_coding/main/interface/video_coding_defines.h
+++ b/webrtc/modules/video_coding/main/interface/video_coding_defines.h
@@ -42,6 +42,8 @@
 #define VCM_I420_PAYLOAD_TYPE      124
 #define VCM_H264_PAYLOAD_TYPE      127
 
+enum { kDefaultStartBitrateKbps = 300 };
+
 enum VCMVideoProtection {
   kProtectionNack,                // Both send-side and receive-side
   kProtectionNackSender,          // Send-side only
diff --git a/webrtc/modules/video_coding/main/source/codec_database.cc b/webrtc/modules/video_coding/main/source/codec_database.cc
index cd8f9d3..e99cc52 100644
--- a/webrtc/modules/video_coding/main/source/codec_database.cc
+++ b/webrtc/modules/video_coding/main/source/codec_database.cc
@@ -114,7 +114,7 @@
       settings->codecType = kVideoCodecVP8;
       // 96 to 127 dynamic payload types for video codecs.
       settings->plType = VCM_VP8_PAYLOAD_TYPE;
-      settings->startBitrate = 100;
+      settings->startBitrate = kDefaultStartBitrateKbps;
       settings->minBitrate = VCM_MIN_BITRATE;
       settings->maxBitrate = 0;
       settings->maxFramerate = VCM_DEFAULT_FRAME_RATE;
@@ -132,7 +132,7 @@
       settings->codecType = kVideoCodecH264;
       // 96 to 127 dynamic payload types for video codecs.
       settings->plType = VCM_H264_PAYLOAD_TYPE;
-      settings->startBitrate = 100;
+      settings->startBitrate = kDefaultStartBitrateKbps;
       settings->minBitrate = VCM_MIN_BITRATE;
       settings->maxBitrate = 0;
       settings->maxFramerate = VCM_DEFAULT_FRAME_RATE;
diff --git a/webrtc/video_engine/vie_encoder.cc b/webrtc/video_engine/vie_encoder.cc
index 0955066..26ad8ac 100644
--- a/webrtc/video_engine/vie_encoder.cc
+++ b/webrtc/video_engine/vie_encoder.cc
@@ -109,8 +109,10 @@
       : owner_(owner) {
   }
   virtual ~ViEPacedSenderCallback() {}
-  virtual bool TimeToSendPacket(uint32_t ssrc, uint16_t sequence_number,
-                                int64_t capture_time_ms, bool retransmission) {
+  virtual bool TimeToSendPacket(uint32_t ssrc,
+                                uint16_t sequence_number,
+                                int64_t capture_time_ms,
+                                bool retransmission) {
     return owner_->TimeToSendPacket(ssrc, sequence_number, capture_time_ms,
                                     retransmission);
   }
@@ -162,9 +164,12 @@
   default_rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(configuration));
   bitrate_observer_.reset(new ViEBitrateObserver(this));
   pacing_callback_.reset(new ViEPacedSenderCallback(this));
-  paced_sender_.reset(
-      new PacedSender(Clock::GetRealTimeClock(), pacing_callback_.get(),
-                      PacedSender::kDefaultInitialPaceKbps, 0));
+  paced_sender_.reset(new PacedSender(
+      Clock::GetRealTimeClock(),
+      pacing_callback_.get(),
+      kDefaultStartBitrateKbps,
+      PacedSender::kDefaultPaceMultiplier * kDefaultStartBitrateKbps,
+      0));
 }
 
 bool ViEEncoder::Init() {
@@ -368,6 +373,7 @@
     pad_up_to_bitrate_kbps = min_transmit_bitrate_kbps_;
 
   paced_sender_->UpdateBitrate(
+      video_codec.startBitrate,
       PacedSender::kDefaultPaceMultiplier * video_codec.startBitrate,
       pad_up_to_bitrate_kbps);
 
@@ -885,6 +891,7 @@
       pad_up_to_bitrate_kbps = bitrate_kbps;
 
     paced_sender_->UpdateBitrate(
+        bitrate_kbps,
         PacedSender::kDefaultPaceMultiplier * bitrate_kbps,
         pad_up_to_bitrate_kbps);
     default_rtp_rtcp_->SetTargetSendBitrate(stream_bitrates);