diff --git a/modules/rtp_rtcp/source/rtp_sender.cc b/modules/rtp_rtcp/source/rtp_sender.cc index 0ab938b610..a2cad52c53 100644 --- a/modules/rtp_rtcp/source/rtp_sender.cc +++ b/modules/rtp_rtcp/source/rtp_sender.cc @@ -812,8 +812,13 @@ bool RTPSender::TrySendPacket(RtpPacketToSend* packet, // the FEC. int64_t now_ms = clock_->TimeInMilliseconds(); int64_t diff_ms = now_ms - packet->capture_time_ms(); - packet->SetExtension(kTimestampTicksPerMs * diff_ms); - packet->SetExtension(AbsoluteSendTime::MsTo24Bits(now_ms)); + if (packet->IsExtensionReserved()) { + packet->SetExtension(kTimestampTicksPerMs * diff_ms); + } + if (packet->IsExtensionReserved()) { + packet->SetExtension( + AbsoluteSendTime::MsTo24Bits(now_ms)); + } if (packet->HasExtension()) { if (populate_network2_timestamp_) { @@ -999,14 +1004,10 @@ std::vector> RTPSender::GeneratePadding( // 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 // to make the code more readable. - rtc::CritScope lock(&send_critsect_); - if (!sending_media_) { - return {}; - } std::vector> padding_packets; size_t bytes_left = target_size_bytes; - if ((rtx_ & kRtxRedundantPayloads) != 0) { + if (SupportsRtxPayloadPadding()) { while (bytes_left >= kMinPayloadPaddingBytes) { std::unique_ptr packet = packet_history_.GetPayloadPaddingPacket( @@ -1024,6 +1025,11 @@ std::vector> RTPSender::GeneratePadding( } } + rtc::CritScope lock(&send_critsect_); + if (!sending_media_) { + return {}; + } + size_t padding_bytes_in_packet; const size_t max_payload_size = max_packet_size_ - RtpHeaderLength(); if (audio_configured_) { @@ -1092,6 +1098,13 @@ std::vector> RTPSender::GeneratePadding( if (rtp_header_extension_map_.IsRegistered(TransportSequenceNumber::kId)) { padding_packet->ReserveExtension(); } + if (rtp_header_extension_map_.IsRegistered(TransmissionOffset::kId)) { + padding_packet->ReserveExtension(); + } + if (rtp_header_extension_map_.IsRegistered(AbsoluteSendTime::kId)) { + padding_packet->ReserveExtension(); + } + padding_packet->SetPadding(padding_bytes_in_packet); bytes_left -= std::min(bytes_left, padding_bytes_in_packet); padding_packets.push_back(std::move(padding_packet)); diff --git a/modules/rtp_rtcp/source/rtp_sender_unittest.cc b/modules/rtp_rtcp/source/rtp_sender_unittest.cc index b5703363fb..c9121c8e11 100644 --- a/modules/rtp_rtcp/source/rtp_sender_unittest.cc +++ b/modules/rtp_rtcp/source/rtp_sender_unittest.cc @@ -2556,6 +2556,16 @@ TEST_P(RtpSenderTest, GeneratePaddingResendsOldPacketsWithRtx) { rtp_sender_->SetRtxPayloadType(kRtxPayload, kPayload); rtp_sender_->SetStorePacketsStatus(true, 1); + ASSERT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension( + kRtpExtensionTransmissionTimeOffset, + kTransmissionTimeOffsetExtensionId)); + ASSERT_EQ( + 0, rtp_sender_->RegisterRtpHeaderExtension(kRtpExtensionAbsoluteSendTime, + kAbsoluteSendTimeExtensionId)); + ASSERT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension( + kRtpExtensionTransportSequenceNumber, + kTransportSequenceNumberExtensionId)); + const size_t kPayloadPacketSize = 1234; std::unique_ptr packet = BuildRtpPacket(kPayload, true, 0, fake_clock_.TimeInMilliseconds()); @@ -2564,6 +2574,7 @@ TEST_P(RtpSenderTest, GeneratePaddingResendsOldPacketsWithRtx) { packet->set_packet_type(RtpPacketToSend::Type::kVideo); // Send a dummy video packet so it ends up in the packet history. + EXPECT_CALL(send_packet_observer_, OnSendPacket).Times(1); EXPECT_TRUE(rtp_sender_->TrySendPacket(packet.get(), PacedPacketInfo())); // Generated padding has large enough budget that the video packet should be @@ -2576,6 +2587,18 @@ TEST_P(RtpSenderTest, GeneratePaddingResendsOldPacketsWithRtx) { EXPECT_EQ(padding_packet->Ssrc(), kRtxSsrc); EXPECT_EQ(padding_packet->payload_size(), kPayloadPacketSize + kRtxHeaderSize); + EXPECT_TRUE(padding_packet->IsExtensionReserved()); + EXPECT_TRUE(padding_packet->IsExtensionReserved()); + EXPECT_TRUE(padding_packet->IsExtensionReserved()); + + // Verify all header extensions are received. + EXPECT_TRUE( + rtp_sender_->TrySendPacket(padding_packet.get(), PacedPacketInfo())); + webrtc::RTPHeader rtp_header; + transport_.last_sent_packet().GetHeader(&rtp_header); + EXPECT_TRUE(rtp_header.extension.hasAbsoluteSendTime); + EXPECT_TRUE(rtp_header.extension.hasTransmissionTimeOffset); + EXPECT_TRUE(rtp_header.extension.hasTransportSequenceNumber); // Not enough budged for payload padding, use plain padding instead. const size_t kPaddingBytesRequested = kMinPaddingSize - 1; @@ -2589,6 +2612,18 @@ TEST_P(RtpSenderTest, GeneratePaddingResendsOldPacketsWithRtx) { EXPECT_EQ(packet->payload_size(), 0u); EXPECT_GT(packet->padding_size(), 0u); padding_bytes_generated += packet->padding_size(); + + EXPECT_TRUE(packet->IsExtensionReserved()); + EXPECT_TRUE(packet->IsExtensionReserved()); + EXPECT_TRUE(packet->IsExtensionReserved()); + + // Verify all header extensions are received. + EXPECT_TRUE(rtp_sender_->TrySendPacket(packet.get(), PacedPacketInfo())); + webrtc::RTPHeader rtp_header; + transport_.last_sent_packet().GetHeader(&rtp_header); + EXPECT_TRUE(rtp_header.extension.hasAbsoluteSendTime); + EXPECT_TRUE(rtp_header.extension.hasTransmissionTimeOffset); + EXPECT_TRUE(rtp_header.extension.hasTransportSequenceNumber); } EXPECT_EQ(padding_bytes_generated, kMaxPaddingSize); @@ -2596,6 +2631,15 @@ TEST_P(RtpSenderTest, GeneratePaddingResendsOldPacketsWithRtx) { TEST_P(RtpSenderTest, GeneratePaddingCreatesPurePaddingWithoutRtx) { rtp_sender_->SetStorePacketsStatus(true, 1); + ASSERT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension( + kRtpExtensionTransmissionTimeOffset, + kTransmissionTimeOffsetExtensionId)); + ASSERT_EQ( + 0, rtp_sender_->RegisterRtpHeaderExtension(kRtpExtensionAbsoluteSendTime, + kAbsoluteSendTimeExtensionId)); + ASSERT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension( + kRtpExtensionTransportSequenceNumber, + kTransportSequenceNumberExtensionId)); const size_t kPayloadPacketSize = 1234; // Send a dummy video packet so it ends up in the packet history. Since we @@ -2605,6 +2649,7 @@ TEST_P(RtpSenderTest, GeneratePaddingCreatesPurePaddingWithoutRtx) { packet->set_allow_retransmission(true); packet->SetPayloadSize(kPayloadPacketSize); packet->set_packet_type(RtpPacketToSend::Type::kVideo); + EXPECT_CALL(send_packet_observer_, OnSendPacket).Times(1); EXPECT_TRUE(rtp_sender_->TrySendPacket(packet.get(), PacedPacketInfo())); // Payload padding not available without RTX, only generate plain padding on @@ -2625,6 +2670,17 @@ TEST_P(RtpSenderTest, GeneratePaddingCreatesPurePaddingWithoutRtx) { EXPECT_EQ(packet->payload_size(), 0u); EXPECT_GT(packet->padding_size(), 0u); padding_bytes_generated += packet->padding_size(); + EXPECT_TRUE(packet->IsExtensionReserved()); + EXPECT_TRUE(packet->IsExtensionReserved()); + EXPECT_TRUE(packet->IsExtensionReserved()); + + // Verify all header extensions are received. + EXPECT_TRUE(rtp_sender_->TrySendPacket(packet.get(), PacedPacketInfo())); + webrtc::RTPHeader rtp_header; + transport_.last_sent_packet().GetHeader(&rtp_header); + EXPECT_TRUE(rtp_header.extension.hasAbsoluteSendTime); + EXPECT_TRUE(rtp_header.extension.hasTransmissionTimeOffset); + EXPECT_TRUE(rtp_header.extension.hasTransportSequenceNumber); } EXPECT_EQ(padding_bytes_generated,