diff --git a/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h b/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h index d10dab860b..5c93e0bfed 100644 --- a/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h +++ b/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h @@ -97,6 +97,10 @@ class MockRtpRtcpInterface : public RtpRtcpInterface { FetchFecPackets, (), (override)); + MOCK_METHOD(void, + OnAbortedRetransmissions, + (rtc::ArrayView), + (override)); MOCK_METHOD(void, OnPacketsAcknowledged, (rtc::ArrayView), diff --git a/modules/rtp_rtcp/source/rtp_rtcp_impl.cc b/modules/rtp_rtcp/source/rtp_rtcp_impl.cc index c3f7151c58..a3662f19d9 100644 --- a/modules/rtp_rtcp/source/rtp_rtcp_impl.cc +++ b/modules/rtp_rtcp/source/rtp_rtcp_impl.cc @@ -400,6 +400,12 @@ ModuleRtpRtcpImpl::FetchFecPackets() { return {}; } +void ModuleRtpRtcpImpl::OnAbortedRetransmissions( + rtc::ArrayView sequence_numbers) { + RTC_DCHECK_NOTREACHED() + << "Stream flushing not supported with legacy rtp modules."; +} + void ModuleRtpRtcpImpl::OnPacketsAcknowledged( rtc::ArrayView sequence_numbers) { RTC_DCHECK(rtp_sender_); diff --git a/modules/rtp_rtcp/source/rtp_rtcp_impl.h b/modules/rtp_rtcp/source/rtp_rtcp_impl.h index 5e0681984b..0f4f00453d 100644 --- a/modules/rtp_rtcp/source/rtp_rtcp_impl.h +++ b/modules/rtp_rtcp/source/rtp_rtcp_impl.h @@ -139,6 +139,9 @@ class ModuleRtpRtcpImpl : public RtpRtcp, public RTCPReceiver::ModuleRtpRtcp { std::vector> FetchFecPackets() override; + void OnAbortedRetransmissions( + rtc::ArrayView sequence_numbers) override; + void OnPacketsAcknowledged( rtc::ArrayView sequence_numbers) override; diff --git a/modules/rtp_rtcp/source/rtp_rtcp_impl2.cc b/modules/rtp_rtcp/source/rtp_rtcp_impl2.cc index 9eb40abfaf..4329a423cb 100644 --- a/modules/rtp_rtcp/source/rtp_rtcp_impl2.cc +++ b/modules/rtp_rtcp/source/rtp_rtcp_impl2.cc @@ -368,6 +368,13 @@ ModuleRtpRtcpImpl2::FetchFecPackets() { return rtp_sender_->packet_sender.FetchFecPackets(); } +void ModuleRtpRtcpImpl2::OnAbortedRetransmissions( + rtc::ArrayView sequence_numbers) { + RTC_DCHECK(rtp_sender_); + RTC_DCHECK_RUN_ON(&rtp_sender_->sequencing_checker); + rtp_sender_->packet_sender.OnAbortedRetransmissions(sequence_numbers); +} + void ModuleRtpRtcpImpl2::OnPacketsAcknowledged( rtc::ArrayView sequence_numbers) { RTC_DCHECK(rtp_sender_); diff --git a/modules/rtp_rtcp/source/rtp_rtcp_impl2.h b/modules/rtp_rtcp/source/rtp_rtcp_impl2.h index a70eea0f2a..34b6b8342d 100644 --- a/modules/rtp_rtcp/source/rtp_rtcp_impl2.h +++ b/modules/rtp_rtcp/source/rtp_rtcp_impl2.h @@ -154,6 +154,9 @@ class ModuleRtpRtcpImpl2 final : public RtpRtcpInterface, std::vector> FetchFecPackets() override; + void OnAbortedRetransmissions( + rtc::ArrayView sequence_numbers) override; + void OnPacketsAcknowledged( rtc::ArrayView sequence_numbers) override; diff --git a/modules/rtp_rtcp/source/rtp_rtcp_interface.h b/modules/rtp_rtcp/source/rtp_rtcp_interface.h index c49115a116..8b1d11aa45 100644 --- a/modules/rtp_rtcp/source/rtp_rtcp_interface.h +++ b/modules/rtp_rtcp/source/rtp_rtcp_interface.h @@ -331,6 +331,9 @@ class RtpRtcpInterface : public RtcpFeedbackSenderInterface { // returned from the FEC generator. virtual std::vector> FetchFecPackets() = 0; + virtual void OnAbortedRetransmissions( + rtc::ArrayView sequence_numbers) = 0; + virtual void OnPacketsAcknowledged( rtc::ArrayView sequence_numbers) = 0; diff --git a/modules/rtp_rtcp/source/rtp_sender_egress.cc b/modules/rtp_rtcp/source/rtp_sender_egress.cc index 5ab910ab58..f1fd1bb7a3 100644 --- a/modules/rtp_rtcp/source/rtp_sender_egress.cc +++ b/modules/rtp_rtcp/source/rtp_sender_egress.cc @@ -390,6 +390,17 @@ RtpSenderEgress::FetchFecPackets() { return {}; } +void RtpSenderEgress::OnAbortedRetransmissions( + rtc::ArrayView sequence_numbers) { + RTC_DCHECK_RUN_ON(&pacer_checker_); + // Mark aborted retransmissions as sent, rather than leaving them in + // a 'pending' state - otherwise they can not be requested again and + // will not be cleared until the history has reached its max size. + for (uint16_t seq_no : sequence_numbers) { + packet_history_->MarkPacketAsSent(seq_no); + } +} + bool RtpSenderEgress::HasCorrectSsrc(const RtpPacketToSend& packet) const { switch (*packet.packet_type()) { case RtpPacketMediaType::kAudio: diff --git a/modules/rtp_rtcp/source/rtp_sender_egress.h b/modules/rtp_rtcp/source/rtp_sender_egress.h index 0b440c29d1..c169e59f9d 100644 --- a/modules/rtp_rtcp/source/rtp_sender_egress.h +++ b/modules/rtp_rtcp/source/rtp_sender_egress.h @@ -91,6 +91,10 @@ class RtpSenderEgress { const FecProtectionParams& key_params); std::vector> FetchFecPackets(); + // Clears pending status for these sequence numbers in the packet history. + void OnAbortedRetransmissions( + rtc::ArrayView sequence_numbers); + private: // Maps capture time in milliseconds to send-side delay in milliseconds. // Send-side delay is the difference between transmission time and capture diff --git a/modules/rtp_rtcp/source/rtp_sender_egress_unittest.cc b/modules/rtp_rtcp/source/rtp_sender_egress_unittest.cc index ddeeb8b002..982f3fed9d 100644 --- a/modules/rtp_rtcp/source/rtp_sender_egress_unittest.cc +++ b/modules/rtp_rtcp/source/rtp_sender_egress_unittest.cc @@ -963,6 +963,33 @@ TEST_P(RtpSenderEgressTest, TransportFeedbackObserverFec) { sender->SendPacket(fec_packet.get(), PacedPacketInfo()); } +TEST_P(RtpSenderEgressTest, SupportsAbortingRetransmissions) { + std::unique_ptr sender = CreateRtpSenderEgress(); + packet_history_.SetStorePacketsStatus( + RtpPacketHistory::StorageMode::kStoreAndCull, 10); + + // Create a packet and send it so it is put in the history. + std::unique_ptr media_packet = BuildRtpPacket(); + media_packet->set_packet_type(RtpPacketMediaType::kVideo); + media_packet->set_allow_retransmission(true); + const uint16_t media_sequence_number = media_packet->SequenceNumber(); + sender->SendPacket(media_packet.get(), PacedPacketInfo()); + + // Fetch a retranmission packet from the history, this should mark the + // media packets as pending so it is not available to grab again. + std::unique_ptr retransmission_packet = + packet_history_.GetPacketAndMarkAsPending(media_sequence_number); + ASSERT_TRUE(retransmission_packet); + EXPECT_FALSE( + packet_history_.GetPacketAndMarkAsPending(media_sequence_number)); + + // Mark retransmission as aborted, fetching packet is possible again. + retransmission_packet.reset(); + uint16_t kAbortedSequenceNumbers[] = {media_sequence_number}; + sender->OnAbortedRetransmissions(kAbortedSequenceNumbers); + EXPECT_TRUE(packet_history_.GetPacketAndMarkAsPending(media_sequence_number)); +} + INSTANTIATE_TEST_SUITE_P(WithAndWithoutOverhead, RtpSenderEgressTest, ::testing::Values(TestConfig(false),