diff --git a/modules/rtp_rtcp/source/packet_sequencer.cc b/modules/rtp_rtcp/source/packet_sequencer.cc index e12b20c3ed..39d40ebc1c 100644 --- a/modules/rtp_rtcp/source/packet_sequencer.cc +++ b/modules/rtp_rtcp/source/packet_sequencer.cc @@ -11,6 +11,7 @@ #include "modules/rtp_rtcp/source/packet_sequencer.h" #include "rtc_base/checks.h" +#include "rtc_base/random.h" namespace webrtc { @@ -36,7 +37,15 @@ PacketSequencer::PacketSequencer(uint32_t media_ssrc, last_rtp_timestamp_(0), last_capture_time_ms_(0), last_timestamp_time_ms_(0), - last_packet_marker_bit_(false) {} + last_packet_marker_bit_(false) { + Random random(clock_->TimeInMicroseconds()); + // TODO(bugs.webrtc.org/11340): Check if we can allow the full range of + // [0, 2^16[ to be used instead. + // Random start, 16 bits. Can't be 0. + constexpr uint16_t kMaxInitRtpSeqNumber = 0x7fff; // 2^15 - 1. + media_sequence_number_ = random.Rand(1, kMaxInitRtpSeqNumber); + rtx_sequence_number_ = random.Rand(1, kMaxInitRtpSeqNumber); +} void PacketSequencer::Sequence(RtpPacketToSend& packet) { if (packet.Ssrc() == media_ssrc_) { diff --git a/modules/rtp_rtcp/source/rtp_rtcp_impl.cc b/modules/rtp_rtcp/source/rtp_rtcp_impl.cc index 3f985e213a..52a16ec36d 100644 --- a/modules/rtp_rtcp/source/rtp_rtcp_impl.cc +++ b/modules/rtp_rtcp/source/rtp_rtcp_impl.cc @@ -44,12 +44,17 @@ const int64_t kDefaultExpectedRetransmissionTimeMs = 125; ModuleRtpRtcpImpl::RtpSenderContext::RtpSenderContext( const RtpRtcpInterface::Configuration& config) : packet_history(config.clock, config.enable_rtx_padding_prioritization), + sequencer_(config.local_media_ssrc, + config.rtx_send_ssrc, + /*require_marker_before_media_padding=*/!config.audio, + config.clock), packet_sender(config, &packet_history), non_paced_sender(&packet_sender), packet_generator( config, &packet_history, - config.paced_sender ? config.paced_sender : &non_paced_sender) {} + config.paced_sender ? config.paced_sender : &non_paced_sender, + &sequencer_) {} std::unique_ptr RtpRtcp::DEPRECATED_Create( const Configuration& configuration) { @@ -440,7 +445,8 @@ std::vector> ModuleRtpRtcpImpl::GeneratePadding(size_t target_size_bytes) { RTC_DCHECK(rtp_sender_); return rtp_sender_->packet_generator.GeneratePadding( - target_size_bytes, rtp_sender_->packet_sender.MediaHasBeenSent()); + target_size_bytes, rtp_sender_->packet_sender.MediaHasBeenSent(), + rtp_sender_->sequencer_.CanSendPaddingOnMediaSsrc()); } std::vector diff --git a/modules/rtp_rtcp/source/rtp_rtcp_impl.h b/modules/rtp_rtcp/source/rtp_rtcp_impl.h index 932a02d521..45cfdb4900 100644 --- a/modules/rtp_rtcp/source/rtp_rtcp_impl.h +++ b/modules/rtp_rtcp/source/rtp_rtcp_impl.h @@ -27,6 +27,7 @@ #include "modules/rtp_rtcp/include/rtp_rtcp.h" #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" // RTCPPacketType #include "modules/rtp_rtcp/source/deprecated/deprecated_rtp_sender_egress.h" +#include "modules/rtp_rtcp/source/packet_sequencer.h" #include "modules/rtp_rtcp/source/rtcp_packet/tmmb_item.h" #include "modules/rtp_rtcp/source/rtcp_receiver.h" #include "modules/rtp_rtcp/source/rtcp_sender.h" @@ -273,6 +274,8 @@ class ModuleRtpRtcpImpl : public RtpRtcp, public RTCPReceiver::ModuleRtpRtcp { explicit RtpSenderContext(const RtpRtcpInterface::Configuration& config); // Storage of packets, for retransmissions and padding, if applicable. RtpPacketHistory packet_history; + // Handles sequence number assignment and padding timestamp generation. + PacketSequencer sequencer_; // Handles final time timestamping/stats/etc and handover to Transport. DEPRECATED_RtpSenderEgress packet_sender; // If no paced sender configured, this class will be used to pass packets diff --git a/modules/rtp_rtcp/source/rtp_rtcp_impl2.cc b/modules/rtp_rtcp/source/rtp_rtcp_impl2.cc index c6d19775f2..38fbf4590d 100644 --- a/modules/rtp_rtcp/source/rtp_rtcp_impl2.cc +++ b/modules/rtp_rtcp/source/rtp_rtcp_impl2.cc @@ -63,12 +63,17 @@ int DelayMillisForDuration(TimeDelta duration) { ModuleRtpRtcpImpl2::RtpSenderContext::RtpSenderContext( const RtpRtcpInterface::Configuration& config) : packet_history(config.clock, config.enable_rtx_padding_prioritization), + sequencer_(config.local_media_ssrc, + config.rtx_send_ssrc, + /*require_marker_before_media_padding=*/!config.audio, + config.clock), packet_sender(config, &packet_history), non_paced_sender(&packet_sender, this), packet_generator( config, &packet_history, - config.paced_sender ? config.paced_sender : &non_paced_sender) {} + config.paced_sender ? config.paced_sender : &non_paced_sender, + &sequencer_) {} void ModuleRtpRtcpImpl2::RtpSenderContext::AssignSequenceNumber( RtpPacketToSend* packet) { packet_generator.AssignSequenceNumber(packet); @@ -394,7 +399,8 @@ std::vector> ModuleRtpRtcpImpl2::GeneratePadding(size_t target_size_bytes) { RTC_DCHECK(rtp_sender_); return rtp_sender_->packet_generator.GeneratePadding( - target_size_bytes, rtp_sender_->packet_sender.MediaHasBeenSent()); + target_size_bytes, rtp_sender_->packet_sender.MediaHasBeenSent(), + rtp_sender_->sequencer_.CanSendPaddingOnMediaSsrc()); } std::vector diff --git a/modules/rtp_rtcp/source/rtp_rtcp_impl2.h b/modules/rtp_rtcp/source/rtp_rtcp_impl2.h index 0440879e12..fb1facb2ae 100644 --- a/modules/rtp_rtcp/source/rtp_rtcp_impl2.h +++ b/modules/rtp_rtcp/source/rtp_rtcp_impl2.h @@ -28,6 +28,7 @@ #include "modules/include/module_fec_types.h" #include "modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h" #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" // RTCPPacketType +#include "modules/rtp_rtcp/source/packet_sequencer.h" #include "modules/rtp_rtcp/source/rtcp_packet/tmmb_item.h" #include "modules/rtp_rtcp/source/rtcp_receiver.h" #include "modules/rtp_rtcp/source/rtcp_sender.h" @@ -265,6 +266,8 @@ class ModuleRtpRtcpImpl2 final : public RtpRtcpInterface, void AssignSequenceNumber(RtpPacketToSend* packet) override; // Storage of packets, for retransmissions and padding, if applicable. RtpPacketHistory packet_history; + // Handles sequence number assignment and padding timestamp generation. + PacketSequencer sequencer_; // Handles final time timestamping/stats/etc and handover to Transport. RtpSenderEgress packet_sender; // If no paced sender configured, this class will be used to pass packets diff --git a/modules/rtp_rtcp/source/rtp_sender.cc b/modules/rtp_rtcp/source/rtp_sender.cc index 100d123f05..de799571f4 100644 --- a/modules/rtp_rtcp/source/rtp_sender.cc +++ b/modules/rtp_rtcp/source/rtp_sender.cc @@ -16,6 +16,7 @@ #include #include +#include "absl/memory/memory.h" #include "absl/strings/match.h" #include "api/array_view.h" #include "api/rtc_event_log/rtc_event_log.h" @@ -41,7 +42,6 @@ namespace { constexpr size_t kMaxPaddingLength = 224; constexpr size_t kMinAudioPaddingLength = 50; constexpr size_t kRtpHeaderLength = 12; -constexpr uint16_t kMaxInitRtpSeqNumber = 32767; // 2^15 -1. // Min size needed to get payload padding from packet history. constexpr int kMinPayloadPaddingBytes = 50; @@ -158,7 +158,8 @@ double GetMaxPaddingSizeFactor(const WebRtcKeyValueConfig* field_trials) { RTPSender::RTPSender(const RtpRtcpInterface::Configuration& config, RtpPacketHistory* packet_history, - RtpPacketSender* packet_sender) + RtpPacketSender* packet_sender, + PacketSequencer* packet_sequencer) : clock_(config.clock), random_(clock_->TimeInMicroseconds()), audio_configured_(config.audio), @@ -173,10 +174,7 @@ RTPSender::RTPSender(const RtpRtcpInterface::Configuration& config, max_packet_size_(IP_PACKET_SIZE - 28), // Default is IP-v4/UDP. rtp_header_extension_map_(config.extmap_allow_mixed), // RTP variables - sequencer_(config.local_media_ssrc, - rtx_ssrc_, - /*require_marker_before_media_padding_=*/!config.audio, - config.clock), + sequencer_(packet_sequencer), always_send_mid_and_rid_(config.always_send_mid_and_rid), ssrc_has_acked_(false), rtx_ssrc_has_acked_(false), @@ -187,14 +185,25 @@ RTPSender::RTPSender(const RtpRtcpInterface::Configuration& config, UpdateHeaderSizes(); // This random initialization is not intended to be cryptographic strong. timestamp_offset_ = random_.Rand(); - // Random start, 16 bits. Can't be 0. - sequencer_.set_rtx_sequence_number(random_.Rand(1, kMaxInitRtpSeqNumber)); - sequencer_.set_media_sequence_number(random_.Rand(1, kMaxInitRtpSeqNumber)); RTC_DCHECK(paced_sender_); RTC_DCHECK(packet_history_); } +RTPSender::RTPSender(const RtpRtcpInterface::Configuration& config, + RtpPacketHistory* packet_history, + RtpPacketSender* packet_sender) + : RTPSender(config, + packet_history, + packet_sender, + new PacketSequencer( + config.local_media_ssrc, + config.rtx_send_ssrc, + /*require_marker_before_media_padding_=*/!config.audio, + config.clock)) { + owned_sequencer_ = absl::WrapUnique(sequencer_); +} + RTPSender::~RTPSender() { // TODO(tommi): Use a thread checker to ensure the object is created and // deleted on the same thread. At the moment this isn't possible due to @@ -384,7 +393,8 @@ bool RTPSender::SupportsRtxPayloadPadding() const { std::vector> RTPSender::GeneratePadding( size_t target_size_bytes, - bool media_has_been_sent) { + bool media_has_been_sent, + bool can_send_padding_on_media_ssrc) { // This method does not actually send packets, it just generates // them and puts them in the pacer queue. Since this should incur // low overhead, keep the lock for the scope of the method in order @@ -446,11 +456,16 @@ std::vector> RTPSender::GeneratePadding( padding_packet->set_packet_type(RtpPacketMediaType::kPadding); padding_packet->SetMarker(false); if (rtx_ == kRtxOff) { - if (!sequencer_.CanSendPaddingOnMediaSsrc()) { + bool can_send_padding = sequencer_ + ? sequencer_->CanSendPaddingOnMediaSsrc() + : can_send_padding_on_media_ssrc; + if (!can_send_padding) { break; } padding_packet->SetSsrc(ssrc_); - sequencer_.Sequence(*padding_packet); + if (sequencer_) { + sequencer_->Sequence(*padding_packet); + } } else { // Without abs-send-time or transport sequence number a media packet // must be sent before padding so that the timestamps used for @@ -465,7 +480,9 @@ std::vector> RTPSender::GeneratePadding( RTC_DCHECK(rtx_ssrc_); padding_packet->SetSsrc(*rtx_ssrc_); padding_packet->SetPayloadType(rtx_payload_type_map_.begin()->second); - sequencer_.Sequence(*padding_packet); + if (sequencer_) { + sequencer_->Sequence(*padding_packet); + } } if (rtp_header_extension_map_.IsRegistered(TransportSequenceNumber::kId)) { @@ -574,9 +591,10 @@ std::unique_ptr RTPSender::AllocatePacket() const { bool RTPSender::AssignSequenceNumber(RtpPacketToSend* packet) { MutexLock lock(&send_mutex_); + RTC_DCHECK(sequencer_); if (!sending_media_) return false; - sequencer_.Sequence(*packet); + sequencer_->Sequence(*packet); return true; } @@ -584,10 +602,11 @@ bool RTPSender::AssignSequenceNumbersAndStoreLastPacketState( rtc::ArrayView> packets) { RTC_DCHECK(!packets.empty()); MutexLock lock(&send_mutex_); + RTC_DCHECK(sequencer_); if (!sending_media_) return false; for (auto& packet : packets) { - sequencer_.Sequence(*packet); + sequencer_->Sequence(*packet); } return true; } @@ -643,10 +662,11 @@ void RTPSender::SetSequenceNumber(uint16_t seq) { bool updated_sequence_number = false; { MutexLock lock(&send_mutex_); - if (sequencer_.media_sequence_number() != seq) { + RTC_DCHECK(sequencer_); + if (sequencer_->media_sequence_number() != seq) { updated_sequence_number = true; } - sequencer_.set_media_sequence_number(seq); + sequencer_->set_media_sequence_number(seq); } if (updated_sequence_number) { @@ -658,7 +678,8 @@ void RTPSender::SetSequenceNumber(uint16_t seq) { uint16_t RTPSender::SequenceNumber() const { MutexLock lock(&send_mutex_); - return sequencer_.media_sequence_number(); + RTC_DCHECK(sequencer_); + return sequencer_->media_sequence_number(); } static void CopyHeaderAndExtensionsToRtxPacket(const RtpPacketToSend& packet, @@ -735,7 +756,9 @@ std::unique_ptr RTPSender::BuildRtxPacket( rtx_packet->SetSsrc(*rtx_ssrc_); // Replace sequence number. - sequencer_.Sequence(*rtx_packet); + if (sequencer_) { + sequencer_->Sequence(*rtx_packet); + } CopyHeaderAndExtensionsToRtxPacket(packet, rtx_packet.get()); @@ -784,7 +807,9 @@ void RTPSender::SetRtpState(const RtpState& rtp_state) { MutexLock lock(&send_mutex_); timestamp_offset_ = rtp_state.start_timestamp; - sequencer_.SetRtpState(rtp_state); + if (sequencer_) { + sequencer_->SetRtpState(rtp_state); + } ssrc_has_acked_ = rtp_state.ssrc_has_acked; UpdateHeaderSizes(); } @@ -795,13 +820,17 @@ RtpState RTPSender::GetRtpState() const { RtpState state; state.start_timestamp = timestamp_offset_; state.ssrc_has_acked = ssrc_has_acked_; - sequencer_.PupulateRtpState(state); + if (sequencer_) { + sequencer_->PupulateRtpState(state); + } return state; } void RTPSender::SetRtxRtpState(const RtpState& rtp_state) { MutexLock lock(&send_mutex_); - sequencer_.set_rtx_sequence_number(rtp_state.sequence_number); + if (sequencer_) { + sequencer_->set_rtx_sequence_number(rtp_state.sequence_number); + } rtx_ssrc_has_acked_ = rtp_state.ssrc_has_acked; } @@ -809,7 +838,9 @@ RtpState RTPSender::GetRtxRtpState() const { MutexLock lock(&send_mutex_); RtpState state; - state.sequence_number = sequencer_.rtx_sequence_number(); + if (sequencer_) { + state.sequence_number = sequencer_->rtx_sequence_number(); + } state.start_timestamp = timestamp_offset_; state.ssrc_has_acked = rtx_ssrc_has_acked_; diff --git a/modules/rtp_rtcp/source/rtp_sender.h b/modules/rtp_rtcp/source/rtp_sender.h index fbf135049c..6662c33f4b 100644 --- a/modules/rtp_rtcp/source/rtp_sender.h +++ b/modules/rtp_rtcp/source/rtp_sender.h @@ -46,7 +46,14 @@ class RTPSender { public: RTPSender(const RtpRtcpInterface::Configuration& config, RtpPacketHistory* packet_history, - RtpPacketSender* packet_sender); + RtpPacketSender* packet_sender, + PacketSequencer* packet_sequencer); + + // TODO(bugs.webrtc.org/11340): Remove when downstream usage is gone. + RTPSender(const RtpRtcpInterface::Configuration& config, + RtpPacketHistory* packet_history, + RtpPacketSender* packet_sender) + ABSL_DEPRECATED("bugs.webrtc.org/11340"); RTPSender() = delete; RTPSender(const RTPSender&) = delete; @@ -92,7 +99,11 @@ class RTPSender { std::vector> GeneratePadding( size_t target_size_bytes, - bool media_has_been_sent) RTC_LOCKS_EXCLUDED(send_mutex_); + bool media_has_been_sent, + // TODO(bugs.webrtc.org/11340): Remove default value when downstream usage + // is fixed. + bool can_send_padding_on_media_ssrc = false) + RTC_LOCKS_EXCLUDED(send_mutex_); // NACK. void OnReceivedNack(const std::vector& nack_sequence_numbers, @@ -209,7 +220,9 @@ class RTPSender { // RTP variables uint32_t timestamp_offset_ RTC_GUARDED_BY(send_mutex_); - PacketSequencer sequencer_ RTC_GUARDED_BY(send_mutex_); + // TODO(bugs.webrtc.org/11340): Remove when downstream usage is gone. + std::unique_ptr owned_sequencer_ RTC_GUARDED_BY(send_mutex_); + PacketSequencer* const sequencer_ RTC_GUARDED_BY(send_mutex_); // RID value to send in the RID or RepairedRID header extension. std::string rid_ RTC_GUARDED_BY(send_mutex_); // MID value to send in the MID header extension. diff --git a/modules/rtp_rtcp/source/rtp_sender_unittest.cc b/modules/rtp_rtcp/source/rtp_sender_unittest.cc index 7237bee648..28e0271c4e 100644 --- a/modules/rtp_rtcp/source/rtp_sender_unittest.cc +++ b/modules/rtp_rtcp/source/rtp_sender_unittest.cc @@ -22,6 +22,7 @@ #include "modules/rtp_rtcp/include/rtp_header_extension_map.h" #include "modules/rtp_rtcp/include/rtp_packet_sender.h" #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" +#include "modules/rtp_rtcp/source/packet_sequencer.h" #include "modules/rtp_rtcp/source/rtp_format_video_generic.h" #include "modules/rtp_rtcp/source/rtp_generic_frame_descriptor.h" #include "modules/rtp_rtcp/source/rtp_generic_frame_descriptor_extension.h" @@ -137,8 +138,8 @@ class RtpSenderTest : public ::testing::Test { std::vector(), nullptr, clock_), - kMarkerBit(true) { - } + deferred_sequencing_(false), + kMarkerBit(true) {} void SetUp() override { SetUpRtpSender(true, false, nullptr); } @@ -167,10 +168,29 @@ class RtpSenderTest : public ::testing::Test { void CreateSender(const RtpRtcpInterface::Configuration& config) { packet_history_ = std::make_unique( config.clock, config.enable_rtx_padding_prioritization); - rtp_sender_ = std::make_unique(config, packet_history_.get(), - config.paced_sender); + sequencer_.emplace(kSsrc, kRtxSsrc, + /*require_marker_before_media_padding=*/!config.audio, + clock_); + rtp_sender_ = + std::make_unique(config, packet_history_.get(), + config.paced_sender, &sequencer_.value()); rtp_sender_->SetSequenceNumber(kSeqNum); rtp_sender_->SetTimestampOffset(0); + deferred_sequencing_ = false; + } + + void CreateSenderWithDeferredSequencing( + const RtpRtcpInterface::Configuration& config) { + packet_history_ = std::make_unique( + config.clock, config.enable_rtx_padding_prioritization); + sequencer_.emplace(kSsrc, kRtxSsrc, + /*require_marker_before_media_padding=*/!config.audio, + clock_); + rtp_sender_ = std::make_unique(config, packet_history_.get(), + config.paced_sender, nullptr); + sequencer_->set_media_sequence_number(kSeqNum); + rtp_sender_->SetTimestampOffset(0); + deferred_sequencing_ = true; } GlobalSimulatedTimeController time_controller_; @@ -180,6 +200,8 @@ class RtpSenderTest : public ::testing::Test { RateLimiter retransmission_rate_limiter_; FlexfecSender flexfec_sender_; + bool deferred_sequencing_; + absl::optional sequencer_; std::unique_ptr packet_history_; std::unique_ptr rtp_sender_; @@ -196,7 +218,9 @@ class RtpSenderTest : public ::testing::Test { packet->SetMarker(marker_bit); packet->SetTimestamp(timestamp); packet->set_capture_time_ms(capture_time_ms); - EXPECT_TRUE(rtp_sender_->AssignSequenceNumber(packet.get())); + if (!deferred_sequencing_) { + EXPECT_TRUE(rtp_sender_->AssignSequenceNumber(packet.get())); + } return packet; } @@ -224,9 +248,16 @@ class RtpSenderTest : public ::testing::Test { rtp_sender_->ExpectedPerPacketOverhead()); } + std::vector> GeneratePadding( + size_t target_size_bytes) { + return rtp_sender_->GeneratePadding( + target_size_bytes, /*media_has_been_sent=*/true, + sequencer_->CanSendPaddingOnMediaSsrc()); + } + size_t GenerateAndSendPadding(size_t target_size_bytes) { size_t generated_bytes = 0; - for (auto& packet : rtp_sender_->GeneratePadding(target_size_bytes, true)) { + for (auto& packet : GeneratePadding(target_size_bytes)) { generated_bytes += packet->payload_size() + packet->padding_size(); rtp_sender_->SendToNetwork(std::move(packet)); } @@ -395,7 +426,8 @@ TEST_F(RtpSenderTest, SendPadding) { media_packet->Timestamp())))))); std::vector> padding_packets = rtp_sender_->GeneratePadding(kPaddingTargetBytes, - /*media_has_been_sent=*/true); + /*media_has_been_sent=*/true, + /*can_send_padding_on_media_ssrc=*/true); ASSERT_THAT(padding_packets, SizeIs(1)); rtp_sender_->SendToNetwork(std::move(padding_packets[0])); } @@ -415,14 +447,18 @@ TEST_F(RtpSenderTest, SendPadding) { } TEST_F(RtpSenderTest, NoPaddingAsFirstPacketWithoutBweExtensions) { - EXPECT_THAT(rtp_sender_->GeneratePadding(/*target_size_bytes=*/100, - /*media_has_been_sent=*/false), + EXPECT_THAT(rtp_sender_->GeneratePadding( + /*target_size_bytes=*/100, + /*media_has_been_sent=*/false, + /*can_send_padding_on_media_ssrc=*/false), IsEmpty()); // Don't send padding before media even with RTX. EnableRtx(); - EXPECT_THAT(rtp_sender_->GeneratePadding(/*target_size_bytes=*/100, - /*media_has_been_sent=*/false), + EXPECT_THAT(rtp_sender_->GeneratePadding( + /*target_size_bytes=*/100, + /*media_has_been_sent=*/false, + /*can_send_padding_on_media_ssrc=*/false), IsEmpty()); } @@ -432,14 +468,18 @@ TEST_F(RtpSenderTest, AllowPaddingAsFirstPacketOnRtxWithTransportCc) { // Padding can't be sent as first packet on media SSRC since we don't know // what payload type to assign. - EXPECT_THAT(rtp_sender_->GeneratePadding(/*target_size_bytes=*/100, - /*media_has_been_sent=*/false), + EXPECT_THAT(rtp_sender_->GeneratePadding( + /*target_size_bytes=*/100, + /*media_has_been_sent=*/false, + /*can_send_padding_on_media_ssrc=*/false), IsEmpty()); // With transportcc padding can be sent as first packet on the RTX SSRC. EnableRtx(); - EXPECT_THAT(rtp_sender_->GeneratePadding(/*target_size_bytes=*/100, - /*media_has_been_sent=*/false), + EXPECT_THAT(rtp_sender_->GeneratePadding( + /*target_size_bytes=*/100, + /*media_has_been_sent=*/false, + /*can_send_padding_on_media_ssrc=*/false), Not(IsEmpty())); } @@ -449,14 +489,18 @@ TEST_F(RtpSenderTest, AllowPaddingAsFirstPacketOnRtxWithAbsSendTime) { // Padding can't be sent as first packet on media SSRC since we don't know // what payload type to assign. - EXPECT_THAT(rtp_sender_->GeneratePadding(/*target_size_bytes=*/100, - /*media_has_been_sent=*/false), + EXPECT_THAT(rtp_sender_->GeneratePadding( + /*target_size_bytes=*/100, + /*media_has_been_sent=*/false, + /*can_send_padding_on_media_ssrc=*/false), IsEmpty()); // With abs send time, padding can be sent as first packet on the RTX SSRC. EnableRtx(); - EXPECT_THAT(rtp_sender_->GeneratePadding(/*target_size_bytes=*/100, - /*media_has_been_sent=*/false), + EXPECT_THAT(rtp_sender_->GeneratePadding( + /*target_size_bytes=*/100, + /*media_has_been_sent=*/false, + /*can_send_padding_on_media_ssrc=*/false), Not(IsEmpty())); } @@ -482,8 +526,7 @@ TEST_F(RtpSenderTest, UpdatesTimestampsOnPlainRtxPadding) { // Timestamps on padding should be offset from the sent media. EXPECT_THAT( - rtp_sender_->GeneratePadding(/*target_size_bytes=*/100, - /*media_has_been_sent=*/true), + GeneratePadding(/*target_size_bytes=*/100), Each(AllOf( Pointee(Property(&RtpPacketToSend::padding_size, kMaxPaddingLength)), Pointee(Property( @@ -520,8 +563,7 @@ TEST_F(RtpSenderTest, KeepsTimestampsOnPayloadPadding) { // Timestamps on payload padding should be set to original. EXPECT_THAT( - rtp_sender_->GeneratePadding(/*target_size_bytes=*/100, - /*media_has_been_sent=*/true), + GeneratePadding(/*target_size_bytes=*/100), Each(AllOf( Pointee(Property(&RtpPacketToSend::padding_size, 0u)), Pointee(Property(&RtpPacketToSend::payload_size, @@ -1004,7 +1046,7 @@ TEST_F(RtpSenderTest, GeneratedPaddingHasBweExtensions) { // Generate a plain padding packet, check that extensions are registered. std::vector> generated_packets = - rtp_sender_->GeneratePadding(/*target_size_bytes=*/1, true); + GeneratePadding(/*target_size_bytes=*/1); ASSERT_THAT(generated_packets, SizeIs(1)); auto& plain_padding = generated_packets.front(); EXPECT_GT(plain_padding->padding_size(), 0u); @@ -1014,7 +1056,7 @@ TEST_F(RtpSenderTest, GeneratedPaddingHasBweExtensions) { EXPECT_GT(plain_padding->padding_size(), 0u); // Generate a payload padding packets, check that extensions are registered. - generated_packets = rtp_sender_->GeneratePadding(kMinPaddingSize, true); + generated_packets = GeneratePadding(kMinPaddingSize); ASSERT_EQ(generated_packets.size(), 1u); auto& payload_padding = generated_packets.front(); EXPECT_EQ(payload_padding->padding_size(), 0u); @@ -1048,7 +1090,7 @@ TEST_F(RtpSenderTest, GeneratePaddingResendsOldPacketsWithRtx) { // Generated padding has large enough budget that the video packet should be // retransmitted as padding. std::vector> generated_packets = - rtp_sender_->GeneratePadding(kMinPaddingSize, true); + GeneratePadding(kMinPaddingSize); ASSERT_EQ(generated_packets.size(), 1u); auto& padding_packet = generated_packets.front(); EXPECT_EQ(padding_packet->packet_type(), RtpPacketMediaType::kPadding); @@ -1060,8 +1102,7 @@ TEST_F(RtpSenderTest, GeneratePaddingResendsOldPacketsWithRtx) { const size_t kPaddingBytesRequested = kMinPaddingSize - 1; size_t padding_bytes_generated = 0; - generated_packets = - rtp_sender_->GeneratePadding(kPaddingBytesRequested, true); + generated_packets = GeneratePadding(kPaddingBytesRequested); EXPECT_EQ(generated_packets.size(), 1u); for (auto& packet : generated_packets) { EXPECT_EQ(packet->packet_type(), RtpPacketMediaType::kPadding); @@ -1105,14 +1146,14 @@ TEST_F(RtpSenderTest, LimitsPayloadPaddingSize) { // Generated padding has large enough budget that the video packet should be // retransmitted as padding. EXPECT_THAT( - rtp_sender_->GeneratePadding(kMinTargerSizeForPayload, true), + GeneratePadding(kMinTargerSizeForPayload), AllOf(Not(IsEmpty()), Each(Pointee(Property(&RtpPacketToSend::padding_size, Eq(0u)))))); // If payload padding is > 2x requested size, plain padding is returned // instead. EXPECT_THAT( - rtp_sender_->GeneratePadding(kMinTargerSizeForPayload - 1, true), + GeneratePadding(kMinTargerSizeForPayload - 1), AllOf(Not(IsEmpty()), Each(Pointee(Property(&RtpPacketToSend::padding_size, Gt(0u)))))); } @@ -1148,7 +1189,7 @@ TEST_F(RtpSenderTest, GeneratePaddingCreatesPurePaddingWithoutRtx) { (kPaddingBytesRequested + kMaxPaddingSize - 1) / kMaxPaddingSize; size_t padding_bytes_generated = 0; std::vector> padding_packets = - rtp_sender_->GeneratePadding(kPaddingBytesRequested, true); + GeneratePadding(kPaddingBytesRequested); EXPECT_EQ(padding_packets.size(), kExpectedNumPaddingPackets); for (auto& packet : padding_packets) { EXPECT_EQ(packet->packet_type(), RtpPacketMediaType::kPadding); @@ -1337,4 +1378,70 @@ TEST_F(RtpSenderTest, MarksPacketsWithKeyframeStatus) { } } +TEST_F(RtpSenderTest, PlainPaddingWithDeferredSequencing) { + CreateSenderWithDeferredSequencing(GetDefaultConfig()); + + EXPECT_THAT( + rtp_sender_->GeneratePadding( + /*target_size_bytes=*/500, + /*media_has_been_sent=*/true, + /*can_send_padding_on_media_ssrc=*/true), + Each(Pointee(AllOf(Property(&RtpPacketToSend::SequenceNumber, 0), + Property(&RtpPacketToSend::padding_size, Gt(0u)), + Property(&RtpPacketToSend::Ssrc, kSsrc))))); +} + +TEST_F(RtpSenderTest, PlainRtxPaddingWithDeferredSequencing) { + CreateSenderWithDeferredSequencing(GetDefaultConfig()); + EnableRtx(); + + EXPECT_THAT( + rtp_sender_->GeneratePadding( + /*target_size_bytes=*/500, + /*media_has_been_sent=*/true, + /*can_send_padding_on_media_ssrc=*/true), + Each(Pointee(AllOf(Property(&RtpPacketToSend::SequenceNumber, 0), + Property(&RtpPacketToSend::padding_size, Gt(0u)), + Property(&RtpPacketToSend::Ssrc, kRtxSsrc))))); +} + +TEST_F(RtpSenderTest, PayloadPaddingWithDeferredSequencing) { + CreateSenderWithDeferredSequencing(GetDefaultConfig()); + EnableRtx(); + ASSERT_TRUE(rtp_sender_->RegisterRtpHeaderExtension( + TransportSequenceNumber::kUri, kTransportSequenceNumberExtensionId)); + + EXPECT_CALL(mock_paced_sender_, EnqueuePackets); + std::unique_ptr media_packet = + SendPacket(clock_->TimeInMilliseconds(), /*payload_size=*/500); + packet_history_->PutRtpPacket(std::move(media_packet), + clock_->TimeInMilliseconds()); + + EXPECT_THAT( + rtp_sender_->GeneratePadding( + /*target_size_bytes=*/500, + /*media_has_been_sent=*/true, + /*can_send_padding_on_media_ssrc=*/true), + Each(Pointee(AllOf(Property(&RtpPacketToSend::SequenceNumber, 0), + Property(&RtpPacketToSend::payload_size, Gt(0u)), + Property(&RtpPacketToSend::Ssrc, kRtxSsrc))))); +} + +TEST_F(RtpSenderTest, RtxRetransmissionWithDeferredSequencing) { + CreateSenderWithDeferredSequencing(GetDefaultConfig()); + EnableRtx(); + + int64_t now_ms = clock_->TimeInMilliseconds(); + auto packet = BuildRtpPacket(kPayload, kMarkerBit, kTimestamp, now_ms); + packet->SetSequenceNumber(kSeqNum); + packet->set_allow_retransmission(true); + packet_history_->PutRtpPacket(std::move(packet), now_ms); + + EXPECT_CALL(mock_paced_sender_, + EnqueuePackets(ElementsAre(Pointee( + AllOf(Property(&RtpPacketToSend::Ssrc, kRtxSsrc), + Property(&RtpPacketToSend::SequenceNumber, 0u)))))); + EXPECT_TRUE(rtp_sender_->ReSendPacket(kSeqNum)); +} + } // namespace webrtc