Configure RtpVideoSender modules at creation

The constructor body and ConfigureSsrcs() configured the RTP modules in
several passes after rtp_streams_ had been constructed. Configure each
module right after creating it instead, with the same per-module call
order, so that rtp_streams_ is fully set up once it's constructed. This
removes ConfigureSsrcs() and most of the constructor body.

Bug: webrtc:42223727
Change-Id: I91f9329584d07fc07a9b3d1e471183387bc1cd67
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/506200
Commit-Queue: Tomas Gunnarsson <tommi@webrtc.org>
Reviewed-by: Rasmus Brandt <brandtr@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#48773}
diff --git a/call/rtp_video_sender.cc b/call/rtp_video_sender.cc
index 78170ab..0683334 100644
--- a/call/rtp_video_sender.cc
+++ b/call/rtp_video_sender.cc
@@ -222,6 +222,65 @@
   return nullptr;
 }
 
+// Configures RTX for the media stream at `simulcast_index`.
+void ConfigureRtx(const RtpConfig& rtp_config,
+                  const std::map<uint32_t, RtpState>& suspended_ssrcs,
+                  size_t simulcast_index,
+                  RtpRtcpInterface& rtp_rtcp) {
+  auto it = suspended_ssrcs.find(rtp_config.rtx.ssrcs[simulcast_index]);
+  if (it != suspended_ssrcs.end())
+    rtp_rtcp.SetRtxState(it->second);
+
+  // Configure RTX payload types.
+  RTC_DCHECK_GE(rtp_config.rtx.payload_type, 0);
+  RtpStreamConfig stream_config = rtp_config.GetStreamConfig(simulcast_index);
+  RTC_DCHECK(stream_config.rtx);
+  rtp_rtcp.SetRtxSendPayloadType(stream_config.rtx->payload_type,
+                                 stream_config.payload_type);
+  rtp_rtcp.SetRtxSendStatus(kRtxRetransmitted | kRtxRedundantPayloads);
+  if (rtp_config.ulpfec.red_payload_type != -1 &&
+      rtp_config.ulpfec.red_rtx_payload_type != -1) {
+    rtp_rtcp.SetRtxSendPayloadType(rtp_config.ulpfec.red_rtx_payload_type,
+                                   rtp_config.ulpfec.red_payload_type);
+  }
+}
+
+// Configures the RTP module that sends the media stream at `simulcast_index`.
+void ConfigureRtpModule(const RtpConfig& rtp_config,
+                        const std::map<uint32_t, RtpState>& suspended_ssrcs,
+                        size_t simulcast_index,
+                        RtpRtcpInterface& rtp_rtcp) {
+  rtp_rtcp.SetSendingStatus(false);
+  rtp_rtcp.SetSendingMediaStatus(false);
+  rtp_rtcp.SetRTCPStatus(RtcpMode::kCompound);
+  // Set NACK.
+  rtp_rtcp.SetStorePacketsStatus(true, kMinSendSidePacketHistorySize);
+
+  for (const RtpExtension& extension : rtp_config.extensions) {
+    RTC_DCHECK(RtpExtension::IsSupportedForVideo(extension.uri));
+    rtp_rtcp.RegisterRtpHeaderExtension(extension.uri, extension.id);
+  }
+
+  // Restore RTP state if previous existed.
+  auto it = suspended_ssrcs.find(rtp_config.ssrcs[simulcast_index]);
+  if (it != suspended_ssrcs.end())
+    rtp_rtcp.SetRtpState(it->second);
+
+  // Set up RTX if available.
+  if (!rtp_config.rtx.ssrcs.empty())
+    ConfigureRtx(rtp_config, suspended_ssrcs, simulcast_index, rtp_rtcp);
+
+  if (!rtp_config.mid.empty())
+    rtp_rtcp.SetMid(rtp_config.mid);
+
+  // Simulcast has one module for each layer. Set the CNAME on all modules.
+  rtp_rtcp.SetCNAME(rtp_config.c_name.c_str());
+  rtp_rtcp.SetMaxRtpPacketSize(rtp_config.max_packet_size);
+  rtp_rtcp.RegisterSendPayloadFrequency(
+      rtp_config.GetStreamConfig(simulcast_index).payload_type,
+      kVideoPayloadTypeFrequency);
+}
+
 std::vector<RtpStreamSender> CreateRtpStreamSenders(
     const Environment& env,
     const RtpConfig& rtp_config,
@@ -290,11 +349,7 @@
     configuration.need_rtp_packet_infos = rtp_config.lntf.enabled;
 
     auto rtp_rtcp = ModuleRtpRtcpImpl2::CreateSendModule(env, configuration);
-    rtp_rtcp->SetSendingStatus(false);
-    rtp_rtcp->SetSendingMediaStatus(false);
-    rtp_rtcp->SetRTCPStatus(RtcpMode::kCompound);
-    // Set NACK.
-    rtp_rtcp->SetStorePacketsStatus(true, kMinSendSidePacketHistorySize);
+    ConfigureRtpModule(rtp_config, suspended_ssrcs, i, *rtp_rtcp);
 
     video_config.clock = &env.clock();
     video_config.rtp_sender = rtp_rtcp->RtpSender();
@@ -474,40 +529,12 @@
   if (has_packet_feedback_)
     transport_->IncludeOverheadInPacedSender();
 
-  // RTP/RTCP initialization.
-
-  for (size_t i = 0; i < rtp_config_.extensions.size(); ++i) {
-    const std::string& extension = rtp_config_.extensions[i].uri;
-    RtpHeaderExtensionId id = rtp_config_.extensions[i].id;
-    RTC_DCHECK(RtpExtension::IsSupportedForVideo(extension));
-    for (const RtpStreamSender& stream : rtp_streams_) {
-      stream.rtp_rtcp->RegisterRtpHeaderExtension(extension, id);
-    }
-  }
-
-  ConfigureSsrcs(suspended_ssrcs);
-
-  if (!rtp_config_.mid.empty()) {
-    for (const RtpStreamSender& stream : rtp_streams_) {
-      stream.rtp_rtcp->SetMid(rtp_config_.mid);
-    }
-  }
-
-  bool fec_enabled = false;
-  for (size_t i = 0; i < rtp_streams_.size(); i++) {
-    const RtpStreamSender& stream = rtp_streams_[i];
-    // Simulcast has one module for each layer. Set the CNAME on all modules.
-    stream.rtp_rtcp->SetCNAME(rtp_config_.c_name.c_str());
-    stream.rtp_rtcp->SetMaxRtpPacketSize(rtp_config_.max_packet_size);
-    stream.rtp_rtcp->RegisterSendPayloadFrequency(
-        rtp_config_.GetStreamConfig(i).payload_type,
-        kVideoPayloadTypeFrequency);
-    if (stream.fec_generator != nullptr) {
-      fec_enabled = true;
-    }
-  }
   // Currently, both ULPFEC and FlexFEC use the same FEC rate calculation logic,
   // so enable that logic if either of those FEC schemes are enabled.
+  const bool fec_enabled =
+      absl::c_any_of(rtp_streams_, [](const RtpStreamSender& stream) {
+        return stream.fec_generator != nullptr;
+      });
   fec_controller_->SetProtectionMethod(fec_enabled, NackEnabled());
 
   fec_controller_->SetProtectionCallback(this);
@@ -757,53 +784,6 @@
     stream.rtp_rtcp->IncomingRtcpPacket(packet);
 }
 
