Plot the capacity of a trace-based delivery filter.

Breaks out the instantaneous rate counters to its own class.

R=solenberg@webrtc.org

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk/webrtc@5494 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/modules/remote_bitrate_estimator/bwe_simulations.cc b/modules/remote_bitrate_estimator/bwe_simulations.cc
index 797d669..976f2a8 100644
--- a/modules/remote_bitrate_estimator/bwe_simulations.cc
+++ b/modules/remote_bitrate_estimator/bwe_simulations.cc
@@ -67,7 +67,7 @@
 TEST_P(BweSimulation, SprintUplinkTest) {
   VerboseLogging(true);
   RateCounterFilter counter1(this, "sender_output");
-  TraceBasedDeliveryFilter filter(this);
+  TraceBasedDeliveryFilter filter(this, "link_capacity");
   RateCounterFilter counter2(this, "receiver_input");
   ASSERT_TRUE(filter.Init(test::ResourcePath("sprint-uplink", "rx")));
   RunFor(60 * 1000);
@@ -76,7 +76,7 @@
 TEST_P(BweSimulation, Verizon4gDownlinkTest) {
   VerboseLogging(true);
   RateCounterFilter counter1(this, "sender_output");
-  TraceBasedDeliveryFilter filter(this);
+  TraceBasedDeliveryFilter filter(this, "link_capacity");
   RateCounterFilter counter2(this, "receiver_input");
   ASSERT_TRUE(filter.Init(test::ResourcePath("verizon4g-downlink", "rx")));
   RunFor(22 * 60 * 1000);
diff --git a/modules/remote_bitrate_estimator/test/bwe_plot.sh b/modules/remote_bitrate_estimator/test/bwe_plot.sh
index 627b930..4695af4 100755
--- a/modules/remote_bitrate_estimator/test/bwe_plot.sh
+++ b/modules/remote_bitrate_estimator/test/bwe_plot.sh
@@ -29,7 +29,7 @@
   linetypes=($(echo "$data_sets" | cut -d '#' -f 2 | cut -d ' ' -f 1))
   echo -n "reset; "
   echo -n "set terminal wxt size 1440,900 font \"Arial,9\"; "
-  echo -n "set xtics 60; set xlabel \"Seconds\"; "
+  echo -n "set xlabel \"Seconds\"; "
   if [ -n $linetypes ]; then
     echo -n "set ylabel 'bitrate (kbps)';"
     echo -n "set ytics nomirror;"
diff --git a/modules/remote_bitrate_estimator/test/bwe_test_framework.cc b/modules/remote_bitrate_estimator/test/bwe_test_framework.cc
index b4a6a09..546ae2c 100644
--- a/modules/remote_bitrate_estimator/test/bwe_test_framework.cc
+++ b/modules/remote_bitrate_estimator/test/bwe_test_framework.cc
@@ -17,6 +17,48 @@
 namespace testing {
 namespace bwe {
 
+class RateCounter {
+ public:
+  RateCounter()
+      : kWindowSizeUs(1000000),
+        packets_per_second_(0),
+        bytes_per_second_(0),
+        last_accumulated_us_(0),
+        window_() {}
+
+  void UpdateRates(int64_t send_time_us, uint32_t payload_size) {
+    packets_per_second_++;
+    bytes_per_second_ += payload_size;
+    last_accumulated_us_ = send_time_us;
+    window_.push_back(std::make_pair(send_time_us, payload_size));
+    while (!window_.empty()) {
+      const TimeSizePair& packet = window_.front();
+      if (packet.first > (last_accumulated_us_ - kWindowSizeUs)) {
+        break;
+      }
+      assert(packets_per_second_ >= 1);
+      assert(bytes_per_second_ >= packet.second);
+      packets_per_second_--;
+      bytes_per_second_ -= packet.second;
+      window_.pop_front();
+    }
+  }
+
+  uint32_t bits_per_second() const {
+    return bytes_per_second_ * 8;
+  }
+  uint32_t packets_per_second() const { return packets_per_second_; }
+
+ private:
+  typedef std::pair<int64_t, uint32_t> TimeSizePair;
+
+  const int64_t kWindowSizeUs;
+  uint32_t packets_per_second_;
+  uint32_t bytes_per_second_;
+  int64_t last_accumulated_us_;
+  std::list<TimeSizePair> window_;
+};
+
 Random::Random(uint32_t seed)
     : a_(0x531FDB97 ^ seed),
       b_(0x6420ECA8 + seed) {
@@ -102,33 +144,31 @@
 
 RateCounterFilter::RateCounterFilter(PacketProcessorListener* listener)
     : PacketProcessor(listener),
-      kWindowSizeUs(1000000),
-      packets_per_second_(0),
-      bytes_per_second_(0),
-      last_accumulated_us_(0),
-      window_(),
+      rate_counter_(new RateCounter()),
       pps_stats_(),
       kbps_stats_(),
-      name_("") {
-}
+      name_("") {}
 
 RateCounterFilter::RateCounterFilter(PacketProcessorListener* listener,
                                      const std::string& name)
     : PacketProcessor(listener),
-      kWindowSizeUs(1000000),
-      packets_per_second_(0),
-      bytes_per_second_(0),
-      last_accumulated_us_(0),
-      window_(),
+      rate_counter_(new RateCounter()),
       pps_stats_(),
       kbps_stats_(),
-      name_(name) {
-}
+      name_(name) {}
 
 RateCounterFilter::~RateCounterFilter() {
   LogStats();
 }
 
+uint32_t RateCounterFilter::packets_per_second() const {
+  return rate_counter_->packets_per_second();
+}
+
+uint32_t RateCounterFilter::bits_per_second() const {
+  return rate_counter_->bits_per_second();
+}
+
 void RateCounterFilter::LogStats() {
   BWE_TEST_LOGGING_CONTEXT("RateCounterFilter");
   pps_stats_.Log("pps");
@@ -138,30 +178,16 @@
 void RateCounterFilter::Plot(int64_t timestamp_ms) {
   BWE_TEST_LOGGING_CONTEXT(name_.c_str());
   BWE_TEST_LOGGING_PLOT("Throughput_#1", timestamp_ms,
-                        (bytes_per_second_ * 8) / 1000.0);
+                        rate_counter_->bits_per_second() / 1000.0);
 }
 
 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();
+    rate_counter_->UpdateRates(it->send_time_us(), it->payload_size());
   }
-  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);
+  pps_stats_.Push(rate_counter_->packets_per_second());
+  kbps_stats_.Push(rate_counter_->bits_per_second() / 1000.0);
 }
 
 LossFilter::LossFilter(PacketProcessorListener* listener)
@@ -311,7 +337,22 @@
     : PacketProcessor(listener),
       delivery_times_us_(),
       next_delivery_it_(),
-      local_time_us_(-1) {}
+      local_time_us_(-1),
+      rate_counter_(new RateCounter),
+      name_("") {}
+
+TraceBasedDeliveryFilter::TraceBasedDeliveryFilter(
+    PacketProcessorListener* listener,
+    const std::string& name)
+    : PacketProcessor(listener),
+      delivery_times_us_(),
+      next_delivery_it_(),
+      local_time_us_(-1),
+      rate_counter_(new RateCounter),
+      name_(name) {}
+
+TraceBasedDeliveryFilter::~TraceBasedDeliveryFilter() {
+}
 
 bool TraceBasedDeliveryFilter::Init(const std::string& filename) {
   FILE* trace_file = fopen(filename.c_str(), "r");
@@ -341,11 +382,21 @@
   return true;
 }
 
+void TraceBasedDeliveryFilter::Plot(int64_t timestamp_ms) {
+  BWE_TEST_LOGGING_CONTEXT(name_.c_str());
+  // This plots the max possible throughput of the trace-based delivery filter,
+  // which will be reached if a packet sent on every packet slot of the trace.
+  BWE_TEST_LOGGING_PLOT("MaxThroughput_#1", timestamp_ms,
+                        rate_counter_->bits_per_second() / 1000.0);
+}
+
 void TraceBasedDeliveryFilter::RunFor(int64_t time_ms, Packets* in_out) {
   assert(in_out);
   for (PacketsIt it = in_out->begin(); it != in_out->end(); ++it) {
     do {
       ProceedToNextSlot();
+      const int kPayloadSize = 1240;
+      rate_counter_->UpdateRates(local_time_us_, kPayloadSize);
     } while (local_time_us_ < it->send_time_us());
     it->set_send_time_us(local_time_us_);
   }
diff --git a/modules/remote_bitrate_estimator/test/bwe_test_framework.h b/modules/remote_bitrate_estimator/test/bwe_test_framework.h
index d7057da..ddddd74 100644
--- a/modules/remote_bitrate_estimator/test/bwe_test_framework.h
+++ b/modules/remote_bitrate_estimator/test/bwe_test_framework.h
@@ -21,11 +21,14 @@
 
 #include "webrtc/modules/interface/module_common_types.h"
 #include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_logging.h"
+#include "webrtc/system_wrappers/interface/scoped_ptr.h"
 
 namespace webrtc {
 namespace testing {
 namespace bwe {
 
+class RateCounter;
+
 template<typename T> class Stats {
  public:
   Stats()
@@ -193,22 +196,18 @@
  public:
   explicit RateCounterFilter(PacketProcessorListener* listener);
   RateCounterFilter(PacketProcessorListener* listener,
-                    const std::string& context);
+                    const std::string& name);
   virtual ~RateCounterFilter();
 
-  uint32_t packets_per_second() const { return packets_per_second_; }
-  uint32_t bits_per_second() const { return bytes_per_second_ * 8; }
+  uint32_t packets_per_second() const;
+  uint32_t bits_per_second() const;
 
   void LogStats();
   virtual void Plot(int64_t timestamp_ms);
   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_;
+  scoped_ptr<RateCounter> rate_counter_;
   Stats<double> pps_stats_;
   Stats<double> kbps_stats_;
   std::string name_;
@@ -298,12 +297,15 @@
 class TraceBasedDeliveryFilter : public PacketProcessor {
  public:
   explicit TraceBasedDeliveryFilter(PacketProcessorListener* listener);
-  virtual ~TraceBasedDeliveryFilter() {}
+  TraceBasedDeliveryFilter(PacketProcessorListener* listener,
+                           const std::string& name);
+  virtual ~TraceBasedDeliveryFilter();
 
   // The file should contain nanosecond timestamps corresponding to the time
   // when the network can accept another packet. The timestamps should be
   // separated by new lines, e.g., "100000000\n125000000\n321000000\n..."
   bool Init(const std::string& filename);
+  virtual void Plot(int64_t timestamp_ms);
   virtual void RunFor(int64_t time_ms, Packets* in_out);
 
  private:
@@ -313,6 +315,8 @@
   TimeList delivery_times_us_;
   TimeList::const_iterator next_delivery_it_;
   int64_t local_time_us_;
+  scoped_ptr<RateCounter> rate_counter_;
+  std::string name_;
 
   DISALLOW_COPY_AND_ASSIGN(TraceBasedDeliveryFilter);
 };