diff --git a/modules/rtp_rtcp/source/rtp_sender.cc b/modules/rtp_rtcp/source/rtp_sender.cc index d9796ceb74..45d5a6a65d 100644 --- a/modules/rtp_rtcp/source/rtp_sender.cc +++ b/modules/rtp_rtcp/source/rtp_sender.cc @@ -47,6 +47,9 @@ constexpr uint32_t kTimestampTicksPerMs = 90; // Min size needed to get payload padding from packet history. constexpr int kMinPayloadPaddingBytes = 50; +// RED header if first byte of payload. +constexpr size_t kRedForFecHeaderLength = 1; + template constexpr RtpExtensionSize CreateExtensionSize() { return {Extension::kId, Extension::kValueSizeBytes}; @@ -611,16 +614,40 @@ bool RTPSender::AssignSequenceNumber(RtpPacketToSend* packet) { RTC_DCHECK(packet->Ssrc() == ssrc_); packet->SetSequenceNumber(sequence_number_++); + UpdateLastPacketState(*packet); + return true; +} + +bool RTPSender::AssignSequenceNumbersAndStoreLastPacketState( + rtc::ArrayView> packets) { + RTC_DCHECK(!packets.empty()); + MutexLock lock(&send_mutex_); + if (!sending_media_) + return false; + for (auto& packet : packets) { + RTC_DCHECK_EQ(packet->Ssrc(), ssrc_); + packet->SetSequenceNumber(sequence_number_++); + } + UpdateLastPacketState(**packets.rbegin()); + return true; +} + +void RTPSender::UpdateLastPacketState(const RtpPacketToSend& packet) { // Remember marker bit to determine if padding can be inserted with // sequence number following |packet|. - last_packet_marker_bit_ = packet->Marker(); - // Remember payload type to use in the padding packet if rtx is disabled. - last_payload_type_ = packet->PayloadType(); + last_packet_marker_bit_ = packet.Marker(); + // Remember media payload type to use in the padding packet if rtx is + // disabled. + if (packet.is_red()) { + RTC_DCHECK_GE(packet.payload_size(), kRedForFecHeaderLength); + last_payload_type_ = packet.PayloadBuffer()[0]; + } else { + last_payload_type_ = packet.PayloadType(); + } // Save timestamps to generate timestamp field and extensions for the padding. - last_rtp_timestamp_ = packet->Timestamp(); + last_rtp_timestamp_ = packet.Timestamp(); last_timestamp_time_ms_ = clock_->TimeInMilliseconds(); - capture_time_ms_ = packet->capture_time_ms(); - return true; + capture_time_ms_ = packet.capture_time_ms(); } void RTPSender::SetSendingMediaStatus(bool enabled) { diff --git a/modules/rtp_rtcp/source/rtp_sender.h b/modules/rtp_rtcp/source/rtp_sender.h index f2b493d0c2..642c647955 100644 --- a/modules/rtp_rtcp/source/rtp_sender.h +++ b/modules/rtp_rtcp/source/rtp_sender.h @@ -137,6 +137,11 @@ class RTPSender { // Return false if sending was turned off. bool AssignSequenceNumber(RtpPacketToSend* packet) RTC_LOCKS_EXCLUDED(send_mutex_); + // Same as AssignSequenceNumber(), but applies sequence numbers atomically to + // a batch of packets. + bool AssignSequenceNumbersAndStoreLastPacketState( + rtc::ArrayView> packets) + RTC_LOCKS_EXCLUDED(send_mutex_); // Maximum header overhead per fec/padding packet. size_t FecOrPaddingPacketMaxRtpHeaderLength() const RTC_LOCKS_EXCLUDED(send_mutex_); @@ -179,6 +184,9 @@ class RTPSender { void UpdateHeaderSizes() RTC_EXCLUSIVE_LOCKS_REQUIRED(send_mutex_); + void UpdateLastPacketState(const RtpPacketToSend& packet) + RTC_EXCLUSIVE_LOCKS_REQUIRED(send_mutex_); + Clock* const clock_; Random random_ RTC_GUARDED_BY(send_mutex_); diff --git a/modules/rtp_rtcp/source/rtp_sender_video.cc b/modules/rtp_rtcp/source/rtp_sender_video.cc index 934be824a4..602cf9d82a 100644 --- a/modules/rtp_rtcp/source/rtp_sender_video.cc +++ b/modules/rtp_rtcp/source/rtp_sender_video.cc @@ -648,8 +648,6 @@ bool RTPSenderVideo::SendVideo( if (!packetizer->NextPacket(packet.get())) return false; RTC_DCHECK_LE(packet->payload_size(), expected_payload_capacity); - if (!rtp_sender_->AssignSequenceNumber(packet.get())) - return false; packet->set_allow_retransmission(allow_retransmission); packet->set_is_key_frame(video_header.frame_type == @@ -670,7 +668,7 @@ bool RTPSenderVideo::SendVideo( red_packet->SetPayloadType(*red_payload_type_); red_packet->set_is_red(true); - // Send |red_packet| instead of |packet| for allocated sequence number. + // Append |red_packet| instead of |packet| to output. red_packet->set_packet_type(RtpPacketMediaType::kVideo); red_packet->set_allow_retransmission(packet->allow_retransmission()); rtp_packets.emplace_back(std::move(red_packet)); @@ -691,6 +689,11 @@ bool RTPSenderVideo::SendVideo( } } + if (!rtp_sender_->AssignSequenceNumbersAndStoreLastPacketState(rtp_packets)) { + // Media not being sent. + return false; + } + LogAndSendToNetwork(std::move(rtp_packets), payload.size()); // Update details about the last sent frame.