Added -show_detector_state which show the detector state in the total bitrate graph.

BUG=none

Review-Url: https://codereview.webrtc.org/2826313004
Cr-Commit-Position: refs/heads/master@{#19020}
diff --git a/webrtc/rtc_tools/event_log_visualizer/analyzer.cc b/webrtc/rtc_tools/event_log_visualizer/analyzer.cc
index 78993f4..b42f082 100644
--- a/webrtc/rtc_tools/event_log_visualizer/analyzer.cc
+++ b/webrtc/rtc_tools/event_log_visualizer/analyzer.cc
@@ -898,7 +898,8 @@
 // Plot the total bandwidth used by all RTP streams.
 void EventLogAnalyzer::CreateTotalBitrateGraph(
     PacketDirection desired_direction,
-    Plot* plot) {
+    Plot* plot,
+    bool show_detector_state) {
   struct TimestampSize {
     TimestampSize(uint64_t t, size_t s) : timestamp(t), size(s) {}
     uint64_t timestamp;
@@ -958,13 +959,46 @@
     }
 
     TimeSeries delay_series("Delay-based estimate", LINE_STEP_GRAPH);
+    IntervalSeries overusing_series("Overusing", "#ff8e82",
+                                    IntervalSeries::kHorizontal);
+    IntervalSeries underusing_series("Underusing", "#5092fc",
+                                     IntervalSeries::kHorizontal);
+    IntervalSeries normal_series("Normal", "#c4ffc4",
+                                 IntervalSeries::kHorizontal);
+    IntervalSeries* last_series = &normal_series;
+    double last_detector_switch = 0.0;
+
+    BandwidthUsage last_detector_state = BandwidthUsage::kBwNormal;
+
     for (auto& delay_update : bwe_delay_updates_) {
       float x =
           static_cast<float>(delay_update.timestamp - begin_time_) / 1000000;
       float y = static_cast<float>(delay_update.bitrate_bps) / 1000;
+
+      if (last_detector_state != delay_update.detector_state) {
+        last_series->intervals.emplace_back(last_detector_switch, x);
+        last_detector_state = delay_update.detector_state;
+        last_detector_switch = x;
+
+        switch (delay_update.detector_state) {
+          case BandwidthUsage::kBwNormal:
+            last_series = &normal_series;
+            break;
+          case BandwidthUsage::kBwUnderusing:
+            last_series = &underusing_series;
+            break;
+          case BandwidthUsage::kBwOverusing:
+            last_series = &overusing_series;
+            break;
+        }
+      }
+
       delay_series.points.emplace_back(x, y);
     }
 
+    RTC_CHECK(last_series);
+    last_series->intervals.emplace_back(last_detector_switch, end_time_);
+
     TimeSeries created_series("Probe cluster created.", DOT_GRAPH);
     for (auto& cluster : bwe_probe_cluster_created_events_) {
       float x = static_cast<float>(cluster.timestamp - begin_time_) / 1000000;
@@ -980,6 +1014,14 @@
         result_series.points.emplace_back(x, y);
       }
     }
+
+    if (show_detector_state) {
+      plot->AppendIntervalSeries(std::move(overusing_series));
+      plot->AppendIntervalSeries(std::move(underusing_series));
+      plot->AppendIntervalSeries(std::move(normal_series));
+    }
+
+    plot->AppendTimeSeries(std::move(bitrate_series));
     plot->AppendTimeSeries(std::move(loss_series));
     plot->AppendTimeSeries(std::move(delay_series));
     plot->AppendTimeSeries(std::move(created_series));
diff --git a/webrtc/rtc_tools/event_log_visualizer/analyzer.h b/webrtc/rtc_tools/event_log_visualizer/analyzer.h
index 0c3fa46..ce4868f 100644
--- a/webrtc/rtc_tools/event_log_visualizer/analyzer.h
+++ b/webrtc/rtc_tools/event_log_visualizer/analyzer.h
@@ -85,7 +85,9 @@
 
   void CreateFractionLossGraph(Plot* plot);
 
-  void CreateTotalBitrateGraph(PacketDirection desired_direction, Plot* plot);
+  void CreateTotalBitrateGraph(PacketDirection desired_direction,
+                               Plot* plot,
+                               bool show_detector_state = false);
 
   void CreateStreamBitrateGraph(PacketDirection desired_direction, Plot* plot);
 
diff --git a/webrtc/rtc_tools/event_log_visualizer/main.cc b/webrtc/rtc_tools/event_log_visualizer/main.cc
index 6e78c89..a4490aa 100644
--- a/webrtc/rtc_tools/event_log_visualizer/main.cc
+++ b/webrtc/rtc_tools/event_log_visualizer/main.cc
@@ -90,6 +90,11 @@
     "trials are separated by \"/\"");
 DEFINE_bool(help, false, "prints this message");
 
