Added protobuf message for loss-based BWE events, and wired it up to the send side bandwidth estimator.

BUG=

Review URL: https://codereview.webrtc.org/1411673003

Cr-Commit-Position: refs/heads/master@{#10531}
diff --git a/webrtc/call/call.cc b/webrtc/call/call.cc
index f83d320..39357d5 100644
--- a/webrtc/call/call.cc
+++ b/webrtc/call/call.cc
@@ -168,6 +168,8 @@
       config_.bitrate_config.min_bitrate_bps,
       config_.bitrate_config.start_bitrate_bps,
       config_.bitrate_config.max_bitrate_bps);
+
+  congestion_controller_->GetBitrateController()->SetEventLog(event_log_);
 }
 
 Call::~Call() {
diff --git a/webrtc/call/rtc_event_log.cc b/webrtc/call/rtc_event_log.cc
index 550b556..abc2eb4 100644
--- a/webrtc/call/rtc_event_log.cc
+++ b/webrtc/call/rtc_event_log.cc
@@ -54,6 +54,9 @@
                      const uint8_t* packet,
                      size_t length) override {}
   void LogAudioPlayout(uint32_t ssrc) override {}
+  void LogBwePacketLossEvent(int32_t bitrate,
+                             uint8_t fraction_loss,
+                             int32_t total_packets) override {}
 };
 
 #else  // ENABLE_RTC_EVENT_LOG is defined
@@ -78,6 +81,9 @@
                      const uint8_t* packet,
                      size_t length) override;
   void LogAudioPlayout(uint32_t ssrc) override;
+  void LogBwePacketLossEvent(int32_t bitrate,
+                             uint8_t fraction_loss,
+                             int32_t total_packets) override;
 
  private:
   // Starts logging. This function assumes the file_ has been opened succesfully
@@ -254,8 +260,7 @@
   rtc::CritScope lock(&crit_);
 
   rtclog::Event event;
-  const int64_t timestamp = clock_->TimeInMicroseconds();
-  event.set_timestamp_us(timestamp);
+  event.set_timestamp_us(clock_->TimeInMicroseconds());
   event.set_type(rtclog::Event::VIDEO_RECEIVER_CONFIG_EVENT);
 
   rtclog::VideoReceiveConfig* receiver_config =
@@ -296,8 +301,7 @@
   rtc::CritScope lock(&crit_);
 
   rtclog::Event event;
-  const int64_t timestamp = clock_->TimeInMicroseconds();
-  event.set_timestamp_us(timestamp);
+  event.set_timestamp_us(clock_->TimeInMicroseconds());
   event.set_type(rtclog::Event::VIDEO_SENDER_CONFIG_EVENT);
 
   rtclog::VideoSendConfig* sender_config = event.mutable_video_sender_config();
@@ -348,8 +352,7 @@
 
   rtc::CritScope lock(&crit_);
   rtclog::Event rtp_event;
-  const int64_t timestamp = clock_->TimeInMicroseconds();
-  rtp_event.set_timestamp_us(timestamp);
+  rtp_event.set_timestamp_us(clock_->TimeInMicroseconds());
   rtp_event.set_type(rtclog::Event::RTP_EVENT);
   rtp_event.mutable_rtp_packet()->set_incoming(incoming);
   rtp_event.mutable_rtp_packet()->set_type(ConvertMediaType(media_type));
