RtcpSender: remove lock recursions.

This change removes lock recursions and adds thread annotations.

Bug: webrtc:11567
Change-Id: Idc872bda693776667f3b9126bd79589d74398b34
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/175640
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Commit-Queue: Markus Handell <handellm@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#31308}
diff --git a/modules/rtp_rtcp/source/rtcp_sender.cc b/modules/rtp_rtcp/source/rtcp_sender.cc
index f06d429..269a735 100644
--- a/modules/rtp_rtcp/source/rtcp_sender.cc
+++ b/modules/rtp_rtcp/source/rtcp_sender.cc
@@ -262,8 +262,8 @@
     return 0;
   }
 
-  return SendCompoundRTCP(feedback_state,
-                          {RTCPPacketType::kRtcpLossNotification});
+  return SendCompoundRTCPLocked(
+      feedback_state, {RTCPPacketType::kRtcpLossNotification}, 0, nullptr);
 }
 
 void RTCPSender::SetRemb(int64_t bitrate_bps, std::vector<uint32_t> ssrcs) {
@@ -712,76 +712,11 @@
 
   {
     rtc::CritScope lock(&critical_section_rtcp_sender_);
-    if (method_ == RtcpMode::kOff) {
-      RTC_LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
-      return -1;
+    auto result = ComputeCompoundRTCPPacket(feedback_state, packet_types,
+                                            nack_size, nack_list, &container);
+    if (result) {
+      return *result;
     }
-    // Add all flags as volatile. Non volatile entries will not be overwritten.
-    // All new volatile flags added will be consumed by the end of this call.
-    SetFlags(packet_types, true);
-
-    // Prevent sending streams to send SR before any media has been sent.
-    const bool can_calculate_rtp_timestamp = (last_frame_capture_time_ms_ >= 0);
-    if (!can_calculate_rtp_timestamp) {
-      bool consumed_sr_flag = ConsumeFlag(kRtcpSr);
-      bool consumed_report_flag = sending_ && ConsumeFlag(kRtcpReport);
-      bool sender_report = consumed_report_flag || consumed_sr_flag;
-      if (sender_report && AllVolatileFlagsConsumed()) {
-        // This call was for Sender Report and nothing else.
-        return 0;
-      }
-      if (sending_ && method_ == RtcpMode::kCompound) {
-        // Not allowed to send any RTCP packet without sender report.
-        return -1;
-      }
-    }
-
-    if (packet_type_counter_.first_packet_time_ms == -1)
-      packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
-
-    // We need to send our NTP even if we haven't received any reports.
-    RtcpContext context(feedback_state, nack_size, nack_list,
-                        clock_->TimeInMicroseconds());
-
-    PrepareReport(feedback_state);
-
-    std::unique_ptr<rtcp::RtcpPacket> packet_bye;
-
-    auto it = report_flags_.begin();
-    while (it != report_flags_.end()) {
-      auto builder_it = builders_.find(it->type);
-      RTC_DCHECK(builder_it != builders_.end())
-          << "Could not find builder for packet type " << it->type;
-      if (it->is_volatile) {
-        report_flags_.erase(it++);
-      } else {
-        ++it;
-      }
-
-      BuilderFunc func = builder_it->second;
-      std::unique_ptr<rtcp::RtcpPacket> packet = (this->*func)(context);
-      if (packet == nullptr)
-        return -1;
-      // If there is a BYE, don't append now - save it and append it
-      // at the end later.
-      if (builder_it->first == kRtcpBye) {
-        packet_bye = std::move(packet);
-      } else {
-        container.Append(packet.release());
-      }
-    }
-
-    // Append the BYE now at the end
-    if (packet_bye) {
-      container.Append(packet_bye.release());
-    }
-
-    if (packet_type_counter_observer_ != nullptr) {
-      packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
-          remote_ssrc_, packet_type_counter_);
-    }
-
-    RTC_DCHECK(AllVolatileFlagsConsumed());
     max_packet_size = max_packet_size_;
   }
 
@@ -789,6 +724,100 @@
   return bytes_sent == 0 ? -1 : 0;
 }
 
