Allow RtpPacketHistory encapsulator function to abort retransmit
Bug: webrtc:10633
Change-Id: I162b2c2f778e8e4c6f31307028db0c352ded2276
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/142230
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Commit-Queue: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28312}
diff --git a/modules/rtp_rtcp/source/rtp_packet_history.cc b/modules/rtp_rtcp/source/rtp_packet_history.cc
index 5336181..e8488e0 100644
--- a/modules/rtp_rtcp/source/rtp_packet_history.cc
+++ b/modules/rtp_rtcp/source/rtp_packet_history.cc
@@ -241,10 +241,14 @@
return nullptr;
}
- packet.pending_transmission_ = true;
-
// Copy and/or encapsulate packet.
- return encapsulate(*packet.packet_);
+ std::unique_ptr<RtpPacketToSend> 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 44ebf43..b988b68 100644
--- a/modules/rtp_rtcp/source/rtp_packet_history.h
+++ b/modules/rtp_rtcp/source/rtp_packet_history.h
@@ -93,6 +93,8 @@
// 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<RtpPacketToSend> GetPacketAndMarkAsPending(
uint16_t sequence_number,
rtc::FunctionView<std::unique_ptr<RtpPacketToSend>(
diff --git a/modules/rtp_rtcp/source/rtp_packet_history_unittest.cc b/modules/rtp_rtcp/source/rtp_packet_history_unittest.cc
index 6a577fa..950cbe6 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 @@
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 =