-void RtpVideoSender::ConfigureSsrcs(
-    const std::map<uint32_t, RtpState>& suspended_ssrcs) {
-  // Configure regular SSRCs.
-  for (size_t i = 0; i < rtp_config_.ssrcs.size(); ++i) {
-    uint32_t ssrc = rtp_config_.ssrcs[i];
-    RtpRtcpInterface* const rtp_rtcp = rtp_streams_[i].rtp_rtcp.get();
-
-    // Restore RTP state if previous existed.
-    auto it = suspended_ssrcs.find(ssrc);
-    if (it != suspended_ssrcs.end())
-      rtp_rtcp->SetRtpState(it->second);
-  }
-
-  // Set up RTX if available.
-  if (rtp_config_.rtx.ssrcs.empty())
-    return;
-
-  RTC_DCHECK_EQ(rtp_config_.rtx.ssrcs.size(), rtp_config_.ssrcs.size());
-  for (size_t i = 0; i < rtp_config_.rtx.ssrcs.size(); ++i) {
-    uint32_t ssrc = rtp_config_.rtx.ssrcs[i];
-    RtpRtcpInterface* const rtp_rtcp = rtp_streams_[i].rtp_rtcp.get();
-    auto it = suspended_ssrcs.find(ssrc);
-    if (it != suspended_ssrcs.end())
-      rtp_rtcp->SetRtxState(it->second);
-  }
-
-  // Configure RTX payload types.
-  RTC_DCHECK_GE(rtp_config_.rtx.payload_type, 0);
-  for (size_t i = 0; i < rtp_streams_.size(); ++i) {
-    const RtpStreamSender& stream = rtp_streams_[i];
-    RtpStreamConfig stream_config = rtp_config_.GetStreamConfig(i);
-    RTC_DCHECK(stream_config.rtx);
-    stream.rtp_rtcp->SetRtxSendPayloadType(stream_config.rtx->payload_type,
-                                           stream_config.payload_type);
-    stream.rtp_rtcp->SetRtxSendStatus(kRtxRetransmitted |
-                                      kRtxRedundantPayloads);
-  }
-  if (rtp_config_.ulpfec.red_payload_type != -1 &&
-      rtp_config_.ulpfec.red_rtx_payload_type != -1) {
-    for (const RtpStreamSender& stream : rtp_streams_) {
-      stream.rtp_rtcp->SetRtxSendPayloadType(
-          rtp_config_.ulpfec.red_rtx_payload_type,
-          rtp_config_.ulpfec.red_payload_type);
-    }
-  }
-}
-
 void RtpVideoSender::OnNetworkAvailability(bool network_available) {
   for (const RtpStreamSender& stream : rtp_streams_) {
     stream.rtp_rtcp->SetRTCPStatus(network_available ? rtp_config_.rtcp_mode
diff --git a/call/rtp_video_sender.h b/call/rtp_video_sender.h
index 8433c93..3527d3c 100644
--- a/call/rtp_video_sender.h
+++ b/call/rtp_video_sender.h
@@ -172,7 +172,6 @@
       RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
   void UpdateModuleSendingState() RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
   void ConfigureProtection();
-  void ConfigureSsrcs(const std::map<uint32_t, RtpState>& suspended_ssrcs);
   bool NackEnabled() const;
   DataRate GetPostEncodeOverhead() const;
   DataRate CalculateOverheadRate(DataRate data_rate,