@@ -364,8 +367,7 @@
                                     size_t length) {
   rtc::CritScope lock(&crit_);
   rtclog::Event rtcp_event;
-  const int64_t timestamp = clock_->TimeInMicroseconds();
-  rtcp_event.set_timestamp_us(timestamp);
+  rtcp_event.set_timestamp_us(clock_->TimeInMicroseconds());
   rtcp_event.set_type(rtclog::Event::RTCP_EVENT);
   rtcp_event.mutable_rtcp_packet()->set_incoming(incoming);
   rtcp_event.mutable_rtcp_packet()->set_type(ConvertMediaType(media_type));
@@ -376,21 +378,33 @@
 void RtcEventLogImpl::LogAudioPlayout(uint32_t ssrc) {
   rtc::CritScope lock(&crit_);
   rtclog::Event event;
-  const int64_t timestamp = clock_->TimeInMicroseconds();
-  event.set_timestamp_us(timestamp);
+  event.set_timestamp_us(clock_->TimeInMicroseconds());
   event.set_type(rtclog::Event::AUDIO_PLAYOUT_EVENT);
   auto playout_event = event.mutable_audio_playout_event();
   playout_event->set_local_ssrc(ssrc);
   HandleEvent(&event);
 }
 
+void RtcEventLogImpl::LogBwePacketLossEvent(int32_t bitrate,
+                                            uint8_t fraction_loss,
+                                            int32_t total_packets) {
+  rtc::CritScope lock(&crit_);
+  rtclog::Event event;
+  event.set_timestamp_us(clock_->TimeInMicroseconds());
+  event.set_type(rtclog::Event::BWE_PACKET_LOSS_EVENT);
+  auto bwe_event = event.mutable_bwe_packet_loss_event();
+  bwe_event->set_bitrate(bitrate);
+  bwe_event->set_fraction_loss(fraction_loss);
+  bwe_event->set_total_packets(total_packets);
+  HandleEvent(&event);
+}
+
 void RtcEventLogImpl::StopLoggingLocked() {
   if (currently_logging_) {
     currently_logging_ = false;
     // Create a LogEnd event
     rtclog::Event event;
-    int64_t timestamp = clock_->TimeInMicroseconds();
-    event.set_timestamp_us(timestamp);
+    event.set_timestamp_us(clock_->TimeInMicroseconds());
     event.set_type(rtclog::Event::LOG_END);
     // Store the event and close the file
     RTC_DCHECK(file_->Open());
diff --git a/webrtc/call/rtc_event_log.h b/webrtc/call/rtc_event_log.h
index 85d7525..489687a 100644
--- a/webrtc/call/rtc_event_log.h
+++ b/webrtc/call/rtc_event_log.h
@@ -77,6 +77,11 @@
   // Logs an audio playout event
   virtual void LogAudioPlayout(uint32_t ssrc) = 0;
 
+  // Logs a bitrate update from the bandwidth estimator based on packet loss.
+  virtual void LogBwePacketLossEvent(int32_t bitrate,
+                                     uint8_t fraction_loss,
+                                     int32_t total_packets) = 0;
+
   // Reads an RtcEventLog file and returns true when reading was successful.
   // The result is stored in the given EventStream object.
   static bool ParseRtcEventLog(const std::string& file_name,
diff --git a/webrtc/call/rtc_event_log.proto b/webrtc/call/rtc_event_log.proto
index 6bdea7b..e8ec99d 100644
--- a/webrtc/call/rtc_event_log.proto
+++ b/webrtc/call/rtc_event_log.proto
@@ -34,10 +34,12 @@
     RTP_EVENT = 3;
     RTCP_EVENT = 4;
     AUDIO_PLAYOUT_EVENT = 5;
-    VIDEO_RECEIVER_CONFIG_EVENT = 6;
-    VIDEO_SENDER_CONFIG_EVENT = 7;
-    AUDIO_RECEIVER_CONFIG_EVENT = 8;
-    AUDIO_SENDER_CONFIG_EVENT = 9;
+    BWE_PACKET_LOSS_EVENT = 6;
+    BWE_PACKET_DELAY_EVENT = 7;
+    VIDEO_RECEIVER_CONFIG_EVENT = 8;
+    VIDEO_SENDER_CONFIG_EVENT = 9;
+    AUDIO_RECEIVER_CONFIG_EVENT = 10;
+    AUDIO_SENDER_CONFIG_EVENT = 11;
   }
 
   // required - Indicates the type of this event
@@ -52,17 +54,20 @@
   // optional - but required if type == AUDIO_PLAYOUT_EVENT
   optional AudioPlayoutEvent audio_playout_event = 5;
 
+  // optional - but required if type == BWE_PACKET_LOSS_EVENT
+  optional BwePacketLossEvent bwe_packet_loss_event = 6;
+
   // optional - but required if type == VIDEO_RECEIVER_CONFIG_EVENT
-  optional VideoReceiveConfig video_receiver_config = 6;
+  optional VideoReceiveConfig video_receiver_config = 8;
 
   // optional - but required if type == VIDEO_SENDER_CONFIG_EVENT
-  optional VideoSendConfig video_sender_config = 7;
+  optional VideoSendConfig video_sender_config = 9;
 
   // optional - but required if type == AUDIO_RECEIVER_CONFIG_EVENT
-  optional AudioReceiveConfig audio_receiver_config = 8;
+  optional AudioReceiveConfig audio_receiver_config = 10;
 
   // optional - but required if type == AUDIO_SENDER_CONFIG_EVENT
-  optional AudioSendConfig audio_sender_config = 9;
+  optional AudioSendConfig audio_sender_config = 11;
 }
 
 
@@ -99,6 +104,19 @@
   optional uint32 local_ssrc = 2;
 }
 
+message BwePacketLossEvent {
+  // required - Bandwidth estimate (in bps) after the update.
+  optional int32 bitrate = 1;
+
+  // required - Fraction of lost packets since last receiver report
+  // computed as floor( 256 * (#lost_packets / #total_packets) ).
+  // The possible values range from 0 to 255.
+  optional uint32 fraction_loss = 2;
+
+  // TODO(terelius): Is this really needed? Remove or make optional?
+  // required - Total number of packets that the BWE update is based on.
+  optional int32 total_packets = 3;
+}
 
 // TODO(terelius): Video and audio streams could in principle share SSRC,
 // so identifying a stream based only on SSRC might not work.
@@ -142,7 +160,7 @@
   optional string name = 1;
 
   // required
-  optional sint32 payload_type = 2;
+  optional int32 payload_type = 2;
 }
 
 
