Wire up new feedback format by introducing a FeedbackPacket type.

The new format instantiates the RemoteBitrateEstimator at the send-side and feeds back all packet arrival timestamps and sequence numbers to the sender, where inter-arrival deltas are calculated.

Next step will be to make feedback packets part of regular packets and send them over the network. This also requires bi-directional simulations.

BUG=4173
R=mflodman@webrtc.org, sprang@webrtc.org

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

Cr-Commit-Position: refs/heads/master@{#8264}
git-svn-id: http://webrtc.googlecode.com/svn/trunk@8264 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/modules/remote_bitrate_estimator/bwe_simulations.cc b/webrtc/modules/remote_bitrate_estimator/bwe_simulations.cc
index 58c8b5b..f607fd0 100644
--- a/webrtc/modules/remote_bitrate_estimator/bwe_simulations.cc
+++ b/webrtc/modules/remote_bitrate_estimator/bwe_simulations.cc
@@ -25,7 +25,8 @@
       AbsoluteSendTimeRemoteBitrateEstimatorFactory();
 
   return BweTestConfig::EstimatorConfig("AST", flow_id, &factory, kAimdControl,
-                                        plot_delay, plot_estimate);
+                                        kRembEstimator, plot_delay,
+                                        plot_estimate);
 }
 
 BweTestConfig MakeAdaptiveBweTestConfig() {
@@ -65,7 +66,7 @@
 TEST_P(BweSimulation, SprintUplinkTest) {
   VerboseLogging(true);
   AdaptiveVideoSource source(0, 30, 300, 0, 0);
-  RegularVideoSender sender(this, &source, 300);
+  PacketSender sender(this, &source, kRembEstimator);
   RateCounterFilter counter1(this, "sender_output");
   TraceBasedDeliveryFilter filter(this, "link_capacity");
   RateCounterFilter counter2(this, "receiver_input");
@@ -76,7 +77,7 @@
 TEST_P(BweSimulation, Verizon4gDownlinkTest) {
   VerboseLogging(true);
   AdaptiveVideoSource source(0, 30, 300, 0, 0);
-  RegularVideoSender sender(this, &source, 300);
+  PacketSender sender(this, &source, kRembEstimator);
   RateCounterFilter counter1(this, "sender_output");
   TraceBasedDeliveryFilter filter(this, "link_capacity");
   RateCounterFilter counter2(this, "receiver_input");
@@ -87,7 +88,7 @@
 TEST_P(BweSimulation, Choke1000kbps500kbps1000kbps) {
   VerboseLogging(true);
   AdaptiveVideoSource source(0, 30, 300, 0, 0);
-  RegularVideoSender sender(this, &source, 300);
+  PacketSender sender(this, &source, kRembEstimator);
   ChokeFilter filter(this);
   RateCounterFilter counter(this, "receiver_input");
   filter.SetCapacity(1000);
@@ -102,7 +103,7 @@
 TEST_P(BweSimulation, PacerChoke1000kbps500kbps1000kbps) {
   VerboseLogging(true);
   PeriodicKeyFrameSource source(0, 30, 300, 0, 0, 1000);
-  PacedVideoSender sender(this, &source, 300);
+  PacedVideoSender sender(this, &source, kRembEstimator);
   ChokeFilter filter(this);
   RateCounterFilter counter(this, "receiver_input");
   filter.SetCapacity(1000);
@@ -117,7 +118,7 @@
 TEST_P(BweSimulation, PacerChoke10000kbps) {
   VerboseLogging(true);
   PeriodicKeyFrameSource source(0, 30, 300, 0, 0, 1000);
-  PacedVideoSender sender(this, &source, 300);
+  PacedVideoSender sender(this, &source, kRembEstimator);
   ChokeFilter filter(this);
   RateCounterFilter counter(this, "receiver_input");
   filter.SetCapacity(10000);
@@ -128,7 +129,7 @@
 TEST_P(BweSimulation, PacerChoke200kbps30kbps200kbps) {
   VerboseLogging(true);
   PeriodicKeyFrameSource source(0, 30, 300, 0, 0, 1000);
-  PacedVideoSender sender(this, &source, 300);
+  PacedVideoSender sender(this, &source, kRembEstimator);
   ChokeFilter filter(this);
   RateCounterFilter counter(this, "receiver_input");
   filter.SetCapacity(200);
@@ -143,7 +144,7 @@
 TEST_P(BweSimulation, Choke200kbps30kbps200kbps) {
   VerboseLogging(true);
   AdaptiveVideoSource source(0, 30, 300, 0, 0);
-  RegularVideoSender sender(this, &source, 300);
+  PacketSender sender(this, &source, kRembEstimator);
   ChokeFilter filter(this);
   RateCounterFilter counter(this, "receiver_input");
   filter.SetCapacity(200);
@@ -158,7 +159,7 @@
 TEST_P(BweSimulation, GoogleWifiTrace3Mbps) {
   VerboseLogging(true);
   AdaptiveVideoSource source(0, 30, 300, 0, 0);
-  RegularVideoSender sender(this, &source, 300);
+  PacketSender sender(this, &source, kRembEstimator);
   RateCounterFilter counter1(this, "sender_output");
   TraceBasedDeliveryFilter filter(this, "link_capacity");
   filter.SetMaxDelay(500);
@@ -170,7 +171,7 @@
 TEST_P(BweSimulation, PacerGoogleWifiTrace3Mbps) {
   VerboseLogging(true);
   PeriodicKeyFrameSource source(0, 30, 300, 0, 0, 1000);
-  PacedVideoSender sender(this, &source, 300);
+  PacedVideoSender sender(this, &source, kRembEstimator);
   RateCounterFilter counter1(this, "sender_output");
   TraceBasedDeliveryFilter filter(this, "link_capacity");
   filter.SetMaxDelay(500);
@@ -196,13 +197,13 @@
   const int kAllFlowIds[] = {0, 1, 2};
   const size_t kNumFlows = sizeof(kAllFlowIds) / sizeof(kAllFlowIds[0]);
   scoped_ptr<AdaptiveVideoSource> sources[kNumFlows];
-  scoped_ptr<RegularVideoSender> senders[kNumFlows];
+  scoped_ptr<PacketSender> senders[kNumFlows];
   for (size_t i = 0; i < kNumFlows; ++i) {
     // Streams started 20 seconds apart to give them different advantage when
     // competing for the bandwidth.
     sources[i].reset(
         new AdaptiveVideoSource(kAllFlowIds[i], 30, 300, 0, i * 20000));
-    senders[i].reset(new RegularVideoSender(this, sources[i].get(), 300));
+    senders[i].reset(new PacketSender(this, sources[i].get(), kRembEstimator));
   }
 
   ChokeFilter choke(this, CreateFlowIds(kAllFlowIds, kNumFlows));
@@ -232,7 +233,8 @@
     // competing for the bandwidth.
     sources[i].reset(new PeriodicKeyFrameSource(kAllFlowIds[i], 30, 300, 0,
                                                 i * 20000, 1000));
-    senders[i].reset(new PacedVideoSender(this, sources[i].get(), 300));
+    senders[i].reset(
+        new PacedVideoSender(this, sources[i].get(), kRembEstimator));
   }
 
   ChokeFilter choke(this, CreateFlowIds(kAllFlowIds, kNumFlows));
diff --git a/webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h b/webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h
index 92a0eb8..4986467 100644
--- a/webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h
+++ b/webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h
@@ -63,10 +63,37 @@
   std::vector<int64_t> recent_arrival_time_ms;
 };
 
+struct PacketInfo {
+  PacketInfo(int64_t arrival_time_ms,
+             int64_t send_time_ms,
+             uint16_t sequence_number,
+             size_t payload_size)
+      : arrival_time_ms(arrival_time_ms),
+        send_time_ms(send_time_ms),
+        sequence_number(sequence_number),
+        payload_size(payload_size) {}
+  // Time corresponding to when the packet was received. Timestamped with the
+  // receiver's clock.
+  int64_t arrival_time_ms;
+  // Time corresponding to when the packet was sent, timestamped with the
+  // sender's clock.
+  int64_t send_time_ms;
+  // Packet identifier, incremented with 1 for every packet generated by the
+  // sender.
+  uint16_t sequence_number;
+  // Size of the packet excluding RTP headers.
+  size_t payload_size;
+};
+
 class RemoteBitrateEstimator : public CallStatsObserver, public Module {
  public:
   virtual ~RemoteBitrateEstimator() {}
 
+  virtual void IncomingPacketFeedbackVector(
+      const std::vector<PacketInfo>& packet_feedback_vector) {
+    assert(false);
+  }
+
   // Called for each incoming packet. Updates the incoming payload bitrate
   // estimate and the over-use detector. If an over-use is detected the
   // remote bitrate estimate will be updated. Note that |payload_size| is the
diff --git a/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.cc b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.cc
index c357577..e32ef72 100644
--- a/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.cc
+++ b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.cc
@@ -111,6 +111,9 @@
                                         uint32_t min_bitrate_bps);
   virtual ~RemoteBitrateEstimatorAbsSendTimeImpl() {}
 
+  virtual void IncomingPacketFeedbackVector(
+      const std::vector<PacketInfo>& packet_feedback_vector) OVERRIDE;
+
   virtual void IncomingPacket(int64_t arrival_time_ms,
                               size_t payload_size,
                               const RTPHeader& header) OVERRIDE;
@@ -129,7 +132,6 @@
  private:
   typedef std::map<unsigned int, int64_t> Ssrcs;
 
-
   static bool IsWithinClusterBounds(int send_delta_ms,
                                     const Cluster& cluster_aggregate) {
     if (cluster_aggregate.count == 0)
@@ -150,6 +152,11 @@
     return static_cast<int>(reinterpret_cast<uint64_t>(this));
   }
 
+  void IncomingPacketInfo(int64_t arrival_time_ms,
+                          uint32_t send_time_24bits,
+                          size_t payload_size,
+                          uint32_t ssrc);
+
   bool IsProbe(int64_t send_time_ms, int payload_size) const
       EXCLUSIVE_LOCKS_REQUIRED(crit_sect_.get());
 
@@ -322,6 +329,19 @@
   return initial_probe || bitrate_above_estimate;
 }
 
+void RemoteBitrateEstimatorAbsSendTimeImpl::IncomingPacketFeedbackVector(
+    const std::vector<PacketInfo>& packet_feedback_vector) {
+  for (const auto& packet_info : packet_feedback_vector) {
+    // TODO(holmer): We should get rid of this conversion if possible as we may
+    // lose precision.
+    uint32_t send_time_32bits = (packet_info.send_time_ms) / kTimestampToMs;
+    uint32_t send_time_24bits =
+        send_time_32bits >> kAbsSendTimeInterArrivalUpshift;
+    IncomingPacketInfo(packet_info.arrival_time_ms, send_time_24bits,
+                       packet_info.payload_size, 0);
+  }
+}
+
 void RemoteBitrateEstimatorAbsSendTimeImpl::IncomingPacket(
     int64_t arrival_time_ms,
     size_t payload_size,
@@ -330,27 +350,38 @@
     LOG(LS_WARNING) << "RemoteBitrateEstimatorAbsSendTimeImpl: Incoming packet "
                        "is missing absolute send time extension!";
   }
-  uint32_t absolute_send_time = header.extension.absoluteSendTime;
-  assert(absolute_send_time < (1ul << 24));
-  int64_t now_ms = clock_->TimeInMilliseconds();
+  IncomingPacketInfo(arrival_time_ms, header.extension.absoluteSendTime,
+                     payload_size, header.ssrc);
+}
+
+void RemoteBitrateEstimatorAbsSendTimeImpl::IncomingPacketInfo(
+    int64_t arrival_time_ms,
+    uint32_t send_time_24bits,
+    size_t payload_size,
+    uint32_t ssrc) {
+  assert(send_time_24bits < (1ul << 24));
+  // Shift up send time to use the full 32 bits that inter_arrival works with,
+  // so wrapping works properly.
+  uint32_t timestamp = send_time_24bits << kAbsSendTimeInterArrivalUpshift;
+  int64_t send_time_ms = static_cast<int64_t>(timestamp) * kTimestampToMs;
+
   CriticalSectionScoped cs(crit_sect_.get());
-  ssrcs_[header.ssrc] = now_ms;
+  int64_t now_ms = clock_->TimeInMilliseconds();
+  // TODO(holmer): SSRCs are only needed for REMB, should be broken out from
+  // here.
+  ssrcs_[ssrc] = now_ms;
   incoming_bitrate_.Update(payload_size, now_ms);
   const BandwidthUsage prior_state = detector_.State();
 
   if (first_packet_time_ms_ == -1)
     first_packet_time_ms_ = clock_->TimeInMilliseconds();
 
-  // Shift up send time to use the full 32 bits that inter_arrival works with,
-  // so wrapping works properly.
-  uint32_t timestamp = absolute_send_time << kAbsSendTimeInterArrivalUpshift;
   uint32_t ts_delta = 0;
   int64_t t_delta = 0;
   int size_delta = 0;
   // For now only try to detect probes while we don't have a valid estimate.
   if (!remote_rate_->ValidEstimate() ||
       now_ms - first_packet_time_ms_ < kInitialProbingIntervalMs) {
-    int64_t send_time_ms = static_cast<int64_t>(timestamp) * kTimestampToMs;
     // TODO(holmer): Use a map instead to get correct order?
     if (total_probes_received_ < kMaxProbePackets) {
       int send_delta_ms = -1;
@@ -370,15 +401,11 @@
   }
   if (!inter_arrival_.get()) {
     inter_arrival_.reset(new InterArrival(
-        (kTimestampGroupLengthMs << kInterArrivalShift) / 1000,
-        kTimestampToMs, remote_rate_->GetControlType() == kAimdControl));
+        (kTimestampGroupLengthMs << kInterArrivalShift) / 1000, kTimestampToMs,
+        remote_rate_->GetControlType() == kAimdControl));
   }
-  if (inter_arrival_->ComputeDeltas(timestamp,
-                                    arrival_time_ms,
-                                    payload_size,
-                                    &ts_delta,
-                                    &t_delta,
-                                    &size_delta)) {
+  if (inter_arrival_->ComputeDeltas(timestamp, arrival_time_ms, payload_size,
+                                    &ts_delta, &t_delta, &size_delta)) {
     double ts_delta_ms = (1000.0 * ts_delta) / (1 << kInterArrivalShift);
     estimator_.Update(t_delta, ts_delta_ms, size_delta, detector_.State());
     detector_.Detect(estimator_.offset(), ts_delta_ms,
diff --git a/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimators_test.cc b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimators_test.cc
index b33f033..1f5dac1 100644
--- a/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimators_test.cc
+++ b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimators_test.cc
@@ -31,10 +31,12 @@
   switch (estimator) {
     case kTransmissionOffset:
       return BweTestConfig::EstimatorConfig("TOF", flow_id, &factories[0],
-                                            kMimdControl, false, false);
+                                            kAimdControl, kRembEstimator, false,
+                                            false);
     case kAbsSendTime:
       return BweTestConfig::EstimatorConfig("AST", flow_id, &factories[1],
-                                            kMimdControl, false, false);
+                                            kAimdControl, kRembEstimator, false,
+                                            false);
   }
   assert(false);
   return BweTestConfig::EstimatorConfig();
@@ -64,7 +66,8 @@
     SetupTestFromConfig(config.bwe_test_config);
     for (size_t i = 0; i < config.number_of_senders; ++i) {
       sources_.push_back(new VideoSource(0, 30, 300, 0, 0));
-      packet_senders_.push_back(new PacketSender(this, sources_.back()));
+      packet_senders_.push_back(
+          new PacketSender(this, sources_.back(), kNullEstimator));
     }
   }
 
@@ -283,7 +286,7 @@
 
 TEST_F(BweFeedbackTest, Choke1000kbps500kbps1000kbps) {
   AdaptiveVideoSource source(0, 30, 300, 0, 0);
-  RegularVideoSender sender(this, &source, 300);
+  PacketSender sender(this, &source, kRembEstimator);
   ChokeFilter filter(this);
   RateCounterFilter counter(this, "receiver_input");
   const int kHighCapacityKbps = 1000;
@@ -301,7 +304,7 @@
 
 TEST_F(BweFeedbackTest, Choke200kbps30kbps200kbps) {
   AdaptiveVideoSource source(0, 30, 300, 0, 0);
-  RegularVideoSender sender(this, &source, 300);
+  PacketSender sender(this, &source, kRembEstimator);
   ChokeFilter filter(this);
   RateCounterFilter counter(this, "receiver_input");
   const int kHighCapacityKbps = 200;
@@ -320,7 +323,7 @@
 
 TEST_F(BweFeedbackTest, Verizon4gDownlinkTest) {
   AdaptiveVideoSource source(0, 30, 300, 0, 0);
-  RegularVideoSender sender(this, &source, 300);
+  PacketSender sender(this, &source, kRembEstimator);
   RateCounterFilter counter1(this, "sender_output");
   TraceBasedDeliveryFilter filter(this, "link_capacity");
   RateCounterFilter counter2(this, "receiver_input");
@@ -333,7 +336,7 @@
 // webrtc:3277
 TEST_F(BweFeedbackTest, DISABLED_GoogleWifiTrace3Mbps) {
   AdaptiveVideoSource source(0, 30, 300, 0, 0);
-  RegularVideoSender sender(this, &source, 300);
+  PacketSender sender(this, &source, kRembEstimator);
   RateCounterFilter counter1(this, "sender_output");
   TraceBasedDeliveryFilter filter(this, "link_capacity");
   filter.SetMaxDelay(500);
diff --git a/webrtc/modules/remote_bitrate_estimator/test/bwe_test.cc b/webrtc/modules/remote_bitrate_estimator/test/bwe_test.cc
index 911f662..1f9526d 100644
--- a/webrtc/modules/remote_bitrate_estimator/test/bwe_test.cc
+++ b/webrtc/modules/remote_bitrate_estimator/test/bwe_test.cc
@@ -26,36 +26,110 @@
 namespace testing {
 namespace bwe {
 
-class PacketReceiver : public RemoteBitrateObserver {
+class PacketReceiver {
  public:
-  static const uint32_t kRemoteBitrateEstimatorMinBitrateBps = 30000;
-  static const int kDelayPlotIntervalMs = 100;
-
   PacketReceiver(const string& test_name,
                  const BweTestConfig::EstimatorConfig& config)
-      : debug_name_(config.debug_name),
+      : flow_id_(config.flow_id),
+        debug_name_(config.debug_name),
         delay_log_prefix_(),
-        estimate_log_prefix_(),
         last_delay_plot_ms_(0),
         plot_delay_(config.plot_delay),
+        baseline_(BaseLineFileInterface::Create(test_name + "_" + debug_name_,
+                                                config.update_baseline)) {
+    // Setup the prefix strings used when logging.
+    std::stringstream ss;
+    ss << "Delay_" << config.flow_id << "#2";
+    delay_log_prefix_ = ss.str();
+  }
+  virtual ~PacketReceiver() {}
+
+  virtual void ReceivePacket(const Packet& packet) {}
+
+  virtual FeedbackPacket* GetFeedback() { return NULL; }
+
+  void LogStats() {
+    BWE_TEST_LOGGING_CONTEXT(debug_name_);
+    BWE_TEST_LOGGING_CONTEXT("Mean");
+    stats_.Log("kbps");
+  }
+
+  void VerifyOrWriteBaseline() { EXPECT_TRUE(baseline_->VerifyOrWrite()); }
+
+ protected:
+  static const int kDelayPlotIntervalMs = 100;
+
+  void LogDelay(int64_t arrival_time_ms, int64_t send_time_ms) {
+    if (plot_delay_) {
+      if (arrival_time_ms - last_delay_plot_ms_ > kDelayPlotIntervalMs) {
+        BWE_TEST_LOGGING_PLOT(delay_log_prefix_, arrival_time_ms,
+                              arrival_time_ms - send_time_ms);
+        last_delay_plot_ms_ = arrival_time_ms;
+      }
+    }
+  }
+
+  const int flow_id_;
+  const string debug_name_;
+  string delay_log_prefix_;
+  int64_t last_delay_plot_ms_;
+  bool plot_delay_;
+  scoped_ptr<BaseLineFileInterface> baseline_;
+  Stats<double> stats_;
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(PacketReceiver);
+};
+
+class SendSideBweReceiver : public PacketReceiver {
+ public:
+  SendSideBweReceiver(const string& test_name,
+                      const BweTestConfig::EstimatorConfig& config)
+      : PacketReceiver(test_name, config) {}
+
+  virtual void EatPacket(const Packet& packet) {
+    const MediaPacket& media_packet = static_cast<const MediaPacket&>(packet);
+    // We're treating the send time (from previous filter) as the arrival
+    // time once packet reaches the estimator.
+    int64_t arrival_time_ms = (media_packet.send_time_us() + 500) / 1000;
+    BWE_TEST_LOGGING_TIME(arrival_time_ms);
+    LogDelay(arrival_time_ms, (media_packet.creation_time_us() + 500) / 1000);
+    packet_feedback_vector_.push_back(PacketInfo(
+        arrival_time_ms, media_packet.GetAbsSendTimeInMs(),
+        media_packet.header().sequenceNumber, media_packet.payload_size()));
+  }
+
+  virtual FeedbackPacket* GetFeedback() {
+    FeedbackPacket* fb =
+        new SendSideBweFeedback(flow_id_, 0, packet_feedback_vector_);
+    packet_feedback_vector_.clear();
+    return fb;
+  }
+
+ private:
+  std::vector<PacketInfo> packet_feedback_vector_;
+};
+
+class RembReceiver : public PacketReceiver, public RemoteBitrateObserver {
+ public:
+  static const uint32_t kRemoteBitrateEstimatorMinBitrateBps = 30000;
+
+  RembReceiver(const string& test_name,
+               const BweTestConfig::EstimatorConfig& config)
+      : PacketReceiver(test_name, config),
+        estimate_log_prefix_(),
         plot_estimate_(config.plot_estimate),
         clock_(0),
-        stats_(),
         recv_stats_(ReceiveStatistics::Create(&clock_)),
         latest_estimate_bps_(-1),
         estimator_(config.estimator_factory->Create(
             this,
             &clock_,
             config.control_type,
-            kRemoteBitrateEstimatorMinBitrateBps)),
-        baseline_(BaseLineFileInterface::Create(test_name + "_" + debug_name_,
-                                                config.update_baseline)) {
+            kRemoteBitrateEstimatorMinBitrateBps)) {
     assert(estimator_.get());
     assert(baseline_.get());
-    // Setup the prefix strings used when logging.
     std::stringstream ss;
-    ss << "Delay_" << config.flow_id << "#2";
-    delay_log_prefix_ = ss.str();
     ss.str("");
     ss << "Estimate_" << config.flow_id << "#1";
     estimate_log_prefix_ = ss.str();
@@ -63,53 +137,45 @@
     estimator_->OnRttUpdate(50);
   }
 
-  void EatPacket(const Packet& packet) {
+  virtual void ReceivePacket(const Packet& packet) {
     BWE_TEST_LOGGING_CONTEXT(debug_name_);
-
-    recv_stats_->IncomingPacket(packet.header(), packet.payload_size(), false);
+    assert(packet.GetPacketType() == Packet::kMediaPacket);
+    const MediaPacket& media_packet = static_cast<const MediaPacket&>(packet);
+    // We're treating the send time (from previous filter) as the arrival
+    // time once packet reaches the estimator.
+    int64_t arrival_time_ms = (media_packet.send_time_us() + 500) / 1000;
+    BWE_TEST_LOGGING_TIME(arrival_time_ms);
+    LogDelay(arrival_time_ms, (media_packet.creation_time_us() + 500) / 1000);
+    recv_stats_->IncomingPacket(media_packet.header(),
+                                media_packet.payload_size(), false);
 
     latest_estimate_bps_ = -1;
 
-    // We're treating the send time (from previous filter) as the arrival
-    // time once packet reaches the estimator.
-    int64_t packet_time_ms = (packet.send_time_us() + 500) / 1000;
-    BWE_TEST_LOGGING_TIME(packet_time_ms);
-    if (plot_delay_) {
-      if (clock_.TimeInMilliseconds() - last_delay_plot_ms_ >
-          kDelayPlotIntervalMs) {
-        BWE_TEST_LOGGING_PLOT(delay_log_prefix_, clock_.TimeInMilliseconds(),
-                              packet_time_ms -
-                              (packet.creation_time_us() + 500) / 1000);
-        last_delay_plot_ms_ = clock_.TimeInMilliseconds();
-      }
-    }
-
     int64_t step_ms = std::max<int64_t>(estimator_->TimeUntilNextProcess(), 0);
-    while ((clock_.TimeInMilliseconds() + step_ms) < packet_time_ms) {
+    while ((clock_.TimeInMilliseconds() + step_ms) < arrival_time_ms) {
       clock_.AdvanceTimeMilliseconds(step_ms);
       estimator_->Process();
       step_ms = std::max<int64_t>(estimator_->TimeUntilNextProcess(), 0);
     }
-    estimator_->IncomingPacket(packet_time_ms, packet.payload_size(),
-                               packet.header());
-    clock_.AdvanceTimeMilliseconds(packet_time_ms -
+    estimator_->IncomingPacket(arrival_time_ms, media_packet.payload_size(),
+                               media_packet.header());
+    clock_.AdvanceTimeMilliseconds(arrival_time_ms -
                                    clock_.TimeInMilliseconds());
-    ASSERT_TRUE(packet_time_ms == clock_.TimeInMilliseconds());
+    ASSERT_TRUE(arrival_time_ms == clock_.TimeInMilliseconds());
   }
 
-  bool GetFeedback(PacketSender::Feedback* feedback) {
-    assert(feedback);
+  virtual FeedbackPacket* GetFeedback() {
     BWE_TEST_LOGGING_CONTEXT(debug_name_);
     uint32_t estimated_bps = 0;
+    RembFeedback* feedback = NULL;
     if (LatestEstimate(&estimated_bps)) {
-      feedback->estimated_bps = estimated_bps;
       StatisticianMap statisticians = recv_stats_->GetActiveStatisticians();
-      if (statisticians.empty()) {
-        feedback->report_block = RTCPReportBlock();
-      } else {
-        feedback->report_block =
-            BuildReportBlock(statisticians.begin()->second);
+      RTCPReportBlock report_block;
+      if (!statisticians.empty()) {
+        report_block = BuildReportBlock(statisticians.begin()->second);
       }
+      feedback = new RembFeedback(flow_id_, clock_.TimeInMilliseconds(),
+                                  estimated_bps, report_block);
       baseline_->Estimate(clock_.TimeInMilliseconds(), estimated_bps);
 
       double estimated_kbps = static_cast<double>(estimated_bps) / 1000.0;
@@ -118,19 +184,8 @@
         BWE_TEST_LOGGING_PLOT(estimate_log_prefix_, clock_.TimeInMilliseconds(),
                               estimated_kbps);
       }
-      return true;
     }
-    return false;
-  }
-
-  void LogStats() {
-    BWE_TEST_LOGGING_CONTEXT(debug_name_);
-    BWE_TEST_LOGGING_CONTEXT("Mean");
-    stats_.Log("kbps");
-  }
-
-  void VerifyOrWriteBaseline() {
-    EXPECT_TRUE(baseline_->VerifyOrWrite());
+    return feedback;
   }
 
   virtual void OnReceiveBitrateChanged(const vector<unsigned int>& ssrcs,
@@ -163,29 +218,39 @@
     return true;
   }
 
-  string debug_name_;
-  string delay_log_prefix_;
   string estimate_log_prefix_;
-  int64_t last_delay_plot_ms_;
-  bool plot_delay_;
   bool plot_estimate_;
   SimulatedClock clock_;
-  Stats<double> stats_;
   scoped_ptr<ReceiveStatistics> recv_stats_;
   int64_t latest_estimate_bps_;
   scoped_ptr<RemoteBitrateEstimator> estimator_;
-  scoped_ptr<BaseLineFileInterface> baseline_;
 
-  DISALLOW_IMPLICIT_CONSTRUCTORS(PacketReceiver);
+  DISALLOW_IMPLICIT_CONSTRUCTORS(RembReceiver);
 };
 
+PacketReceiver* CreatePacketReceiver(
+    BandwidthEstimatorType type,
+    const string& test_name,
+    const BweTestConfig::EstimatorConfig& config) {
+  switch (type) {
+    case kRembEstimator:
+      return new RembReceiver(test_name, config);
+    case kFullSendSideEstimator:
+      return new SendSideBweReceiver(test_name, config);
+    case kNullEstimator:
+      return new PacketReceiver(test_name, config);
+  }
+  assert(false);
+  return NULL;
+}
+
 class PacketProcessorRunner {
  public:
   explicit PacketProcessorRunner(PacketProcessor* processor)
       : processor_(processor) {}
 
   ~PacketProcessorRunner() {
-    for (auto* packet : queue_)
+    for (Packet* packet : queue_)
       delete packet;
   }
 
@@ -253,16 +318,14 @@
 
 BweTest::~BweTest() {
   BWE_TEST_LOGGING_GLOBAL_ENABLE(true);
-  for (EstimatorMap::iterator it = estimators_.begin(); it != estimators_.end();
-      ++it) {
-    it->second->VerifyOrWriteBaseline();
-    it->second->LogStats();
+  for (const auto& estimator : estimators_) {
+    estimator.second->VerifyOrWriteBaseline();
+    estimator.second->LogStats();
   }
   BWE_TEST_LOGGING_GLOBAL_CONTEXT("");
 
-  for (EstimatorMap::iterator it = estimators_.begin();
-       it != estimators_.end(); ++it) {
-    delete it->second;
+  for (const auto& estimator : estimators_) {
+    delete estimator.second;
   }
 }
 
@@ -272,11 +335,11 @@
   string test_name =
       string(test_info->test_case_name()) + "_" + string(test_info->name());
   BWE_TEST_LOGGING_GLOBAL_CONTEXT(test_name);
-  for (vector<BweTestConfig::EstimatorConfig>::const_iterator it =
-       config.estimator_configs.begin(); it != config.estimator_configs.end();
-       ++it) {
+  for (const auto& estimator_config : config.estimator_configs) {
     estimators_.insert(
-        std::make_pair(it->flow_id, new PacketReceiver(test_name, *it)));
+        std::make_pair(estimator_config.flow_id,
+                       CreatePacketReceiver(estimator_config.bwe_type,
+                                            test_name, estimator_config)));
   }
   BWE_TEST_LOGGING_GLOBAL_ENABLE(false);
 }
@@ -287,7 +350,7 @@
     senders_.push_back(static_cast<PacketSender*>(processor));
   }
   processors_.push_back(PacketProcessorRunner(processor));
-  for (const auto& flow_id : processor->flow_ids()) {
+  for (const int& flow_id : processor->flow_ids()) {
     RTC_UNUSED(flow_id);
     assert(estimators_.count(flow_id) == 1);
   }
@@ -308,22 +371,18 @@
   BWE_TEST_LOGGING_GLOBAL_ENABLE(enable);
 }
 
-void BweTest::GiveFeedbackToAffectedSenders(int flow_id,
-                                            PacketReceiver* estimator) {
-  std::list<PacketSender*> affected_senders;
-  for (auto* sender : senders_) {
-    if (sender->flow_ids().find(flow_id) != sender->flow_ids().end()) {
-      affected_senders.push_back(sender);
+void BweTest::GiveFeedbackToAffectedSenders(PacketReceiver* estimator) {
+  FeedbackPacket* feedback = estimator->GetFeedback();
+  if (feedback) {
+    for (PacketSender* sender : senders_) {
+      if (sender->flow_ids().find(feedback->flow_id()) !=
+          sender->flow_ids().end()) {
+        sender->GiveFeedback(*feedback);
+        break;
+      }
     }
   }
-  PacketSender::Feedback feedback = {0};
-  if (estimator->GetFeedback(&feedback) && !affected_senders.empty()) {
-    // Allocate the bitrate evenly between the senders.
-    feedback.estimated_bps /= affected_senders.size();
-    for (auto* sender : affected_senders) {
-      sender->GiveFeedback(feedback);
-    }
-  }
+  delete feedback;
 }
 
 void BweTest::RunFor(int64_t time_ms) {
@@ -340,7 +399,7 @@
        time_now_ms_ <= run_time_ms_ - simulation_interval_ms_;
        time_now_ms_ += simulation_interval_ms_) {
     Packets packets;
-    for (auto& processor : processors_) {
+    for (PacketProcessorRunner& processor : processors_) {
       processor.RunFor(simulation_interval_ms_, time_now_ms_, &packets);
     }
 
@@ -359,15 +418,15 @@
       ASSERT_TRUE(IsTimeSorted(packets));
     }
 
-    for (const auto* packet : packets) {
+    for (const Packet* packet : packets) {
       EstimatorMap::iterator est_it = estimators_.find(packet->flow_id());
       ASSERT_TRUE(est_it != estimators_.end());
-      est_it->second->EatPacket(*packet);
+      est_it->second->ReceivePacket(*packet);
       delete packet;
     }
 
     for (const auto& estimator : estimators_) {
-      GiveFeedbackToAffectedSenders(estimator.first, estimator.second);
+      GiveFeedbackToAffectedSenders(estimator.second);
     }
   }
 }
diff --git a/webrtc/modules/remote_bitrate_estimator/test/bwe_test.h b/webrtc/modules/remote_bitrate_estimator/test/bwe_test.h
index e3e0097..2648733 100644
--- a/webrtc/modules/remote_bitrate_estimator/test/bwe_test.h
+++ b/webrtc/modules/remote_bitrate_estimator/test/bwe_test.h
@@ -29,55 +29,59 @@
         : debug_name(),
           flow_id(0),
           estimator_factory(NULL),
-          control_type(kMimdControl),
+          control_type(kAimdControl),
+          bwe_type(kRembEstimator),
           update_baseline(false),
           plot_delay(true),
-          plot_estimate(true) {
-    }
+          plot_estimate(true) {}
     EstimatorConfig(std::string debug_name,
                     int flow_id,
                     const RemoteBitrateEstimatorFactory* estimator_factory,
+                    BandwidthEstimatorType estimator_type,
                     bool plot_delay,
                     bool plot_estimate)
         : debug_name(debug_name),
           flow_id(flow_id),
           estimator_factory(estimator_factory),
-          control_type(kMimdControl),
+          control_type(kAimdControl),
+          bwe_type(kRembEstimator),
           update_baseline(false),
           plot_delay(plot_delay),
-          plot_estimate(plot_estimate) {
-    }
+          plot_estimate(plot_estimate) {}
     EstimatorConfig(std::string debug_name,
                     int flow_id,
                     const RemoteBitrateEstimatorFactory* estimator_factory,
                     RateControlType control_type,
+                    BandwidthEstimatorType estimator_type,
                     bool plot_delay,
                     bool plot_estimate)
         : debug_name(debug_name),
           flow_id(flow_id),
           estimator_factory(estimator_factory),
           control_type(control_type),
+          bwe_type(estimator_type),
           update_baseline(false),
           plot_delay(plot_delay),
-          plot_estimate(plot_estimate) {
-    }
+          plot_estimate(plot_estimate) {}
     EstimatorConfig(std::string debug_name,
                     int flow_id,
                     const RemoteBitrateEstimatorFactory* estimator_factory,
                     RateControlType control_type,
+                    BandwidthEstimatorType estimator_type,
                     bool update_baseline)
         : debug_name(debug_name),
           flow_id(flow_id),
           estimator_factory(estimator_factory),
           control_type(control_type),
+          bwe_type(kRembEstimator),
           update_baseline(update_baseline),
           plot_delay(false),
-          plot_estimate(false) {
-    }
+          plot_estimate(false) {}
     std::string debug_name;
     int flow_id;
     const RemoteBitrateEstimatorFactory* estimator_factory;
     RateControlType control_type;
+    BandwidthEstimatorType bwe_type;
     bool update_baseline;
     bool plot_delay;
     bool plot_estimate;
@@ -108,7 +112,7 @@
 
   void FindPacketsToProcess(const FlowIds& flow_ids, Packets* in,
                             Packets* out);
-  void GiveFeedbackToAffectedSenders(int flow_id, PacketReceiver* estimator);
+  void GiveFeedbackToAffectedSenders(PacketReceiver* estimator);
 
   int64_t run_time_ms_;
   int64_t time_now_ms_;
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 1520db7..b2627a1 100644
--- a/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.cc
+++ b/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.cc
@@ -17,6 +17,10 @@
 namespace webrtc {
 namespace testing {
 namespace bwe {
+
+const int kMinBitrateKbps = 10;
+const int kMaxBitrateKbps = 20000;
+
 class DelayCapHelper {
  public:
   DelayCapHelper() : max_delay_us_(0), delay_stats_() {}
@@ -120,29 +124,14 @@
 }
 
 Packet::Packet()
-    : flow_id_(0),
-      creation_time_us_(-1),
-      send_time_us_(-1),
-      payload_size_(0) {
-  memset(&header_, 0, sizeof(header_));
+    : flow_id_(0), creation_time_us_(-1), send_time_us_(-1), payload_size_(0) {
 }
 
-Packet::Packet(int flow_id, int64_t send_time_us, size_t payload_size,
-               const RTPHeader& header)
+Packet::Packet(int flow_id, int64_t send_time_us, size_t payload_size)
     : flow_id_(flow_id),
       creation_time_us_(send_time_us),
       send_time_us_(send_time_us),
-      payload_size_(payload_size),
-      header_(header) {
-}
-
-Packet::Packet(int64_t send_time_us, uint32_t sequence_number)
-    : flow_id_(0),
-      creation_time_us_(send_time_us),
-      send_time_us_(send_time_us),
-      payload_size_(0) {
-  memset(&header_, 0, sizeof(header_));
-  header_.sequenceNumber = sequence_number;
+      payload_size_(payload_size) {
 }
 
 Packet::~Packet() {
@@ -157,12 +146,56 @@
   send_time_us_ = send_time_us;
 }
 
-void Packet::SetAbsSendTimeMs(int64_t abs_send_time_ms) {
+MediaPacket::MediaPacket() {
+  memset(&header_, 0, sizeof(header_));
+}
+
+MediaPacket::MediaPacket(int flow_id,
+                         int64_t send_time_us,
+                         size_t payload_size,
+                         const RTPHeader& header)
+    : Packet(flow_id, send_time_us, payload_size), header_(header) {
+}
+
+MediaPacket::MediaPacket(int64_t send_time_us, uint32_t sequence_number)
+    : Packet(0, send_time_us, 0) {
+  memset(&header_, 0, sizeof(header_));
+  header_.sequenceNumber = sequence_number;
+}
+
+int64_t MediaPacket::GetAbsSendTimeInMs() const {
+  const int kInterArrivalShift = 26;
+  const int kAbsSendTimeInterArrivalUpshift = 8;
+  const double kTimestampToMs =
+      1000.0 / static_cast<double>(1 << kInterArrivalShift);
+  uint32_t timestamp = header_.extension.absoluteSendTime
+                       << kAbsSendTimeInterArrivalUpshift;
+  return static_cast<int64_t>(timestamp) * kTimestampToMs;
+}
+
+void MediaPacket::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;
 }
 
+RembFeedback::RembFeedback(int flow_id,
+                           int64_t send_time_us,
+                           uint32_t estimated_bps,
+                           RTCPReportBlock report_block)
+    : FeedbackPacket(flow_id, send_time_us),
+      estimated_bps_(estimated_bps),
+      report_block_(report_block) {
+}
+
+SendSideBweFeedback::SendSideBweFeedback(
+    int flow_id,
+    int64_t send_time_us,
+    const std::vector<PacketInfo>& packet_feedback_vector)
+    : FeedbackPacket(flow_id, send_time_us),
+      packet_feedback_vector_(packet_feedback_vector) {
+}
+
 bool IsTimeSorted(const Packets& packets) {
   PacketsConstIt last_it = packets.begin();
   for (PacketsConstIt it = last_it; it != packets.end(); ++it) {
@@ -233,7 +266,7 @@
       name_(name) {
   std::stringstream ss;
   ss << name_ << "_";
-  for (auto flow_id : flow_ids) {
+  for (int flow_id : flow_ids) {
     ss << flow_id << ",";
   }
   name_ = ss.str();
@@ -269,7 +302,7 @@
 
 void RateCounterFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
   assert(in_out);
-  for (const auto* packet : *in_out) {
+  for (const Packet* packet : *in_out) {
     rate_counter_->UpdateRates(packet->send_time_us(), packet->payload_size());
   }
   packets_per_second_stats_.Push(rate_counter_->packets_per_second());
@@ -317,7 +350,7 @@
 
 void DelayFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
   assert(in_out);
-  for (auto* packet : *in_out) {
+  for (Packet* packet : *in_out) {
     int64_t new_send_time_us = packet->send_time_us() + delay_us_;
     last_send_time_us_ = std::max(last_send_time_us_, new_send_time_us);
     packet->set_send_time_us(last_send_time_us_);
@@ -341,7 +374,7 @@
 
 void JitterFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
   assert(in_out);
-  for (auto* packet : *in_out) {
+  for (Packet* packet : *in_out) {
     int64_t new_send_time_us = packet->send_time_us();
     new_send_time_us += random_.Gaussian(0, stddev_jitter_us_);
     last_send_time_us_ = std::max(last_send_time_us_, new_send_time_us);
@@ -372,7 +405,7 @@
       if (random_.Rand() < reorder_fraction_) {
         int64_t t1 = (*last_it)->send_time_us();
         int64_t t2 = (*it)->send_time_us();
-        std::swap(**last_it, **it);
+        std::swap(*last_it, *it);
         (*last_it)->set_send_time_us(t1);
         (*it)->set_send_time_us(t2);
       }
@@ -540,7 +573,7 @@
     ++next_delivery_it_;
     if (next_delivery_it_ == delivery_times_us_.end()) {
       // When the trace wraps we allow two packets to be sent back-to-back.
-      for (auto& delivery_time_us : delivery_times_us_) {
+      for (int64_t& delivery_time_us : delivery_times_us_) {
         delivery_time_us += local_time_us_ - current_offset_us_;
       }
       current_offset_us_ += local_time_us_ - current_offset_us_;
@@ -600,9 +633,10 @@
     while (payload_size > 0) {
       ++prototype_header_.sequenceNumber;
       uint32_t size = NextPacketSize(frame_size, payload_size);
-      new_packets.push_back(
-          new Packet(flow_id_, send_time_us, size, prototype_header_));
-      new_packets.back()->SetAbsSendTimeMs(next_frame_ms_);
+      MediaPacket* new_packet =
+          new MediaPacket(flow_id_, send_time_us, size, prototype_header_);
+      new_packets.push_back(new_packet);
+      new_packet->SetAbsSendTimeMs(next_frame_ms_);
       payload_size -= size;
     }
 
@@ -672,60 +706,155 @@
   return std::min(avg_size, remaining_payload);
 }
 
-PacketSender::PacketSender(PacketProcessorListener* listener,
-                           VideoSource* source)
-    : PacketProcessor(listener, source->flow_id(), true), source_(source) {
-}
-
-void PacketSender::RunFor(int64_t time_ms, Packets* in_out) {
-  source_->RunFor(time_ms, in_out);
-}
-
-RegularVideoSender::RegularVideoSender(PacketProcessorListener* listener,
-                                       VideoSource* source,
-                                       uint32_t kbps)
-    // It is important that the first_frame_offset and the initial time of
-    // clock_ are both zero, otherwise we can't have absolute time in this
-    // class.
-    : PacketSender(listener, source),
-      clock_(kInitialTimeMs),
-      bitrate_controller_(BitrateController::CreateBitrateController(&clock_,
-                                                                     false)),
+RembSendSideBwe::RembSendSideBwe(int kbps,
+                                 BitrateObserver* observer,
+                                 Clock* clock)
+    : bitrate_controller_(
+          BitrateController::CreateBitrateController(clock, false)),
       feedback_observer_(bitrate_controller_->CreateRtcpBandwidthObserver()),
-      modules_() {
-  const int kMinBitrateBps = 10000;
-  const int kMaxBitrateBps = 20000000;
-  bitrate_controller_->SetBitrateObserver(this, 1000 * kbps, kMinBitrateBps,
-                                          kMaxBitrateBps);
-  modules_.push_back(bitrate_controller_.get());
+      clock_(clock) {
+  assert(kbps >= kMinBitrateKbps);
+  assert(kbps <= kMaxBitrateKbps);
+  bitrate_controller_->SetBitrateObserver(
+      observer, 1000 * kbps, 1000 * kMinBitrateKbps, 1000 * kMaxBitrateKbps);
 }
 
-RegularVideoSender::~RegularVideoSender() {
+RembSendSideBwe::~RembSendSideBwe() {
 }
 
-void RegularVideoSender::GiveFeedback(const Feedback& feedback) {
-  feedback_observer_->OnReceivedEstimatedBitrate(feedback.estimated_bps);
+void RembSendSideBwe::GiveFeedback(const FeedbackPacket& feedback) {
+  const RembFeedback& remb_feedback =
+      static_cast<const RembFeedback&>(feedback);
+  feedback_observer_->OnReceivedEstimatedBitrate(remb_feedback.estimated_bps());
   ReportBlockList report_blocks;
-  report_blocks.push_back(feedback.report_block);
-  feedback_observer_->OnReceivedRtcpReceiverReport(report_blocks, 0,
-                                                   clock_.TimeInMilliseconds());
+  report_blocks.push_back(remb_feedback.report_block());
+  feedback_observer_->OnReceivedRtcpReceiverReport(
+      report_blocks, 0, clock_->TimeInMilliseconds());
   bitrate_controller_->Process();
 }
 
-void RegularVideoSender::RunFor(int64_t time_ms, Packets* in_out) {
+int64_t RembSendSideBwe::TimeUntilNextProcess() {
+  return bitrate_controller_->TimeUntilNextProcess();
+}
+
+int RembSendSideBwe::Process() {
+  return bitrate_controller_->Process();
+}
+
+FullSendSideBwe::FullSendSideBwe(int kbps,
+                                 BitrateObserver* observer,
+                                 Clock* clock)
+    : bitrate_controller_(
+          BitrateController::CreateBitrateController(clock, false)),
+      rbe_(AbsoluteSendTimeRemoteBitrateEstimatorFactory()
+               .Create(this, clock, kAimdControl, 1000 * kMinBitrateKbps)),
+      feedback_observer_(bitrate_controller_->CreateRtcpBandwidthObserver()),
+      clock_(clock) {
+  assert(kbps >= kMinBitrateKbps);
+  assert(kbps <= kMaxBitrateKbps);
+  bitrate_controller_->SetBitrateObserver(
+      observer, 1000 * kbps, 1000 * kMinBitrateKbps, 1000 * kMaxBitrateKbps);
+}
+
+FullSendSideBwe::~FullSendSideBwe() {
+}
+
+void FullSendSideBwe::GiveFeedback(const FeedbackPacket& feedback) {
+  const SendSideBweFeedback& fb =
+      static_cast<const SendSideBweFeedback&>(feedback);
+  if (fb.packet_feedback_vector().empty())
+    return;
+  rbe_->IncomingPacketFeedbackVector(fb.packet_feedback_vector());
+  if (rbe_->TimeUntilNextProcess() <= 0)
+    rbe_->Process();
+  // TODO(holmer): Handle losses in between feedback packets.
+  int expected_packets = fb.packet_feedback_vector().back().sequence_number -
+                         fb.packet_feedback_vector().front().sequence_number +
+                         1;
+  int lost_packets = expected_packets - fb.packet_feedback_vector().size();
+  report_block_.fractionLost = (lost_packets << 8) / expected_packets;
+  report_block_.cumulativeLost += lost_packets;
+  ReportBlockList report_blocks;
+  report_blocks.push_back(report_block_);
+  feedback_observer_->OnReceivedRtcpReceiverReport(
+      report_blocks, 0, clock_->TimeInMilliseconds());
+  bitrate_controller_->Process();
+}
+
+void FullSendSideBwe::OnReceiveBitrateChanged(
+    const std::vector<unsigned int>& ssrcs,
+    unsigned int bitrate) {
+  feedback_observer_->OnReceivedEstimatedBitrate(bitrate);
+}
+
+int64_t FullSendSideBwe::TimeUntilNextProcess() {
+  return bitrate_controller_->TimeUntilNextProcess();
+}
+
+int FullSendSideBwe::Process() {
+  rbe_->Process();
+  return bitrate_controller_->Process();
+}
+
+SendSideBwe* CreateEstimator(BandwidthEstimatorType estimator,
+                             int kbps,
+                             BitrateObserver* observer,
+                             Clock* clock) {
+  switch (estimator) {
+    case kRembEstimator:
+      return new RembSendSideBwe(kbps, observer, clock);
+    case kFullSendSideEstimator:
+      return new FullSendSideBwe(kbps, observer, clock);
+    case kNullEstimator: {
+      static NullSendSideBwe null_bwe;
+      return &null_bwe;
+    }
+  }
+  assert(false);
+  return NULL;
+}
+
+PacketSender::PacketSender(PacketProcessorListener* listener,
+                           VideoSource* source,
+                           BandwidthEstimatorType estimator)
+    : PacketProcessor(listener, source->flow_id(), true),
+      // For Packet::send_time_us() to be comparable with timestamps from
+      // clock_, the clock of the PacketSender and the Source must be aligned.
+      // We assume that both start at time 0.
+      clock_(0),
+      source_(source),
+      bwe_(CreateEstimator(estimator,
+                           8 * source_->bytes_per_second() / 1000,
+                           this,
+                           &clock_)) {
+  modules_.push_back(bwe_.get());
+}
+
+PacketSender::~PacketSender() {
+}
+
+void PacketSender::RunFor(int64_t time_ms, Packets* in_out) {
   start_of_run_ms_ = clock_.TimeInMilliseconds();
   while (time_ms > 0) {
     int64_t time_to_run_ms = std::min(time_ms, static_cast<int64_t>(100));
-    PacketSender::RunFor(time_to_run_ms, in_out);
+    source_->RunFor(time_to_run_ms, in_out);
     clock_.AdvanceTimeMilliseconds(time_to_run_ms);
-    bitrate_controller_->Process();
+    bwe_->Process();
     time_ms -= time_to_run_ms;
   }
 }
 
-void RegularVideoSender::OnNetworkChanged(uint32_t target_bitrate_bps,
-                                          uint8_t fraction_lost,
-                                          int64_t rtt) {
+int PacketSender::GetFeedbackIntervalMs() const {
+  return bwe_->GetFeedbackIntervalMs();
+}
+
+void PacketSender::GiveFeedback(const FeedbackPacket& feedback) {
+  bwe_->GiveFeedback(feedback);
+}
+
+void PacketSender::OnNetworkChanged(uint32_t target_bitrate_bps,
+                                    uint8_t fraction_lost,
+                                    int64_t rtt) {
   source_->SetBitrateBps(target_bitrate_bps);
   std::stringstream ss;
   ss << "SendEstimate_" << source_->flow_id() << "#1";
@@ -735,23 +864,22 @@
 
 PacedVideoSender::PacedVideoSender(PacketProcessorListener* listener,
                                    VideoSource* source,
-                                   uint32_t kbps)
-    // It is important that the first_frame_offset and the initial time of
-    // clock_ are both zero, otherwise we can't have absolute time in this
-    // class.
-    : RegularVideoSender(listener, source, kbps),
+                                   BandwidthEstimatorType estimator)
+    : PacketSender(listener, source, estimator),
       pacer_(&clock_,
              this,
-             kbps,
-             PacedSender::kDefaultPaceMultiplier* kbps,
+             8 * source->bytes_per_second() / 1000,
+             PacedSender::kDefaultPaceMultiplier * 8 *
+                 source->bytes_per_second() /
+                 1000,
              0) {
   modules_.push_back(&pacer_);
 }
 
 PacedVideoSender::~PacedVideoSender() {
-  for (auto* packet : pacer_queue_)
+  for (Packet* packet : pacer_queue_)
     delete packet;
-  for (auto* packet : queue_)
+  for (Packet* packet : queue_)
     delete packet;
 }
 
@@ -786,11 +914,13 @@
       CallProcess(modules_);
     } else {
       // Time to send next packet to pacer.
-      pacer_.SendPacket(PacedSender::kNormalPriority, (*it)->header().ssrc,
-                        (*it)->header().sequenceNumber,
-                        ((*it)->send_time_us() + 500) / 1000,
-                        (*it)->payload_size(), false);
-      pacer_queue_.push_back(*it);
+      MediaPacket* media_packet = static_cast<MediaPacket*>(*it);
+      pacer_.SendPacket(PacedSender::kNormalPriority,
+                        media_packet->header().ssrc,
+                        media_packet->header().sequenceNumber,
+                        (media_packet->send_time_us() + 500) / 1000,
+                        media_packet->payload_size(), false);
+      pacer_queue_.push_back(media_packet);
       assert(pacer_queue_.size() < 10000);
       ++it;
     }
@@ -801,7 +931,7 @@
 int64_t PacedVideoSender::TimeUntilNextProcess(
     const std::list<Module*>& modules) {
   int64_t time_until_next_process_ms = 10;
-  for (auto* module : modules) {
+  for (Module* module : modules) {
     int64_t next_process_ms = module->TimeUntilNextProcess();
     if (next_process_ms < time_until_next_process_ms)
       time_until_next_process_ms = next_process_ms;
@@ -812,7 +942,7 @@
 }
 
 void PacedVideoSender::CallProcess(const std::list<Module*>& modules) {
-  for (auto* module : modules) {
+  for (Module* module : modules) {
     if (module->TimeUntilNextProcess() <= 0) {
       module->Process();
     }
@@ -842,14 +972,15 @@
                                         bool retransmission) {
   for (Packets::iterator it = pacer_queue_.begin(); it != pacer_queue_.end();
        ++it) {
-    if ((*it)->header().sequenceNumber == sequence_number) {
+    MediaPacket* media_packet = static_cast<MediaPacket*>(*it);
+    if (media_packet->header().sequenceNumber == sequence_number) {
       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(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);
+      assert(pace_out_time_ms >= (media_packet->send_time_us() + 500) / 1000);
+      media_packet->SetAbsSendTimeMs(pace_out_time_ms);
+      media_packet->set_send_time_us(1000 * pace_out_time_ms);
+      queue_.push_back(media_packet);
       pacer_queue_.erase(it);
       return true;
     }
@@ -864,7 +995,7 @@
 void PacedVideoSender::OnNetworkChanged(uint32_t target_bitrate_bps,
                                         uint8_t fraction_lost,
                                         int64_t rtt) {
-  RegularVideoSender::OnNetworkChanged(target_bitrate_bps, fraction_lost, rtt);
+  PacketSender::OnNetworkChanged(target_bitrate_bps, fraction_lost, rtt);
   pacer_.UpdateBitrate(
       target_bitrate_bps / 1000,
       PacedSender::kDefaultPaceMultiplier * target_bitrate_bps / 1000, 0);
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 3d79c96..bed7e7d 100644
--- a/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.h
+++ b/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.h
@@ -15,6 +15,7 @@
 #include <math.h>
 
 #include <algorithm>
+#include <limits>
 #include <list>
 #include <numeric>
 #include <sstream>
@@ -24,6 +25,7 @@
 #include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
 #include "webrtc/modules/interface/module_common_types.h"
 #include "webrtc/modules/pacing/include/paced_sender.h"
+#include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
 #include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_logging.h"
 #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h"
 #include "webrtc/system_wrappers/interface/clock.h"
@@ -160,29 +162,86 @@
 
 class Packet {
  public:
-  Packet();
-  Packet(int flow_id, int64_t send_time_us, size_t payload_size,
-         const RTPHeader& header);
-  Packet(int64_t send_time_us, uint32_t sequence_number);
+  enum Type { kMediaPacket, kFeedbackPacket };
 
+  Packet();
+  Packet(int flow_id, int64_t send_time_us, size_t payload_size);
   virtual ~Packet();
 
-  bool operator<(const Packet& rhs) const;
+  virtual bool operator<(const Packet& rhs) const;
 
-  int flow_id() const { return flow_id_; }
-  int64_t creation_time_us() const { return creation_time_us_; }
-  void set_send_time_us(int64_t send_time_us);
-  int64_t send_time_us() const { return send_time_us_; }
-  void SetAbsSendTimeMs(int64_t abs_send_time_ms);
-  size_t payload_size() const { return payload_size_; }
-  const RTPHeader& header() const { return header_; }
+  virtual int flow_id() const { return flow_id_; }
+  virtual int64_t creation_time_us() const { return creation_time_us_; }
+  virtual void set_send_time_us(int64_t send_time_us);
+  virtual int64_t send_time_us() const { return send_time_us_; }
+  virtual size_t payload_size() const { return payload_size_; }
+  virtual Packet::Type GetPacketType() const = 0;
 
  private:
   int flow_id_;
   int64_t creation_time_us_;  // Time when the packet was created.
   int64_t send_time_us_;   // Time the packet left last processor touching it.
   size_t payload_size_;    // Size of the (non-existent, simulated) payload.
-  RTPHeader header_;       // Actual contents.
+};
+
+class MediaPacket : public Packet {
+ public:
+  MediaPacket();
+  MediaPacket(int flow_id,
+              int64_t send_time_us,
+              size_t payload_size,
+              const RTPHeader& header);
+  MediaPacket(int64_t send_time_us, uint32_t sequence_number);
+  virtual ~MediaPacket() {}
+
+  int64_t GetAbsSendTimeInMs() const;
+  void SetAbsSendTimeMs(int64_t abs_send_time_ms);
+  const RTPHeader& header() const { return header_; }
+  virtual Packet::Type GetPacketType() const { return kMediaPacket; }
+
+ private:
+  RTPHeader header_;
+};
+
+class FeedbackPacket : public Packet {
+ public:
+  FeedbackPacket(int flow_id, int64_t send_time_us)
+      : Packet(flow_id, send_time_us, 0) {}
+  virtual ~FeedbackPacket() {}
+
+  virtual Packet::Type GetPacketType() const { return kFeedbackPacket; }
+};
+
+class RembFeedback : public FeedbackPacket {
+ public:
+  RembFeedback(int flow_id,
+               int64_t send_time_us,
+               uint32_t estimated_bps,
+               RTCPReportBlock report_block);
+  virtual ~RembFeedback() {}
+
+  uint32_t estimated_bps() const { return estimated_bps_; }
+  RTCPReportBlock report_block() const { return report_block_; }
+
+ private:
+  const uint32_t estimated_bps_;
+  const RTCPReportBlock report_block_;
+};
+
+class SendSideBweFeedback : public FeedbackPacket {
+ public:
+  typedef std::map<uint16_t, int64_t> ArrivalTimesMap;
+  SendSideBweFeedback(int flow_id,
+                      int64_t send_time_us,
+                      const std::vector<PacketInfo>& packet_feedback_vector);
+  virtual ~SendSideBweFeedback() {}
+
+  const std::vector<PacketInfo>& packet_feedback_vector() const {
+    return packet_feedback_vector_;
+  }
+
+ private:
+  const std::vector<PacketInfo> packet_feedback_vector_;
 };
 
 typedef std::list<Packet*> Packets;
@@ -303,6 +362,7 @@
   DISALLOW_IMPLICIT_CONSTRUCTORS(JitterFilter);
 };
 
+// Reorders two consecutive packets with a probability of reorder_percent.
 class ReorderFilter : public PacketProcessor {
  public:
   explicit ReorderFilter(PacketProcessorListener* listener);
@@ -448,70 +508,123 @@
   DISALLOW_IMPLICIT_CONSTRUCTORS(PeriodicKeyFrameSource);
 };
 
-class PacketSender : public PacketProcessor {
+class SendSideBwe : public Module {
  public:
-  struct Feedback {
-    uint32_t estimated_bps;
-    RTCPReportBlock report_block;
-  };
+  SendSideBwe() {}
+  virtual ~SendSideBwe() {}
 
-  PacketSender(PacketProcessorListener* listener, VideoSource* source);
-  virtual ~PacketSender() {}
+  virtual int GetFeedbackIntervalMs() const = 0;
+  virtual void GiveFeedback(const FeedbackPacket& feedback) = 0;
 
-  virtual uint32_t GetCapacityKbps() const { return 0; }
+ private:
+  DISALLOW_COPY_AND_ASSIGN(SendSideBwe);
+};
+
+class NullSendSideBwe : public SendSideBwe {
+ public:
+  NullSendSideBwe() {}
+  virtual ~NullSendSideBwe() {}
+
+  virtual int GetFeedbackIntervalMs() const OVERRIDE { return 1000; }
+  virtual void GiveFeedback(const FeedbackPacket& feedback) OVERRIDE {}
+  virtual int64_t TimeUntilNextProcess() OVERRIDE {
+    return std::numeric_limits<int64_t>::max();
+  }
+  virtual int Process() OVERRIDE { return 0; }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(NullSendSideBwe);
+};
+
+class RembSendSideBwe : public SendSideBwe {
+ public:
+  RembSendSideBwe(int kbps, BitrateObserver* observer, Clock* clock);
+  virtual ~RembSendSideBwe();
+
+  virtual int GetFeedbackIntervalMs() const OVERRIDE { return 100; }
+  virtual void GiveFeedback(const FeedbackPacket& feedback) OVERRIDE;
+  virtual int64_t TimeUntilNextProcess() OVERRIDE;
+  virtual int Process() OVERRIDE;
+
+ protected:
+  scoped_ptr<BitrateController> bitrate_controller_;
+  scoped_ptr<RtcpBandwidthObserver> feedback_observer_;
+
+ private:
+  Clock* clock_;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(RembSendSideBwe);
+};
+
+class FullSendSideBwe : public SendSideBwe, public RemoteBitrateObserver {
+ public:
+  FullSendSideBwe(int kbps, BitrateObserver* observer, Clock* clock);
+  virtual ~FullSendSideBwe();
+
+  virtual int GetFeedbackIntervalMs() const OVERRIDE { return 100; }
+  virtual void GiveFeedback(const FeedbackPacket& feedback) OVERRIDE;
+  virtual void OnReceiveBitrateChanged(const std::vector<unsigned int>& ssrcs,
+                                       unsigned int bitrate) OVERRIDE;
+  virtual int64_t TimeUntilNextProcess() OVERRIDE;
+  virtual int Process() OVERRIDE;
+
+ protected:
+  scoped_ptr<BitrateController> bitrate_controller_;
+  scoped_ptr<RemoteBitrateEstimator> rbe_;
+  scoped_ptr<RtcpBandwidthObserver> feedback_observer_;
+
+ private:
+  Clock* const clock_;
+  RTCPReportBlock report_block_;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(FullSendSideBwe);
+};
+
+enum BandwidthEstimatorType {
+  kNullEstimator,
+  kRembEstimator,
+  kFullSendSideEstimator
+};
+
+class PacketSender : public PacketProcessor, public BitrateObserver {
+ public:
+  PacketSender(PacketProcessorListener* listener,
+               VideoSource* source,
+               BandwidthEstimatorType estimator);
+  virtual ~PacketSender();
 
   // Call GiveFeedback() with the returned interval in milliseconds, provided
   // there is a new estimate available.
   // Note that changing the feedback interval affects the timing of when the
   // output of the estimators is sampled and therefore the baseline files may
   // have to be regenerated.
-  virtual int GetFeedbackIntervalMs() const { return 1000; }
-  virtual void GiveFeedback(const Feedback& feedback) {}
+  virtual int GetFeedbackIntervalMs() const;
+  virtual void GiveFeedback(const FeedbackPacket& feedback);
   virtual void RunFor(int64_t time_ms, Packets* in_out) OVERRIDE;
 
   virtual VideoSource* source() const { return source_; }
 
- protected:
-  VideoSource* source_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(PacketSender);
-};
-
-class RegularVideoSender : public PacketSender, public BitrateObserver {
- public:
-  RegularVideoSender(PacketProcessorListener* listener,
-                     VideoSource* source,
-                     uint32_t kbps);
-  virtual ~RegularVideoSender();
-
-  virtual int GetFeedbackIntervalMs() const OVERRIDE { return 100; }
-  virtual void GiveFeedback(const Feedback& feedback) OVERRIDE;
-  virtual void RunFor(int64_t time_ms, Packets* in_out) OVERRIDE;
-
   // Implements BitrateObserver.
   virtual void OnNetworkChanged(uint32_t target_bitrate_bps,
                                 uint8_t fraction_lost,
                                 int64_t rtt) OVERRIDE;
 
  protected:
-  static const int64_t kInitialTimeMs = 0;
   SimulatedClock clock_;
+  VideoSource* source_;
+  scoped_ptr<SendSideBwe> bwe_;
   int64_t start_of_run_ms_;
-  scoped_ptr<BitrateController> bitrate_controller_;
-  scoped_ptr<RtcpBandwidthObserver> feedback_observer_;
   std::list<Module*> modules_;
 
  private:
-  DISALLOW_IMPLICIT_CONSTRUCTORS(RegularVideoSender);
+  DISALLOW_COPY_AND_ASSIGN(PacketSender);
 };
 
-class PacedVideoSender : public RegularVideoSender,
-                         public PacedSender::Callback {
+class PacedVideoSender : public PacketSender, public PacedSender::Callback {
  public:
   PacedVideoSender(PacketProcessorListener* listener,
                    VideoSource* source,
-                   uint32_t kbps);
+                   BandwidthEstimatorType estimator);
   virtual ~PacedVideoSender();
 
   virtual void RunFor(int64_t time_ms, Packets* in_out) OVERRIDE;
diff --git a/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework_unittest.cc b/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework_unittest.cc
index 6865da5..ac57054 100644
--- a/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework_unittest.cc
+++ b/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework_unittest.cc
@@ -58,8 +58,10 @@
 static bool IsSequenceNumberSorted(const Packets& packets) {
   PacketsConstIt last_it = packets.begin();
   for (PacketsConstIt it = last_it; it != packets.end(); ++it) {
-    if (IsNewerSequenceNumber((*last_it)->header().sequenceNumber,
-                              (*it)->header().sequenceNumber)) {
+    const MediaPacket* packet = static_cast<const MediaPacket*>(*it);
+    const MediaPacket* last_packet = static_cast<const MediaPacket*>(*last_it);
+    if (IsNewerSequenceNumber(last_packet->header().sequenceNumber,
+                              packet->header().sequenceNumber)) {
       return false;
     }
     last_it = it;
@@ -72,20 +74,20 @@
   // Insert some packets in order...
   EXPECT_TRUE(IsTimeSorted(packets));
 
-  packets.push_back(new Packet(100, 0));
+  packets.push_back(new MediaPacket(100, 0));
   EXPECT_TRUE(IsTimeSorted(packets));
 
-  packets.push_back(new Packet(110, 0));
+  packets.push_back(new MediaPacket(110, 0));
   EXPECT_TRUE(IsTimeSorted(packets));
 
   // ...and one out-of-order...
-  packets.push_back(new Packet(100, 0));
+  packets.push_back(new MediaPacket(100, 0));
   EXPECT_FALSE(IsTimeSorted(packets));
 
   // ...remove the out-of-order packet, insert another in-order packet.
   delete packets.back();
   packets.pop_back();
-  packets.push_back(new Packet(120, 0));
+  packets.push_back(new MediaPacket(120, 0));
   EXPECT_TRUE(IsTimeSorted(packets));
 
   for (auto* packet : packets)
@@ -97,20 +99,20 @@
   // Insert some packets in order...
   EXPECT_TRUE(IsSequenceNumberSorted(packets));
 
-  packets.push_back(new Packet(0, 100));
+  packets.push_back(new MediaPacket(0, 100));
   EXPECT_TRUE(IsSequenceNumberSorted(packets));
 
-  packets.push_back(new Packet(0, 110));
+  packets.push_back(new MediaPacket(0, 110));
   EXPECT_TRUE(IsSequenceNumberSorted(packets));
 
   // ...and one out-of-order...
-  packets.push_back(new Packet(0, 100));
+  packets.push_back(new MediaPacket(0, 100));
   EXPECT_FALSE(IsSequenceNumberSorted(packets));
 
   // ...remove the out-of-order packet, insert another in-order packet.
   delete packets.back();
   packets.pop_back();
-  packets.push_back(new Packet(0, 120));
+  packets.push_back(new MediaPacket(0, 120));
   EXPECT_TRUE(IsSequenceNumberSorted(packets));
 
   for (auto* packet : packets)
@@ -193,7 +195,7 @@
     // "Send" a packet every 10 ms.
     for (int64_t i = 0; i < run_for_ms; i += 10, now_ms_ += 10) {
       packets.push_back(
-          new Packet(0, now_ms_ * 1000, payload_bits / 8, header));
+          new MediaPacket(0, now_ms_ * 1000, payload_bits / 8, header));
     }
     filter_.RunFor(run_for_ms, &packets);
     ASSERT_TRUE(IsTimeSorted(packets));
@@ -265,7 +267,7 @@
   for (int i = 0; i < 2225; ++i) {
     Packets packets;
     for (int j = 0; j < i % 10; ++j)
-      packets.push_back(new Packet(i, i));
+      packets.push_back(new MediaPacket(i, i));
     sent_packets += packets.size();
     filter.RunFor(0, &packets);
     ASSERT_TRUE(IsTimeSorted(packets));
@@ -320,8 +322,8 @@
                        uint32_t out_packets) {
     Packets packets;
     for (uint32_t i = 0; i < in_packets; ++i) {
-      packets.push_back(new Packet(now_ms_ * 1000 + (sequence_number_ >> 4),
-                                   sequence_number_));
+      packets.push_back(new MediaPacket(
+          now_ms_ * 1000 + (sequence_number_ >> 4), sequence_number_));
       sequence_number_++;
     }
     filter_.RunFor(run_for_ms, &packets);
@@ -421,7 +423,7 @@
   // Delay a bunch of packets, accumulate them to the 'acc' list.
   delay.SetDelay(100.0f);
   for (uint32_t i = 0; i < 10; ++i) {
-    packets.push_back(new Packet(i * 100, i));
+    packets.push_back(new MediaPacket(i * 100, i));
   }
   delay.RunFor(1000, &packets);
   acc.splice(acc.end(), packets);
@@ -432,7 +434,7 @@
   // to the 'acc' list and verify that it is all sorted.
   delay.SetDelay(0.0f);
   for (uint32_t i = 10; i < 50; ++i) {
-    packets.push_back(new Packet(i * 100, i));
+    packets.push_back(new MediaPacket(i * 100, i));
   }
   delay.RunFor(1000, &packets);
   acc.splice(acc.end(), packets);
@@ -474,8 +476,8 @@
   for (uint32_t i = 0; i < 1000; ++i) {
     Packets packets;
     for (uint32_t j = 0; j < i % 100; ++j) {
-      packets.push_back(new Packet(now_ms * 1000, sequence_number));
-      original.push_back(new Packet(now_ms * 1000, sequence_number));
+      packets.push_back(new MediaPacket(now_ms * 1000, sequence_number));
+      original.push_back(new MediaPacket(now_ms * 1000, sequence_number));
       ++sequence_number;
       now_ms += 5 * stddev_jitter_ms;
     }
@@ -496,8 +498,11 @@
   Stats<double> jitter_us;
   for (PacketsIt it1 = original.begin(), it2 = jittered.begin();
        it1 != original.end() && it2 != jittered.end(); ++it1, ++it2) {
-    EXPECT_EQ((*it1)->header().sequenceNumber, (*it2)->header().sequenceNumber);
-    jitter_us.Push((*it2)->send_time_us() - (*it1)->send_time_us());
+    const MediaPacket* packet1 = static_cast<const MediaPacket*>(*it1);
+    const MediaPacket* packet2 = static_cast<const MediaPacket*>(*it2);
+    EXPECT_EQ(packet1->header().sequenceNumber,
+              packet2->header().sequenceNumber);
+    jitter_us.Push(packet1->send_time_us() - packet2->send_time_us());
   }
   EXPECT_NEAR(0.0, jitter_us.GetMean(), stddev_jitter_ms * 1000.0 * 0.008);
   EXPECT_NEAR(stddev_jitter_ms * 1000.0, jitter_us.GetStdDev(),
@@ -536,7 +541,7 @@
   int64_t now_ms = 0;
   uint32_t sequence_number = 1;
   for (uint32_t i = 0; i < kPacketCount; ++i, now_ms += 10) {
-    packets.push_back(new Packet(now_ms * 1000, sequence_number++));
+    packets.push_back(new MediaPacket(now_ms * 1000, sequence_number++));
   }
   ASSERT_TRUE(IsTimeSorted(packets));
   ASSERT_TRUE(IsSequenceNumberSorted(packets));
@@ -552,7 +557,8 @@
   uint32_t distance = 0;
   uint32_t last_sequence_number = 0;
   for (auto* packet : packets) {
-    uint32_t sequence_number = packet->header().sequenceNumber;
+    const MediaPacket* media_packet = static_cast<const MediaPacket*>(packet);
+    uint32_t sequence_number = media_packet->header().sequenceNumber;
     if (sequence_number < last_sequence_number) {
       distance += last_sequence_number - sequence_number;
     }
@@ -622,7 +628,7 @@
       int64_t send_time_ms = now_ms_ + (i * run_for_ms) / packets_to_generate;
       header.sequenceNumber = sequence_number_++;
       // Payload is 1000 bits.
-      packets.push_back(new Packet(0, send_time_ms * 1000, 125, header));
+      packets.push_back(new MediaPacket(0, send_time_ms * 1000, 125, header));
       send_times_us_.push_back(send_time_ms * 1000);
     }
     ASSERT_TRUE(IsTimeSorted(packets));
@@ -648,8 +654,9 @@
 
   void CheckMaxDelay(int64_t max_delay_ms) {
     for (const auto* packet : output_packets_) {
-      int64_t delay_us = packet->send_time_us() -
-                         send_times_us_[packet->header().sequenceNumber];
+      const MediaPacket* media_packet = static_cast<const MediaPacket*>(packet);
+      int64_t delay_us = media_packet->send_time_us() -
+                         send_times_us_[media_packet->header().sequenceNumber];
       EXPECT_GE(max_delay_ms * 1000, delay_us);
     }
   }
@@ -781,20 +788,23 @@
   uint32_t rtp_timestamp = 0;
   uint32_t rtp_timestamp_wraps = 0;
   for (const auto* packet : packets) {
-    EXPECT_LE(send_time_us, packet->send_time_us());
-    send_time_us = packet->send_time_us();
-    if (sender->source()->max_payload_size_bytes() != packet->payload_size()) {
-      EXPECT_EQ(expected_payload_size, packet->payload_size());
+    const MediaPacket* media_packet = static_cast<const MediaPacket*>(packet);
+    EXPECT_LE(send_time_us, media_packet->send_time_us());
+    send_time_us = media_packet->send_time_us();
+    if (sender->source()->max_payload_size_bytes() !=
+        media_packet->payload_size()) {
+      EXPECT_EQ(expected_payload_size, media_packet->payload_size());
     }
-    total_payload_size += packet->payload_size();
-    if (absolute_send_time > packet->header().extension.absoluteSendTime) {
+    total_payload_size += media_packet->payload_size();
+    if (absolute_send_time >
+        media_packet->header().extension.absoluteSendTime) {
       absolute_send_time_wraps++;
     }
-    absolute_send_time = packet->header().extension.absoluteSendTime;
-    if (rtp_timestamp > packet->header().timestamp) {
+    absolute_send_time = media_packet->header().extension.absoluteSendTime;
+    if (rtp_timestamp > media_packet->header().timestamp) {
       rtp_timestamp_wraps++;
     }
-    rtp_timestamp = packet->header().timestamp;
+    rtp_timestamp = media_packet->header().timestamp;
   }
   EXPECT_EQ(expected_total_payload_size, total_payload_size);
   EXPECT_GE(1u, absolute_send_time_wraps);
@@ -807,7 +817,7 @@
 TEST(BweTestFramework_VideoSenderTest, Fps1Kbps80_1s) {
   // 1 fps, 80 kbps
   VideoSource source(0, 1.0f, 80, 0x1234, 0);
-  PacketSender sender(NULL, &source);
+  PacketSender sender(NULL, &source, kNullEstimator);
   EXPECT_EQ(10000u, source.bytes_per_second());
   // We're at 1 fps, so all packets should be generated on first call, giving 10
   // packets of each 1000 bytes, total 10000 bytes.
@@ -825,7 +835,7 @@
 TEST(BweTestFramework_VideoSenderTest, Fps1Kbps80_1s_Offset) {
   // 1 fps, 80 kbps, offset 0.5 of a frame period, ==0.5s in this case.
   VideoSource source(0, 1.0f, 80, 0x1234, 500);
-  PacketSender sender(NULL, &source);
+  PacketSender sender(NULL, &source, kNullEstimator);
   EXPECT_EQ(10000u, source.bytes_per_second());
   // 499ms, no output.
   TestVideoSender(&sender, 499, 0, 0, 0);
@@ -846,7 +856,7 @@
 TEST(BweTestFramework_VideoSenderTest, Fps50Kpbs80_11s) {
   // 50 fps, 80 kbps.
   VideoSource source(0, 50.0f, 80, 0x1234, 0);
-  PacketSender sender(NULL, &source);
+  PacketSender sender(NULL, &source, kNullEstimator);
   EXPECT_EQ(10000u, source.bytes_per_second());
   // 9998ms, should see 500 frames, 200 byte payloads, total 100000 bytes.
   TestVideoSender(&sender, 9998, 500, 200, 100000);
@@ -863,7 +873,7 @@
 TEST(BweTestFramework_VideoSenderTest, Fps10Kpbs120_1s) {
   // 20 fps, 120 kbps.
   VideoSource source(0, 20.0f, 120, 0x1234, 0);
-  PacketSender sender(NULL, &source);
+  PacketSender sender(NULL, &source, kNullEstimator);
   EXPECT_EQ(15000u, source.bytes_per_second());
   // 498ms, 10 frames with 750 byte payloads, total 7500 bytes.
   TestVideoSender(&sender, 498, 10, 750, 7500);
@@ -880,7 +890,7 @@
 TEST(BweTestFramework_VideoSenderTest, Fps30Kbps800_20s) {
   // 20 fps, 820 kbps.
   VideoSource source(0, 25.0f, 820, 0x1234, 0);
-  PacketSender sender(NULL, &source);
+  PacketSender sender(NULL, &source, kNullEstimator);
   EXPECT_EQ(102500u, source.bytes_per_second());
   // 9998ms, 250 frames. 820 kbps = 102500 bytes/s, so total should be 1025000.
   // Each frame is 102500/25=4100 bytes, or 5 packets (4 @1000 bytes, 1 @100),
@@ -902,7 +912,7 @@
 TEST(BweTestFramework_VideoSenderTest, TestAppendInOrder) {
   // 1 fps, 80 kbps, 250ms offset.
   VideoSource source1(0, 1.0f, 80, 0x1234, 250);
-  PacketSender sender1(NULL, &source1);
+  PacketSender sender1(NULL, &source1, kNullEstimator);
   EXPECT_EQ(10000u, source1.bytes_per_second());
   Packets packets;
   // Generate some packets, verify they are sorted.
@@ -918,7 +928,7 @@
 
   // Another sender, 2 fps, 160 kbps, 150ms offset
   VideoSource source2(0, 2.0f, 160, 0x2234, 150);
-  PacketSender sender2(NULL, &source2);
+  PacketSender sender2(NULL, &source2, kNullEstimator);
   EXPECT_EQ(20000u, source2.bytes_per_second());
   // Generate some packets, verify that they are merged with the packets already
   // on the list.
@@ -936,13 +946,13 @@
 
 TEST(BweTestFramework_VideoSenderTest, FeedbackIneffective) {
   VideoSource source(0, 25.0f, 820, 0x1234, 0);
-  PacketSender sender(NULL, &source);
+  PacketSender sender(NULL, &source, kNullEstimator);
 
   EXPECT_EQ(102500u, source.bytes_per_second());
   TestVideoSender(&sender, 9998, 1000, 500, 1025000);
 
   // Make sure feedback has no effect on a regular video sender.
-  PacketSender::Feedback feedback = { 512000 };
+  RembFeedback feedback(0, 0, 512000, RTCPReportBlock());
   sender.GiveFeedback(feedback);
   EXPECT_EQ(102500u, source.bytes_per_second());
   TestVideoSender(&sender, 9998, 1000, 500, 1025000);
@@ -950,20 +960,20 @@
 
 TEST(BweTestFramework_AdaptiveVideoSenderTest, FeedbackChangesBitrate) {
   AdaptiveVideoSource source(0, 25.0f, 820, 0x1234, 0);
-  RegularVideoSender sender(NULL, &source, 820);
+  PacketSender sender(NULL, &source, kRembEstimator);
   EXPECT_EQ(102500u, source.bytes_per_second());
   TestVideoSender(&sender, 9998, 1000, 500, 1025000);
 
   // Make sure we can reduce the bitrate.
-  PacketSender::Feedback feedback = { 512000 };
+  RembFeedback feedback(0, 0, 512000, RTCPReportBlock());
   sender.GiveFeedback(feedback);
   EXPECT_EQ(64000u, source.bytes_per_second());
   TestVideoSender(&sender, 9998, 750, 160, 640000);
 
   // Increase the bitrate to the initial bitrate and verify that the output is
   // the same.
-  feedback.estimated_bps = 820000;
-  sender.GiveFeedback(feedback);
+  RembFeedback feedback2(0, 0, 820000, RTCPReportBlock());
+  sender.GiveFeedback(feedback2);
   Packets packets;
   sender.RunFor(10000, &packets);
   EXPECT_EQ(102500u, source.bytes_per_second());