Add simulation of receive-side bandwidth estimate to event_log_analyzer.

Previously reviewed at https://codereview.webrtc.org/2986683002/

Bug: webrtc:7726
Change-Id: I9568bd8387d79f313d6c7d53ded7c23460df1598
Reviewed-on: https://webrtc-review.googlesource.com/6360
Reviewed-by: Philip Eliasson <philipel@webrtc.org>
Commit-Queue: Björn Terelius <terelius@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20141}
diff --git a/logging/rtc_event_log/rtc_event_log2text.cc b/logging/rtc_event_log/rtc_event_log2text.cc
index af38964..173106a 100644
--- a/logging/rtc_event_log/rtc_event_log2text.cc
+++ b/logging/rtc_event_log/rtc_event_log2text.cc
@@ -38,6 +38,7 @@
 #include "modules/rtp_rtcp/source/rtp_utility.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/flags.h"
+#include "rtc_base/logging.h"
 
 namespace {
 
@@ -386,6 +387,7 @@
     RTC_CHECK(ParseSsrc(FLAG_ssrc)) << "Flag verification has failed.";
 
   webrtc::RtpHeaderExtensionMap default_map = GetDefaultHeaderExtensionMap();
+  bool default_map_used = false;
 
   webrtc::ParsedRtcEventLog parsed_stream;
   if (!parsed_stream.ParseFile(input_file)) {
@@ -433,8 +435,12 @@
               parsed_stream.GetRtpHeader(i, &direction, header, &header_length,
                                          &total_length, nullptr);
 
-          if (extension_map == nullptr)
+          if (extension_map == nullptr) {
             extension_map = &default_map;
+            if (!default_map_used)
+              LOG(LS_WARNING) << "Using default header extension map";
+            default_map_used = true;
+          }
 
           // Parse header to get SSRC and RTP time.
           webrtc::RtpUtility::RtpHeaderParser rtp_parser(header, header_length);
diff --git a/rtc_tools/event_log_visualizer/analyzer.cc b/rtc_tools/event_log_visualizer/analyzer.cc
index 9447483..6c42a72 100644
--- a/rtc_tools/event_log_visualizer/analyzer.cc
+++ b/rtc_tools/event_log_visualizer/analyzer.cc
@@ -30,6 +30,7 @@
 #include "modules/audio_coding/neteq/tools/neteq_replacement_input.h"
 #include "modules/audio_coding/neteq/tools/neteq_test.h"
 #include "modules/audio_coding/neteq/tools/resample_input_audio_file.h"
+#include "modules/congestion_controller/include/receive_side_congestion_controller.h"
 #include "modules/congestion_controller/include/send_side_congestion_controller.h"
 #include "modules/include/module_common_types.h"
 #include "modules/rtp_rtcp/include/rtp_rtcp.h"
@@ -1107,7 +1108,7 @@
   }
 }
 
