Makes WebRTC-Pacer-SmallFirstProbePacket default enabled.

This is expected to yield slightly higher bandwidth estimates when
probing is used, since it reduces a bias in how packet sizes are counted.

Bug: webrtc:11780
Change-Id: I6a4a3af0c50670d248dbe043a4d9da60915e3699
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/187491
Commit-Queue: Erik Språng <sprang@webrtc.org>
Reviewed-by: Sebastian Jansson <srte@webrtc.org>
Reviewed-by: Philip Eliasson <philipel@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32394}
diff --git a/modules/congestion_controller/goog_cc/goog_cc_network_control_unittest.cc b/modules/congestion_controller/goog_cc/goog_cc_network_control_unittest.cc
index 361da92..c12681c 100644
--- a/modules/congestion_controller/goog_cc/goog_cc_network_control_unittest.cc
+++ b/modules/congestion_controller/goog_cc/goog_cc_network_control_unittest.cc
@@ -573,7 +573,7 @@
   // trial, we have worse behavior.
   DataRate average_bitrate =
       AverageBitrateAfterCrossInducedLoss("googcc_unit/no_cross_loss_based");
-  RTC_DCHECK_LE(average_bitrate, DataRate::KilobitsPerSec(650));
+  RTC_DCHECK_LE(average_bitrate, DataRate::KilobitsPerSec(625));
 }
 
 TEST_F(GoogCcNetworkControllerTest,
@@ -583,7 +583,7 @@
   ScopedFieldTrials trial("WebRTC-Bwe-LossBasedControl/Enabled/");
   DataRate average_bitrate =
       AverageBitrateAfterCrossInducedLoss("googcc_unit/cross_loss_based");
-  RTC_DCHECK_GE(average_bitrate, DataRate::KilobitsPerSec(750));
+  RTC_DCHECK_GE(average_bitrate, DataRate::KilobitsPerSec(725));
 }
 
 TEST_F(GoogCcNetworkControllerTest, LossBasedEstimatorCapsRateAtModerateLoss) {
diff --git a/modules/pacing/pacing_controller.cc b/modules/pacing/pacing_controller.cc
index 107316d..133c97f 100644
--- a/modules/pacing/pacing_controller.cc
+++ b/modules/pacing/pacing_controller.cc
@@ -112,7 +112,7 @@
           IsEnabled(*field_trials_, "WebRTC-Pacer-PadInSilence")),
       pace_audio_(IsEnabled(*field_trials_, "WebRTC-Pacer-BlockAudio")),
       small_first_probe_packet_(
-          IsEnabled(*field_trials_, "WebRTC-Pacer-SmallFirstProbePacket")),
+          !IsDisabled(*field_trials_, "WebRTC-Pacer-SmallFirstProbePacket")),
       ignore_transport_overhead_(
           IsEnabled(*field_trials_, "WebRTC-Pacer-IgnoreTransportOverhead")),
       padding_target_duration_(GetDynamicPaddingTarget(*field_trials_)),
diff --git a/modules/pacing/pacing_controller_unittest.cc b/modules/pacing/pacing_controller_unittest.cc
index 7340282..a953d5b 100644
--- a/modules/pacing/pacing_controller_unittest.cc
+++ b/modules/pacing/pacing_controller_unittest.cc
@@ -1429,7 +1429,8 @@
   EXPECT_NEAR((packets_sent - 1) * kPacketSize * 8000 /
                   (clock_.TimeInMilliseconds() - start),
               kFirstClusterRate.bps(), kProbingErrorMargin.bps());
-  EXPECT_EQ(0, packet_sender.padding_sent());
+  // Probing always starts with a small padding packet.
+  EXPECT_EQ(1, packet_sender.padding_sent());
 
   clock_.AdvanceTime(TimeUntilNextProcess());
   start = clock_.TimeInMilliseconds();