@@ -152,7 +170,7 @@
   optional string name = 1;
 
   // required
-  optional sint32 id = 2;
+  optional int32 id = 2;
 }
 
 
@@ -163,13 +181,13 @@
   optional uint32 rtx_ssrc = 1;
 
   // required - Payload type to use for the RTX stream.
-  optional sint32 rtx_payload_type = 2;
+  optional int32 rtx_payload_type = 2;
 }
 
 
 message RtxMap {
   // required
-  optional sint32 payload_type = 1;
+  optional int32 payload_type = 1;
 
   // required
   optional RtxConfig config = 2;
@@ -189,7 +207,7 @@
   repeated uint32 rtx_ssrcs = 3;
 
   // required if rtx_ssrcs is used - Payload type for retransmitted packets.
-  optional sint32 rtx_payload_type = 4;
+  optional int32 rtx_payload_type = 4;
 
   // required - Canonical end-point identifier.
   optional string c_name = 5;
@@ -205,7 +223,7 @@
   optional string name = 1;
 
   // required
-  optional sint32 payload_type = 2;
+  optional int32 payload_type = 2;
 }
 
 
diff --git a/webrtc/call/rtc_event_log_unittest.cc b/webrtc/call/rtc_event_log_unittest.cc
index a4fdd13..ff5abad 100644
--- a/webrtc/call/rtc_event_log_unittest.cc
+++ b/webrtc/call/rtc_event_log_unittest.cc
@@ -276,6 +276,21 @@
   EXPECT_EQ(ssrc, playout_event.local_ssrc());
 }
 