+int32_t RTCPSender::SendCompoundRTCPLocked(
+    const FeedbackState& feedback_state,
+    const std::set<RTCPPacketType>& packet_types,
+    int32_t nack_size,
+    const uint16_t* nack_list) {
+  PacketContainer container(transport_, event_log_);
+  auto result = ComputeCompoundRTCPPacket(feedback_state, packet_types,
+                                          nack_size, nack_list, &container);
+  if (result) {
+    return *result;
+  }
+  size_t bytes_sent = container.SendPackets(max_packet_size_);
+  return bytes_sent == 0 ? -1 : 0;
+}
+
+absl::optional<int32_t> RTCPSender::ComputeCompoundRTCPPacket(
+    const FeedbackState& feedback_state,
+    const std::set<RTCPPacketType>& packet_types,
+    int32_t nack_size,
+    const uint16_t* nack_list,
+    rtcp::CompoundPacket* out_packet) {
+  if (method_ == RtcpMode::kOff) {
+    RTC_LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
+    return -1;
+  }
+  // Add all flags as volatile. Non volatile entries will not be overwritten.
+  // All new volatile flags added will be consumed by the end of this call.
+  SetFlags(packet_types, true);
+
+  // Prevent sending streams to send SR before any media has been sent.
+  const bool can_calculate_rtp_timestamp = (last_frame_capture_time_ms_ >= 0);
+  if (!can_calculate_rtp_timestamp) {
+    bool consumed_sr_flag = ConsumeFlag(kRtcpSr);
+    bool consumed_report_flag = sending_ && ConsumeFlag(kRtcpReport);
+    bool sender_report = consumed_report_flag || consumed_sr_flag;
+    if (sender_report && AllVolatileFlagsConsumed()) {
+      // This call was for Sender Report and nothing else.
+      return 0;
+    }
+    if (sending_ && method_ == RtcpMode::kCompound) {
+      // Not allowed to send any RTCP packet without sender report.
+      return -1;
+    }
+  }
+
+  if (packet_type_counter_.first_packet_time_ms == -1)
+    packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
+
+  // We need to send our NTP even if we haven't received any reports.
+  RtcpContext context(feedback_state, nack_size, nack_list,
+                      clock_->TimeInMicroseconds());
+
+  PrepareReport(feedback_state);
+
+  std::unique_ptr<rtcp::RtcpPacket> packet_bye;
+
+  auto it = report_flags_.begin();
+  while (it != report_flags_.end()) {
+    auto builder_it = builders_.find(it->type);
+    RTC_DCHECK(builder_it != builders_.end())
+        << "Could not find builder for packet type " << it->type;
+    if (it->is_volatile) {
+      report_flags_.erase(it++);
+    } else {
+      ++it;
+    }
+
+    BuilderFunc func = builder_it->second;
+    std::unique_ptr<rtcp::RtcpPacket> packet = (this->*func)(context);
+    if (packet == nullptr)
+      return -1;
+    // If there is a BYE, don't append now - save it and append it
+    // at the end later.
+    if (builder_it->first == kRtcpBye) {
+      packet_bye = std::move(packet);
+    } else {
+      out_packet->Append(packet.release());
+    }
+  }
+
+  // Append the BYE now at the end
+  if (packet_bye) {
+    out_packet->Append(packet_bye.release());
+  }
+
+  if (packet_type_counter_observer_ != nullptr) {
+    packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
+        remote_ssrc_, packet_type_counter_);
+  }
+
+  RTC_DCHECK(AllVolatileFlagsConsumed());
+  return absl::nullopt;
+}
+
 void RTCPSender::PrepareReport(const FeedbackState& feedback_state) {
   bool generate_report;
   if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
diff --git a/modules/rtp_rtcp/source/rtcp_sender.h b/modules/rtp_rtcp/source/rtcp_sender.h
index 32c1e1d..7da2546 100644
--- a/modules/rtp_rtcp/source/rtcp_sender.h
+++ b/modules/rtp_rtcp/source/rtcp_sender.h
@@ -27,6 +27,7 @@
 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
 #include "modules/rtp_rtcp/source/rtcp_nack_stats.h"
 #include "modules/rtp_rtcp/source/rtcp_packet.h"
+#include "modules/rtp_rtcp/source/rtcp_packet/compound_packet.h"
 #include "modules/rtp_rtcp/source/rtcp_packet/dlrr.h"
 #include "modules/rtp_rtcp/source/rtcp_packet/report_block.h"
 #include "modules/rtp_rtcp/source/rtcp_packet/tmmb_item.h"
@@ -66,84 +67,124 @@
   explicit RTCPSender(const RtpRtcp::Configuration& config);
   virtual ~RTCPSender();
 
-  RtcpMode Status() const;
-  void SetRTCPStatus(RtcpMode method);
+  RtcpMode Status() const RTC_LOCKS_EXCLUDED(critical_section_rtcp_sender_);
+  void SetRTCPStatus(RtcpMode method)
+      RTC_LOCKS_EXCLUDED(critical_section_rtcp_sender_);
 
-  bool Sending() const;
+  bool Sending() const RTC_LOCKS_EXCLUDED(critical_section_rtcp_sender_);
   int32_t SetSendingStatus(const FeedbackState& feedback_state,
-                           bool enabled);  // combine the functions
+                           bool enabled)
+      RTC_LOCKS_EXCLUDED(
+          critical_section_rtcp_sender_);  // combine the functions
 
