Add functions to send feedback according to RFC 8888 in ReceiveSideCongestionController.

With this cl, sending can be forced with field trial "WebRTC-RFC8888CongestionControlFeedback/force_send:true/"
In the future, ReceiveSideCongestionController::EnablSendCongestionControlFeedbackAccordingToRfc8888 if RFC 8888 has been negotiated.

Bug: webrtc:42225697
Change-Id: Ib09066aa89ca7b3fffc551da541090c69ab8d75f
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/352720
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Commit-Queue: Per Kjellander <perkj@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#42413}
diff --git a/modules/congestion_controller/BUILD.gn b/modules/congestion_controller/BUILD.gn
index 22a7f09..2c00735 100644
--- a/modules/congestion_controller/BUILD.gn
+++ b/modules/congestion_controller/BUILD.gn
@@ -19,9 +19,11 @@
 
   deps = [
     "../../api:rtp_parameters",
+    "../../api:sequence_checker",
     "../../api/environment",
     "../../api/transport:network_control",
     "../../api/units:data_rate",
+    "../../api/units:data_size",
     "../../api/units:time_delta",
     "../../api/units:timestamp",
     "../../rtc_base:logging",
@@ -29,6 +31,7 @@
     "../../rtc_base/synchronization:mutex",
     "../pacing",
     "../remote_bitrate_estimator",
+    "../remote_bitrate_estimator:congestion_control_feedback_generator",
     "../remote_bitrate_estimator:transport_sequence_number_feedback_generator",
     "../rtp_rtcp:rtp_rtcp_format",
     "//third_party/abseil-cpp/absl/base:nullability",
@@ -45,6 +48,7 @@
     ]
     deps = [
       ":congestion_controller",
+      "../../api:rtp_parameters",
       "../../api/environment:environment_factory",
       "../../api/test/network_emulation",
       "../../api/test/network_emulation:create_cross_traffic",
@@ -53,6 +57,7 @@
       "../../api/units:time_delta",
       "../../api/units:timestamp",
       "../../system_wrappers",
+      "../../test:explicit_key_value_config",
       "../../test:test_support",
       "../../test/scenario",
       "../pacing",
diff --git a/modules/congestion_controller/include/receive_side_congestion_controller.h b/modules/congestion_controller/include/receive_side_congestion_controller.h
index deb3a3e..7dec287 100644
--- a/modules/congestion_controller/include/receive_side_congestion_controller.h
+++ b/modules/congestion_controller/include/receive_side_congestion_controller.h
@@ -15,10 +15,12 @@
 
 #include "absl/base/nullability.h"
 #include "api/environment/environment.h"
+#include "api/sequence_checker.h"
 #include "api/transport/network_control.h"
 #include "api/units/data_rate.h"
 #include "api/units/time_delta.h"
 #include "modules/congestion_controller/remb_throttler.h"
+#include "modules/remote_bitrate_estimator/congestion_control_feedback_generator.h"
 #include "modules/remote_bitrate_estimator/transport_sequence_number_feedback_generator.h"
 #include "modules/rtp_rtcp/source/rtp_packet_received.h"
 #include "rtc_base/synchronization/mutex.h"
@@ -42,6 +44,8 @@
 
   ~ReceiveSideCongestionController() override = default;
 
+  void EnablSendCongestionControlFeedbackAccordingToRfc8888();
+
   void OnReceivedPacket(const RtpPacketReceived& packet, MediaType media_type);
 
   // Implements CallStatsObserver.
@@ -74,8 +78,18 @@
 
   const Environment env_;
   RembThrottler remb_throttler_;
+
+  // TODO: bugs.webrtc.org/42224904 - Use sequence checker for all usage of
+  // ReceiveSideCongestionController. At the time of
+  // writing OnReceivedPacket and MaybeProcess can unfortunately be called on an
+  // arbitrary thread by external projects.
+  SequenceChecker sequence_checker_;
+
+  bool send_rfc8888_congestion_feedback_ = false;
   TransportSequenceNumberFeedbackGenenerator
       transport_sequence_number_feedback_generator_;
+  CongestionControlFeedbackGenerator congestion_control_feedback_generator_
+      RTC_GUARDED_BY(sequence_checker_);
 
   mutable Mutex mutex_;
   std::unique_ptr<RemoteBitrateEstimator> rbe_ RTC_GUARDED_BY(mutex_);
diff --git a/modules/congestion_controller/receive_side_congestion_controller.cc b/modules/congestion_controller/receive_side_congestion_controller.cc
index c86b277..591dba3 100644
--- a/modules/congestion_controller/receive_side_congestion_controller.cc
+++ b/modules/congestion_controller/receive_side_congestion_controller.cc
@@ -10,14 +10,18 @@
 
 #include "modules/congestion_controller/include/receive_side_congestion_controller.h"
 
+#include <memory>
+
 #include "absl/base/nullability.h"
 #include "api/environment/environment.h"
 #include "api/media_types.h"
+#include "api/sequence_checker.h"
 #include "api/units/data_rate.h"
-#include "modules/pacing/packet_router.h"
-#include "modules/remote_bitrate_estimator/include/bwe_defines.h"
+#include "modules/remote_bitrate_estimator/congestion_control_feedback_generator.h"
 #include "modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.h"
 #include "modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.h"
+#include "modules/remote_bitrate_estimator/transport_sequence_number_feedback_generator.h"
+#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
 #include "rtc_base/logging.h"
 
 namespace webrtc {
@@ -77,17 +81,37 @@
     absl::Nullable<NetworkStateEstimator*> network_state_estimator)
     : env_(env),
       remb_throttler_(std::move(remb_sender), &env_.clock()),
-      transport_sequence_number_feedback_generator_(std::move(feedback_sender),
+      transport_sequence_number_feedback_generator_(feedback_sender,
                                                     network_state_estimator),
+      congestion_control_feedback_generator_(env, feedback_sender),
       rbe_(std::make_unique<RemoteBitrateEstimatorSingleStream>(
           env_,
           &remb_throttler_)),
       using_absolute_send_time_(false),
-      packets_since_absolute_send_time_(0) {}
+      packets_since_absolute_send_time_(0) {
+  FieldTrialParameter<bool> force_send_rfc8888_feedback("force_send", false);
+  ParseFieldTrial(
+      {&force_send_rfc8888_feedback},
+      env.field_trials().Lookup("WebRTC-RFC8888CongestionControlFeedback"));
+  if (force_send_rfc8888_feedback) {
+    EnablSendCongestionControlFeedbackAccordingToRfc8888();
+  }
+}
+
+void ReceiveSideCongestionController::
+    EnablSendCongestionControlFeedbackAccordingToRfc8888() {
+  RTC_DCHECK_RUN_ON(&sequence_checker_);
+  send_rfc8888_congestion_feedback_ = true;
+}
 
 void ReceiveSideCongestionController::OnReceivedPacket(
     const RtpPacketReceived& packet,
     MediaType media_type) {
+  if (send_rfc8888_congestion_feedback_) {
+    RTC_DCHECK_RUN_ON(&sequence_checker_);
+    congestion_control_feedback_generator_.OnReceivedPacket(packet);
+    return;
+  }
   bool has_transport_sequence_number =
       packet.HasExtension<TransportSequenceNumber>() ||
       packet.HasExtension<TransportSequenceNumberV2>();
@@ -108,12 +132,20 @@
 }
 
 void ReceiveSideCongestionController::OnBitrateChanged(int bitrate_bps) {
+  RTC_DCHECK_RUN_ON(&sequence_checker_);
+  DataRate send_bandwidth_estimate = DataRate::BitsPerSec(bitrate_bps);
   transport_sequence_number_feedback_generator_.OnSendBandwidthEstimateChanged(
-      DataRate::BitsPerSec(bitrate_bps));
+      send_bandwidth_estimate);
+  congestion_control_feedback_generator_.OnSendBandwidthEstimateChanged(
+      send_bandwidth_estimate);
 }
 
 TimeDelta ReceiveSideCongestionController::MaybeProcess() {
   Timestamp now = env_.clock().CurrentTime();
+  if (send_rfc8888_congestion_feedback_) {
+    RTC_DCHECK_RUN_ON(&sequence_checker_);
+    return congestion_control_feedback_generator_.Process(now);
+  }
   mutex_.Lock();
   TimeDelta time_until_rbe = rbe_->Process();
   mutex_.Unlock();
@@ -130,8 +162,11 @@
 
 void ReceiveSideCongestionController::SetTransportOverhead(
     DataSize overhead_per_packet) {
+  RTC_DCHECK_RUN_ON(&sequence_checker_);
   transport_sequence_number_feedback_generator_.SetTransportOverhead(
       overhead_per_packet);
+  congestion_control_feedback_generator_.SetTransportOverhead(
+      overhead_per_packet);
 }
 
 }  // namespace webrtc
diff --git a/modules/congestion_controller/receive_side_congestion_controller_unittest.cc b/modules/congestion_controller/receive_side_congestion_controller_unittest.cc
index 5788898..8681560 100644
--- a/modules/congestion_controller/receive_side_congestion_controller_unittest.cc
+++ b/modules/congestion_controller/receive_side_congestion_controller_unittest.cc
@@ -11,17 +11,18 @@
 #include "modules/congestion_controller/include/receive_side_congestion_controller.h"
 
 #include "api/environment/environment_factory.h"
+#include "api/media_types.h"
 #include "api/test/network_emulation/create_cross_traffic.h"
 #include "api/test/network_emulation/cross_traffic.h"
 #include "api/units/data_rate.h"
 #include "api/units/data_size.h"
 #include "api/units/time_delta.h"
 #include "api/units/timestamp.h"
-#include "modules/pacing/packet_router.h"
 #include "modules/rtp_rtcp/include/rtp_header_extension_map.h"
 #include "modules/rtp_rtcp/source/rtp_header_extensions.h"
 #include "modules/rtp_rtcp/source/rtp_packet_received.h"
 #include "system_wrappers/include/clock.h"
+#include "test/explicit_key_value_config.h"
 #include "test/gmock.h"
 #include "test/gtest.h"
 #include "test/scenario/scenario.h"
@@ -34,6 +35,7 @@
 using ::testing::AtLeast;
 using ::testing::ElementsAre;
 using ::testing::MockFunction;
+using ::testing::SizeIs;
 
 constexpr DataRate kInitialBitrate = DataRate::BitsPerSec(60'000);
 
@@ -81,6 +83,76 @@
   controller.SetMaxDesiredReceiveBitrate(DataRate::BitsPerSec(123));
 }
 
+TEST(ReceiveSideCongestionControllerTest, SendsRfc8888FeedbackIfForced) {
+  test::ExplicitKeyValueConfig field_trials(
+      "WebRTC-RFC8888CongestionControlFeedback/force_send:true/");
+  MockFunction<void(std::vector<std::unique_ptr<rtcp::RtcpPacket>>)>
+      rtcp_sender;
+  MockFunction<void(uint64_t, std::vector<uint32_t>)> remb_sender;
+  SimulatedClock clock(123456);
+  ReceiveSideCongestionController controller(
+      CreateEnvironment(&clock, &field_trials), rtcp_sender.AsStdFunction(),
+      remb_sender.AsStdFunction(), nullptr);
+
+  EXPECT_CALL(rtcp_sender, Call);
+  RtpPacketReceived packet;
+  packet.set_arrival_time(clock.CurrentTime());
+  controller.OnReceivedPacket(packet, MediaType::VIDEO);
+  TimeDelta next_process = controller.MaybeProcess();
+  clock.AdvanceTime(next_process);
+  next_process = controller.MaybeProcess();
+}
+
+TEST(ReceiveSideCongestionControllerTest, SendsRfc8888FeedbackIfEnabled) {
+  MockFunction<void(std::vector<std::unique_ptr<rtcp::RtcpPacket>>)>
+      rtcp_sender;
+  MockFunction<void(uint64_t, std::vector<uint32_t>)> remb_sender;
+  SimulatedClock clock(123456);
+  ReceiveSideCongestionController controller(
+      CreateEnvironment(&clock), rtcp_sender.AsStdFunction(),
+      remb_sender.AsStdFunction(), nullptr);
+  controller.EnablSendCongestionControlFeedbackAccordingToRfc8888();
+
+  EXPECT_CALL(rtcp_sender, Call)
+      .WillOnce(
+          [&](std::vector<std::unique_ptr<rtcp::RtcpPacket>> rtcp_packets) {
+            ASSERT_THAT(rtcp_packets, SizeIs(1));
+            rtc::Buffer buffer = rtcp_packets[0]->Build();
+            rtcp::CommonHeader header;
+            EXPECT_TRUE(header.Parse(buffer.data(), buffer.size()));
+            EXPECT_EQ(header.fmt(),
+                      rtcp::CongestionControlFeedback::kFeedbackMessageType);
+          });
+
+  RtpPacketReceived packet;
+  packet.set_arrival_time(clock.CurrentTime());
+  controller.OnReceivedPacket(packet, MediaType::VIDEO);
+  TimeDelta next_process = controller.MaybeProcess();
+  clock.AdvanceTime(next_process);
+  next_process = controller.MaybeProcess();
+}
+
+TEST(ReceiveSideCongestionControllerTest,
+     SendsNoFeedbackIfNotRfcRfc8888EnabledAndNoTransportFeedback) {
+  MockFunction<void(std::vector<std::unique_ptr<rtcp::RtcpPacket>>)>
+      rtcp_sender;
+  MockFunction<void(uint64_t, std::vector<uint32_t>)> remb_sender;
+  SimulatedClock clock(123456);
+  ReceiveSideCongestionController controller(
+      CreateEnvironment(&clock), rtcp_sender.AsStdFunction(),
+      remb_sender.AsStdFunction(), nullptr);
+
+  // No Transport feedback is sent because received packet does not have
+  // transport sequence number rtp header extension.
+  EXPECT_CALL(rtcp_sender, Call).Times(0);
+  RtpPacketReceived packet;
+  packet.set_arrival_time(clock.CurrentTime());
+  controller.OnReceivedPacket(packet, MediaType::VIDEO);
+  TimeDelta next_process = controller.MaybeProcess();
+  clock.AdvanceTime(next_process);
+  next_process = controller.MaybeProcess();
+}
+
 TEST(ReceiveSideCongestionControllerTest, ConvergesToCapacity) {
   Scenario s("receive_cc_unit/converge");
   NetworkSimulationConfig net_conf;
diff --git a/modules/remote_bitrate_estimator/congestion_control_feedback_generator.h b/modules/remote_bitrate_estimator/congestion_control_feedback_generator.h
index 7183d5f..3a65745 100644
--- a/modules/remote_bitrate_estimator/congestion_control_feedback_generator.h
+++ b/modules/remote_bitrate_estimator/congestion_control_feedback_generator.h
@@ -44,10 +44,9 @@
 class CongestionControlFeedbackGenerator
     : public RtpTransportFeedbackGenerator {
  public:
-  using RtcpSender = std::function<void(
-      std::vector<std::unique_ptr<rtcp::RtcpPacket>> packets)>;
-  CongestionControlFeedbackGenerator(const Environment& env,
-                                     RtcpSender feedback_sender);
+  CongestionControlFeedbackGenerator(
+      const Environment& env,
+      RtpTransportFeedbackGenerator::RtcpSender feedback_sender);
   ~CongestionControlFeedbackGenerator() = default;
 
   void OnReceivedPacket(const RtpPacketReceived& packet) override;
diff --git a/modules/remote_bitrate_estimator/rtp_transport_feedback_generator.h b/modules/remote_bitrate_estimator/rtp_transport_feedback_generator.h
index 724b589..d835608 100644
--- a/modules/remote_bitrate_estimator/rtp_transport_feedback_generator.h
+++ b/modules/remote_bitrate_estimator/rtp_transport_feedback_generator.h
@@ -11,6 +11,9 @@
 #ifndef MODULES_REMOTE_BITRATE_ESTIMATOR_RTP_TRANSPORT_FEEDBACK_GENERATOR_H_
 #define MODULES_REMOTE_BITRATE_ESTIMATOR_RTP_TRANSPORT_FEEDBACK_GENERATOR_H_
 
+#include <memory>
+#include <vector>
+
 #include "api/units/data_rate.h"
 #include "api/units/data_size.h"
 #include "api/units/time_delta.h"
@@ -21,6 +24,10 @@
 
 class RtpTransportFeedbackGenerator {
  public:
+  // Function intented to be used for sending RTCP messages generated by an
+  // implementation of this class.
+  using RtcpSender = std::function<void(
+      std::vector<std::unique_ptr<rtcp::RtcpPacket>> packets)>;
   virtual ~RtpTransportFeedbackGenerator() = default;
 
   virtual void OnReceivedPacket(const RtpPacketReceived& packet) = 0;
diff --git a/modules/remote_bitrate_estimator/transport_sequence_number_feedback_generator.h b/modules/remote_bitrate_estimator/transport_sequence_number_feedback_generator.h
index 2291031..4c2fb31 100644
--- a/modules/remote_bitrate_estimator/transport_sequence_number_feedback_generator.h
+++ b/modules/remote_bitrate_estimator/transport_sequence_number_feedback_generator.h
@@ -44,12 +44,8 @@
 class TransportSequenceNumberFeedbackGenenerator
     : public RtpTransportFeedbackGenerator {
  public:
-  // Used for sending transport feedback messages when send side
-  // BWE is used.
-  using RtcpSender = std::function<void(
-      std::vector<std::unique_ptr<rtcp::RtcpPacket>> packets)>;
   TransportSequenceNumberFeedbackGenenerator(
-      RtcpSender feedback_sender,
+      RtpTransportFeedbackGenerator::RtcpSender feedback_sender,
       NetworkStateEstimator* network_state_estimator);
   ~TransportSequenceNumberFeedbackGenenerator();