Fix issue with zero rtt reports when using FlexFEC and add perf test.

BUG=webrtc:7938

Review-Url: https://codereview.webrtc.org/2966153002
Cr-Commit-Position: refs/heads/master@{#18898}
diff --git a/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc b/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc
index dc14905..416afbe 100644
--- a/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc
+++ b/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc
@@ -209,8 +209,10 @@
   if (first_report_time_ms_ == -1)
     first_report_time_ms_ = now_ms;
 
-  // Update RTT.
-  last_round_trip_time_ms_ = rtt;
+  // Update RTT if we were able to compute an RTT based on this RTCP.
+  // FlexFEC doesn't send RTCP SR, which means we won't be able to compute RTT.
+  if (rtt > 0)
+    last_round_trip_time_ms_ = rtt;
 
   // Check sequence number diff and weight loss report
   if (number_of_packets > 0) {
diff --git a/webrtc/video/full_stack_tests.cc b/webrtc/video/full_stack_tests.cc
index 4a7334f..e15b41a 100644
--- a/webrtc/video/full_stack_tests.cc
+++ b/webrtc/video/full_stack_tests.cc
@@ -136,6 +136,34 @@
   RunTest(foreman_cif);
 }
 
+TEST_F(FullStackTest, ForemanCif500kbpsPlr3Flexfec) {
+  VideoQualityTest::Params foreman_cif;
+  foreman_cif.call.send_side_bwe = true;
+  foreman_cif.video = {true,  352,          288, 30, 30000, 500000, 2000000,
+                       false, "VP8",        1,   0,  0,     false,  true,
+                       "",    "foreman_cif"};
+  foreman_cif.analyzer = {"foreman_cif_500kbps_delay_50_0_plr_3_flexfec", 0.0,
+                          0.0, kFullStackTestDurationSecs};
+  foreman_cif.pipe.loss_percent = 3;
+  foreman_cif.pipe.link_capacity_kbps = 500;
+  foreman_cif.pipe.queue_delay_ms = 50;
+  RunTest(foreman_cif);
+}
+
+TEST_F(FullStackTest, ForemanCif500kbpsPlr3Ulpfec) {
+  VideoQualityTest::Params foreman_cif;
+  foreman_cif.call.send_side_bwe = true;
+  foreman_cif.video = {true,  352,          288, 30, 30000, 500000, 2000000,
+                       false, "VP8",        1,   0,  0,     true,   false,
+                       "",    "foreman_cif"};
+  foreman_cif.analyzer = {"foreman_cif_500kbps_delay_50_0_plr_3_ulpfec", 0.0,
+                          0.0, kFullStackTestDurationSecs};
+  foreman_cif.pipe.loss_percent = 3;
+  foreman_cif.pipe.link_capacity_kbps = 500;
+  foreman_cif.pipe.queue_delay_ms = 50;
+  RunTest(foreman_cif);
+}
+
 #if defined(WEBRTC_USE_H264)
 TEST_F(FullStackTest, ForemanCifWithoutPacketlossH264) {
   // TODO(pbos): Decide on psnr/ssim thresholds for foreman_cif.
diff --git a/webrtc/video/video_quality_test.cc b/webrtc/video/video_quality_test.cc
index 5e99b50..1ae2e16 100644
--- a/webrtc/video/video_quality_test.cc
+++ b/webrtc/video/video_quality_test.cc
@@ -155,6 +155,7 @@
                 Clock* clock)
       : transport_(transport),
         receiver_(nullptr),
+        call_(nullptr),
         send_stream_(nullptr),
         receive_stream_(nullptr),
         captured_frame_forwarder_(this, clock),
@@ -168,6 +169,7 @@
         selected_tl_(selected_tl),
         pre_encode_proxy_(this),
         encode_timing_proxy_(this),
+        last_fec_bytes_(0),
         frames_to_process_(duration_frames),
         frames_recorded_(0),
         frames_processed_(0),
@@ -230,6 +232,12 @@
     video_capturer->AddOrUpdateSink(InputInterface(), wants);
   }
 
+  void SetCall(Call* call) {
+    rtc::CritScope lock(&crit_);
+    RTC_DCHECK(!call_);
+    call_ = call;
+  }
+
   void SetSendStream(VideoSendStream* stream) {
     rtc::CritScope lock(&crit_);
     RTC_DCHECK(!send_stream_);
@@ -650,6 +658,9 @@
     while (!done_.Wait(kSendStatsPollingIntervalMs)) {
       rtc::CritScope crit(&comparison_lock_);
 
+      Call::Stats call_stats = call_->GetStats();
+      send_bandwidth_bps_.AddSample(call_stats.send_bandwidth_bps);
+
       VideoSendStream::Stats send_stats = send_stream_->GetStats();
       // It's not certain that we yet have estimates for any of these stats.
       // Check that they are positive before mixing them in.
@@ -661,6 +672,13 @@
         encode_usage_percent_.AddSample(send_stats.encode_usage_percent);
       if (send_stats.media_bitrate_bps > 0)
         media_bitrate_bps_.AddSample(send_stats.media_bitrate_bps);
+      size_t fec_bytes = 0;
+      for (auto kv : send_stats.substreams) {
+        fec_bytes += kv.second.rtp_stats.fec.payload_bytes +
+                     kv.second.rtp_stats.fec.padding_bytes;
+      }
+      fec_bitrate_bps_.AddSample((fec_bytes - last_fec_bytes_) * 8);
+      last_fec_bytes_ = fec_bytes;
 
       if (receive_stream_ != nullptr) {
         VideoReceiveStream::Stats receive_stats = receive_stream_->GetStats();
@@ -764,6 +782,8 @@
     PrintResult("encode_frame_rate", encode_frame_rate_, " fps");
     PrintResult("encode_time", encode_time_ms_, " ms");
     PrintResult("media_bitrate", media_bitrate_bps_, " bps");
+    PrintResult("fec_bitrate", fec_bitrate_bps_, " bps");
+    PrintResult("send_bandwidth", send_bandwidth_bps_, " bps");
 
     if (receive_stream_ != nullptr) {
       PrintResult("decode_time", decode_time_ms_, " ms");
@@ -969,6 +989,7 @@
     frames_.push_back(video_frame);
   }
 
+  Call* call_;
   VideoSendStream* send_stream_;
   VideoReceiveStream* receive_stream_;
   CapturedFrameForwarder captured_frame_forwarder_;
@@ -997,8 +1018,11 @@
   test::Statistics decode_time_ms_ GUARDED_BY(comparison_lock_);
   test::Statistics decode_time_max_ms_ GUARDED_BY(comparison_lock_);
   test::Statistics media_bitrate_bps_ GUARDED_BY(comparison_lock_);
+  test::Statistics fec_bitrate_bps_ GUARDED_BY(comparison_lock_);
+  test::Statistics send_bandwidth_bps_ GUARDED_BY(comparison_lock_);
   test::Statistics memory_usage_ GUARDED_BY(comparison_lock_);
 
+  size_t last_fec_bytes_;
 
   const int frames_to_process_;
   int frames_recorded_;
@@ -1717,6 +1741,7 @@
       kSendRtxSsrcs[params_.ss.selected_stream],
       static_cast<size_t>(params_.ss.selected_stream), params.ss.selected_sl,
       params_.video.selected_tl, is_quick_test_enabled, clock_);
+  analyzer.SetCall(sender_call_.get());
   analyzer.SetReceiver(receiver_call_->Receiver());
   send_transport.SetReceiver(&analyzer);
   recv_transport.SetReceiver(sender_call_->Receiver());