-  int32_t SetNackStatus(bool enable);
+  int32_t SetNackStatus(bool enable)
+      RTC_LOCKS_EXCLUDED(critical_section_rtcp_sender_);
 
-  void SetTimestampOffset(uint32_t timestamp_offset);
+  void SetTimestampOffset(uint32_t timestamp_offset)
+      RTC_LOCKS_EXCLUDED(critical_section_rtcp_sender_);
 
   // TODO(bugs.webrtc.org/6458): Remove default parameter value when all the
   // depending projects are updated to correctly set payload type.
   void SetLastRtpTime(uint32_t rtp_timestamp,
                       int64_t capture_time_ms,
-                      int8_t payload_type = -1);
+                      int8_t payload_type = -1)
+      RTC_LOCKS_EXCLUDED(critical_section_rtcp_sender_);
 
-  void SetRtpClockRate(int8_t payload_type, int rtp_clock_rate_hz);
+  void SetRtpClockRate(int8_t payload_type, int rtp_clock_rate_hz)
+      RTC_LOCKS_EXCLUDED(critical_section_rtcp_sender_);
 
   uint32_t SSRC() const { return ssrc_; }
 
-  void SetRemoteSSRC(uint32_t ssrc);
+  void SetRemoteSSRC(uint32_t ssrc)
+      RTC_LOCKS_EXCLUDED(critical_section_rtcp_sender_);
 
-  int32_t SetCNAME(const char* cName);
+  int32_t SetCNAME(const char* cName)
+      RTC_LOCKS_EXCLUDED(critical_section_rtcp_sender_);
 
-  int32_t AddMixedCNAME(uint32_t SSRC, const char* c_name);
+  int32_t AddMixedCNAME(uint32_t SSRC, const char* c_name)
+      RTC_LOCKS_EXCLUDED(critical_section_rtcp_sender_);
 
-  int32_t RemoveMixedCNAME(uint32_t SSRC);
+  int32_t RemoveMixedCNAME(uint32_t SSRC)
+      RTC_LOCKS_EXCLUDED(critical_section_rtcp_sender_);
 
-  bool TimeToSendRTCPReport(bool sendKeyframeBeforeRTP = false) const;
+  bool TimeToSendRTCPReport(bool sendKeyframeBeforeRTP = false) const
+      RTC_LOCKS_EXCLUDED(critical_section_rtcp_sender_);
 
   int32_t SendRTCP(const FeedbackState& feedback_state,
                    RTCPPacketType packetType,
                    int32_t nackSize = 0,
-                   const uint16_t* nackList = 0);
+                   const uint16_t* nackList = 0)
+      RTC_LOCKS_EXCLUDED(critical_section_rtcp_sender_);
 
   int32_t SendCompoundRTCP(const FeedbackState& feedback_state,
                            const std::set<RTCPPacketType>& packetTypes,
                            int32_t nackSize = 0,
-                           const uint16_t* nackList = 0);
+                           const uint16_t* nackList = nullptr)
+      RTC_LOCKS_EXCLUDED(critical_section_rtcp_sender_);
 
   int32_t SendLossNotification(const FeedbackState& feedback_state,
                                uint16_t last_decoded_seq_num,
                                uint16_t last_received_seq_num,
                                bool decodability_flag,
-                               bool buffering_allowed);
+                               bool buffering_allowed)
+      RTC_LOCKS_EXCLUDED(critical_section_rtcp_sender_);
 
