diff --git a/modules/rtp_rtcp/source/rtp_packet_history.cc b/modules/rtp_rtcp/source/rtp_packet_history.cc index 53361811f8..e8488e0fb6 100644 --- a/modules/rtp_rtcp/source/rtp_packet_history.cc +++ b/modules/rtp_rtcp/source/rtp_packet_history.cc @@ -241,10 +241,14 @@ std::unique_ptr RtpPacketHistory::GetPacketAndMarkAsPending( return nullptr; } - packet.pending_transmission_ = true; - // Copy and/or encapsulate packet. - return encapsulate(*packet.packet_); + std::unique_ptr encapsulated_packet = + encapsulate(*packet.packet_); + if (encapsulated_packet) { + packet.pending_transmission_ = true; + } + + return encapsulated_packet; } void RtpPacketHistory::MarkPacketAsSent(uint16_t sequence_number) { diff --git a/modules/rtp_rtcp/source/rtp_packet_history.h b/modules/rtp_rtcp/source/rtp_packet_history.h index 44ebf4325f..b988b68068 100644 --- a/modules/rtp_rtcp/source/rtp_packet_history.h +++ b/modules/rtp_rtcp/source/rtp_packet_history.h @@ -93,6 +93,8 @@ class RtpPacketHistory { // In addition to getting packet and marking as sent, this method takes an // encapsulator function that takes a reference to the packet and outputs a // copy that may be wrapped in a container, eg RTX. + // If the the encapsulator returns nullptr, the retransmit is aborted and the + // packet will not be marked as pending. std::unique_ptr GetPacketAndMarkAsPending( uint16_t sequence_number, rtc::FunctionView( diff --git a/modules/rtp_rtcp/source/rtp_packet_history_unittest.cc b/modules/rtp_rtcp/source/rtp_packet_history_unittest.cc index 6a577fa185..950cbe6a14 100644 --- a/modules/rtp_rtcp/source/rtp_packet_history_unittest.cc +++ b/modules/rtp_rtcp/source/rtp_packet_history_unittest.cc @@ -734,6 +734,23 @@ TEST_F(RtpPacketHistoryTest, GetPacketWithEncapsulation) { EXPECT_EQ(retransmit_packet->Ssrc(), kSsrc + 1); } +TEST_F(RtpPacketHistoryTest, GetPacketWithEncapsulationAbortOnNullptr) { + hist_.SetStorePacketsStatus(StorageMode::kStoreAndCull, 1); + + hist_.PutRtpPacket(CreateRtpPacket(kStartSeqNum), kAllowRetransmission, + fake_clock_.TimeInMicroseconds()); + + // Retransmission request, but the encapsulator determines that this packet is + // not suitable for retransmission (bandwidth exhausted?) so the retransmit is + // aborted and the packet is not marked as pending. + EXPECT_FALSE(hist_.GetPacketAndMarkAsPending( + kStartSeqNum, [](const RtpPacketToSend& packet) { return nullptr; })); + + // New try, this time getting the packet should work, and it should not be + // blocked due to any pending status. + EXPECT_TRUE(hist_.GetPacketAndMarkAsPending(kStartSeqNum)); +} + TEST_F(RtpPacketHistoryTest, DontRemovePendingTransmissions) { const int64_t kRttMs = RtpPacketHistory::kMinPacketDurationMs * 2; const int64_t kPacketTimeoutMs =