diff --git a/modules/rtp_rtcp/source/rtcp_sender.cc b/modules/rtp_rtcp/source/rtcp_sender.cc index f06d429fb9..269a73597c 100644 --- a/modules/rtp_rtcp/source/rtcp_sender.cc +++ b/modules/rtp_rtcp/source/rtcp_sender.cc @@ -262,8 +262,8 @@ int32_t RTCPSender::SendLossNotification(const FeedbackState& feedback_state, 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 ssrcs) { @@ -712,76 +712,11 @@ int32_t RTCPSender::SendCompoundRTCP( { 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 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 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 @@ int32_t RTCPSender::SendCompoundRTCP( return bytes_sent == 0 ? -1 : 0; } +int32_t RTCPSender::SendCompoundRTCPLocked( + const FeedbackState& feedback_state, + const std::set& 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 RTCPSender::ComputeCompoundRTCPPacket( + const FeedbackState& feedback_state, + const std::set& 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 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 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 32c1e1dbc1..7da2546bf7 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 @@ class RTCPSender { 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& 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 ssrcs); + void SetRemb(int64_t bitrate_bps, std::vector 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 bounding_set); + void SetTmmbn(std::vector 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& csrcs); + void SetCsrcs(const std::vector& 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> rtcp_packets); + std::vector> rtcp_packets) + RTC_LOCKS_EXCLUDED(critical_section_rtcp_sender_); private: class RtcpContext; + int32_t SendCompoundRTCPLocked(const FeedbackState& feedback_state, + const std::set& packet_types, + int32_t nack_size, + const uint16_t* nack_list) + RTC_EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); + + absl::optional ComputeCompoundRTCPPacket( + const FeedbackState& feedback_state, + const std::set& 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_);