@@ -1738,7 +1739,6 @@
 }
 
 TEST_P(PacingControllerTest, SmallFirstProbePacket) {
-  ScopedFieldTrials trial("WebRTC-Pacer-SmallFirstProbePacket/Enabled/");
   MockPacketSender callback;
   pacer_ = std::make_unique<PacingController>(&clock_, &callback, nullptr,
                                               nullptr, GetParam());
diff --git a/modules/pacing/task_queue_paced_sender_unittest.cc b/modules/pacing/task_queue_paced_sender_unittest.cc
index 7fe21d1..d389e27 100644
--- a/modules/pacing/task_queue_paced_sender_unittest.cc
+++ b/modules/pacing/task_queue_paced_sender_unittest.cc
@@ -469,6 +469,7 @@
 
     // Expected size for each probe in a cluster is twice the expected bits
     // sent during min_probe_delta.
+    // Expect one additional call since probe always starts with a small
     const TimeDelta kProbeTimeDelta = TimeDelta::Millis(2);
     const DataSize kProbeSize = kProbeRate * kProbeTimeDelta;
     const size_t kNumPacketsInProbe =
@@ -477,7 +478,7 @@
         packet_router,
         SendPacket(_, ::testing::Field(&PacedPacketInfo::probe_cluster_id,
                                        kProbeClusterId)))
-        .Times(kNumPacketsInProbe);
+        .Times(kNumPacketsInProbe + 1);
 
     pacer.EnqueuePackets(
         GeneratePackets(RtpPacketMediaType::kVideo, kNumPacketsInProbe));
@@ -546,7 +547,10 @@
     time_controller.AdvanceTime(kMinProbeDelta);
 
     // Verify the amount of probing data sent.
-    EXPECT_EQ(data_sent, kProbingRate * TimeDelta::Millis(1));
+    // Probe always starts with a small (1 byte) padding packet that's not
+    // counted into the probe rate here.
+    EXPECT_EQ(data_sent,
+              kProbingRate * TimeDelta::Millis(1) + DataSize::Bytes(1));
   }
 }  // namespace test
 }  // namespace webrtc
diff --git a/test/scenario/scenario_config.h b/test/scenario/scenario_config.h
index c9d636a..c7320e9 100644
--- a/test/scenario/scenario_config.h
+++ b/test/scenario/scenario_config.h
@@ -129,6 +129,7 @@
     using Codec = VideoCodecType;
     Codec codec = Codec::kVideoCodecGeneric;
     absl::optional<DataRate> max_data_rate;
+    absl::optional<DataRate> min_data_rate;
     absl::optional<int> max_framerate;
     // Counted in frame count.
     absl::optional<int> key_frame_interval = 3000;
@@ -149,6 +150,7 @@
 
     DegradationPreference degradation_preference =
         DegradationPreference::MAINTAIN_FRAMERATE;