+void VerifyBweLossEvent(const rtclog::Event& event,
+                        int32_t bitrate,
+                        uint8_t fraction_loss,
+                        int32_t total_packets) {
+  ASSERT_TRUE(IsValidBasicEvent(event));
+  ASSERT_EQ(rtclog::Event::BWE_PACKET_LOSS_EVENT, event.type());
+  const rtclog::BwePacketLossEvent& bwe_event = event.bwe_packet_loss_event();
+  ASSERT_TRUE(bwe_event.has_bitrate());
+  EXPECT_EQ(bitrate, bwe_event.bitrate());
+  ASSERT_TRUE(bwe_event.has_fraction_loss());
+  EXPECT_EQ(fraction_loss, bwe_event.fraction_loss());
+  ASSERT_TRUE(bwe_event.has_total_packets());
+  EXPECT_EQ(total_packets, bwe_event.total_packets());
+}
+
 void VerifyLogStartEvent(const rtclog::Event& event) {
   ASSERT_TRUE(IsValidBasicEvent(event));
   EXPECT_EQ(rtclog::Event::LOG_START, event.type());
@@ -398,15 +413,18 @@
 void LogSessionAndReadBack(size_t rtp_count,
                            size_t rtcp_count,
                            size_t playout_count,
+                           size_t bwe_loss_count,
                            uint32_t extensions_bitvector,
                            uint32_t csrcs_count,
                            unsigned int random_seed) {
   ASSERT_LE(rtcp_count, rtp_count);
   ASSERT_LE(playout_count, rtp_count);
+  ASSERT_LE(bwe_loss_count, rtp_count);
   std::vector<rtc::Buffer> rtp_packets;
   std::vector<rtc::Buffer> rtcp_packets;
   std::vector<size_t> rtp_header_sizes;
   std::vector<uint32_t> playout_ssrcs;
+  std::vector<std::pair<int32_t, uint8_t> > bwe_loss_updates;
 
   VideoReceiveStream::Config receiver_config(nullptr);
   VideoSendStream::Config sender_config(nullptr);
@@ -431,6 +449,10 @@
   for (size_t i = 0; i < playout_count; i++) {
     playout_ssrcs.push_back(static_cast<uint32_t>(rand()));
   }
+  // Create bwe_loss_count random bitrate updates for BwePacketLoss.
+  for (size_t i = 0; i < bwe_loss_count; i++) {
+    bwe_loss_updates.push_back(std::pair<int32_t, uint8_t>(rand(), rand()));
+  }
   // Create configurations for the video streams.
   GenerateVideoReceiveConfig(extensions_bitvector, &receiver_config);
   GenerateVideoSendConfig(extensions_bitvector, &sender_config);
@@ -448,7 +470,9 @@
     rtc::scoped_ptr<RtcEventLog> log_dumper(RtcEventLog::Create());
     log_dumper->LogVideoReceiveStreamConfig(receiver_config);
     log_dumper->LogVideoSendStreamConfig(sender_config);
-    size_t rtcp_index = 1, playout_index = 1;
+    size_t rtcp_index = 1;
+    size_t playout_index = 1;
+    size_t bwe_loss_index = 1;
     for (size_t i = 1; i <= rtp_count; i++) {
       log_dumper->LogRtpHeader(
           (i % 2 == 0),  // Every second packet is incoming.
@@ -466,6 +490,12 @@
         log_dumper->LogAudioPlayout(playout_ssrcs[playout_index - 1]);
         playout_index++;
       }
+      if (i * bwe_loss_count >= bwe_loss_index * rtp_count) {
+        log_dumper->LogBwePacketLossEvent(
+            bwe_loss_updates[bwe_loss_index - 1].first,
+            bwe_loss_updates[bwe_loss_index - 1].second, i);
+        bwe_loss_index++;
+      }
       if (i == rtp_count / 2) {
         log_dumper->StartLogging(temp_filename, 10000000);
       }
@@ -480,12 +510,15 @@
   // Verify that what we read back from the event log is the same as
   // what we wrote down. For RTCP we log the full packets, but for
   // RTP we should only log the header.
-  const int event_count =
-      config_count + playout_count + rtcp_count + rtp_count + 1;
+  const int event_count = config_count + playout_count + bwe_loss_count +
+                          rtcp_count + rtp_count + 1;
   EXPECT_EQ(event_count, parsed_stream.stream_size());
   VerifyReceiveStreamConfig(parsed_stream.stream(0), receiver_config);
   VerifySendStreamConfig(parsed_stream.stream(1), sender_config);
-  size_t event_index = config_count, rtcp_index = 1, playout_index = 1;
+  size_t event_index = config_count;
+  size_t rtcp_index = 1;
+  size_t playout_index = 1;
+  size_t bwe_loss_index = 1;
   for (size_t i = 1; i <= rtp_count; i++) {
     VerifyRtpEvent(parsed_stream.stream(event_index),
                    (i % 2 == 0),  // Every second packet is incoming.
@@ -508,6 +541,13 @@
       event_index++;
       playout_index++;
     }
+    if (i * bwe_loss_count >= bwe_loss_index * rtp_count) {
+      VerifyBweLossEvent(parsed_stream.stream(event_index),
+                         bwe_loss_updates[bwe_loss_index - 1].first,
+                         bwe_loss_updates[bwe_loss_index - 1].second, i);
+      event_index++;
+      bwe_loss_index++;
+    }
     if (i == rtp_count / 2) {
       VerifyLogStartEvent(parsed_stream.stream(event_index));
       event_index++;
@@ -519,10 +559,11 @@
 }
 
 TEST(RtcEventLogTest, LogSessionAndReadBack) {
-  // Log 5 RTP, 2 RTCP, and 0 playout events with no header extensions or CSRCS.
-  LogSessionAndReadBack(5, 2, 0, 0, 0, 321);
+  // Log 5 RTP, 2 RTCP, 0 playout events and 0 BWE events
+  // with no header extensions or CSRCS.
+  LogSessionAndReadBack(5, 2, 0, 0, 0, 0, 321);
 
-  // Enable AbsSendTime and TransportSequenceNumbers
+  // Enable AbsSendTime and TransportSequenceNumbers.
   uint32_t extensions = 0;
   for (uint32_t i = 0; i < kNumExtensions; i++) {
     if (kExtensionTypes[i] == RTPExtensionType::kRtpExtensionAbsoluteSendTime ||
@@ -531,19 +572,20 @@
       extensions |= 1u << i;
     }
   }
-  LogSessionAndReadBack(8, 2, 0, extensions, 0, 3141592653u);
+  LogSessionAndReadBack(8, 2, 0, 0, extensions, 0, 3141592653u);
 
-  extensions = (1u << kNumExtensions) - 1;  // Enable all header extensions
-  LogSessionAndReadBack(9, 2, 3, extensions, 2, 2718281828u);
+  extensions = (1u << kNumExtensions) - 1;  // Enable all header extensions.
+  LogSessionAndReadBack(9, 2, 3, 2, extensions, 2, 2718281828u);
 
   // Try all combinations of header extensions and up to 2 CSRCS.
   for (extensions = 0; extensions < (1u << kNumExtensions); extensions++) {
     for (uint32_t csrcs_count = 0; csrcs_count < 3; csrcs_count++) {
       LogSessionAndReadBack(5 + extensions,   // Number of RTP packets.
                             2 + csrcs_count,  // Number of RTCP packets.
-                            3 + csrcs_count,  // Number of playout events
-                            extensions,       // Bit vector choosing extensions
-                            csrcs_count,      // Number of contributing sources
+                            3 + csrcs_count,  // Number of playout events.
+                            1 + csrcs_count,  // Number of BWE loss events.
+                            extensions,       // Bit vector choosing extensions.
+                            csrcs_count,      // Number of contributing sources.
                             rand());
     }
   }
diff --git a/webrtc/modules/bitrate_controller/bitrate_controller_impl.cc b/webrtc/modules/bitrate_controller/bitrate_controller_impl.cc
index d779562..f8fd2bb 100644
--- a/webrtc/modules/bitrate_controller/bitrate_controller_impl.cc
+++ b/webrtc/modules/bitrate_controller/bitrate_controller_impl.cc
@@ -129,6 +129,11 @@
   MaybeTriggerOnNetworkChanged();
 }
 
+void BitrateControllerImpl::SetEventLog(RtcEventLog* event_log) {
+  rtc::CritScope cs(&critsect_);
+  bandwidth_estimation_.SetEventLog(event_log);
+}
+
 void BitrateControllerImpl::OnReceivedEstimatedBitrate(uint32_t bitrate) {
   {
     rtc::CritScope cs(&critsect_);
diff --git a/webrtc/modules/bitrate_controller/bitrate_controller_impl.h b/webrtc/modules/bitrate_controller/bitrate_controller_impl.h
index a33a0e6..b601899 100644
--- a/webrtc/modules/bitrate_controller/bitrate_controller_impl.h
+++ b/webrtc/modules/bitrate_controller/bitrate_controller_impl.h
@@ -41,6 +41,8 @@
 
   void SetReservedBitrate(uint32_t reserved_bitrate_bps) override;
 
+  void SetEventLog(RtcEventLog* event_log) override;
+
   int64_t TimeUntilNextProcess() override;
   int32_t Process() override;
 
diff --git a/webrtc/modules/bitrate_controller/include/bitrate_controller.h b/webrtc/modules/bitrate_controller/include/bitrate_controller.h
index 5b20287..d1eca8e 100644
--- a/webrtc/modules/bitrate_controller/include/bitrate_controller.h
+++ b/webrtc/modules/bitrate_controller/include/bitrate_controller.h
@@ -23,6 +23,7 @@
 namespace webrtc {
 
 class CriticalSectionWrapper;
+class RtcEventLog;
 struct PacketInfo;
 
 class BitrateObserver {
@@ -56,6 +57,8 @@
   virtual void SetStartBitrate(int start_bitrate_bps) = 0;
   virtual void SetMinMaxBitrate(int min_bitrate_bps, int max_bitrate_bps) = 0;
 
+  virtual void SetEventLog(RtcEventLog* event_log) = 0;
+
   // Gets the available payload bandwidth in bits per second. Note that
   // this bandwidth excludes packet headers.
   virtual bool AvailableBandwidth(uint32_t* bandwidth) const = 0;
diff --git a/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc b/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc
index 9fa7b0d..c1c10e8 100644
--- a/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc
+++ b/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc
@@ -16,6 +16,7 @@
 #include "webrtc/system_wrappers/include/field_trial.h"
 #include "webrtc/system_wrappers/include/logging.h"
 #include "webrtc/system_wrappers/include/metrics.h"
+#include "webrtc/call/rtc_event_log.h"
 
 namespace webrtc {
 namespace {
@@ -59,7 +60,8 @@
       initially_lost_packets_(0),
       bitrate_at_2_seconds_kbps_(0),
       uma_update_state_(kNoUpdate),
-      rampup_uma_stats_updated_(kNumUmaRampupMetrics, false) {}
+      rampup_uma_stats_updated_(kNumUmaRampupMetrics, false),
+      event_log_(nullptr) {}
 
 SendSideBandwidthEstimation::~SendSideBandwidthEstimation() {}
 
@@ -206,6 +208,11 @@
       // rates).
       bitrate_ += 1000;
 
+      if (event_log_) {
+        event_log_->LogBwePacketLossEvent(
+            bitrate_, last_fraction_loss_,
+            expected_packets_since_last_loss_update_);
+      }
     } else if (last_fraction_loss_ <= 26) {
       // Loss between 2% - 10%: Do nothing.
     } else {
@@ -224,6 +231,11 @@
             512.0);
         has_decreased_since_last_fraction_loss_ = true;
       }
+      if (event_log_) {
+        event_log_->LogBwePacketLossEvent(
+            bitrate_, last_fraction_loss_,
+            expected_packets_since_last_loss_update_);
+      }
     }
   }
   bitrate_ = CapBitrateToThresholds(now_ms, bitrate_);
@@ -274,4 +286,9 @@
   }
   return bitrate;
 }
+
+void SendSideBandwidthEstimation::SetEventLog(RtcEventLog* event_log) {
+  event_log_ = event_log;
+}
+
 }  // namespace webrtc
diff --git a/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h b/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h
index baf8857..7ffb42c 100644
--- a/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h
+++ b/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h
@@ -19,6 +19,9 @@
 #include "webrtc/system_wrappers/include/critical_section_wrapper.h"
 
 namespace webrtc {
+
+class RtcEventLog;
+
 class SendSideBandwidthEstimation {
  public:
   SendSideBandwidthEstimation();
@@ -42,6 +45,8 @@
   void SetMinMaxBitrate(int min_bitrate, int max_bitrate);
   int GetMinBitrate() const;
 
+  void SetEventLog(RtcEventLog* event_log);
+
  private:
   enum UmaState { kNoUpdate, kFirstDone, kDone };
 
@@ -81,6 +86,7 @@
   int bitrate_at_2_seconds_kbps_;
   UmaState uma_update_state_;
   std::vector<bool> rampup_uma_stats_updated_;
+  RtcEventLog* event_log_;
 };
 }  // namespace webrtc
 #endif  // WEBRTC_MODULES_BITRATE_CONTROLLER_SEND_SIDE_BANDWIDTH_ESTIMATION_H_