-  void SetRemb(int64_t bitrate_bps, std::vector<uint32_t> ssrcs);
+  void SetRemb(int64_t bitrate_bps, std::vector<uint32_t> ssrcs)
+      RTC_LOCKS_EXCLUDED(critical_section_rtcp_sender_);
 
-  void UnsetRemb();
+  void UnsetRemb() RTC_LOCKS_EXCLUDED(critical_section_rtcp_sender_);
 
-  bool TMMBR() const;
+  bool TMMBR() const RTC_LOCKS_EXCLUDED(critical_section_rtcp_sender_);
 
-  void SetTMMBRStatus(bool enable);
+  void SetTMMBRStatus(bool enable)
+      RTC_LOCKS_EXCLUDED(critical_section_rtcp_sender_);
 
-  void SetMaxRtpPacketSize(size_t max_packet_size);
+  void SetMaxRtpPacketSize(size_t max_packet_size)
+      RTC_LOCKS_EXCLUDED(critical_section_rtcp_sender_);
 
-  void SetTmmbn(std::vector<rtcp::TmmbItem> bounding_set);
+  void SetTmmbn(std::vector<rtcp::TmmbItem> bounding_set)
+      RTC_LOCKS_EXCLUDED(critical_section_rtcp_sender_);
 
   int32_t SetApplicationSpecificData(uint8_t subType,
                                      uint32_t name,
                                      const uint8_t* data,
-                                     uint16_t length);
+                                     uint16_t length)
+      RTC_LOCKS_EXCLUDED(critical_section_rtcp_sender_);
 
-  void SendRtcpXrReceiverReferenceTime(bool enable);
+  void SendRtcpXrReceiverReferenceTime(bool enable)
+      RTC_LOCKS_EXCLUDED(critical_section_rtcp_sender_);
 
-  bool RtcpXrReceiverReferenceTime() const;
+  bool RtcpXrReceiverReferenceTime() const
+      RTC_LOCKS_EXCLUDED(critical_section_rtcp_sender_);
 
-  void SetCsrcs(const std::vector<uint32_t>& csrcs);
+  void SetCsrcs(const std::vector<uint32_t>& csrcs)
+      RTC_LOCKS_EXCLUDED(critical_section_rtcp_sender_);
 
-  void SetTargetBitrate(unsigned int target_bitrate);
-  void SetVideoBitrateAllocation(const VideoBitrateAllocation& bitrate);
+  void SetTargetBitrate(unsigned int target_bitrate)
+      RTC_LOCKS_EXCLUDED(critical_section_rtcp_sender_);
+  void SetVideoBitrateAllocation(const VideoBitrateAllocation& bitrate)
+      RTC_LOCKS_EXCLUDED(critical_section_rtcp_sender_);
   void SendCombinedRtcpPacket(
-      std::vector<std::unique_ptr<rtcp::RtcpPacket>> rtcp_packets);
+      std::vector<std::unique_ptr<rtcp::RtcpPacket>> rtcp_packets)
+      RTC_LOCKS_EXCLUDED(critical_section_rtcp_sender_);
 
  private:
   class RtcpContext;
 
+  int32_t SendCompoundRTCPLocked(const FeedbackState& feedback_state,
+                                 const std::set<RTCPPacketType>& packet_types,
+                                 int32_t nack_size,
+                                 const uint16_t* nack_list)
+      RTC_EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_);
+
+  absl::optional<int32_t> ComputeCompoundRTCPPacket(
+      const FeedbackState& feedback_state,
+      const std::set<RTCPPacketType>& packet_types,
+      int32_t nack_size,
+      const uint16_t* nack_list,
+      rtcp::CompoundPacket* out_packet)
+      RTC_EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_);
+
   // Determine which RTCP messages should be sent and setup flags.
   void PrepareReport(const FeedbackState& feedback_state)
       RTC_EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_);