+    bool suspend_below_min_bitrate = false;
   } encoder;
   struct Stream {
     Stream();
diff --git a/test/scenario/video_stream.cc b/test/scenario/video_stream.cc
index 4284c19..3c368861 100644
--- a/test/scenario/video_stream.cc
+++ b/test/scenario/video_stream.cc
@@ -265,6 +265,7 @@
   if (config.encoder.max_framerate) {
     for (auto& layer : encoder_config.simulcast_layers) {
       layer.max_framerate = *config.encoder.max_framerate;
+      layer.min_bitrate_bps = config.encoder.min_data_rate->bps_or(-1);
     }
   }
 
@@ -412,6 +413,8 @@
   send_config.encoder_settings.encoder_factory = encoder_factory_.get();
   send_config.encoder_settings.bitrate_allocator_factory =
       bitrate_allocator_factory_.get();
+  send_config.suspend_below_min_bitrate =
+      config.encoder.suspend_below_min_bitrate;
 
   sender_->SendTask([&] {
     if (config.stream.fec_controller_factory) {
diff --git a/test/scenario/video_stream_unittest.cc b/test/scenario/video_stream_unittest.cc
index 19735a8..52be3f8 100644
--- a/test/scenario/video_stream_unittest.cc
+++ b/test/scenario/video_stream_unittest.cc
@@ -244,5 +244,69 @@
   EXPECT_GT(num_vga_frames_, 0u);
 }
 
+TEST(VideoStreamTest, SuspendsBelowMinBitrate) {
+  const DataRate kMinVideoBitrate = DataRate::KilobitsPerSec(30);
+
+  // Declared before scenario to avoid use after free.
+  std::atomic<Timestamp> last_frame_timestamp(Timestamp::MinusInfinity());
+
+  Scenario s;
+  NetworkSimulationConfig net_config;
+  net_config.bandwidth = kMinVideoBitrate * 4;
+  net_config.delay = TimeDelta::Millis(10);
+  auto* client = s.CreateClient("send", [&](CallClientConfig* c) {
+    // Min transmit rate needs to be lower than kMinVideoBitrate for this test
+    // to make sense.
+    c->transport.rates.min_rate = kMinVideoBitrate / 2;
+    c->transport.rates.start_rate = kMinVideoBitrate;
+    c->transport.rates.max_rate = kMinVideoBitrate * 2;
+  });
+  auto send_net = s.CreateMutableSimulationNode(
+      [&](NetworkSimulationConfig* c) { *c = net_config; });
+  auto ret_net = {s.CreateSimulationNode(net_config)};
+  auto* route =
+      s.CreateRoutes(client, {send_net->node()},
+                     s.CreateClient("return", CallClientConfig()), ret_net);
+
+  s.CreateVideoStream(route->forward(), [&](VideoStreamConfig* c) {
+    c->hooks.frame_pair_handlers = {[&](const VideoFramePair& pair) {
+      if (pair.repeated == 0) {
+        last_frame_timestamp = pair.capture_time;
+      }
+    }};
+    c->source.framerate = 30;
+    c->source.generator.width = 320;
+    c->source.generator.height = 180;
+    c->encoder.implementation = CodecImpl::kFake;
+    c->encoder.codec = Codec::kVideoCodecVP8;
+    c->encoder.min_data_rate = kMinVideoBitrate;
+    c->encoder.suspend_below_min_bitrate = true;
+    c->stream.pad_to_rate = kMinVideoBitrate;
+  });
+
+  // Run for a few seconds, check we have received at least one frame.
+  s.RunFor(TimeDelta::Seconds(2));
+  EXPECT_TRUE(last_frame_timestamp.load().IsFinite());
+
+  // Degrade network to below min bitrate.
+  send_net->UpdateConfig([&](NetworkSimulationConfig* c) {
+    c->bandwidth = kMinVideoBitrate * 0.9;
+  });
+
+  // Run for 20s, verify that no frames arrive that were captured after the
+  // first five seconds, allowing some margin for BWE backoff to trigger and
+  // packets already in the pipeline to potentially arrive.
+  s.RunFor(TimeDelta::Seconds(20));
+  EXPECT_GT(s.Now() - last_frame_timestamp, TimeDelta::Seconds(15));
+
+  // Relax the network constraints and run for a while more, verify that we
+  // start receiving frames again.
+  send_net->UpdateConfig(
+      [&](NetworkSimulationConfig* c) { c->bandwidth = kMinVideoBitrate * 4; });
+  last_frame_timestamp = Timestamp::MinusInfinity();
+  s.RunFor(TimeDelta::Seconds(15));
+  EXPECT_TRUE(last_frame_timestamp.load().IsFinite());
+}
+
 }  // namespace test
 }  // namespace webrtc
diff --git a/video/video_send_stream_tests.cc b/video/video_send_stream_tests.cc
index 02e8b2b..300c4ac 100644
--- a/video/video_send_stream_tests.cc
+++ b/video/video_send_stream_tests.cc
@@ -1276,180 +1276,6 @@
   TestPacketFragmentationSize(kVP8, true);
 }
 
