Refactor Remote Estimators Test into a more reusable form.

BUG=
R=andresp@webrtc.org, mflodman@webrtc.org, stefan@webrtc.org

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@5186 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/modules/modules.gyp b/webrtc/modules/modules.gyp
index 0888263..65c4827 100644
--- a/webrtc/modules/modules.gyp
+++ b/webrtc/modules/modules.gyp
@@ -184,6 +184,8 @@
             'remote_bitrate_estimator/test/bwe_test_framework_unittest.cc',
             'remote_bitrate_estimator/test/bwe_test_logging.cc',
             'remote_bitrate_estimator/test/bwe_test_logging.h',
+            'remote_bitrate_estimator/test/bwe_test.cc',
+            'remote_bitrate_estimator/test/bwe_test.h',
             'rtp_rtcp/source/mock/mock_rtp_payload_strategy.h',
             'rtp_rtcp/source/fec_receiver_unittest.cc',
             'rtp_rtcp/source/fec_test_helper.cc',
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 deeeb90..ed8e5c5 100644
--- a/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimators_test.cc
+++ b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimators_test.cc
@@ -8,444 +8,225 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "gtest/gtest.h"
-#include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.h"
 #include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
-#include "webrtc/system_wrappers/interface/clock.h"
-#include "webrtc/system_wrappers/interface/constructor_magic.h"
-#include "webrtc/system_wrappers/interface/scoped_ptr.h"
-
-#define ENABLE_1_SENDER 1
-#define ENABLE_3_SENDERS 1
-#define ENABLE_10_SENDERS 1
-#define ENABLE_BASIC_TESTS 1
-#define ENABLE_LOSS_TESTS 0
-#define ENABLE_DELAY_TESTS 0
-#define ENABLE_JITTER_TESTS 0
-#define ENABLE_REORDER_TESTS 0
-#define ENABLE_CHOKE_TESTS 0
-#define ENABLE_MULTI_TESTS 0
-
-#define ENABLE_TOF_ESTIMATOR 1
-#define ENABLE_AST_ESTIMATOR 1
-
-using std::vector;
+#include "webrtc/modules/remote_bitrate_estimator/test/bwe_test.h"
 
 namespace webrtc {
 namespace testing {
 namespace bwe {
 
-const int64_t kSimulationIntervalMs = 1000;
+std::vector<const PacketSenderFactory*> VideoSenderFactories(uint32_t count) {
+  class VideoPacketSenderFactory : public PacketSenderFactory {
+   public:
+    VideoPacketSenderFactory(float fps, uint32_t kbps, uint32_t ssrc,
+                             float frame_offset)
+        : fps_(fps),
+          kbps_(kbps),
+          ssrc_(ssrc),
+          frame_offset_(frame_offset) {
+    }
+    virtual ~VideoPacketSenderFactory() {}
+    virtual PacketSender* Create() const {
+      return new VideoSender(NULL, fps_, kbps_, ssrc_, frame_offset_);
+    }
+   private:
+    float fps_;
+    uint32_t kbps_;
+    uint32_t ssrc_;
+    float frame_offset_;
+  };
 
-namespace stl_helpers {
-template<typename T> void DeleteElements(T* container) {
-  if (!container) return;
-  for (typename T::iterator it = container->begin(); it != container->end();
-      ++it) {
-    delete *it;
+  static const VideoPacketSenderFactory factories[] = {
+    VideoPacketSenderFactory(30.00f, 150, 0x1234, 0.13f),
+    VideoPacketSenderFactory(15.00f, 500, 0x2345, 0.16f),
+    VideoPacketSenderFactory(30.00f, 1200, 0x3456, 0.26f),
+    VideoPacketSenderFactory(7.49f, 150, 0x4567, 0.05f),
+    VideoPacketSenderFactory(7.50f, 150, 0x5678, 0.15f),
+    VideoPacketSenderFactory(7.51f, 150, 0x6789, 0.25f),
+    VideoPacketSenderFactory(15.02f, 150, 0x7890, 0.27f),
+    VideoPacketSenderFactory(15.03f, 150, 0x8901, 0.38f),
+    VideoPacketSenderFactory(30.02f, 150, 0x9012, 0.39f),
+    VideoPacketSenderFactory(30.03f, 150, 0x0123, 0.52f)
+  };
+  assert(count <= sizeof(factories) / sizeof(factories[0]));
+
+  std::vector<const PacketSenderFactory*> result;
+  for (uint32_t i = 0; i < count; ++i) {
+    result.push_back(&factories[i]);
   }
-  container->clear();
+  return result;
 }
-}  // namespace stl_helpers
 
-class TestedEstimator : public RemoteBitrateObserver {
- public:
-  TestedEstimator(const std::string& debug_name,
-                  const RemoteBitrateEstimatorFactory& factory)
-      : debug_name_(debug_name),
-        clock_(0),
-        stats_(),
-        relative_estimator_stats_(),
-        latest_estimate_kbps_(-1.0),
-        estimator_(factory.Create(this, &clock_)),
-        relative_estimator_(NULL) {
-    assert(estimator_.get());
-    // Default RTT in RemoteRateControl is 200 ms ; 50 ms is more realistic.
-    estimator_->OnRttUpdate(50);
+std::vector<BweTestConfig::EstimatorConfig> EstimatorConfigs() {
+  static const RemoteBitrateEstimatorFactory factories[] = {
+    RemoteBitrateEstimatorFactory(),
+    AbsoluteSendTimeRemoteBitrateEstimatorFactory()
+  };
+
+  std::vector<BweTestConfig::EstimatorConfig> result;
+  result.push_back(BweTestConfig::EstimatorConfig("TOF", &factories[0]));
+  result.push_back(BweTestConfig::EstimatorConfig("AST", &factories[1]));
+  return result;
+}
+
+BweTestConfig MakeBweTestConfig(uint32_t sender_count) {
+  BweTestConfig result = {
+    VideoSenderFactories(sender_count), EstimatorConfigs()
+  };
+  return result;
+}
+
+INSTANTIATE_TEST_CASE_P(VideoSendersTest, BweTest,
+    ::testing::Values(MakeBweTestConfig(1),
+                      MakeBweTestConfig(3)));
+
+TEST_P(BweTest, UnlimitedSpeed) {
+  VerboseLogging(false);
+  RunFor(10 * 60 * 1000);
+}
+
+TEST_P(BweTest, SteadyLoss) {
+  LossFilter loss(this);
+  loss.SetLoss(20.0);
+  RunFor(10 * 60 * 1000);
+}
+
+TEST_P(BweTest, IncreasingLoss1) {
+  LossFilter loss(this);
+  for (int i = 0; i < 76; ++i) {
+    loss.SetLoss(i);
+    RunFor(5000);
   }
+}
 
-  void SetRelativeEstimator(TestedEstimator* relative_estimator) {
-    relative_estimator_ = relative_estimator;
+TEST_P(BweTest, SteadyDelay) {
+  DelayFilter delay(this);
+  delay.SetDelay(1000);
+  RunFor(10 * 60 * 1000);
+}
+
+TEST_P(BweTest, IncreasingDelay1) {
+  DelayFilter delay(this);
+  RunFor(10 * 60 * 1000);
+  for (int i = 0; i < 30 * 2; ++i) {
+    delay.SetDelay(i);
+    RunFor(10 * 1000);
   }
+  RunFor(10 * 60 * 1000);
+}
 
-  void EatPacket(const BwePacket& packet) {
-    BWE_TEST_LOGGING_CONTEXT(debug_name_);
-
-    latest_estimate_kbps_ = -1.0;
-
-    // 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);
-
-    int64_t step_ms = estimator_->TimeUntilNextProcess();
-    while ((clock_.TimeInMilliseconds() + step_ms) < packet_time_ms) {
-      clock_.AdvanceTimeMilliseconds(step_ms);
-      estimator_->Process();
-      step_ms = estimator_->TimeUntilNextProcess();
-    }
-
-    estimator_->IncomingPacket(packet_time_ms, packet.payload_size(),
-                               packet.header());
-    clock_.AdvanceTimeMilliseconds(packet_time_ms -
-                                   clock_.TimeInMilliseconds());
-    ASSERT_TRUE(packet_time_ms == clock_.TimeInMilliseconds());
+TEST_P(BweTest, IncreasingDelay2) {
+  DelayFilter delay(this);
+  RateCounterFilter counter(this);
+  RunFor(1 * 60 * 1000);
+  for (int i = 1; i < 51; ++i) {
+    delay.SetDelay(10.0f * i);
+    RunFor(10 * 1000);
   }
+  delay.SetDelay(0.0f);
+  RunFor(10 * 60 * 1000);
+}
 
-  void CheckEstimate() {
-    BWE_TEST_LOGGING_CONTEXT(debug_name_);
-    double estimated_kbps = 0.0;
-    if (LatestEstimate(&estimated_kbps)) {
-      stats_.Push(estimated_kbps);
-      BWE_TEST_LOGGING_PLOT("Estimate", clock_.TimeInMilliseconds(),
-                            estimated_kbps / 100);
-      double relative_estimate_kbps = 0.0;
-      if (relative_estimator_ &&
-          relative_estimator_->LatestEstimate(&relative_estimate_kbps)) {
-        relative_estimator_stats_.Push(estimated_kbps - relative_estimate_kbps);
-      }
-    }
+TEST_P(BweTest, JumpyDelay1) {
+  DelayFilter delay(this);
+  RunFor(10 * 60 * 1000);
+  for (int i = 1; i < 200; ++i) {
+    delay.SetDelay((10 * i) % 500);
+    RunFor(1000);
+    delay.SetDelay(1.0f);
+    RunFor(1000);
   }
+  delay.SetDelay(0.0f);
+  RunFor(10 * 60 * 1000);
+}
 
-  void LogStats() {
-    BWE_TEST_LOGGING_CONTEXT(debug_name_);
-    BWE_TEST_LOGGING_CONTEXT("Mean");
-    stats_.Log("kbps");
-    if (relative_estimator_) {
-      BWE_TEST_LOGGING_CONTEXT("Diff");
-      relative_estimator_stats_.Log("kbps");
-    }
+TEST_P(BweTest, SteadyJitter) {
+  JitterFilter jitter(this);
+  RateCounterFilter counter(this);
+  jitter.SetJitter(20);
+  RunFor(2 * 60 * 1000);
+}
+
+TEST_P(BweTest, IncreasingJitter1) {
+  JitterFilter jitter(this);
+  for (int i = 0; i < 2 * 60 * 2; ++i) {
+    jitter.SetJitter(i);
+    RunFor(10 * 1000);
   }
+  RunFor(10 * 60 * 1000);
+}
 
-  virtual void OnReceiveBitrateChanged(const vector<unsigned int>& ssrcs,
-                                       unsigned int bitrate) {
+TEST_P(BweTest, IncreasingJitter2) {
+  JitterFilter jitter(this);
+  RunFor(30 * 1000);
+  for (int i = 1; i < 51; ++i) {
+    jitter.SetJitter(10.0f * i);
+    RunFor(10 * 1000);
   }
+  jitter.SetJitter(0.0f);
+  RunFor(10 * 60 * 1000);
+}
 
- private:
-  bool LatestEstimate(double* estimate_kbps) {
-    if (latest_estimate_kbps_ < 0.0) {
-      vector<unsigned int> ssrcs;
-      unsigned int bps = 0;
-      if (!estimator_->LatestEstimate(&ssrcs, &bps)) {
-        return false;
-      }
-      latest_estimate_kbps_ = bps / 1000.0;
-    }
-    *estimate_kbps = latest_estimate_kbps_;
-    return true;
+TEST_P(BweTest, SteadyReorder) {
+  ReorderFilter reorder(this);
+  reorder.SetReorder(20.0);
+  RunFor(10 * 60 * 1000);
+}
+
+TEST_P(BweTest, IncreasingReorder1) {
+  ReorderFilter reorder(this);
+  for (int i = 0; i < 76; ++i) {
+    reorder.SetReorder(i);
+    RunFor(5000);
   }
+}
 
-  std::string debug_name_;
-  bool log_estimates_;
-  SimulatedClock clock_;
-  Stats<double> stats_;
-  Stats<double> relative_estimator_stats_;
-  double latest_estimate_kbps_;
-  scoped_ptr<RemoteBitrateEstimator> estimator_;
-  TestedEstimator* relative_estimator_;
+TEST_P(BweTest, SteadyChoke) {
+  ChokeFilter choke(this);
+  choke.SetCapacity(140);
+  RunFor(10 * 60 * 1000);
+}
 
-  DISALLOW_IMPLICIT_CONSTRUCTORS(TestedEstimator);
-};
-
-class RemoteBitrateEstimatorsTest : public ::testing::Test {
- public:
-  RemoteBitrateEstimatorsTest()
-      : run_time_ms_(0),
-        estimators_(),
-        previous_packets_(),
-        processors_(),
-        video_senders_() {
+TEST_P(BweTest, IncreasingChoke1) {
+  ChokeFilter choke(this);
+  for (int i = 1200; i >= 100; i -= 100) {
+    choke.SetCapacity(i);
+    RunFor(5000);
   }
-  virtual ~RemoteBitrateEstimatorsTest() {
-    stl_helpers::DeleteElements(&estimators_);
-    stl_helpers::DeleteElements(&video_senders_);
-  }
+}
 
-  virtual void SetUp() {
-#if ENABLE_TOF_ESTIMATOR
-    estimators_.push_back(new TestedEstimator("TOF",
-        RemoteBitrateEstimatorFactory()));
-#endif
-#if ENABLE_AST_ESTIMATOR
-    estimators_.push_back(new TestedEstimator("AST",
-        AbsoluteSendTimeRemoteBitrateEstimatorFactory()));
-#endif
-    // Set all estimators as relative to the first one.
-    for (uint32_t i = 1; i < estimators_.size(); ++i) {
-      estimators_[i]->SetRelativeEstimator(estimators_[0]);
-    }
+TEST_P(BweTest, IncreasingChoke2) {
+  ChokeFilter choke(this);
+  RunFor(60 * 1000);
+  for (int i = 1200; i >= 100; i -= 20) {
+    choke.SetCapacity(i);
+    RunFor(1000);
   }
+}
 
- protected:
-  void RunFor(int64_t time_ms) {
-    for (run_time_ms_ += time_ms; run_time_ms_ >= kSimulationIntervalMs;
-        run_time_ms_ -= kSimulationIntervalMs) {
-      Packets packets;
-      for (vector<PacketProcessorInterface*>::const_iterator it =
-           processors_.begin(); it != processors_.end(); ++it) {
-        (*it)->RunFor(kSimulationIntervalMs, &packets);
-      }
+TEST_P(BweTest, Multi1) {
+  DelayFilter delay(this);
+  ChokeFilter choke(this);
+  RateCounterFilter counter(this);
+  choke.SetCapacity(1000);
+  RunFor(1 * 60 * 1000);
+  for (int i = 1; i < 51; ++i) {
+    delay.SetDelay(100.0f * i);
+    RunFor(10 * 1000);
+  }
+  RunFor(500 * 1000);
+  delay.SetDelay(0.0f);
+  RunFor(5 * 60 * 1000);
+}
 
-      // Verify packets are in order between batches.
-      if (!packets.empty() && !previous_packets_.empty()) {
-        packets.splice(packets.begin(), previous_packets_,
-                       --previous_packets_.end());
-        ASSERT_TRUE(IsTimeSorted(packets));
-        packets.erase(packets.begin());
-      } else {
-        ASSERT_TRUE(IsTimeSorted(packets));
-      }
-
-      for (PacketsConstIt pit = packets.begin(); pit != packets.end(); ++pit) {
-        for (vector<TestedEstimator*>::iterator eit = estimators_.begin();
-            eit != estimators_.end(); ++eit) {
-          (*eit)->EatPacket(*pit);
-        }
-      }
-
-      previous_packets_.swap(packets);
-
-      for (vector<TestedEstimator*>::iterator eit = estimators_.begin();
-          eit != estimators_.end(); ++eit) {
-        (*eit)->CheckEstimate();
-      }
-    }
-  }
-
-  void AddVideoSenders(uint32_t count) {
-    struct { float fps; uint32_t kbps; uint32_t ssrc; float frame_offset; }
-        configs[] = {
-            { 30.00f, 150, 0x1234, 0.13f },
-            { 15.00f, 500, 0x2345, 0.16f },
-            { 30.00f, 1200, 0x3456, 0.26f },
-            { 7.49f, 150, 0x4567, 0.05f },
-            { 7.50f, 150, 0x5678, 0.15f },
-            { 7.51f, 150, 0x6789, 0.25f },
-            { 15.02f, 150, 0x7890, 0.27f },
-            { 15.03f, 150, 0x8901, 0.38f },
-            { 30.02f, 150, 0x9012, 0.39f },
-            { 30.03f, 150, 0x0123, 0.52f }
-        };
-    assert(count <= sizeof(configs) / sizeof(configs[0]));
-    uint32_t total_capacity = 0;
-    for (uint32_t i = 0; i < count; ++i) {
-      video_senders_.push_back(new VideoSender(configs[i].fps, configs[i].kbps,
-          configs[i].ssrc, configs[i].frame_offset));
-      processors_.push_back(video_senders_.back());
-      total_capacity += configs[i].kbps;
-    }
-    BWE_TEST_LOGGING_LOG1("RequiredLinkCapacity", "%d kbps", total_capacity)
-  }
-
-  void LogStats() {
-    for (vector<TestedEstimator*>::iterator eit = estimators_.begin();
-        eit != estimators_.end(); ++eit) {
-      (*eit)->LogStats();
-    }
-  }
-
-  void UnlimitedSpeedTest() {
-    RunFor(10 * 60 * 1000);
-  }
-
-  void SteadyLossTest() {
-    LossFilter loss;
-    processors_.push_back(&loss);
-    loss.SetLoss(20.0);
-    RunFor(10 * 60 * 1000);
-  }
-  void IncreasingLoss1Test() {
-    LossFilter loss;
-    processors_.push_back(&loss);
-    for (int i = 0; i < 76; ++i) {
-      loss.SetLoss(i);
-      RunFor(5000);
-    }
-  }
-
-  void SteadyDelayTest() {
-    DelayFilter delay;
-    processors_.push_back(&delay);
-    delay.SetDelay(1000);
-    RunFor(10 * 60 * 1000);
-  }
-  void IncreasingDelay1Test() {
-    DelayFilter delay;
-    processors_.push_back(&delay);
-    RunFor(10 * 60 * 1000);
-    for (int i = 0; i < 30 * 2; ++i) {
-      delay.SetDelay(i);
-      RunFor(10 * 1000);
-    }
-    RunFor(10 * 60 * 1000);
-  }
-  void IncreasingDelay2Test() {
-    DelayFilter delay;
-    RateCounterFilter counter;
-    processors_.push_back(&delay);
-    processors_.push_back(&counter);
-    RunFor(1 * 60 * 1000);
-    for (int i = 1; i < 51; ++i) {
-      delay.SetDelay(10.0f * i);
-      RunFor(10 * 1000);
-    }
-    delay.SetDelay(0.0f);
-    RunFor(10 * 60 * 1000);
-  }
-  void JumpyDelay1Test() {
-    DelayFilter delay;
-    processors_.push_back(&delay);
-    RunFor(10 * 60 * 1000);
-    for (int i = 1; i < 200; ++i) {
-      delay.SetDelay((10 * i) % 500);
-      RunFor(1000);
-      delay.SetDelay(1.0f);
-      RunFor(1000);
-    }
-    delay.SetDelay(0.0f);
-    RunFor(10 * 60 * 1000);
-  }
-
-  void SteadyJitterTest() {
-    JitterFilter jitter;
-    RateCounterFilter counter;
-    processors_.push_back(&jitter);
-    processors_.push_back(&counter);
-    jitter.SetJitter(20);
-    RunFor(2 * 60 * 1000);
-  }
-  void IncreasingJitter1Test() {
-    JitterFilter jitter;
-    processors_.push_back(&jitter);
-    for (int i = 0; i < 2 * 60 * 2; ++i) {
-      jitter.SetJitter(i);
-      RunFor(10 * 1000);
-    }
-    RunFor(10 * 60 * 1000);
-  }
-  void IncreasingJitter2Test() {
-    JitterFilter jitter;
-    processors_.push_back(&jitter);
-    RunFor(30 * 1000);
-    for (int i = 1; i < 51; ++i) {
-      jitter.SetJitter(10.0f * i);
-      RunFor(10 * 1000);
-    }
-    jitter.SetJitter(0.0f);
-    RunFor(10 * 60 * 1000);
-  }
-
-  void SteadyReorderTest() {
-    ReorderFilter reorder;
-    processors_.push_back(&reorder);
-    reorder.SetReorder(20.0);
-    RunFor(10 * 60 * 1000);
-  }
-  void IncreasingReorder1Test() {
-    ReorderFilter reorder;
-    processors_.push_back(&reorder);
-    for (int i = 0; i < 76; ++i) {
-      reorder.SetReorder(i);
-      RunFor(5000);
-    }
-  }
-
-  void SteadyChokeTest() {
-    ChokeFilter choke;
-    processors_.push_back(&choke);
-    choke.SetCapacity(140);
-    RunFor(10 * 60 * 1000);
-  }
-  void IncreasingChoke1Test() {
-    ChokeFilter choke;
-    processors_.push_back(&choke);
-    for (int i = 1200; i >= 100; i -= 100) {
-      choke.SetCapacity(i);
-      RunFor(5000);
-    }
-  }
-  void IncreasingChoke2Test() {
-    ChokeFilter choke;
-    processors_.push_back(&choke);
-    RunFor(60 * 1000);
-    for (int i = 1200; i >= 100; i -= 20) {
-      choke.SetCapacity(i);
-      RunFor(1000);
-    }
-  }
-
-  void Multi1Test() {
-    DelayFilter delay;
-    ChokeFilter choke;
-    RateCounterFilter counter;
-    processors_.push_back(&delay);
-    processors_.push_back(&choke);
-    processors_.push_back(&counter);
-    choke.SetCapacity(1000);
-    RunFor(1 * 60 * 1000);
-    for (int i = 1; i < 51; ++i) {
-      delay.SetDelay(100.0f * i);
-      RunFor(10 * 1000);
-    }
-    delay.SetDelay(0.0f);
-    RunFor(5 * 60 * 1000);
-  }
-  void Multi2Test() {
-    ChokeFilter choke;
-    JitterFilter jitter;
-    RateCounterFilter counter;
-    processors_.push_back(&choke);
-    processors_.push_back(&jitter);
-    processors_.push_back(&counter);
-    choke.SetCapacity(2000);
-    jitter.SetJitter(120);
-    RunFor(5 * 60 * 1000);
-  }
-
- private:
-  int64_t run_time_ms_;
-  vector<TestedEstimator*> estimators_;
-  Packets previous_packets_;
-  vector<PacketProcessorInterface*> processors_;
-  vector<VideoSender*> video_senders_;
-
-  DISALLOW_COPY_AND_ASSIGN(RemoteBitrateEstimatorsTest);
-};
-
-#define SINGLE_TEST(enabled, test_name, video_senders, log)\
-    TEST_F(RemoteBitrateEstimatorsTest, test_name##_##video_senders##Sender) {\
-      BWE_TEST_LOGGING_ENABLE(log);\
-      if (enabled) {\
-        BWE_TEST_LOGGING_CONTEXT(#test_name);\
-        AddVideoSenders(video_senders);\
-        test_name##Test();\
-        LogStats();\
-      }\
-    }
-
-#define MULTI_TEST(enabled, test_name, log)\
-    SINGLE_TEST((enabled) && ENABLE_1_SENDER, test_name, 1, log)\
-    SINGLE_TEST((enabled) && ENABLE_3_SENDERS, test_name, 3, log)\
-    SINGLE_TEST((enabled) && ENABLE_10_SENDERS, test_name, 10, log)
-
-MULTI_TEST(ENABLE_BASIC_TESTS, UnlimitedSpeed, true)
-MULTI_TEST(ENABLE_LOSS_TESTS, SteadyLoss, true)
-MULTI_TEST(ENABLE_LOSS_TESTS, IncreasingLoss1, true)
-MULTI_TEST(ENABLE_DELAY_TESTS, SteadyDelay, true)
-MULTI_TEST(ENABLE_DELAY_TESTS, IncreasingDelay1, true)
-MULTI_TEST(ENABLE_DELAY_TESTS, IncreasingDelay2, true)
-MULTI_TEST(ENABLE_DELAY_TESTS, JumpyDelay1, true)
-MULTI_TEST(ENABLE_JITTER_TESTS, SteadyJitter, true)
-MULTI_TEST(ENABLE_JITTER_TESTS, IncreasingJitter1, true)
-MULTI_TEST(ENABLE_JITTER_TESTS, IncreasingJitter2, true)
-MULTI_TEST(ENABLE_REORDER_TESTS, SteadyReorder, true)
-MULTI_TEST(ENABLE_REORDER_TESTS, IncreasingReorder1, true)
-MULTI_TEST(ENABLE_CHOKE_TESTS, SteadyChoke, true)
-MULTI_TEST(ENABLE_CHOKE_TESTS, IncreasingChoke1, true)
-MULTI_TEST(ENABLE_CHOKE_TESTS, IncreasingChoke2, true)
-MULTI_TEST(ENABLE_MULTI_TESTS, Multi1, true)
-MULTI_TEST(ENABLE_MULTI_TESTS, Multi2, true)
-
+TEST_P(BweTest, Multi2) {
+  ChokeFilter choke(this);
+  JitterFilter jitter(this);
+  RateCounterFilter counter(this);
+  choke.SetCapacity(2000);
+  jitter.SetJitter(120);
+  RunFor(5 * 60 * 1000);
+}
 }  // namespace bwe
 }  // namespace testing
 }  // namespace webrtc
diff --git a/webrtc/modules/remote_bitrate_estimator/test/bwe_test.cc b/webrtc/modules/remote_bitrate_estimator/test/bwe_test.cc
new file mode 100644
index 0000000..3046a5b
--- /dev/null
+++ b/webrtc/modules/remote_bitrate_estimator/test/bwe_test.cc
@@ -0,0 +1,263 @@
+/*
+ *  Copyright (c) 2013 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/remote_bitrate_estimator/test/bwe_test.h"
+
+#include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.h"
+#include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
+#include "webrtc/system_wrappers/interface/clock.h"
+#include "webrtc/system_wrappers/interface/scoped_ptr.h"
+
+using std::string;
+using std::vector;
+
+namespace webrtc {
+namespace testing {
+namespace bwe {
+
+namespace stl_helpers {
+template<typename T> void DeleteElements(T* container) {
+  if (!container) return;
+  for (typename T::iterator it = container->begin(); it != container->end();
+      ++it) {
+    delete *it;
+  }
+  container->clear();
+}
+}  // namespace stl_helpers
+
+class BweTest::TestedEstimator : public RemoteBitrateObserver {
+ public:
+  explicit TestedEstimator(const BweTestConfig::EstimatorConfig& config)
+      : debug_name_(config.debug_name),
+        clock_(0),
+        stats_(),
+        relative_estimator_stats_(),
+        latest_estimate_kbps_(-1.0),
+        estimator_(config.estimator_factory->Create(this, &clock_)),
+        relative_estimator_(NULL) {
+    assert(estimator_.get());
+    // Default RTT in RemoteRateControl is 200 ms ; 50 ms is more realistic.
+    estimator_->OnRttUpdate(50);
+  }
+
+  void SetRelativeEstimator(TestedEstimator* relative_estimator) {
+    relative_estimator_ = relative_estimator;
+  }
+
+  void EatPacket(const Packet& packet) {
+    BWE_TEST_LOGGING_CONTEXT(debug_name_);
+
+    latest_estimate_kbps_ = -1.0;
+
+    // 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);
+
+    int64_t step_ms = estimator_->TimeUntilNextProcess();
+    while ((clock_.TimeInMilliseconds() + step_ms) < packet_time_ms) {
+      clock_.AdvanceTimeMilliseconds(step_ms);
+      estimator_->Process();
+      step_ms = estimator_->TimeUntilNextProcess();
+    }
+
+    estimator_->IncomingPacket(packet_time_ms, packet.payload_size(),
+                               packet.header());
+    clock_.AdvanceTimeMilliseconds(packet_time_ms -
+                                   clock_.TimeInMilliseconds());
+    ASSERT_TRUE(packet_time_ms == clock_.TimeInMilliseconds());
+  }
+
+  bool CheckEstimate(PacketSender::Feedback* feedback) {
+    assert(feedback);
+    BWE_TEST_LOGGING_CONTEXT(debug_name_);
+    double estimated_kbps = 0.0;
+    if (LatestEstimate(&estimated_kbps)) {
+      stats_.Push(estimated_kbps);
+      BWE_TEST_LOGGING_PLOT("Estimate", clock_.TimeInMilliseconds(),
+                            estimated_kbps / 100);
+      double relative_estimate_kbps = 0.0;
+      if (relative_estimator_ &&
+          relative_estimator_->LatestEstimate(&relative_estimate_kbps)) {
+        relative_estimator_stats_.Push(estimated_kbps - relative_estimate_kbps);
+      }
+      feedback->estimated_kbps = estimated_kbps;
+      return true;
+    }
+    return false;
+  }
+
+  void LogStats() {
+    BWE_TEST_LOGGING_CONTEXT(debug_name_);
+    BWE_TEST_LOGGING_CONTEXT("Mean");
+    stats_.Log("kbps");
+    if (relative_estimator_) {
+      BWE_TEST_LOGGING_CONTEXT("Diff");
+      relative_estimator_stats_.Log("kbps");
+    }
+  }
+
+  virtual void OnReceiveBitrateChanged(const vector<unsigned int>& ssrcs,
+                                       unsigned int bitrate) {
+  }
+
+ private:
+  bool LatestEstimate(double* estimate_kbps) {
+    if (latest_estimate_kbps_ < 0.0) {
+      vector<unsigned int> ssrcs;
+      unsigned int bps = 0;
+      if (!estimator_->LatestEstimate(&ssrcs, &bps)) {
+        return false;
+      }
+      latest_estimate_kbps_ = bps / 1000.0;
+    }
+    *estimate_kbps = latest_estimate_kbps_;
+    return true;
+  }
+
+  string debug_name_;
+  bool log_estimates_;
+  SimulatedClock clock_;
+  Stats<double> stats_;
+  Stats<double> relative_estimator_stats_;
+  double latest_estimate_kbps_;
+  scoped_ptr<RemoteBitrateEstimator> estimator_;
+  TestedEstimator* relative_estimator_;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(TestedEstimator);
+};
+
+BweTest::BweTest()
+    : run_time_ms_(0),
+      simulation_interval_ms_(-1),
+      previous_packets_(),
+      packet_senders_(),
+      estimators_(),
+      processors_() {
+}
+
+BweTest::~BweTest() {
+  stl_helpers::DeleteElements(&estimators_);
+  stl_helpers::DeleteElements(&packet_senders_);
+}
+
+void BweTest::SetUp() {
+  BWE_TEST_LOGGING_GLOBAL_CONTEXT(::testing::UnitTest::GetInstance()->
+      current_test_info()->test_case_name());
+
+  const BweTestConfig& config = GetParam();
+
+  uint32_t total_capacity = 0;
+  for (vector<const PacketSenderFactory*>::const_iterator it =
+      config.sender_factories.begin(); it != config.sender_factories.end();
+      ++it) {
+    PacketSender* sender = (*it)->Create();
+    assert(sender);
+    total_capacity += sender->GetCapacityKbps();
+    packet_senders_.push_back(sender);
+    processors_.push_back(sender);
+  }
+  BWE_TEST_LOGGING_LOG1("RequiredLinkCapacity", "%d kbps", total_capacity)
+
+  // Set simulation interval from first packet sender.
+  if (packet_senders_.size() > 0) {
+    simulation_interval_ms_ = packet_senders_[0]->GetFeedbackIntervalMs();
+  }
+
+  for (vector<BweTestConfig::EstimatorConfig>:: const_iterator it =
+      config.estimator_configs.begin(); it != config.estimator_configs.end();
+      ++it) {
+    estimators_.push_back(new TestedEstimator(*it));
+  }
+  if (estimators_.size() > 1) {
+    // Set all estimators as relative to the first one.
+    for (uint32_t i = 1; i < estimators_.size(); ++i) {
+      estimators_[i]->SetRelativeEstimator(estimators_[0]);
+    }
+  }
+
+  BWE_TEST_LOGGING_GLOBAL_ENABLE(false);
+}
+
+void BweTest::TearDown() {
+  BWE_TEST_LOGGING_GLOBAL_ENABLE(true);
+  LogStats();
+  BWE_TEST_LOGGING_GLOBAL_CONTEXT("");
+}
+
+void BweTest::AddPacketProcessor(
+    PacketProcessor* processor) {
+  assert(processor);
+  processors_.push_back(processor);
+}
+
+void BweTest::RemovePacketProcessor(
+    PacketProcessor* processor) {
+  vector<PacketProcessor*>::iterator it =
+      std::find(processors_.begin(), processors_.end(), processor);
+  assert(it != processors_.end());
+  processors_.erase(it);
+}
+
+void BweTest::VerboseLogging(bool enable) {
+  BWE_TEST_LOGGING_GLOBAL_ENABLE(enable);
+}
+
+void BweTest::RunFor(int64_t time_ms) {
+  for (run_time_ms_ += time_ms; run_time_ms_ >= simulation_interval_ms_;
+      run_time_ms_ -= simulation_interval_ms_) {
+    Packets packets;
+    for (vector<PacketProcessor*>::const_iterator it =
+         processors_.begin(); it != processors_.end(); ++it) {
+      (*it)->RunFor(simulation_interval_ms_, &packets);
+    }
+
+    // Verify packets are in order between batches.
+    if (!packets.empty() && !previous_packets_.empty()) {
+      packets.splice(packets.begin(), previous_packets_,
+                     --previous_packets_.end());
+      ASSERT_TRUE(IsTimeSorted(packets));
+      packets.erase(packets.begin());
+    } else {
+      ASSERT_TRUE(IsTimeSorted(packets));
+    }
+
+    for (PacketsConstIt pit = packets.begin(); pit != packets.end(); ++pit) {
+      for (vector<TestedEstimator*>::iterator eit = estimators_.begin();
+          eit != estimators_.end(); ++eit) {
+        (*eit)->EatPacket(*pit);
+      }
+    }
+
+    previous_packets_.swap(packets);
+
+    for (vector<TestedEstimator*>::iterator eit = estimators_.begin();
+        eit != estimators_.end(); ++eit) {
+      PacketSender::Feedback feedback = {0};
+      if ((*eit)->CheckEstimate(&feedback)) {
+        for (vector<PacketSender*>::iterator psit = packet_senders_.begin();
+            psit != packet_senders_.end(); ++psit) {
+          (*psit)->GiveFeedback(feedback);
+        }
+      }
+    }
+  }
+}
+
+void BweTest::LogStats() {
+  for (vector<TestedEstimator*>::iterator eit = estimators_.begin();
+      eit != estimators_.end(); ++eit) {
+    (*eit)->LogStats();
+  }
+}
+}  // namespace bwe
+}  // namespace testing
+}  // namespace webrtc
diff --git a/webrtc/modules/remote_bitrate_estimator/test/bwe_test.h b/webrtc/modules/remote_bitrate_estimator/test/bwe_test.h
new file mode 100644
index 0000000..0945ea6
--- /dev/null
+++ b/webrtc/modules/remote_bitrate_estimator/test/bwe_test.h
@@ -0,0 +1,70 @@
+/*
+ *  Copyright (c) 2013 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 <string>
+#include <vector>
+#include "gtest/gtest.h"
+#include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.h"
+#include "webrtc/system_wrappers/interface/constructor_magic.h"
+
+namespace webrtc {
+
+struct RemoteBitrateEstimatorFactory;
+
+namespace testing {
+namespace bwe {
+
+struct BweTestConfig {
+  struct EstimatorConfig {
+    EstimatorConfig() : debug_name(), estimator_factory(NULL) {}
+    EstimatorConfig(std::string debug_name,
+                    const RemoteBitrateEstimatorFactory* estimator_factory)
+        : debug_name(debug_name),
+          estimator_factory(estimator_factory) {
+    }
+    std::string debug_name;
+    const RemoteBitrateEstimatorFactory* estimator_factory;
+  };
+
+  std::vector<const PacketSenderFactory*> sender_factories;
+  std::vector<EstimatorConfig> estimator_configs;
+};
+
+class BweTest : public ::testing::TestWithParam<BweTestConfig>,
+    public PacketProcessorListener {
+ public:
+  BweTest();
+  virtual ~BweTest();
+
+  virtual void SetUp();
+  virtual void TearDown();
+  virtual void AddPacketProcessor(PacketProcessor* processor);
+  virtual void RemovePacketProcessor(PacketProcessor* processor);
+
+ protected:
+  void VerboseLogging(bool enable);
+  void RunFor(int64_t time_ms);
+  void LogStats();
+
+ private:
+  class TestedEstimator;
+
+  int64_t run_time_ms_;
+  int64_t simulation_interval_ms_;
+  Packets previous_packets_;
+  std::vector<PacketSender*> packet_senders_;
+  std::vector<TestedEstimator*> estimators_;
+  std::vector<PacketProcessor*> processors_;
+
+  DISALLOW_COPY_AND_ASSIGN(BweTest);
+};
+}  // namespace bwe
+}  // namespace testing
+}  // namespace webrtc
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 b90a7f6..9b64eaf 100644
--- a/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.cc
+++ b/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.cc
@@ -14,6 +14,62 @@
 namespace testing {
 namespace bwe {
 
+Random::Random(uint32_t seed)
+    : a_(0x531FDB97 ^ seed),
+      b_(0x6420ECA8 + seed) {
+}
+
+float Random::Rand() {
+  const float kScale = 1.0f / 0xffffffff;
+  float result = kScale * b_;
+  a_ ^= b_;
+  b_ += a_;
+  return result;
+}
+
+int Random::Gaussian(int mean, int standard_deviation) {
+  // Creating a Normal distribution variable from two independent uniform
+  // variables based on the Box-Muller transform, which is defined on the
+  // interval (0, 1], hence the mask+add below.
+  const double kPi = 3.14159265358979323846;
+  const double kScale = 1.0 / 0x80000000ul;
+  double u1 = kScale * ((a_ & 0x7ffffffful) + 1);
+  double u2 = kScale * ((b_ & 0x7ffffffful) + 1);
+  a_ ^= b_;
+  b_ += a_;
+  return static_cast<int>(mean + standard_deviation *
+      std::sqrt(-2 * std::log(u1)) * std::cos(2 * kPi * u2));
+}
+
+Packet::Packet()
+    : send_time_us_(0),
+      payload_size_(0) {
+   memset(&header_, 0, sizeof(header_));
+}
+
+Packet::Packet(int64_t send_time_us, uint32_t payload_size,
+          const RTPHeader& header)
+  : send_time_us_(send_time_us),
+    payload_size_(payload_size),
+    header_(header) {
+}
+
+Packet::Packet(int64_t send_time_us, uint32_t sequence_number)
+    : send_time_us_(send_time_us),
+      payload_size_(0) {
+   memset(&header_, 0, sizeof(header_));
+   header_.sequenceNumber = sequence_number;
+}
+
+bool Packet::operator<(const Packet& rhs) const {
+  return send_time_us_ < rhs.send_time_us_;
+}
+
+void Packet::set_send_time_us(int64_t send_time_us) {
+  assert(send_time_us >= 0);
+  send_time_us_ = send_time_us;
+}
+
 bool IsTimeSorted(const Packets& packets) {
   PacketsConstIt last_it = packets.begin();
   for (PacketsConstIt it = last_it; it != packets.end(); ++it) {
@@ -24,6 +80,261 @@
   }
   return true;
 }
+
+PacketProcessor::PacketProcessor(PacketProcessorListener* listener)
+    : listener_(listener) {
+  if (listener_) {
+    listener_->AddPacketProcessor(this);
+  }
+}
+
+PacketProcessor::~PacketProcessor() {
+  if (listener_) {
+    listener_->RemovePacketProcessor(this);
+  }
+}
+
+RateCounterFilter::RateCounterFilter(PacketProcessorListener* listener)
+    : PacketProcessor(listener),
+      kWindowSizeUs(1000000),
+      packets_per_second_(0),
+      bytes_per_second_(0),
+      last_accumulated_us_(0),
+      window_(),
+      pps_stats_(),
+      kbps_stats_() {
+}
+
+RateCounterFilter::~RateCounterFilter() {
+  LogStats();
+}
+
+void RateCounterFilter::LogStats() {
+  BWE_TEST_LOGGING_CONTEXT("RateCounterFilter");
+  pps_stats_.Log("pps");
+  kbps_stats_.Log("kbps");
+}
+
+void RateCounterFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
+  assert(in_out);
+  for (PacketsConstIt it = in_out->begin(); it != in_out->end(); ++it) {
+    packets_per_second_++;
+    bytes_per_second_ += it->payload_size();
+    last_accumulated_us_ = it->send_time_us();
+  }
+  window_.insert(window_.end(), in_out->begin(), in_out->end());
+  while (!window_.empty()) {
+    const Packet& packet = window_.front();
+    if (packet.send_time_us() > (last_accumulated_us_ - kWindowSizeUs)) {
+      break;
+    }
+    assert(packets_per_second_ >= 1);
+    assert(bytes_per_second_ >= packet.payload_size());
+    packets_per_second_--;
+    bytes_per_second_ -= packet.payload_size();
+    window_.pop_front();
+  }
+  pps_stats_.Push(packets_per_second_);
+  kbps_stats_.Push((bytes_per_second_ * 8) / 1000.0);
+}
+
+LossFilter::LossFilter(PacketProcessorListener* listener)
+    : PacketProcessor(listener),
+      random_(0x12345678),
+      loss_fraction_(0.0f) {
+}
+
+void LossFilter::SetLoss(float loss_percent) {
+  BWE_TEST_LOGGING_ENABLE(false);
+  BWE_TEST_LOGGING_LOG1("Loss", "%f%%", loss_percent);
+  assert(loss_percent >= 0.0f);
+  assert(loss_percent <= 100.0f);
+  loss_fraction_ = loss_percent * 0.01f;
+}
+
+void LossFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
+  assert(in_out);
+  for (PacketsIt it = in_out->begin(); it != in_out->end(); ) {
+    if (random_.Rand() < loss_fraction_) {
+      it = in_out->erase(it);
+    } else {
+      ++it;
+    }
+  }
+}
+
+DelayFilter::DelayFilter(PacketProcessorListener* listener)
+    : PacketProcessor(listener),
+      delay_us_(0),
+      last_send_time_us_(0) {
+}
+
+void DelayFilter::SetDelay(int64_t delay_ms) {
+  BWE_TEST_LOGGING_ENABLE(false);
+  BWE_TEST_LOGGING_LOG1("Delay", "%d ms", static_cast<int>(delay_ms));
+  assert(delay_ms >= 0);
+  delay_us_ = delay_ms * 1000;
+}
+
+void DelayFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
+  assert(in_out);
+  for (PacketsIt it = in_out->begin(); it != in_out->end(); ++it) {
+    int64_t new_send_time_us = it->send_time_us() + delay_us_;
+    last_send_time_us_ = std::max(last_send_time_us_, new_send_time_us);
+    it->set_send_time_us(last_send_time_us_);
+  }
+}
+
+JitterFilter::JitterFilter(PacketProcessorListener* listener)
+    : PacketProcessor(listener),
+      random_(0x89674523),
+      stddev_jitter_us_(0),
+      last_send_time_us_(0) {
+}
+
+void JitterFilter::SetJitter(int64_t stddev_jitter_ms) {
+  BWE_TEST_LOGGING_ENABLE(false);
+  BWE_TEST_LOGGING_LOG1("Jitter", "%d ms",
+                        static_cast<int>(stddev_jitter_ms));
+  assert(stddev_jitter_ms >= 0);
+  stddev_jitter_us_ = stddev_jitter_ms * 1000;
+}
+
+void JitterFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
+  assert(in_out);
+  for (PacketsIt it = in_out->begin(); it != in_out->end(); ++it) {
+    int64_t new_send_time_us = it->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);
+    it->set_send_time_us(last_send_time_us_);
+  }
+}
+
+ReorderFilter::ReorderFilter(PacketProcessorListener* listener)
+    : PacketProcessor(listener),
+      random_(0x27452389),
+      reorder_fraction_(0.0f) {
+}
+
+void ReorderFilter::SetReorder(float reorder_percent) {
+  BWE_TEST_LOGGING_ENABLE(false);
+  BWE_TEST_LOGGING_LOG1("Reordering", "%f%%", reorder_percent);
+  assert(reorder_percent >= 0.0f);
+  assert(reorder_percent <= 100.0f);
+  reorder_fraction_ = reorder_percent * 0.01f;
+}
+
+void ReorderFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
+  assert(in_out);
+  if (in_out->size() >= 2) {
+    PacketsIt last_it = in_out->begin();
+    PacketsIt it = last_it;
+    while (++it != in_out->end()) {
+      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);
+        last_it->set_send_time_us(t1);
+        it->set_send_time_us(t2);
+      }
+      last_it = it;
+    }
+  }
+}
+
+ChokeFilter::ChokeFilter(PacketProcessorListener* listener)
+    : PacketProcessor(listener),
+      kbps_(1200),
+      max_delay_us_(0),
+      last_send_time_us_(0) {
+}
+
+void ChokeFilter::SetCapacity(uint32_t kbps) {
+  BWE_TEST_LOGGING_ENABLE(false);
+  BWE_TEST_LOGGING_LOG1("BitrateChoke", "%d kbps", kbps);
+  kbps_ = kbps;
+}
+
+void ChokeFilter::SetMaxDelay(int64_t max_delay_ms) {
+  BWE_TEST_LOGGING_ENABLE(false);
+  BWE_TEST_LOGGING_LOG1("Max Delay", "%d ms", static_cast<int>(max_delay_ms));
+  assert(max_delay_ms >= 0);
+  max_delay_us_ = max_delay_ms * 1000;
+}
+
+void ChokeFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
+  assert(in_out);
+  for (PacketsIt it = in_out->begin(); it != in_out->end(); ) {
+    int64_t earliest_send_time_us = last_send_time_us_ +
+        (it->payload_size() * 8 * 1000 + kbps_ / 2) / kbps_;
+    int64_t new_send_time_us = std::max(it->send_time_us(),
+                                        earliest_send_time_us);
+    if (max_delay_us_ == 0 ||
+        max_delay_us_ >= (new_send_time_us - it->send_time_us())) {
+      it->set_send_time_us(new_send_time_us);
+      last_send_time_us_ = new_send_time_us;
+      ++it;
+    } else {
+      it = in_out->erase(it);
+    }
+  }
+}
+
+PacketSender::PacketSender(PacketProcessorListener* listener)
+    : PacketProcessor(listener) {
+}
+
+VideoSender::VideoSender(PacketProcessorListener* listener, float fps,
+                         uint32_t kbps, uint32_t ssrc, float first_frame_offset)
+    : PacketSender(listener),
+      kMaxPayloadSizeBytes(1000),
+      kTimestampBase(0xff80ff00ul),
+      frame_period_ms_(1000.0 / fps),
+      next_frame_ms_(frame_period_ms_ * first_frame_offset),
+      now_ms_(0.0),
+      bytes_per_second_((1000 * kbps) / 8),
+      frame_size_bytes_(bytes_per_second_ / fps),
+      prototype_header_() {
+  assert(first_frame_offset >= 0.0f);
+  assert(first_frame_offset < 1.0f);
+  memset(&prototype_header_, 0, sizeof(prototype_header_));
+  prototype_header_.ssrc = ssrc;
+  prototype_header_.sequenceNumber = 0xf000u;
+}
+
+uint32_t VideoSender::GetCapacityKbps() const {
+  return (bytes_per_second_ * 8) / 1000;
+}
+
+void VideoSender::RunFor(int64_t time_ms, Packets* in_out) {
+  assert(in_out);
+  now_ms_ += time_ms;
+  Packets newPackets;
+  while (now_ms_ >= next_frame_ms_) {
+    prototype_header_.sequenceNumber++;
+    prototype_header_.timestamp = kTimestampBase +
+        static_cast<uint32_t>(next_frame_ms_ * 90.0);
+    prototype_header_.extension.absoluteSendTime = (kTimestampBase +
+        ((static_cast<int64_t>(next_frame_ms_ * (1 << 18)) + 500) / 1000)) &
+            0x00fffffful;
+    prototype_header_.extension.transmissionTimeOffset = 0;
+
+    // Generate new packets for this frame, all with the same timestamp,
+    // but the payload size is capped, so if the whole frame doesn't fit in
+    // 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_;
+    while (payload_size > 0) {
+      uint32_t size = std::min(kMaxPayloadSizeBytes, payload_size);
+      newPackets.push_back(Packet(send_time_us, size, prototype_header_));
+      payload_size -= size;
+    }
+
+    next_frame_ms_ += frame_period_ms_;
+  }
+  in_out->merge(newPackets);
+}
 }  // namespace bwe
 }  // namespace testing
 }  // namespace webrtc
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 3b340bc..c19cb2b 100644
--- a/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.h
+++ b/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.h
@@ -26,44 +26,6 @@
 namespace testing {
 namespace bwe {
 
-class Random {
- public:
-  explicit Random(uint32_t seed)
-      : a_(0x531FDB97 ^ seed),
-        b_(0x6420ECA8 + seed) {
-  }
-
-  // Return semi-random number in the interval [0.0, 1.0].
-  float Rand() {
-    const float kScale = 1.0f / 0xffffffff;
-    float result = kScale * b_;
-    a_ ^= b_;
-    b_ += a_;
-    return result;
-  }
-
-  // Normal Distribution.
-  int Gaussian(int mean, int standard_deviation) {
-    // Creating a Normal distribution variable from two independent uniform
-    // variables based on the Box-Muller transform, which is defined on the
-    // interval (0, 1], hence the mask+add below.
-    const double kPi = 3.14159265358979323846;
-    const double kScale = 1.0 / 0x80000000ul;
-    double u1 = kScale * ((a_ & 0x7ffffffful) + 1);
-    double u2 = kScale * ((b_ & 0x7ffffffful) + 1);
-    a_ ^= b_;
-    b_ += a_;
-    return static_cast<int>(mean + standard_deviation *
-        std::sqrt(-2 * std::log(u1)) * std::cos(2 * kPi * u2));
-  }
-
- private:
-  uint32_t a_;
-  uint32_t b_;
-
-  DISALLOW_IMPLICIT_CONSTRUCTORS(Random);
-};
-
 template<typename T> class Stats {
  public:
   Stats()
@@ -149,36 +111,36 @@
   T max_;
 };
 
-class BwePacket {
+class Random {
  public:
-  BwePacket()
-      : send_time_us_(0),
-        payload_size_(0) {
-     memset(&header_, 0, sizeof(header_));
-  }
+  explicit Random(uint32_t seed);
 
-  BwePacket(int64_t send_time_us, uint32_t payload_size,
-            const RTPHeader& header)
-    : send_time_us_(send_time_us),
-      payload_size_(payload_size),
-      header_(header) {
-  }
+  // Return pseudo random number in the interval [0.0, 1.0].
+  float Rand();
 
-  BwePacket(int64_t send_time_us, uint32_t sequence_number)
-      : send_time_us_(send_time_us),
-        payload_size_(0) {
-     memset(&header_, 0, sizeof(header_));
-     header_.sequenceNumber = sequence_number;
-  }
+  // Normal Distribution.
+  int Gaussian(int mean, int standard_deviation);
 
-  bool operator<(const BwePacket& rhs) const {
-    return send_time_us_ < rhs.send_time_us_;
-  }
+  // TODO(solenberg): Random from histogram.
+  // template<typename T> int Distribution(const std::vector<T> histogram) {
 
-  void set_send_time_us(int64_t send_time_us) {
-    assert(send_time_us >= 0);
-    send_time_us_ = send_time_us;
-  }
+ private:
+  uint32_t a_;
+  uint32_t b_;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(Random);
+};
+
+class Packet {
+ public:
+  Packet();
+  Packet(int64_t send_time_us, uint32_t payload_size,
+            const RTPHeader& header);
+  Packet(int64_t send_time_us, uint32_t sequence_number);
+
+  bool operator<(const Packet& rhs) const;
+
+  void set_send_time_us(int64_t send_time_us);
   int64_t send_time_us() const { return send_time_us_; }
   uint32_t payload_size() const { return payload_size_; }
   const RTPHeader& header() const { return header_; }
@@ -189,73 +151,180 @@
   RTPHeader header_;       // Actual contents.
 };
 
-typedef std::list<BwePacket> Packets;
-typedef std::list<BwePacket>::iterator PacketsIt;
-typedef std::list<BwePacket>::const_iterator PacketsConstIt;
+typedef std::list<Packet> Packets;
+typedef std::list<Packet>::iterator PacketsIt;
+typedef std::list<Packet>::const_iterator PacketsConstIt;
 
 bool IsTimeSorted(const Packets& packets);
 
-class PacketProcessorInterface {
+class PacketProcessor;
+
+class PacketProcessorListener {
  public:
-  virtual ~PacketProcessorInterface() {}
+  virtual ~PacketProcessorListener() {}
+
+  virtual void AddPacketProcessor(PacketProcessor* processor) = 0;
+  virtual void RemovePacketProcessor(PacketProcessor* processor) = 0;
+};
+
+class PacketProcessor {
+ public:
+  explicit PacketProcessor(PacketProcessorListener* listener);
+  virtual ~PacketProcessor();
 
   // Run simulation for |time_ms| micro seconds, consuming packets from, and
   // producing packets into in_out. The outgoing packet list must be sorted on
   // |send_time_us_|. The simulation time |time_ms| is optional to use.
   virtual void RunFor(int64_t time_ms, Packets* in_out) = 0;
+
+ private:
+  PacketProcessorListener* listener_;
+
+  DISALLOW_COPY_AND_ASSIGN(PacketProcessor);
 };
 
-class VideoSender : public PacketProcessorInterface {
+class RateCounterFilter : public PacketProcessor {
  public:
-  VideoSender(float fps, uint32_t kbps, uint32_t ssrc, float first_frame_offset)
-      : kMaxPayloadSizeBytes(1000),
-        kTimestampBase(0xff80ff00ul),
-        frame_period_ms_(1000.0 / fps),
-        next_frame_ms_(frame_period_ms_ * first_frame_offset),
-        now_ms_(0.0),
-        bytes_per_second_(1000 * kbps / 8),
-        frame_size_bytes_(bytes_per_second_ / fps),
-        prototype_header_() {
-    assert(first_frame_offset >= 0.0f);
-    assert(first_frame_offset < 1.0f);
-    memset(&prototype_header_, 0, sizeof(prototype_header_));
-    prototype_header_.ssrc = ssrc;
-    prototype_header_.sequenceNumber = 0xf000u;
-  }
+  explicit RateCounterFilter(PacketProcessorListener* listener);
+  virtual ~RateCounterFilter();
+
+  uint32_t packets_per_second() const { return packets_per_second_; }
+  uint32_t bits_per_second() const { return bytes_per_second_ * 8; }
+
+  void LogStats();
+  virtual void RunFor(int64_t time_ms, Packets* in_out);
+
+ private:
+  const int64_t kWindowSizeUs;
+  uint32_t packets_per_second_;
+  uint32_t bytes_per_second_;
+  int64_t last_accumulated_us_;
+  Packets window_;
+  Stats<double> pps_stats_;
+  Stats<double> kbps_stats_;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(RateCounterFilter);
+};
+
+class LossFilter : public PacketProcessor {
+ public:
+  explicit LossFilter(PacketProcessorListener* listener);
+  virtual ~LossFilter() {}
+
+  void SetLoss(float loss_percent);
+  virtual void RunFor(int64_t time_ms, Packets* in_out);
+
+ private:
+  Random random_;
+  float loss_fraction_;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(LossFilter);
+};
+
+class DelayFilter : public PacketProcessor {
+ public:
+  explicit DelayFilter(PacketProcessorListener* listener);
+  virtual ~DelayFilter() {}
+
+  void SetDelay(int64_t delay_ms);
+  virtual void RunFor(int64_t time_ms, Packets* in_out);
+
+ private:
+  int64_t delay_us_;
+  int64_t last_send_time_us_;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(DelayFilter);
+};
+
+class JitterFilter : public PacketProcessor {
+ public:
+  explicit JitterFilter(PacketProcessorListener* listener);
+  virtual ~JitterFilter() {}
+
+  void SetJitter(int64_t stddev_jitter_ms);
+  virtual void RunFor(int64_t time_ms, Packets* in_out);
+
+ private:
+  Random random_;
+  int64_t stddev_jitter_us_;
+  int64_t last_send_time_us_;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(JitterFilter);
+};
+
+class ReorderFilter : public PacketProcessor {
+ public:
+  explicit ReorderFilter(PacketProcessorListener* listener);
+  virtual ~ReorderFilter() {}
+
+  void SetReorder(float reorder_percent);
+  virtual void RunFor(int64_t time_ms, Packets* in_out);
+
+ private:
+  Random random_;
+  float reorder_fraction_;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ReorderFilter);
+};
+
+// Apply a bitrate choke with an infinite queue on the packet stream.
+class ChokeFilter : public PacketProcessor {
+ public:
+  explicit ChokeFilter(PacketProcessorListener* listener);
+  virtual ~ChokeFilter() {}
+
+  void SetCapacity(uint32_t kbps);
+  void SetMaxDelay(int64_t max_delay_ms);
+  virtual void RunFor(int64_t time_ms, Packets* in_out);
+
+ private:
+  uint32_t kbps_;
+  int64_t max_delay_us_;
+  int64_t last_send_time_us_;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ChokeFilter);
+};
+
+class PacketSender : public PacketProcessor {
+ public:
+  struct Feedback {
+    double estimated_kbps;
+  };
+
+  explicit PacketSender(PacketProcessorListener* listener);
+  virtual ~PacketSender() {}
+
+  virtual uint32_t GetCapacityKbps() const { return 0; }
+
+  // Call GiveFeedback() with the returned interval in milliseconds, provided
+  // there is a new estimate available.
+  virtual int64_t GetFeedbackIntervalMs() const { return 1000; }
+  virtual void GiveFeedback(const Feedback& feedback) {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(PacketSender);
+};
+
+struct PacketSenderFactory {
+  PacketSenderFactory() {}
+  virtual ~PacketSenderFactory() {}
+  virtual PacketSender* Create() const = 0;
+};
+
+class VideoSender : public PacketSender {
+ public:
+  VideoSender(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; }
   uint32_t bytes_per_second() const { return bytes_per_second_; }
 
-  virtual void RunFor(int64_t time_ms, Packets* in_out) {
-    assert(in_out);
-    now_ms_ += time_ms;
-    Packets newPackets;
-    while (now_ms_ >= next_frame_ms_) {
-      prototype_header_.sequenceNumber++;
-      prototype_header_.timestamp = kTimestampBase +
-          static_cast<uint32_t>(next_frame_ms_ * 90.0);
-      prototype_header_.extension.absoluteSendTime = (kTimestampBase +
-          ((static_cast<int64_t>(next_frame_ms_ * (1 << 18)) + 500) / 1000)) &
-              0x00fffffful;
-      prototype_header_.extension.transmissionTimeOffset = 0;
+  virtual uint32_t GetCapacityKbps() const;
 
-      // Generate new packets for this frame, all with the same timestamp,
-      // but the payload size is capped, so if the whole frame doesn't fit in
-      // 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_;
-      while (payload_size > 0) {
-        uint32_t size = std::min(kMaxPayloadSizeBytes, payload_size);
-        newPackets.push_back(BwePacket(send_time_us, size, prototype_header_));
-        payload_size -= size;
-      }
-
-      next_frame_ms_ += frame_period_ms_;
-    }
-    in_out->merge(newPackets);
-  }
+  // TODO(solenberg): void SetFrameRate(float fps);
+  // TODO(solenberg): void SetRate(uint32_t kbps);
+  virtual void RunFor(int64_t time_ms, Packets* in_out);
 
  private:
   const uint32_t kMaxPayloadSizeBytes;
@@ -269,242 +338,6 @@
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(VideoSender);
 };
-
-class RateCounterFilter : public PacketProcessorInterface {
- public:
-  RateCounterFilter()
-      : kWindowSizeUs(1000000),
-        packets_per_second_(0),
-        bytes_per_second_(0),
-        last_accumulated_us_(0),
-        window_(),
-        pps_stats_(),
-        kbps_stats_() {
-  }
-  virtual ~RateCounterFilter() {
-    LogStats();
-  }
-
-  uint32_t packets_per_second() const { return packets_per_second_; }
-  uint32_t bits_per_second() const { return bytes_per_second_ * 8; }
-
-  void LogStats() {
-    BWE_TEST_LOGGING_CONTEXT("RateCounterFilter");
-    pps_stats_.Log("pps");
-    kbps_stats_.Log("kbps");
-  }
-
-  virtual void RunFor(int64_t /*time_ms*/, Packets* in_out) {
-    assert(in_out);
-    for (PacketsConstIt it = in_out->begin(); it != in_out->end(); ++it) {
-      packets_per_second_++;
-      bytes_per_second_ += it->payload_size();
-      last_accumulated_us_ = it->send_time_us();
-    }
-    window_.insert(window_.end(), in_out->begin(), in_out->end());
-    while (!window_.empty()) {
-      const BwePacket& packet = window_.front();
-      if (packet.send_time_us() > (last_accumulated_us_ - kWindowSizeUs)) {
-        break;
-      }
-      assert(packets_per_second_ >= 1);
-      assert(bytes_per_second_ >= packet.payload_size());
-      packets_per_second_--;
-      bytes_per_second_ -= packet.payload_size();
-      window_.pop_front();
-    }
-    pps_stats_.Push(packets_per_second_);
-    kbps_stats_.Push((bytes_per_second_ * 8) / 1000.0);
-  }
-
- private:
-  const int64_t kWindowSizeUs;
-  uint32_t packets_per_second_;
-  uint32_t bytes_per_second_;
-  int64_t last_accumulated_us_;
-  Packets window_;
-  Stats<double> pps_stats_;
-  Stats<double> kbps_stats_;
-
-  DISALLOW_COPY_AND_ASSIGN(RateCounterFilter);
-};
-
-class LossFilter : public PacketProcessorInterface {
- public:
-  LossFilter() : random_(0x12345678), loss_fraction_(0.0f) {}
-  virtual ~LossFilter() {}
-
-  void SetLoss(float loss_percent) {
-    BWE_TEST_LOGGING_ENABLE(false);
-    BWE_TEST_LOGGING_LOG1("Loss", "%f%%", loss_percent);
-    assert(loss_percent >= 0.0f);
-    assert(loss_percent <= 100.0f);
-    loss_fraction_ = loss_percent * 0.01f;
-  }
-
-  virtual void RunFor(int64_t /*time_ms*/, Packets* in_out) {
-    assert(in_out);
-    for (PacketsIt it = in_out->begin(); it != in_out->end(); ) {
-      if (random_.Rand() < loss_fraction_) {
-        it = in_out->erase(it);
-      } else {
-        ++it;
-      }
-    }
-  }
-
- private:
-  Random random_;
-  float loss_fraction_;
-
-  DISALLOW_COPY_AND_ASSIGN(LossFilter);
-};
-
-class DelayFilter : public PacketProcessorInterface {
- public:
-  DelayFilter() : delay_us_(0), last_send_time_us_(0) {}
-  virtual ~DelayFilter() {}
-
-  void SetDelay(int64_t delay_ms) {
-    BWE_TEST_LOGGING_ENABLE(false);
-    BWE_TEST_LOGGING_LOG1("Delay", "%d ms", static_cast<int>(delay_ms));
-    assert(delay_ms >= 0);
-    delay_us_ = delay_ms * 1000;
-  }
-
-  virtual void RunFor(int64_t /*time_ms*/, Packets* in_out) {
-    assert(in_out);
-    for (PacketsIt it = in_out->begin(); it != in_out->end(); ++it) {
-      int64_t new_send_time_us = it->send_time_us() + delay_us_;
-      last_send_time_us_ = std::max(last_send_time_us_, new_send_time_us);
-      it->set_send_time_us(last_send_time_us_);
-    }
-  }
-
- private:
-  int64_t delay_us_;
-  int64_t last_send_time_us_;
-
-  DISALLOW_COPY_AND_ASSIGN(DelayFilter);
-};
-
-class JitterFilter : public PacketProcessorInterface {
- public:
-  JitterFilter()
-      : random_(0x89674523),
-        stddev_jitter_us_(0),
-        last_send_time_us_(0) {
-  }
-  virtual ~JitterFilter() {}
-
-  void SetJitter(int64_t stddev_jitter_ms) {
-    BWE_TEST_LOGGING_ENABLE(false);
-    BWE_TEST_LOGGING_LOG1("Jitter", "%d ms",
-                          static_cast<int>(stddev_jitter_ms));
-    assert(stddev_jitter_ms >= 0);
-    stddev_jitter_us_ = stddev_jitter_ms * 1000;
-  }
-
-  virtual void RunFor(int64_t /*time_ms*/, Packets* in_out) {
-    assert(in_out);
-    for (PacketsIt it = in_out->begin(); it != in_out->end(); ++it) {
-      int64_t new_send_time_us = it->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);
-      it->set_send_time_us(last_send_time_us_);
-    }
-  }
-
- private:
-  Random random_;
-  int64_t stddev_jitter_us_;
-  int64_t last_send_time_us_;
-
-  DISALLOW_COPY_AND_ASSIGN(JitterFilter);
-};
-
-class ReorderFilter : public PacketProcessorInterface {
- public:
-  ReorderFilter() : random_(0x27452389), reorder_fraction_(0.0f) {}
-  virtual ~ReorderFilter() {}
-
-  void SetReorder(float reorder_percent) {
-    BWE_TEST_LOGGING_ENABLE(false);
-    BWE_TEST_LOGGING_LOG1("Reordering", "%f%%", reorder_percent);
-    assert(reorder_percent >= 0.0f);
-    assert(reorder_percent <= 100.0f);
-    reorder_fraction_ = reorder_percent * 0.01f;
-  }
-
-  virtual void RunFor(int64_t /*time_ms*/, Packets* in_out) {
-    assert(in_out);
-    if (in_out->size() >= 2) {
-      PacketsIt last_it = in_out->begin();
-      PacketsIt it = last_it;
-      while (++it != in_out->end()) {
-        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);
-          last_it->set_send_time_us(t1);
-          it->set_send_time_us(t2);
-        }
-        last_it = it;
-      }
-    }
-  }
-
- private:
-  Random random_;
-  float reorder_fraction_;
-
-  DISALLOW_COPY_AND_ASSIGN(ReorderFilter);
-};
-
-// Apply a bitrate choke with an infinite queue on the packet stream.
-class ChokeFilter : public PacketProcessorInterface {
- public:
-  ChokeFilter() : kbps_(1200), max_delay_us_(0), last_send_time_us_(0) {}
-  virtual ~ChokeFilter() {}
-
-  void SetCapacity(uint32_t kbps) {
-    BWE_TEST_LOGGING_ENABLE(false);
-    BWE_TEST_LOGGING_LOG1("BitrateChoke", "%d kbps", kbps);
-    kbps_ = kbps;
-  }
-
-  void SetMaxDelay(int64_t max_delay_ms) {
-    BWE_TEST_LOGGING_ENABLE(false);
-    BWE_TEST_LOGGING_LOG1("Max Delay", "%d ms", static_cast<int>(max_delay_ms));
-    assert(max_delay_ms >= 0);
-    max_delay_us_ = max_delay_ms * 1000;
-  }
-
-  virtual void RunFor(int64_t /*time_ms*/, Packets* in_out) {
-    assert(in_out);
-    for (PacketsIt it = in_out->begin(); it != in_out->end(); ) {
-      int64_t earliest_send_time_us = last_send_time_us_ +
-          (it->payload_size() * 8 * 1000 + kbps_ / 2) / kbps_;
-      int64_t new_send_time_us = std::max(it->send_time_us(),
-                                          earliest_send_time_us);
-      if (max_delay_us_ == 0 ||
-          max_delay_us_ >= (new_send_time_us - it->send_time_us())) {
-        it->set_send_time_us(new_send_time_us);
-        last_send_time_us_ = new_send_time_us;
-        ++it;
-      } else {
-        it = in_out->erase(it);
-      }
-    }
-  }
-
- private:
-  uint32_t kbps_;
-  int64_t max_delay_us_;
-  int64_t last_send_time_us_;
-
-  DISALLOW_COPY_AND_ASSIGN(ChokeFilter);
-};
 }  // namespace bwe
 }  // namespace testing
 }  // namespace webrtc
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 b6a7123..440044a 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
@@ -66,45 +66,45 @@
   return true;
 }
 
-TEST(BweTestFramework_BwePacketTest, IsTimeSorted) {
+TEST(BweTestFramework_PacketTest, IsTimeSorted) {
   Packets packets;
   // Insert some packets in order...
   EXPECT_TRUE(IsTimeSorted(packets));
 
-  packets.push_back(BwePacket(100, 0));
+  packets.push_back(Packet(100, 0));
   EXPECT_TRUE(IsTimeSorted(packets));
 
-  packets.push_back(BwePacket(110, 0));
+  packets.push_back(Packet(110, 0));
   EXPECT_TRUE(IsTimeSorted(packets));
 
   // ...and one out-of-order...
-  packets.push_back(BwePacket(100, 0));
+  packets.push_back(Packet(100, 0));
   EXPECT_FALSE(IsTimeSorted(packets));
 
   // ...remove the out-of-order packet, insert another in-order packet.
   packets.pop_back();
-  packets.push_back(BwePacket(120, 0));
+  packets.push_back(Packet(120, 0));
   EXPECT_TRUE(IsTimeSorted(packets));
 }
 
-TEST(BweTestFramework_BwePacketTest, IsSequenceNumberSorted) {
+TEST(BweTestFramework_PacketTest, IsSequenceNumberSorted) {
   Packets packets;
   // Insert some packets in order...
   EXPECT_TRUE(IsSequenceNumberSorted(packets));
 
-  packets.push_back(BwePacket(0, 100));
+  packets.push_back(Packet(0, 100));
   EXPECT_TRUE(IsSequenceNumberSorted(packets));
 
-  packets.push_back(BwePacket(0, 110));
+  packets.push_back(Packet(0, 110));
   EXPECT_TRUE(IsSequenceNumberSorted(packets));
 
   // ...and one out-of-order...
-  packets.push_back(BwePacket(0, 100));
+  packets.push_back(Packet(0, 100));
   EXPECT_FALSE(IsSequenceNumberSorted(packets));
 
   // ...remove the out-of-order packet, insert another in-order packet.
   packets.pop_back();
-  packets.push_back(BwePacket(0, 120));
+  packets.push_back(Packet(0, 120));
   EXPECT_TRUE(IsSequenceNumberSorted(packets));
 }
 
@@ -168,167 +168,10 @@
   EXPECT_EQ(3, stats.GetMax());
 }
 
-void TestVideoSender(VideoSender* sender, int64_t run_for_ms,
-                     uint32_t expected_packets,
-                     uint32_t expected_payload_size,
-                     uint32_t expected_total_payload_size) {
-  assert(sender);
-  Packets packets;
-  sender->RunFor(run_for_ms, &packets);
-  ASSERT_TRUE(IsTimeSorted(packets));
-  ASSERT_TRUE(IsSequenceNumberSorted(packets));
-  EXPECT_EQ(expected_packets, packets.size());
-  int64_t send_time_us = -1;
-  uint32_t total_payload_size = 0;
-  uint32_t absolute_send_time = 0;
-  uint32_t absolute_send_time_wraps = 0;
-  uint32_t rtp_timestamp = 0;
-  uint32_t rtp_timestamp_wraps = 0;
-  for (PacketsIt it = packets.begin(); it != packets.end(); ++it) {
-    EXPECT_LE(send_time_us, it->send_time_us());
-    send_time_us = it->send_time_us();
-    if (sender->max_payload_size_bytes() != it->payload_size()) {
-      EXPECT_EQ(expected_payload_size, it->payload_size());
-    }
-    total_payload_size += it->payload_size();
-    if (absolute_send_time > it->header().extension.absoluteSendTime) {
-      absolute_send_time_wraps++;
-    }
-    absolute_send_time = it->header().extension.absoluteSendTime;
-    if (rtp_timestamp > it->header().timestamp) {
-      rtp_timestamp_wraps++;
-    }
-    rtp_timestamp = it->header().timestamp;
-  }
-  EXPECT_EQ(expected_total_payload_size, total_payload_size);
-  EXPECT_GE(1u, absolute_send_time_wraps);
-  EXPECT_GE(1u, rtp_timestamp_wraps);
-}
-
-TEST(BweTestFramework_VideoSenderTest, Fps1Kpbs80_1s) {
-  // 1 fps, 80 kbps
-  VideoSender sender(1.0f, 80, 0x1234, 0);
-  EXPECT_EQ(10000u, sender.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.
-  TestVideoSender(&sender, 1, 10, 1000, 10000);
-  // 999ms, should see no output here.
-  TestVideoSender(&sender, 998, 0, 0, 0);
-  // 1999ms, should get data for one more frame.
-  TestVideoSender(&sender, 1000, 10, 1000, 10000);
-  // 2000ms, one more frame.
-  TestVideoSender(&sender, 1, 10, 1000, 10000);
-  // 2999ms, should see nothing.
-  TestVideoSender(&sender, 999, 0, 0, 0);
-}
-
-TEST(BweTestFramework_VideoSenderTest, Fps1Kpbs80_1s_Offset) {
-  // 1 fps, 80 kbps, offset 0.5 of a frame period, ==0.5s in this case.
-  VideoSender sender(1.0f, 80, 0x1234, 0.5f);
-  EXPECT_EQ(10000u, sender.bytes_per_second());
-  // 499ms, no output.
-  TestVideoSender(&sender, 499, 0, 0, 0);
-  // 500ms, first frame (this is the offset we set), 10 packets of 1000 bytes.
-  TestVideoSender(&sender, 1, 10, 1000, 10000);
-  // 1499ms, nothing.
-  TestVideoSender(&sender, 999, 0, 0, 0);
-  // 1999ms, second frame.
-  TestVideoSender(&sender, 500, 10, 1000, 10000);
-  // 2499ms, nothing.
-  TestVideoSender(&sender, 500, 0, 0, 0);
-  // 2500ms, third frame.
-  TestVideoSender(&sender, 1, 10, 1000, 10000);
-  // 3499ms, nothing.
-  TestVideoSender(&sender, 999, 0, 0, 0);
-}
-
-TEST(BweTestFramework_VideoSenderTest, Fps50Kpbs80_11s) {
-  // 50 fps, 80 kbps.
-  VideoSender sender(50.0f, 80, 0x1234, 0);
-  EXPECT_EQ(10000u, sender.bytes_per_second());
-  // 9998ms, should see 500 frames, 200 byte payloads, total 100000 bytes.
-  TestVideoSender(&sender, 9998, 500, 200, 100000);
-  // 9999ms, nothing.
-  TestVideoSender(&sender, 1, 0, 0, 0);
-  // 10000ms, 501st frame as a single packet.
-  TestVideoSender(&sender, 1, 1, 200, 200);
-  // 10998ms, 49 more frames.
-  TestVideoSender(&sender, 998, 49, 200, 9800);
-  // 10999ms, nothing.
-  TestVideoSender(&sender, 1, 0, 0, 0);
-}
-
-TEST(BweTestFramework_VideoSenderTest, Fps10Kpbs120_1s) {
-  // 20 fps, 120 kbps.
-  VideoSender sender(20.0f, 120, 0x1234, 0);
-  EXPECT_EQ(15000u, sender.bytes_per_second());
-  // 498ms, 10 frames with 750 byte payloads, total 7500 bytes.
-  TestVideoSender(&sender, 498, 10, 750, 7500);
-  // 499ms, nothing.
-  TestVideoSender(&sender, 1, 0, 0, 0);
-  // 500ms, one more frame.
-  TestVideoSender(&sender, 1, 1, 750, 750);
-  // 998ms, 9 more frames.
-  TestVideoSender(&sender, 498, 9, 750, 6750);
-  // 999ms, nothing.
-  TestVideoSender(&sender, 1, 0, 0, 0);
-}
-
-TEST(BweTestFramework_VideoSenderTest, Fps30Kpbs800_20s) {
-  // 20 fps, 820 kbps.
-  VideoSender sender(25.0f, 820, 0x1234, 0);
-  EXPECT_EQ(102500u, sender.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),
-  // so packet count should be 5*250=1250 and last packet of each frame has
-  // 100 bytes of payload.
-  TestVideoSender(&sender, 9998, 1250, 100, 1025000);
-  // 9999ms, nothing.
-  TestVideoSender(&sender, 1, 0, 0, 0);
-  // 19998ms, 250 more frames.
-  TestVideoSender(&sender, 9999, 1250, 100, 1025000);
-  // 19999ms, nothing.
-  TestVideoSender(&sender, 1, 0, 0, 0);
-  // 20038ms, one more frame, as described above (25fps == 40ms/frame).
-  TestVideoSender(&sender, 39, 5, 100, 4100);
-  // 20039ms, nothing.
-  TestVideoSender(&sender, 1, 0, 0, 0);
-}
-
-TEST(BweTestFramework_VideoSenderTest, TestAppendInOrder) {
-  // 1 fps, 80 kbps, 250ms offset.
-  VideoSender sender1(1.0f, 80, 0x1234, 0.25f);
-  EXPECT_EQ(10000u, sender1.bytes_per_second());
-  Packets packets;
-  // Generate some packets, verify they are sorted.
-  sender1.RunFor(999, &packets);
-  ASSERT_TRUE(IsTimeSorted(packets));
-  ASSERT_TRUE(IsSequenceNumberSorted(packets));
-  EXPECT_EQ(10u, packets.size());
-  // Generate some more packets and verify they are appended to end of list.
-  sender1.RunFor(1000, &packets);
-  ASSERT_TRUE(IsTimeSorted(packets));
-  ASSERT_TRUE(IsSequenceNumberSorted(packets));
-  EXPECT_EQ(20u, packets.size());
-
-  // Another sender, 2 fps, 160 kpbs, 150ms offset
-  VideoSender sender2(2.0f, 160, 0x2234, 0.30f);
-  EXPECT_EQ(20000u, sender2.bytes_per_second());
-  // Generate some packets, verify that they are merged with the packets already
-  // on the list.
-  sender2.RunFor(999, &packets);
-  ASSERT_TRUE(IsTimeSorted(packets));
-  EXPECT_EQ(40u, packets.size());
-  // Generate some more.
-  sender2.RunFor(1000, &packets);
-  ASSERT_TRUE(IsTimeSorted(packets));
-  EXPECT_EQ(60u, packets.size());
-}
-
 class BweTestFramework_RateCounterFilterTest : public ::testing::Test {
  public:
   BweTestFramework_RateCounterFilterTest()
-    : filter_(),
+    : filter_(NULL),
       now_ms_(0) {
   }
   virtual ~BweTestFramework_RateCounterFilterTest() {}
@@ -340,7 +183,7 @@
     RTPHeader header = {0};
     // "Send" a packet every 10 ms.
     for (int64_t i = 0; i < run_for_ms; i += 10, now_ms_ += 10) {
-      packets.push_back(BwePacket(now_ms_ * 1000, payload_bits / 8, header));
+      packets.push_back(Packet(now_ms_ * 1000, payload_bits / 8, header));
     }
     filter_.RunFor(run_for_ms, &packets);
     ASSERT_TRUE(IsTimeSorted(packets));
@@ -386,7 +229,7 @@
 }
 
 static void TestLossFilter(float loss_percent, bool zero_tolerance) {
-  LossFilter filter;
+  LossFilter filter(NULL);
   filter.SetLoss(loss_percent);
   Packets::size_type sent_packets = 0;
   Packets::size_type remaining_packets = 0;
@@ -406,7 +249,7 @@
   // Generate and process 10000 packets in different batch sizes (some empty)
   for (int i = 0; i < 2225; ++i) {
     Packets packets;
-    packets.insert(packets.end(), i % 10, BwePacket());
+    packets.insert(packets.end(), i % 10, Packet());
     sent_packets += packets.size();
     filter.RunFor(0, &packets);
     ASSERT_TRUE(IsTimeSorted(packets));
@@ -445,7 +288,7 @@
 class BweTestFramework_DelayFilterTest : public ::testing::Test {
  public:
   BweTestFramework_DelayFilterTest()
-    : filter_(),
+    : filter_(NULL),
       now_ms_(0),
       sequence_number_(0) {
   }
@@ -456,7 +299,7 @@
                        uint32_t out_packets) {
     Packets packets;
     for (uint32_t i = 0; i < in_packets; ++i) {
-      packets.push_back(BwePacket(now_ms_ * 1000 + (sequence_number_ >> 4),
+      packets.push_back(Packet(now_ms_ * 1000 + (sequence_number_ >> 4),
                                   sequence_number_));
       sequence_number_++;
     }
@@ -550,14 +393,14 @@
 }
 
 TEST_F(BweTestFramework_DelayFilterTest, JumpToZeroDelay) {
-  DelayFilter delay;
+  DelayFilter delay(NULL);
   Packets acc;
   Packets packets;
 
   // 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(BwePacket(i * 100, i));
+    packets.push_back(Packet(i * 100, i));
   }
   delay.RunFor(1000, &packets);
   acc.splice(acc.end(), packets);
@@ -568,7 +411,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(BwePacket(i * 100, i));
+    packets.push_back(Packet(i * 100, i));
   }
   delay.RunFor(1000, &packets);
   acc.splice(acc.end(), packets);
@@ -595,7 +438,7 @@
 }
 
 static void TestJitterFilter(int64_t stddev_jitter_ms) {
-  JitterFilter filter;
+  JitterFilter filter(NULL);
   filter.SetJitter(stddev_jitter_ms);
 
   int64_t now_ms = 0;
@@ -607,7 +450,7 @@
   for (uint32_t i = 0; i < 1000; ++i) {
     Packets packets;
     for (uint32_t j = 0; j < i % 100; ++j) {
-      packets.push_back(BwePacket(now_ms * 1000, sequence_number++));
+      packets.push_back(Packet(now_ms * 1000, sequence_number++));
       now_ms += 5 * stddev_jitter_ms;
     }
     original.insert(original.end(), packets.begin(), packets.end());
@@ -664,13 +507,13 @@
   int64_t now_ms = 0;
   uint32_t sequence_number = 1;
   for (uint32_t i = 0; i < kPacketCount; ++i, now_ms += 10) {
-    packets.push_back(BwePacket(now_ms * 1000, sequence_number++));
+    packets.push_back(Packet(now_ms * 1000, sequence_number++));
   }
   ASSERT_TRUE(IsTimeSorted(packets));
   ASSERT_TRUE(IsSequenceNumberSorted(packets));
 
   // Reorder packets, verify that send times are still in order.
-  ReorderFilter filter;
+  ReorderFilter filter(NULL);
   filter.SetReorder(reorder_percent);
   filter.RunFor(now_ms, &packets);
   ASSERT_TRUE(IsTimeSorted(packets));
@@ -724,7 +567,7 @@
 class BweTestFramework_ChokeFilterTest : public ::testing::Test {
  public:
   BweTestFramework_ChokeFilterTest()
-    : filter_(),
+    : filter_(NULL),
       now_ms_(0),
       sequence_number_(0),
       output_packets_(),
@@ -744,7 +587,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(BwePacket(send_time_ms * 1000, 125, header));
+      packets.push_back(Packet(send_time_ms * 1000, 125, header));
       send_times_us_.push_back(send_time_ms * 1000);
     }
     ASSERT_TRUE(IsTimeSorted(packets));
@@ -757,7 +600,7 @@
     // Sum up the transmitted bytes up until the current time.
     uint32_t bytes_transmitted = 0;
     while (!output_packets_.empty()) {
-      const BwePacket& packet = output_packets_.front();
+      const Packet& packet = output_packets_.front();
       if (packet.send_time_us() > now_ms_ * 1000) {
         break;
       }
@@ -770,7 +613,7 @@
   void CheckMaxDelay(int64_t max_delay_ms) {
     for (PacketsIt it = output_packets_.begin(); it != output_packets_.end();
         ++it) {
-      const BwePacket& packet = *it;
+      const Packet& packet = *it;
       int64_t delay_us = packet.send_time_us() -
           send_times_us_[packet.header().sequenceNumber];
       EXPECT_GE(max_delay_ms * 1000, delay_us);
@@ -853,6 +696,163 @@
   TestChoke(100, 100, 2);
   TestChoke(9900, 0, 98);
 }
+
+void TestVideoSender(VideoSender* sender, int64_t run_for_ms,
+                     uint32_t expected_packets,
+                     uint32_t expected_payload_size,
+                     uint32_t expected_total_payload_size) {
+  assert(sender);
+  Packets packets;
+  sender->RunFor(run_for_ms, &packets);
+  ASSERT_TRUE(IsTimeSorted(packets));
+  ASSERT_TRUE(IsSequenceNumberSorted(packets));
+  EXPECT_EQ(expected_packets, packets.size());
+  int64_t send_time_us = -1;
+  uint32_t total_payload_size = 0;
+  uint32_t absolute_send_time = 0;
+  uint32_t absolute_send_time_wraps = 0;
+  uint32_t rtp_timestamp = 0;
+  uint32_t rtp_timestamp_wraps = 0;
+  for (PacketsIt it = packets.begin(); it != packets.end(); ++it) {
+    EXPECT_LE(send_time_us, it->send_time_us());
+    send_time_us = it->send_time_us();
+    if (sender->max_payload_size_bytes() != it->payload_size()) {
+      EXPECT_EQ(expected_payload_size, it->payload_size());
+    }
+    total_payload_size += it->payload_size();
+    if (absolute_send_time > it->header().extension.absoluteSendTime) {
+      absolute_send_time_wraps++;
+    }
+    absolute_send_time = it->header().extension.absoluteSendTime;
+    if (rtp_timestamp > it->header().timestamp) {
+      rtp_timestamp_wraps++;
+    }
+    rtp_timestamp = it->header().timestamp;
+  }
+  EXPECT_EQ(expected_total_payload_size, total_payload_size);
+  EXPECT_GE(1u, absolute_send_time_wraps);
+  EXPECT_GE(1u, rtp_timestamp_wraps);
+}
+
+TEST(BweTestFramework_VideoSenderTest, Fps1Kpbs80_1s) {
+  // 1 fps, 80 kbps
+  VideoSender sender(NULL, 1.0f, 80, 0x1234, 0);
+  EXPECT_EQ(10000u, sender.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.
+  TestVideoSender(&sender, 1, 10, 1000, 10000);
+  // 999ms, should see no output here.
+  TestVideoSender(&sender, 998, 0, 0, 0);
+  // 1999ms, should get data for one more frame.
+  TestVideoSender(&sender, 1000, 10, 1000, 10000);
+  // 2000ms, one more frame.
+  TestVideoSender(&sender, 1, 10, 1000, 10000);
+  // 2999ms, should see nothing.
+  TestVideoSender(&sender, 999, 0, 0, 0);
+}
+
+TEST(BweTestFramework_VideoSenderTest, Fps1Kpbs80_1s_Offset) {
+  // 1 fps, 80 kbps, offset 0.5 of a frame period, ==0.5s in this case.
+  VideoSender sender(NULL, 1.0f, 80, 0x1234, 0.5f);
+  EXPECT_EQ(10000u, sender.bytes_per_second());
+  // 499ms, no output.
+  TestVideoSender(&sender, 499, 0, 0, 0);
+  // 500ms, first frame (this is the offset we set), 10 packets of 1000 bytes.
+  TestVideoSender(&sender, 1, 10, 1000, 10000);
+  // 1499ms, nothing.
+  TestVideoSender(&sender, 999, 0, 0, 0);
+  // 1999ms, second frame.
+  TestVideoSender(&sender, 500, 10, 1000, 10000);
+  // 2499ms, nothing.
+  TestVideoSender(&sender, 500, 0, 0, 0);
+  // 2500ms, third frame.
+  TestVideoSender(&sender, 1, 10, 1000, 10000);
+  // 3499ms, nothing.
+  TestVideoSender(&sender, 999, 0, 0, 0);
+}
+
+TEST(BweTestFramework_VideoSenderTest, Fps50Kpbs80_11s) {
+  // 50 fps, 80 kbps.
+  VideoSender sender(NULL, 50.0f, 80, 0x1234, 0);
+  EXPECT_EQ(10000u, sender.bytes_per_second());
+  // 9998ms, should see 500 frames, 200 byte payloads, total 100000 bytes.
+  TestVideoSender(&sender, 9998, 500, 200, 100000);
+  // 9999ms, nothing.
+  TestVideoSender(&sender, 1, 0, 0, 0);
+  // 10000ms, 501st frame as a single packet.
+  TestVideoSender(&sender, 1, 1, 200, 200);
+  // 10998ms, 49 more frames.
+  TestVideoSender(&sender, 998, 49, 200, 9800);
+  // 10999ms, nothing.
+  TestVideoSender(&sender, 1, 0, 0, 0);
+}
+
+TEST(BweTestFramework_VideoSenderTest, Fps10Kpbs120_1s) {
+  // 20 fps, 120 kbps.
+  VideoSender sender(NULL, 20.0f, 120, 0x1234, 0);
+  EXPECT_EQ(15000u, sender.bytes_per_second());
+  // 498ms, 10 frames with 750 byte payloads, total 7500 bytes.
+  TestVideoSender(&sender, 498, 10, 750, 7500);
+  // 499ms, nothing.
+  TestVideoSender(&sender, 1, 0, 0, 0);
+  // 500ms, one more frame.
+  TestVideoSender(&sender, 1, 1, 750, 750);
+  // 998ms, 9 more frames.
+  TestVideoSender(&sender, 498, 9, 750, 6750);
+  // 999ms, nothing.
+  TestVideoSender(&sender, 1, 0, 0, 0);
+}
+
+TEST(BweTestFramework_VideoSenderTest, Fps30Kpbs800_20s) {
+  // 20 fps, 820 kbps.
+  VideoSender sender(NULL, 25.0f, 820, 0x1234, 0);
+  EXPECT_EQ(102500u, sender.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),
+  // so packet count should be 5*250=1250 and last packet of each frame has
+  // 100 bytes of payload.
+  TestVideoSender(&sender, 9998, 1250, 100, 1025000);
+  // 9999ms, nothing.
+  TestVideoSender(&sender, 1, 0, 0, 0);
+  // 19998ms, 250 more frames.
+  TestVideoSender(&sender, 9999, 1250, 100, 1025000);
+  // 19999ms, nothing.
+  TestVideoSender(&sender, 1, 0, 0, 0);
+  // 20038ms, one more frame, as described above (25fps == 40ms/frame).
+  TestVideoSender(&sender, 39, 5, 100, 4100);
+  // 20039ms, nothing.
+  TestVideoSender(&sender, 1, 0, 0, 0);
+}
+
+TEST(BweTestFramework_VideoSenderTest, TestAppendInOrder) {
+  // 1 fps, 80 kbps, 250ms offset.
+  VideoSender sender1(NULL, 1.0f, 80, 0x1234, 0.25f);
+  EXPECT_EQ(10000u, sender1.bytes_per_second());
+  Packets packets;
+  // Generate some packets, verify they are sorted.
+  sender1.RunFor(999, &packets);
+  ASSERT_TRUE(IsTimeSorted(packets));
+  ASSERT_TRUE(IsSequenceNumberSorted(packets));
+  EXPECT_EQ(10u, packets.size());
+  // Generate some more packets and verify they are appended to end of list.
+  sender1.RunFor(1000, &packets);
+  ASSERT_TRUE(IsTimeSorted(packets));
+  ASSERT_TRUE(IsSequenceNumberSorted(packets));
+  EXPECT_EQ(20u, packets.size());
+
+  // Another sender, 2 fps, 160 kpbs, 150ms offset
+  VideoSender sender2(NULL, 2.0f, 160, 0x2234, 0.30f);
+  EXPECT_EQ(20000u, sender2.bytes_per_second());
+  // Generate some packets, verify that they are merged with the packets already
+  // on the list.
+  sender2.RunFor(999, &packets);
+  ASSERT_TRUE(IsTimeSorted(packets));
+  EXPECT_EQ(40u, packets.size());
+  // Generate some more.
+  sender2.RunFor(1000, &packets);
+  ASSERT_TRUE(IsTimeSorted(packets));
+  EXPECT_EQ(60u, packets.size());
+}
 }  // namespace bwe
 }  // namespace testing
 }  // namespace webrtc
diff --git a/webrtc/modules/remote_bitrate_estimator/test/bwe_test_logging.cc b/webrtc/modules/remote_bitrate_estimator/test/bwe_test_logging.cc
index ae1d42b..1a43f09 100644
--- a/webrtc/modules/remote_bitrate_estimator/test/bwe_test_logging.cc
+++ b/webrtc/modules/remote_bitrate_estimator/test/bwe_test_logging.cc
@@ -25,20 +25,24 @@
 
 Logging Logging::g_Logging;
 
-Logging::Context::Context(uint32_t name, int64_t timestamp_ms, bool enabled) {
+static std::string ToString(uint32_t v) {
   const size_t kBufferSize = 16;
   char string_buffer[kBufferSize] = {0};
 #if defined(_MSC_VER) && defined(_WIN32)
-  _snprintf(string_buffer, kBufferSize - 1, "%08x", name);
+  _snprintf(string_buffer, kBufferSize - 1, "%08x", v);
 #else
-  snprintf(string_buffer, kBufferSize, "%08x", name);
+  snprintf(string_buffer, kBufferSize, "%08x", v);
 #endif
-  Logging::GetInstance()->PushState(string_buffer, timestamp_ms, enabled);
+  return string_buffer;
+}
+
+Logging::Context::Context(uint32_t name, int64_t timestamp_ms, bool enabled) {
+  Logging::GetInstance()->PushState(ToString(name), timestamp_ms, enabled);
 }
 
 Logging::Context::Context(const std::string& name, int64_t timestamp_ms,
                           bool enabled) {
-  Logging::GetInstance()->PushState(name.c_str(), timestamp_ms, enabled);
+  Logging::GetInstance()->PushState(name, timestamp_ms, enabled);
 }
 
 Logging::Context::Context(const char* name, int64_t timestamp_ms,
@@ -54,11 +58,31 @@
   return &g_Logging;
 }
 
+void Logging::SetGlobalContext(uint32_t name) {
+  CriticalSectionScoped cs(crit_sect_.get());
+  thread_map_[ThreadWrapper::GetThreadId()].global_state.tag = ToString(name);
+}
+
+void Logging::SetGlobalContext(const std::string& name) {
+  CriticalSectionScoped cs(crit_sect_.get());
+  thread_map_[ThreadWrapper::GetThreadId()].global_state.tag = name;
+}
+
+void Logging::SetGlobalContext(const char* name) {
+  CriticalSectionScoped cs(crit_sect_.get());
+  thread_map_[ThreadWrapper::GetThreadId()].global_state.tag = name;
+}
+
+void Logging::SetGlobalEnable(bool enabled) {
+  CriticalSectionScoped cs(crit_sect_.get());
+  thread_map_[ThreadWrapper::GetThreadId()].global_state.enabled = enabled;
+}
+
 void Logging::Log(const char format[], ...) {
   CriticalSectionScoped cs(crit_sect_.get());
   ThreadMap::iterator it = thread_map_.find(ThreadWrapper::GetThreadId());
   assert(it != thread_map_.end());
-  const State& state = it->second.top();
+  const State& state = it->second.stack.top();
   if (state.enabled) {
     printf("%s\t", state.tag.c_str());
     va_list args;
@@ -73,7 +97,7 @@
   CriticalSectionScoped cs(crit_sect_.get());
   ThreadMap::iterator it = thread_map_.find(ThreadWrapper::GetThreadId());
   assert(it != thread_map_.end());
-  const State& state = it->second.top();
+  const State& state = it->second.stack.top();
   if (state.enabled) {
     printf("PLOT\t%s\t%f\t%f\n", state.tag.c_str(), state.timestamp_ms * 0.001,
            value);
@@ -85,37 +109,48 @@
       thread_map_() {
 }
 
-void Logging::PushState(const char append_to_tag[], int64_t timestamp_ms,
-                        bool enabled) {
-  assert(append_to_tag);
-  CriticalSectionScoped cs(crit_sect_.get());
-  std::stack<State>* stack = &thread_map_[ThreadWrapper::GetThreadId()];
-  if (stack->empty()) {
-    State new_state(append_to_tag, std::max(static_cast<int64_t>(0),
-                                            timestamp_ms), enabled);
-    stack->push(new_state);
-  } else {
-    stack->push(stack->top());
-    State* state = &stack->top();
-    if (state->tag != "" && std::string(append_to_tag) != "") {
-      state->tag.append("_");
-    }
-    state->tag.append(append_to_tag);
-    state->timestamp_ms = std::max(timestamp_ms, state->timestamp_ms);
-    state->enabled = enabled && state->enabled;
+Logging::State::State() : tag(""), timestamp_ms(0), enabled(true) {}
+
+Logging::State::State(const std::string& tag, int64_t timestamp_ms,
+                      bool enabled)
+    : tag(tag),
+      timestamp_ms(timestamp_ms),
+      enabled(enabled) {
+}
+
+void Logging::State::MergePrevious(const State& previous) {
+  if (tag == "") {
+    tag = previous.tag;
+  } else if (previous.tag != "") {
+    tag = previous.tag + "_" + tag;
   }
+  timestamp_ms = std::max(previous.timestamp_ms, timestamp_ms);
+  enabled = previous.enabled && enabled;
+}
+
+void Logging::PushState(const std::string& append_to_tag, int64_t timestamp_ms,
+                        bool enabled) {
+  CriticalSectionScoped cs(crit_sect_.get());
+  State new_state(append_to_tag, timestamp_ms, enabled);
+  ThreadState* thread_state = &thread_map_[ThreadWrapper::GetThreadId()];
+  std::stack<State>* stack = &thread_state->stack;
+  if (stack->empty()) {
+    new_state.MergePrevious(thread_state->global_state);
+  } else {
+    new_state.MergePrevious(stack->top());
+  }
+  stack->push(new_state);
 }
 
 void Logging::PopState() {
   CriticalSectionScoped cs(crit_sect_.get());
   ThreadMap::iterator it = thread_map_.find(ThreadWrapper::GetThreadId());
   assert(it != thread_map_.end());
-  int64_t newest_timestamp_ms = it->second.top().timestamp_ms;
-  it->second.pop();
-  if (it->second.empty()) {
-    thread_map_.erase(it);
-  } else {
-    State* state = &it->second.top();
+  std::stack<State>* stack = &it->second.stack;
+  int64_t newest_timestamp_ms = stack->top().timestamp_ms;
+  stack->pop();
+  if (!stack->empty()) {
+    State* state = &stack->top();
     // Update time so that next log/plot will use the latest time seen so far
     // in this call tree.
     state->timestamp_ms = std::max(state->timestamp_ms, newest_timestamp_ms);
diff --git a/webrtc/modules/remote_bitrate_estimator/test/bwe_test_logging.h b/webrtc/modules/remote_bitrate_estimator/test/bwe_test_logging.h
index 0ff5825..c949763 100644
--- a/webrtc/modules/remote_bitrate_estimator/test/bwe_test_logging.h
+++ b/webrtc/modules/remote_bitrate_estimator/test/bwe_test_logging.h
@@ -51,6 +51,15 @@
 
 #if !(BWE_TEST_LOGGING_COMPILE_TIME_ENABLE)
 
+// Set a thread-global base logging context. This name will be prepended to all
+// hierarchical contexts.
+// |name| is a char*, std::string or uint32_t to name the context.
+#define BWE_TEST_LOGGING_GLOBAL_CONTEXT(name)
+
+// Thread-globally allow/disallow logging.
+// |enable| is expected to be a bool.
+#define BWE_TEST_LOGGING_GLOBAL_ENABLE(enabled)
+
 // Insert a (hierarchical) logging context.
 // |name| is a char*, std::string or uint32_t to name the context.
 #define BWE_TEST_LOGGING_CONTEXT(name)
@@ -93,6 +102,16 @@
 #include "webrtc/system_wrappers/interface/constructor_magic.h"
 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
 
+#define BWE_TEST_LOGGING_GLOBAL_CONTEXT(name) \
+    do { \
+      webrtc::testing::bwe::Logging::GetInstance()->SetGlobalContext(name); \
+    } while (0);
+
+#define BWE_TEST_LOGGING_GLOBAL_ENABLE(enabled) \
+    do { \
+      webrtc::testing::bwe::Logging::GetInstance()->SetGlobalEnable(enabled); \
+    } while (0);
+
 #define __BWE_TEST_LOGGING_CONTEXT_NAME(ctx, line) ctx ## line
 #define __BWE_TEST_LOGGING_CONTEXT_DECLARE(ctx, line, name, time, enabled) \
     webrtc::testing::bwe::Logging::Context \
@@ -162,24 +181,33 @@
   };
 
   static Logging* GetInstance();
+
+  void SetGlobalContext(uint32_t name);
+  void SetGlobalContext(const std::string& name);
+  void SetGlobalContext(const char* name);
+  void SetGlobalEnable(bool enabled);
+
   void Log(const char format[], ...);
   void Plot(double value);
 
  private:
   struct State {
-    State(const char new_tag[], int64_t timestamp_ms, bool enabled)
-        : tag(new_tag),
-          timestamp_ms(timestamp_ms),
-          enabled(enabled) {
-    }
+    State();
+    State(const std::string& new_tag, int64_t timestamp_ms, bool enabled);
+    void MergePrevious(const State& previous);
+
     std::string tag;
     int64_t timestamp_ms;
     bool enabled;
   };
-  typedef std::map<uint32_t, std::stack<State> > ThreadMap;
+  struct ThreadState {
+    State global_state;
+    std::stack<State> stack;
+  };
+  typedef std::map<uint32_t, ThreadState> ThreadMap;
 
   Logging();
-  void PushState(const char append_to_tag[], int64_t timestamp_ms,
+  void PushState(const std::string& append_to_tag, int64_t timestamp_ms,
                  bool enabled);
   void PopState();