+DEFINE_bool(
+    show_detector_state,
+    false,
+    "Mark the delay based bwe detector state on the total bitrate graph");
+
 int main(int argc, char* argv[]) {
   std::string program_name = argv[0];
   std::string usage =
@@ -178,11 +183,13 @@
   if (FLAG_plot_all || FLAG_plot_total_bitrate) {
     if (FLAG_incoming) {
       analyzer.CreateTotalBitrateGraph(webrtc::PacketDirection::kIncomingPacket,
-                                       collection->AppendNewPlot());
+                                       collection->AppendNewPlot(),
+                                       FLAG_show_detector_state);
     }
     if (FLAG_outgoing) {
       analyzer.CreateTotalBitrateGraph(webrtc::PacketDirection::kOutgoingPacket,
-                                       collection->AppendNewPlot());
+                                       collection->AppendNewPlot(),
+                                       FLAG_show_detector_state);
     }
   }
 
diff --git a/webrtc/rtc_tools/event_log_visualizer/plot_base.cc b/webrtc/rtc_tools/event_log_visualizer/plot_base.cc
index 8bf3533..783f2b8 100644
--- a/webrtc/rtc_tools/event_log_visualizer/plot_base.cc
+++ b/webrtc/rtc_tools/event_log_visualizer/plot_base.cc
@@ -75,6 +75,10 @@
   series_list_.emplace_back(std::move(time_series));
 }
 