-void EventLogAnalyzer::CreateBweSimulationGraph(Plot* plot) {
+void EventLogAnalyzer::CreateSendSideBweSimulationGraph(Plot* plot) {
   std::multimap<uint64_t, const LoggedRtpPacket*> outgoing_rtp;
   std::multimap<uint64_t, const LoggedRtcpPacket*> incoming_rtcp;
 
@@ -1226,7 +1227,85 @@
 
   plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin);
   plot->SetSuggestedYAxis(0, 10, "Bitrate (kbps)", kBottomMargin, kTopMargin);
-  plot->SetTitle("Simulated BWE behavior");
+  plot->SetTitle("Simulated send-side BWE behavior");
+}
+
+void EventLogAnalyzer::CreateReceiveSideBweSimulationGraph(Plot* plot) {
+  class RembInterceptingPacketRouter : public PacketRouter {
+   public:
+    void OnReceiveBitrateChanged(const std::vector<uint32_t>& ssrcs,
+                                 uint32_t bitrate_bps) override {
+      last_bitrate_bps_ = bitrate_bps;
+      bitrate_updated_ = true;
+      PacketRouter::OnReceiveBitrateChanged(ssrcs, bitrate_bps);
+    }
+    uint32_t last_bitrate_bps() const { return last_bitrate_bps_; }
+    bool GetAndResetBitrateUpdated() {
+      bool bitrate_updated = bitrate_updated_;
+      bitrate_updated_ = false;
+      return bitrate_updated;
+    }
+
+   private:
+    uint32_t last_bitrate_bps_;
+    bool bitrate_updated_;
+  };
+
+  std::multimap<uint64_t, const LoggedRtpPacket*> incoming_rtp;
+
+  for (const auto& kv : rtp_packets_) {
+    if (kv.first.GetDirection() == PacketDirection::kIncomingPacket &&
+        IsVideoSsrc(kv.first)) {
+      for (const LoggedRtpPacket& rtp_packet : kv.second)
+        incoming_rtp.insert(std::make_pair(rtp_packet.timestamp, &rtp_packet));
+    }
+  }
+
+  SimulatedClock clock(0);
+  RembInterceptingPacketRouter packet_router;
+  // TODO(terelius): The PacketRrouter is the used as the RemoteBitrateObserver.
+  // Is this intentional?
+  ReceiveSideCongestionController rscc(&clock, &packet_router);
+  // TODO(holmer): Log the call config and use that here instead.
+  // static const uint32_t kDefaultStartBitrateBps = 300000;
+  // rscc.SetBweBitrates(0, kDefaultStartBitrateBps, -1);
+
+  TimeSeries time_series("Receive side estimate", LINE_DOT_GRAPH);
+  TimeSeries acked_time_series("Received bitrate", LINE_GRAPH);
+
+  RateStatistics acked_bitrate(250, 8000);
+  int64_t last_update_us = 0;
+  for (const auto& kv : incoming_rtp) {
+    const LoggedRtpPacket& packet = *kv.second;
+    int64_t arrival_time_ms = packet.timestamp / 1000;
+    size_t payload = packet.total_length; /*Should subtract header?*/
+    clock.AdvanceTimeMicroseconds(packet.timestamp -
+                                  clock.TimeInMicroseconds());
+    rscc.OnReceivedPacket(arrival_time_ms, payload, packet.header);
+    acked_bitrate.Update(payload, arrival_time_ms);
+    rtc::Optional<uint32_t> bitrate_bps = acked_bitrate.Rate(arrival_time_ms);
+    if (bitrate_bps) {
+      uint32_t y = *bitrate_bps / 1000;
+      float x = static_cast<float>(clock.TimeInMicroseconds() - begin_time_) /
+                1000000;
+      acked_time_series.points.emplace_back(x, y);
+    }
+    if (packet_router.GetAndResetBitrateUpdated() ||
+        clock.TimeInMicroseconds() - last_update_us >= 1e6) {
+      uint32_t y = packet_router.last_bitrate_bps() / 1000;
+      float x = static_cast<float>(clock.TimeInMicroseconds() - begin_time_) /
+                1000000;
+      time_series.points.emplace_back(x, y);
+      last_update_us = clock.TimeInMicroseconds();
+    }
+  }
+  // Add the data set to the plot.
+  plot->AppendTimeSeries(std::move(time_series));
+  plot->AppendTimeSeries(std::move(acked_time_series));
+
+  plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin);
+  plot->SetSuggestedYAxis(0, 10, "Bitrate (kbps)", kBottomMargin, kTopMargin);
+  plot->SetTitle("Simulated receive-side BWE behavior");
 }
 
 void EventLogAnalyzer::CreateNetworkDelayFeedbackGraph(Plot* plot) {
diff --git a/rtc_tools/event_log_visualizer/analyzer.h b/rtc_tools/event_log_visualizer/analyzer.h
index 65ca19bf..5504282 100644
--- a/rtc_tools/event_log_visualizer/analyzer.h
+++ b/rtc_tools/event_log_visualizer/analyzer.h
@@ -90,7 +90,8 @@
 
   void CreateStreamBitrateGraph(PacketDirection desired_direction, Plot* plot);
 
-  void CreateBweSimulationGraph(Plot* plot);
+  void CreateSendSideBweSimulationGraph(Plot* plot);
+  void CreateReceiveSideBweSimulationGraph(Plot* plot);
 
   void CreateNetworkDelayFeedbackGraph(Plot* plot);
   void CreateTimestampGraph(Plot* plot);
diff --git a/rtc_tools/event_log_visualizer/main.cc b/rtc_tools/event_log_visualizer/main.cc
index aa92a7f..fc9f707 100644
--- a/rtc_tools/event_log_visualizer/main.cc
+++ b/rtc_tools/event_log_visualizer/main.cc
@@ -71,6 +71,10 @@
 DEFINE_bool(plot_outgoing_stream_bitrate,
             true,
             "Plot the bitrate used by each outgoing stream.");
+DEFINE_bool(plot_simulated_receiveside_bwe,
+            false,
+            "Run the receive-side bandwidth estimator with the incoming rtp "
+            "packets and plot the resulting estimate.");
 DEFINE_bool(plot_simulated_sendside_bwe,
             false,
             "Run the send-side bandwidth estimator with the outgoing rtp and "
@@ -227,8 +231,11 @@
     analyzer.CreateStreamBitrateGraph(webrtc::PacketDirection::kOutgoingPacket,
                                       collection->AppendNewPlot());
   }
+  if (FLAG_plot_simulated_receiveside_bwe) {
+    analyzer.CreateReceiveSideBweSimulationGraph(collection->AppendNewPlot());
+  }
   if (FLAG_plot_simulated_sendside_bwe) {
-    analyzer.CreateBweSimulationGraph(collection->AppendNewPlot());
+    analyzer.CreateSendSideBweSimulationGraph(collection->AppendNewPlot());
   }
   if (FLAG_plot_network_delay_feedback) {
     analyzer.CreateNetworkDelayFeedbackGraph(collection->AppendNewPlot());
@@ -290,6 +297,7 @@
   FLAG_plot_outgoing_bitrate = setting;
   FLAG_plot_incoming_stream_bitrate = setting;
   FLAG_plot_outgoing_stream_bitrate = setting;
+  FLAG_plot_simulated_receiveside_bwe = setting;
   FLAG_plot_simulated_sendside_bwe = setting;
   FLAG_plot_network_delay_feedback = setting;
   FLAG_plot_fraction_loss_feedback = setting;