-// The test will go through a number of phases.
-// 1. Start sending packets.
-// 2. As soon as the RTP stream has been detected, signal a low REMB value to
-//    suspend the stream.
-// 3. Wait until |kSuspendTimeFrames| have been captured without seeing any RTP
-//    packets.
-// 4. Signal a high REMB and then wait for the RTP stream to start again.
-//    When the stream is detected again, and the stats show that the stream
-//    is no longer suspended, the test ends.
-TEST_F(VideoSendStreamTest, SuspendBelowMinBitrate) {
-  static const int kSuspendTimeFrames = 60;  // Suspend for 2 seconds @ 30 fps.
-
-  class RembObserver : public test::SendTest {
-   public:
-    class CaptureObserver : public rtc::VideoSinkInterface<VideoFrame> {
-     public:
-      explicit CaptureObserver(RembObserver* remb_observer)
-          : remb_observer_(remb_observer) {}
-
-      void OnFrame(const VideoFrame&) {
-        MutexLock lock(&remb_observer_->mutex_);
-        if (remb_observer_->test_state_ == kDuringSuspend &&
-            ++remb_observer_->suspended_frame_count_ > kSuspendTimeFrames) {
-          VideoSendStream::Stats stats = remb_observer_->stream_->GetStats();
-          EXPECT_TRUE(stats.suspended);
-          remb_observer_->SendRtcpFeedback(remb_observer_->high_remb_bps_);
-          remb_observer_->test_state_ = kWaitingForPacket;
-        }
-      }
-
-     private:
-      RembObserver* const remb_observer_;
-    };
-
-    RembObserver()
-        : SendTest(kDefaultTimeoutMs),
-          clock_(Clock::GetRealTimeClock()),
-          capture_observer_(this),
-          stream_(nullptr),
-          test_state_(kBeforeSuspend),
-          rtp_count_(0),
-          last_sequence_number_(0),
-          suspended_frame_count_(0),
-          low_remb_bps_(0),
-          high_remb_bps_(0) {}
-
-   private:
-    Action OnSendRtp(const uint8_t* packet, size_t length) override {
-      MutexLock lock(&mutex_);
-      ++rtp_count_;
-      RtpPacket rtp_packet;
-      EXPECT_TRUE(rtp_packet.Parse(packet, length));
-      last_sequence_number_ = rtp_packet.SequenceNumber();
-
-      if (test_state_ == kBeforeSuspend) {
-        // The stream has started. Try to suspend it.
-        SendRtcpFeedback(low_remb_bps_);
-        test_state_ = kDuringSuspend;
-      } else if (test_state_ == kDuringSuspend) {
-        if (rtp_packet.padding_size() == 0) {
-          // Received non-padding packet during suspension period. Reset the
-          // counter.
-          suspended_frame_count_ = 0;
-        }
-        SendRtcpFeedback(0);  // REMB is only sent if value is > 0.
-      } else if (test_state_ == kWaitingForPacket) {
-        if (rtp_packet.padding_size() == 0) {
-          // Non-padding packet observed. Test is almost complete. Will just
-          // have to wait for the stats to change.
-          test_state_ = kWaitingForStats;
-        }
-        SendRtcpFeedback(0);  // REMB is only sent if value is > 0.
-      } else if (test_state_ == kWaitingForStats) {
-        VideoSendStream::Stats stats = stream_->GetStats();
-        if (stats.suspended == false) {
-          // Stats flipped to false. Test is complete.
-          observation_complete_.Set();
-        }
-        SendRtcpFeedback(0);  // REMB is only sent if value is > 0.
-      }
-
-      return SEND_PACKET;
-    }
-
-    void set_low_remb_bps(int value) {
-      MutexLock lock(&mutex_);
-      low_remb_bps_ = value;
-    }
-
-    void set_high_remb_bps(int value) {
-      MutexLock lock(&mutex_);
-      high_remb_bps_ = value;
-    }
-
-    void OnVideoStreamsCreated(
-        VideoSendStream* send_stream,
-        const std::vector<VideoReceiveStream*>& receive_streams) override {
-      stream_ = send_stream;
-    }
-
-    void OnFrameGeneratorCapturerCreated(
-        test::FrameGeneratorCapturer* frame_generator_capturer) override {
-      frame_generator_capturer->AddOrUpdateSink(&capture_observer_,
-                                                rtc::VideoSinkWants());
-    }
-
-    void ModifyVideoConfigs(
-        VideoSendStream::Config* send_config,
-        std::vector<VideoReceiveStream::Config>* receive_configs,
-        VideoEncoderConfig* encoder_config) override {
-      RTC_DCHECK_EQ(1, encoder_config->number_of_streams);
-      transport_adapter_.reset(
-          new internal::TransportAdapter(send_config->send_transport));
-      transport_adapter_->Enable();
-      send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
-      send_config->suspend_below_min_bitrate = true;
-      int min_bitrate_bps =
-          test::DefaultVideoStreamFactory::kDefaultMinBitratePerStream[0];
-      set_low_remb_bps(min_bitrate_bps - 10000);
-      int threshold_window = std::max(min_bitrate_bps / 10, 20000);
-      ASSERT_GT(encoder_config->max_bitrate_bps,
-                min_bitrate_bps + threshold_window + 5000);
-      set_high_remb_bps(min_bitrate_bps + threshold_window + 5000);
-    }
-
-    void PerformTest() override {
-      EXPECT_TRUE(Wait()) << "Timed out during suspend-below-min-bitrate test.";
-    }
-
-    enum TestState {
-      kBeforeSuspend,
-      kDuringSuspend,
-      kWaitingForPacket,
-      kWaitingForStats
-    };
-
-    virtual void SendRtcpFeedback(int remb_value)
-        RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_) {
-      FakeReceiveStatistics receive_stats(kVideoSendSsrcs[0],
-                                          last_sequence_number_, rtp_count_, 0);
-      RtpRtcpInterface::Configuration config;
-      config.clock = clock_;
-      config.receive_statistics = &receive_stats;
-      config.outgoing_transport = transport_adapter_.get();
-      config.rtcp_report_interval_ms = kRtcpIntervalMs;
-      config.local_media_ssrc = kVideoSendSsrcs[0];
-      RTCPSender rtcp_sender(config);
-
-      rtcp_sender.SetRTCPStatus(RtcpMode::kReducedSize);
-      rtcp_sender.SetRemoteSSRC(kVideoSendSsrcs[0]);
-      if (remb_value > 0) {
-        rtcp_sender.SetRemb(remb_value, std::vector<uint32_t>());
-      }
-      RTCPSender::FeedbackState feedback_state;
-      EXPECT_EQ(0, rtcp_sender.SendRTCP(feedback_state, kRtcpRr));
-    }
-
-    std::unique_ptr<internal::TransportAdapter> transport_adapter_;
-    Clock* const clock_;
-    CaptureObserver capture_observer_;
-    VideoSendStream* stream_;
-
-    Mutex mutex_;
-    TestState test_state_ RTC_GUARDED_BY(mutex_);
-    int rtp_count_ RTC_GUARDED_BY(mutex_);
-    int last_sequence_number_ RTC_GUARDED_BY(mutex_);
-    int suspended_frame_count_ RTC_GUARDED_BY(mutex_);
-    int low_remb_bps_ RTC_GUARDED_BY(mutex_);
-    int high_remb_bps_ RTC_GUARDED_BY(mutex_);
-  } test;
-
-  RunBaseTest(&test);
-}
-
 // This test that padding stops being send after a while if the Camera stops
 // producing video frames and that padding resumes if the camera restarts.
 TEST_F(VideoSendStreamTest, NoPaddingWhenVideoIsMuted) {