+void Plot::AppendIntervalSeries(IntervalSeries&& interval_series) {
+  interval_list_.emplace_back(std::move(interval_series));
+}
+
 void Plot::AppendTimeSeriesIfNotEmpty(TimeSeries&& time_series) {
   if (time_series.points.size() > 0) {
     series_list_.emplace_back(std::move(time_series));
diff --git a/webrtc/rtc_tools/event_log_visualizer/plot_base.h b/webrtc/rtc_tools/event_log_visualizer/plot_base.h
index bdcea2e..347fca4 100644
--- a/webrtc/rtc_tools/event_log_visualizer/plot_base.h
+++ b/webrtc/rtc_tools/event_log_visualizer/plot_base.h
@@ -53,6 +53,29 @@
   std::vector<TimeSeriesPoint> points;
 };
 
+struct Interval {
+  Interval() = default;
+  Interval(double begin, double end) : begin(begin), end(end) {}
+
+  double begin;
+  double end;
+};
+
+struct IntervalSeries {
+  enum Orientation { kHorizontal, kVertical };
+
+  IntervalSeries() = default;
+  IntervalSeries(const std::string& label,
+                 const std::string& color,
+                 IntervalSeries::Orientation orientation)
+      : label(label), color(color), orientation(orientation) {}
+
+  std::string label;
+  std::string color;
+  Orientation orientation;
+  std::vector<Interval> intervals;
+};
+
 // A container that represents a general graph, with axes, title and one or
 // more data series. A subclass should define the output format by overriding
 // the Draw() method.
@@ -109,6 +132,9 @@
   // Add a new TimeSeries to the plot.
   void AppendTimeSeries(TimeSeries&& time_series);
 
+  // Add a new IntervalSeries to the plot.
+  void AppendIntervalSeries(IntervalSeries&& interval_series);
+
   // Add a new TimeSeries to the plot if the series contains contains data.
   // Otherwise, the call has no effect and the timeseries is destroyed.
   void AppendTimeSeriesIfNotEmpty(TimeSeries&& time_series);
@@ -122,6 +148,7 @@
   std::string yaxis_label_;
   std::string title_;
   std::vector<TimeSeries> series_list_;
+  std::vector<IntervalSeries> interval_list_;
 };
 
 class PlotCollection {
diff --git a/webrtc/rtc_tools/event_log_visualizer/plot_python.cc b/webrtc/rtc_tools/event_log_visualizer/plot_python.cc
index d4ae043..dae2855 100644
--- a/webrtc/rtc_tools/event_log_visualizer/plot_python.cc
+++ b/webrtc/rtc_tools/event_log_visualizer/plot_python.cc
@@ -14,6 +14,8 @@
 
 #include <memory>
 
+#include "webrtc/rtc_base/checks.h"
+
 namespace webrtc {
 namespace plotting {
 
@@ -74,6 +76,8 @@
         printf("y%zu = [v for dup in y%zu for v in [dup, dup]]\n", i, i);
         printf(
             "plt.plot(x%zu[1:], y%zu[:-1], color=rgb_colors[%zu], "
+            "path_effects=[pe.Stroke(linewidth=2, foreground='black'), "
+            "pe.Normal()], "
             "label=\'%s\')\n",
             i, i, i, series_list_[i].label.c_str());
       } else if (series_list_[i].style == DOT_GRAPH) {
@@ -85,6 +89,47 @@
         printf("raise Exception(\"Unknown graph type\")\n");
       }
     }
+
+    // IntervalSeries
+    printf("interval_colors = ['#ff8e82','#5092fc','#c4ffc4']\n");
+    RTC_CHECK_LE(interval_list_.size(), 3);
+    // To get the intervals to show up in the legend we have to created patches
+    // for them.
+    printf("legend_patches = []\n");
+    for (size_t i = 0; i < interval_list_.size(); i++) {
+      // List intervals
+      printf("\n# === IntervalSeries: %s ===\n",
+             interval_list_[i].label.c_str());
+      printf("ival%zu = [", i);
+      if (interval_list_[i].intervals.size() > 0) {
+        printf("(%G, %G)", interval_list_[i].intervals[0].begin,
+               interval_list_[i].intervals[0].end);
+      }
+      for (size_t j = 1; j < interval_list_[i].intervals.size(); j++) {
+        printf(", (%G, %G)", interval_list_[i].intervals[j].begin,
+               interval_list_[i].intervals[j].end);
+      }
+      printf("]\n");
+
+      printf("for i in range(0, %zu):\n", interval_list_[i].intervals.size());
+      if (interval_list_[i].orientation == IntervalSeries::kVertical) {
+        printf(
+            "  plt.axhspan(ival%zu[i][0], ival%zu[i][1], "
+            "facecolor=interval_colors[%zu], "
+            "alpha=0.3)\n",
+            i, i, i);
+      } else {
+        printf(
+            "  plt.axvspan(ival%zu[i][0], ival%zu[i][1], "
+            "facecolor=interval_colors[%zu], "
+            "alpha=0.3)\n",
+            i, i, i);
+      }
+      printf(
+          "legend_patches.append(mpatches.Patch(ec=\'black\', "
+          "fc=interval_colors[%zu], label='%s'))\n",
+          i, interval_list_[i].label.c_str());
+    }
   }
 
   printf("plt.xlim(%f, %f)\n", xaxis_min_, xaxis_max_);
@@ -92,8 +137,12 @@
   printf("plt.xlabel(\'%s\')\n", xaxis_label_.c_str());
   printf("plt.ylabel(\'%s\')\n", yaxis_label_.c_str());
   printf("plt.title(\'%s\')\n", title_.c_str());
-  if (!series_list_.empty()) {
-    printf("plt.legend(loc=\'best\', fontsize=\'small\')\n");
+  if (!series_list_.empty() || !interval_list_.empty()) {
+    printf("handles, labels = plt.gca().get_legend_handles_labels()\n");
+    printf("for lp in legend_patches:\n");
+    printf("   handles.append(lp)\n");
+    printf("   labels.append(lp.get_label())\n");
+    printf("plt.legend(handles, labels, loc=\'best\', fontsize=\'small\')\n");
   }
 }
 
@@ -103,6 +152,8 @@
 
 void PythonPlotCollection::Draw() {
   printf("import matplotlib.pyplot as plt\n");
+  printf("import matplotlib.patches as mpatches\n");
+  printf("import matplotlib.patheffects as pe\n");
   printf("import colorsys\n");
   for (size_t i = 0; i < plots_.size(); i++) {
     printf("plt.figure(%zu)\n", i);