From 3890e99b705065dbc60e6d16932d8584bd67200d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Spr=C3=A5ng?= Date: Wed, 24 Apr 2019 19:26:40 +0200 Subject: [PATCH] Remove packets from RtpPacketHistory if acked via TransportFeedback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the receiver has indicated that a packet has been received, via a TransportFeedback RTCP message, it is safe to remove it from the RtpPacketHistory as we can be sure it won't be needed anymore. This will reduce memory usage, reduce the risk of overflow in the history at very high bitrates, and hopefully make payload based padding a little more useful. Bug: webrtc:8975 Change-Id: I703a353252943f63d7d6edda68f03bc482633fd6 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/133028 Commit-Queue: Erik Språng Reviewed-by: Sebastian Jansson Reviewed-by: Danil Chapovalov Cr-Commit-Position: refs/heads/master@{#27745} --- call/rtp_video_sender.cc | 56 +++++-- call/rtp_video_sender.h | 8 +- call/rtp_video_sender_unittest.cc | 145 ++++++++++++++++-- modules/rtp_rtcp/include/rtp_rtcp.h | 5 + modules/rtp_rtcp/include/rtp_rtcp_defines.h | 14 +- modules/rtp_rtcp/mocks/mock_rtp_rtcp.h | 4 +- modules/rtp_rtcp/source/rtp_packet_history.cc | 11 ++ modules/rtp_rtcp/source/rtp_packet_history.h | 4 + modules/rtp_rtcp/source/rtp_rtcp_impl.cc | 5 + modules/rtp_rtcp/source/rtp_rtcp_impl.h | 1 + modules/rtp_rtcp/source/rtp_sender.cc | 6 + modules/rtp_rtcp/source/rtp_sender.h | 5 +- 12 files changed, 236 insertions(+), 28 deletions(-) diff --git a/call/rtp_video_sender.cc b/call/rtp_video_sender.cc index 019f8422c8..c977ddfaee 100644 --- a/call/rtp_video_sender.cc +++ b/call/rtp_video_sender.cc @@ -16,6 +16,7 @@ #include #include "absl/memory/memory.h" +#include "api/array_view.h" #include "api/transport/field_trial_based_config.h" #include "call/rtp_transport_controller_send_interface.h" #include "modules/pacing/packet_router.h" @@ -323,18 +324,14 @@ RtpVideoSender::RtpVideoSender( fec_controller_->SetProtectionCallback(this); // Signal congestion controller this object is ready for OnPacket* callbacks. - if (fec_controller_->UseLossVectorMask()) { - transport_->RegisterPacketFeedbackObserver(this); - } + transport_->RegisterPacketFeedbackObserver(this); } RtpVideoSender::~RtpVideoSender() { for (const RtpStreamSender& stream : rtp_streams_) { transport_->packet_router()->RemoveSendRtpModule(stream.rtp_rtcp.get()); } - if (fec_controller_->UseLossVectorMask()) { - transport_->DeRegisterPacketFeedbackObserver(this); - } + transport_->DeRegisterPacketFeedbackObserver(this); } void RtpVideoSender::RegisterProcessThread( @@ -567,6 +564,7 @@ void RtpVideoSender::DeliverRtcp(const uint8_t* packet, size_t length) { void RtpVideoSender::ConfigureSsrcs(const RtpConfig& rtp_config) { // Configure regular SSRCs. + ssrc_to_acknowledged_packets_observers_.clear(); for (size_t i = 0; i < rtp_config.ssrcs.size(); ++i) { uint32_t ssrc = rtp_config.ssrcs[i]; RtpRtcp* const rtp_rtcp = rtp_streams_[i].rtp_rtcp.get(); @@ -576,6 +574,12 @@ void RtpVideoSender::ConfigureSsrcs(const RtpConfig& rtp_config) { auto it = suspended_ssrcs_.find(ssrc); if (it != suspended_ssrcs_.end()) rtp_rtcp->SetRtpState(it->second); + + AcknowledgedPacketsObserver* receive_observer = + rtp_rtcp->GetAcknowledgedPacketsObserver(); + if (receive_observer != nullptr) { + ssrc_to_acknowledged_packets_observers_[ssrc] = receive_observer; + } } // Set up RTX if available. @@ -791,15 +795,41 @@ void RtpVideoSender::OnPacketAdded(uint32_t ssrc, uint16_t seq_num) { void RtpVideoSender::OnPacketFeedbackVector( const std::vector& packet_feedback_vector) { - rtc::CritScope lock(&crit_); - // Lost feedbacks are not considered to be lost packets. + const bool use_loss_mask = fec_controller_->UseLossVectorMask(); + + std::vector loss_mask; + std::map> acked_packets; for (const PacketFeedback& packet : packet_feedback_vector) { - auto it = feedback_packet_seq_num_set_.find(packet.sequence_number); - if (it != feedback_packet_seq_num_set_.end()) { - const bool lost = packet.arrival_time_ms == PacketFeedback::kNotReceived; - loss_mask_vector_.push_back(lost); - feedback_packet_seq_num_set_.erase(it); + if (use_loss_mask) { + // Lost feedbacks are not considered to be lost packets. + auto it = feedback_packet_seq_num_set_.find(packet.sequence_number); + if (it != feedback_packet_seq_num_set_.end()) { + const bool lost = + packet.arrival_time_ms == PacketFeedback::kNotReceived; + loss_mask.push_back(lost); + feedback_packet_seq_num_set_.erase(it); + } } + if (packet.ssrc) { + if (ssrc_to_acknowledged_packets_observers_.find(*packet.ssrc) != + ssrc_to_acknowledged_packets_observers_.end()) { + acked_packets[*packet.ssrc].push_back(packet.rtp_sequence_number); + } + } + } + + if (use_loss_mask) { + rtc::CritScope cs(&crit_); + loss_mask_vector_.insert(loss_mask_vector_.end(), loss_mask.begin(), + loss_mask.end()); + } + for (const auto& kv : acked_packets) { + const uint32_t ssrc = kv.first; + rtc::ArrayView rtp_sequence_numbers(kv.second); + RTC_DCHECK(ssrc_to_acknowledged_packets_observers_.find(ssrc) != + ssrc_to_acknowledged_packets_observers_.end()); + ssrc_to_acknowledged_packets_observers_[ssrc]->OnPacketsAcknowledged( + rtp_sequence_numbers); } } diff --git a/call/rtp_video_sender.h b/call/rtp_video_sender.h index e17bb49a36..162875b204 100644 --- a/call/rtp_video_sender.h +++ b/call/rtp_video_sender.h @@ -172,7 +172,7 @@ class RtpVideoSender : public RtpVideoSenderInterface, std::map suspended_ssrcs_; std::unique_ptr flexfec_sender_; - std::unique_ptr fec_controller_; + const std::unique_ptr fec_controller_; // Rtp modules are assumed to be sorted in simulcast index order. const std::vector rtp_streams_; @@ -197,6 +197,12 @@ class RtpVideoSender : public RtpVideoSenderInterface, std::vector frame_counts_ RTC_GUARDED_BY(crit_); FrameCountObserver* const frame_count_observer_; + // Effectively const map from ssrc to AcknowledgedPacketsObserver. This + // map is set at construction time and never changed, but it's + // non-trivial to make it properly const. + std::map + ssrc_to_acknowledged_packets_observers_; + RTC_DISALLOW_COPY_AND_ASSIGN(RtpVideoSender); }; diff --git a/call/rtp_video_sender_unittest.cc b/call/rtp_video_sender_unittest.cc index 9416173c3c..65f4ca78ee 100644 --- a/call/rtp_video_sender_unittest.cc +++ b/call/rtp_video_sender_unittest.cc @@ -15,8 +15,13 @@ #include "api/task_queue/default_task_queue_factory.h" #include "call/rtp_transport_controller_send.h" #include "call/rtp_video_sender.h" +#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" +#include "modules/rtp_rtcp/source/byte_io.h" +#include "modules/rtp_rtcp/source/rtcp_packet/nack.h" +#include "modules/rtp_rtcp/source/rtp_packet.h" #include "modules/video_coding/fec_controller_default.h" #include "modules/video_coding/include/video_codec_interface.h" +#include "rtc_base/event.h" #include "rtc_base/rate_limiter.h" #include "test/field_trial.h" #include "test/gmock.h" @@ -27,6 +32,7 @@ #include "video/send_statistics_proxy.h" using ::testing::_; +using ::testing::Invoke; using ::testing::NiceMock; using ::testing::SaveArg; using ::testing::Unused; @@ -36,6 +42,8 @@ namespace { const int8_t kPayloadType = 96; const uint32_t kSsrc1 = 12345; const uint32_t kSsrc2 = 23456; +const uint32_t kRtxSsrc1 = 34567; +const uint32_t kRtxSsrc2 = 45678; const int16_t kInitialPictureId1 = 222; const int16_t kInitialPictureId2 = 44; const int16_t kInitialTl0PicIdx1 = 99; @@ -60,6 +68,7 @@ RtpSenderObservers CreateObservers( RtpSenderObservers observers; observers.rtcp_rtt_stats = rtcp_rtt_stats; observers.intra_frame_callback = intra_frame_callback; + observers.rtcp_loss_notification_observer = nullptr; observers.rtcp_stats = rtcp_stats; observers.rtp_stats = rtp_stats; observers.bitrate_observer = bitrate_observer; @@ -70,16 +79,43 @@ RtpSenderObservers CreateObservers( return observers; } +BitrateConstraints GetBitrateConfig() { + BitrateConstraints bitrate_config; + bitrate_config.min_bitrate_bps = 30000; + bitrate_config.start_bitrate_bps = 300000; + bitrate_config.max_bitrate_bps = 3000000; + return bitrate_config; +} + +VideoSendStream::Config CreateVideoSendStreamConfig( + Transport* transport, + const std::vector& ssrcs, + const std::vector& rtx_ssrcs, + int payload_type) { + VideoSendStream::Config config(transport); + config.rtp.ssrcs = ssrcs; + config.rtp.rtx.ssrcs = rtx_ssrcs; + config.rtp.payload_type = payload_type; + config.rtp.rtx.payload_type = payload_type + 1; + config.rtp.nack.rtp_history_ms = 1000; + return config; +} + class RtpVideoSenderTestFixture { public: RtpVideoSenderTestFixture( const std::vector& ssrcs, + const std::vector& rtx_ssrcs, int payload_type, const std::map& suspended_payload_states, FrameCountObserver* frame_count_observer) : clock_(1000000), - config_(&transport_), + config_(CreateVideoSendStreamConfig(&transport_, + ssrcs, + rtx_ssrcs, + payload_type)), send_delay_stats_(&clock_), + bitrate_config_(GetBitrateConfig()), task_queue_factory_(CreateDefaultTaskQueueFactory()), transport_controller_(&clock_, &event_log_, @@ -94,10 +130,6 @@ class RtpVideoSenderTestFixture { config_, VideoEncoderConfig::ContentType::kRealtimeVideo), retransmission_rate_limiter_(&clock_, kRetransmitWindowSizeMs) { - for (uint32_t ssrc : ssrcs) { - config_.rtp.ssrcs.push_back(ssrc); - } - config_.rtp.payload_type = payload_type; std::map suspended_ssrcs; router_ = absl::make_unique( &clock_, suspended_ssrcs, suspended_payload_states, config_.rtp, @@ -111,14 +143,18 @@ class RtpVideoSenderTestFixture { } RtpVideoSenderTestFixture( const std::vector& ssrcs, + const std::vector& rtx_ssrcs, int payload_type, const std::map& suspended_payload_states) : RtpVideoSenderTestFixture(ssrcs, + rtx_ssrcs, payload_type, suspended_payload_states, /*frame_count_observer=*/nullptr) {} RtpVideoSender* router() { return router_.get(); } + MockTransport& transport() { return transport_; } + SimulatedClock& clock() { return clock_; } private: NiceMock transport_; @@ -148,7 +184,7 @@ TEST(RtpVideoSenderTest, SendOnOneModule) { encoded_image.data()[0] = kPayload; encoded_image.set_size(1); - RtpVideoSenderTestFixture test({kSsrc1}, kPayloadType, {}); + RtpVideoSenderTestFixture test({kSsrc1}, {kRtxSsrc1}, kPayloadType, {}); EXPECT_NE( EncodedImageCallback::Result::OK, test.router()->OnEncodedImage(encoded_image, nullptr, nullptr).error); @@ -179,7 +215,8 @@ TEST(RtpVideoSenderTest, SendSimulcastSetActive) { encoded_image_1.data()[0] = kPayload; encoded_image_1.set_size(1); - RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, kPayloadType, {}); + RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2}, + kPayloadType, {}); CodecSpecificInfo codec_info; codec_info.codecType = kVideoCodecVP8; @@ -226,7 +263,8 @@ TEST(RtpVideoSenderTest, SendSimulcastSetActiveModules) { EncodedImage encoded_image_2(encoded_image_1); encoded_image_2.SetSpatialIndex(1); - RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, kPayloadType, {}); + RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2}, + kPayloadType, {}); CodecSpecificInfo codec_info; codec_info.codecType = kVideoCodecVP8; @@ -256,7 +294,8 @@ TEST(RtpVideoSenderTest, SendSimulcastSetActiveModules) { } TEST(RtpVideoSenderTest, CreateWithNoPreviousStates) { - RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, kPayloadType, {}); + RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2}, + kPayloadType, {}); test.router()->SetActive(true); std::map initial_states = @@ -280,7 +319,8 @@ TEST(RtpVideoSenderTest, CreateWithPreviousStates) { std::map states = {{kSsrc1, state1}, {kSsrc2, state2}}; - RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, kPayloadType, states); + RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2}, + kPayloadType, states); test.router()->SetActive(true); std::map initial_states = @@ -301,7 +341,8 @@ TEST(RtpVideoSenderTest, FrameCountCallbacks) { void(const FrameCounts& frame_counts, uint32_t ssrc)); } callback; - RtpVideoSenderTestFixture test({kSsrc1}, kPayloadType, {}, &callback); + RtpVideoSenderTestFixture test({kSsrc1}, {kRtxSsrc1}, kPayloadType, {}, + &callback); constexpr uint8_t kPayload = 'a'; EncodedImage encoded_image; @@ -346,4 +387,86 @@ TEST(RtpVideoSenderTest, FrameCountCallbacks) { EXPECT_EQ(1, frame_counts.delta_frames); } +TEST(RtpVideoSenderTest, PropagatesTransportFeedbackToRtpSender) { + const int64_t kTimeoutMs = 500; + + RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2}, + kPayloadType, {}); + test.router()->SetActive(true); + + constexpr uint8_t kPayload = 'a'; + EncodedImage encoded_image; + encoded_image.SetTimestamp(1); + encoded_image.capture_time_ms_ = 2; + encoded_image._frameType = VideoFrameType::kVideoFrameKey; + encoded_image.Allocate(1); + encoded_image.data()[0] = kPayload; + encoded_image.set_size(1); + + // Send image, capture first RTP packet. + rtc::Event event; + uint16_t rtp_sequence_number = 0; + uint16_t transport_sequence_number = 0; + EXPECT_CALL(test.transport(), SendRtp(_, _, _)) + .WillOnce( + Invoke([&event, &rtp_sequence_number, &transport_sequence_number]( + const uint8_t* packet, size_t length, + const PacketOptions& options) { + RtpPacket rtp_packet; + EXPECT_TRUE(rtp_packet.Parse(packet, length)); + rtp_sequence_number = rtp_packet.SequenceNumber(); + transport_sequence_number = options.packet_id; + event.Set(); + return true; + })); + EXPECT_EQ( + EncodedImageCallback::Result::OK, + test.router()->OnEncodedImage(encoded_image, nullptr, nullptr).error); + test.clock().AdvanceTimeMilliseconds(33); + + ASSERT_TRUE(event.Wait(kTimeoutMs)); + + // Construct a NACK message for requesting retransmission of the packet. + std::vector nack_list; + nack_list.push_back(rtp_sequence_number); + rtcp::Nack nack; + nack.SetMediaSsrc(kSsrc1); + nack.SetPacketIds(nack_list); + rtc::Buffer nack_buffer = nack.Build(); + + uint16_t retransmitted_rtp_sequence_number = 0; + EXPECT_CALL(test.transport(), SendRtp) + .WillOnce([&event, &retransmitted_rtp_sequence_number]( + const uint8_t* packet, size_t length, + const PacketOptions& options) { + RtpPacket rtp_packet; + EXPECT_TRUE(rtp_packet.Parse(packet, length)); + EXPECT_EQ(rtp_packet.Ssrc(), kRtxSsrc1); + // Capture the retransmitted sequence number from the RTX header. + rtc::ArrayView payload = rtp_packet.payload(); + retransmitted_rtp_sequence_number = + ByteReader::ReadBigEndian(payload.data()); + event.Set(); + return true; + }); + test.router()->DeliverRtcp(nack_buffer.data(), nack_buffer.size()); + ASSERT_TRUE(event.Wait(kTimeoutMs)); + EXPECT_EQ(retransmitted_rtp_sequence_number, rtp_sequence_number); + + // Simulate transport feedback indicating packet has been received. + PacketFeedback feedback(test.clock().TimeInMilliseconds(), + transport_sequence_number); + feedback.rtp_sequence_number = rtp_sequence_number; + feedback.ssrc = kSsrc1; + test.router()->OnPacketFeedbackVector( + std::vector(1, feedback)); + + // Advance time to make sure retranmission would be allowed and try again. + // This time the retranmission should not happen since the paket history + // has been notified of the ack and removed the packet. + test.clock().AdvanceTimeMilliseconds(33); + EXPECT_CALL(test.transport(), SendRtp).Times(0); + test.router()->DeliverRtcp(nack_buffer.data(), nack_buffer.size()); + ASSERT_FALSE(event.Wait(kTimeoutMs)); +} } // namespace webrtc diff --git a/modules/rtp_rtcp/include/rtp_rtcp.h b/modules/rtp_rtcp/include/rtp_rtcp.h index 1c589f4c93..9fb26cbbea 100644 --- a/modules/rtp_rtcp/include/rtp_rtcp.h +++ b/modules/rtp_rtcp/include/rtp_rtcp.h @@ -275,6 +275,11 @@ class RtpRtcp : public Module, public RtcpFeedbackSenderInterface { virtual StreamDataCountersCallback* GetSendChannelRtpStatisticsCallback() const = 0; + // Returns a pointer to an observer that handles information about packets + // that have been received by the remote end, or nullptr if not applicable. + virtual AcknowledgedPacketsObserver* GetAcknowledgedPacketsObserver() + const = 0; + // ************************************************************************** // RTCP // ************************************************************************** diff --git a/modules/rtp_rtcp/include/rtp_rtcp_defines.h b/modules/rtp_rtcp/include/rtp_rtcp_defines.h index 4a4b82555e..de73c3adfe 100644 --- a/modules/rtp_rtcp/include/rtp_rtcp_defines.h +++ b/modules/rtp_rtcp/include/rtp_rtcp_defines.h @@ -16,6 +16,7 @@ #include #include "absl/strings/string_view.h" +#include "absl/types/optional.h" #include "absl/types/variant.h" #include "api/audio_codecs/audio_format.h" #include "api/rtp_headers.h" @@ -276,7 +277,7 @@ struct PacketFeedback { PacedPacketInfo pacing_info; // The SSRC and RTP sequence number of the packet this feedback refers to. - uint32_t ssrc; + absl::optional ssrc; uint16_t rtp_sequence_number; }; @@ -313,6 +314,17 @@ class TransportFeedbackObserver { virtual void OnTransportFeedback(const rtcp::TransportFeedback& feedback) = 0; }; +class AcknowledgedPacketsObserver { + public: + AcknowledgedPacketsObserver() = default; + virtual ~AcknowledgedPacketsObserver() = default; + + // Indicates RTP sequence numbers for packets that have been acknowledged as + // received by the remote end. + virtual void OnPacketsAcknowledged( + rtc::ArrayView sequence_numbers) = 0; +}; + // Interface for PacketRouter to send rtcp feedback on behalf of // congestion controller. // TODO(bugs.webrtc.org/8239): Remove and use RtcpTransceiver directly diff --git a/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h b/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h index 668d52707d..733ec28c47 100644 --- a/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h +++ b/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h @@ -157,7 +157,9 @@ class MockRtpRtcp : public RtpRtcp { MOCK_METHOD1(RegisterSendChannelRtpStatisticsCallback, void(StreamDataCountersCallback*)); MOCK_CONST_METHOD0(GetSendChannelRtpStatisticsCallback, - StreamDataCountersCallback*(void)); + StreamDataCountersCallback*()); + MOCK_CONST_METHOD0(GetAcknowledgedPacketsObserver, + AcknowledgedPacketsObserver*()); MOCK_METHOD1(SetVideoBitrateAllocation, void(const VideoBitrateAllocation&)); MOCK_METHOD0(RtpSender, RTPSender*()); MOCK_CONST_METHOD0(RtpSender, const RTPSender*()); diff --git a/modules/rtp_rtcp/source/rtp_packet_history.cc b/modules/rtp_rtcp/source/rtp_packet_history.cc index ac39e22391..217a54243d 100644 --- a/modules/rtp_rtcp/source/rtp_packet_history.cc +++ b/modules/rtp_rtcp/source/rtp_packet_history.cc @@ -232,6 +232,17 @@ std::unique_ptr RtpPacketHistory::GetBestFittingPacket( return absl::make_unique(*best_packet); } +void RtpPacketHistory::CullAcknowledgedPackets( + rtc::ArrayView sequence_numbers) { + rtc::CritScope cs(&lock_); + for (uint16_t sequence_number : sequence_numbers) { + auto stored_packet_it = packet_history_.find(sequence_number); + if (stored_packet_it != packet_history_.end()) { + RemovePacket(stored_packet_it); + } + } +} + void RtpPacketHistory::Reset() { packet_history_.clear(); packet_size_.clear(); diff --git a/modules/rtp_rtcp/source/rtp_packet_history.h b/modules/rtp_rtcp/source/rtp_packet_history.h index 5e6463ba30..cf87ddf205 100644 --- a/modules/rtp_rtcp/source/rtp_packet_history.h +++ b/modules/rtp_rtcp/source/rtp_packet_history.h @@ -89,6 +89,9 @@ class RtpPacketHistory { std::unique_ptr GetBestFittingPacket( size_t packet_size) const; + // Cull packets that have been acknowledged as received by the remote end. + void CullAcknowledgedPackets(rtc::ArrayView sequence_numbers); + private: struct StoredPacket { StoredPacket(); @@ -133,6 +136,7 @@ class RtpPacketHistory { // Map from rtp sequence numbers to stored packet. std::map packet_history_ RTC_GUARDED_BY(lock_); + // Map from packet size to sequence number. std::map packet_size_ RTC_GUARDED_BY(lock_); // The earliest packet in the history. This might not be the lowest sequence diff --git a/modules/rtp_rtcp/source/rtp_rtcp_impl.cc b/modules/rtp_rtcp/source/rtp_rtcp_impl.cc index a15558d95a..97cc8798b2 100644 --- a/modules/rtp_rtcp/source/rtp_rtcp_impl.cc +++ b/modules/rtp_rtcp/source/rtp_rtcp_impl.cc @@ -867,6 +867,11 @@ ModuleRtpRtcpImpl::GetSendChannelRtpStatisticsCallback() const { return rtp_sender_->GetRtpStatisticsCallback(); } +AcknowledgedPacketsObserver* ModuleRtpRtcpImpl::GetAcknowledgedPacketsObserver() + const { + return rtp_sender_.get(); +} + void ModuleRtpRtcpImpl::SetVideoBitrateAllocation( const VideoBitrateAllocation& bitrate) { rtcp_sender_.SetVideoBitrateAllocation(bitrate); diff --git a/modules/rtp_rtcp/source/rtp_rtcp_impl.h b/modules/rtp_rtcp/source/rtp_rtcp_impl.h index cb565f8f63..de0080013d 100644 --- a/modules/rtp_rtcp/source/rtp_rtcp_impl.h +++ b/modules/rtp_rtcp/source/rtp_rtcp_impl.h @@ -276,6 +276,7 @@ class ModuleRtpRtcpImpl : public RtpRtcp, public RTCPReceiver::ModuleRtpRtcp { StreamDataCountersCallback* callback) override; StreamDataCountersCallback* GetSendChannelRtpStatisticsCallback() const override; + AcknowledgedPacketsObserver* GetAcknowledgedPacketsObserver() const override; void OnReceivedNack( const std::vector& nack_sequence_numbers) override; diff --git a/modules/rtp_rtcp/source/rtp_sender.cc b/modules/rtp_rtcp/source/rtp_sender.cc index 2e198fc999..05b54bce58 100644 --- a/modules/rtp_rtcp/source/rtp_sender.cc +++ b/modules/rtp_rtcp/source/rtp_sender.cc @@ -1207,6 +1207,7 @@ void RTPSender::AddPacketToTransportFeedback( RtpPacketSendInfo packet_info; packet_info.ssrc = SSRC(); packet_info.transport_sequence_number = packet_id; + packet_info.has_rtp_sequence_number = true; packet_info.rtp_sequence_number = packet.SequenceNumber(); packet_info.length = packet_size; packet_info.pacing_info = pacing_info; @@ -1238,4 +1239,9 @@ void RTPSender::SetRtt(int64_t rtt_ms) { packet_history_.SetRtt(rtt_ms); flexfec_packet_history_.SetRtt(rtt_ms); } + +void RTPSender::OnPacketsAcknowledged( + rtc::ArrayView sequence_numbers) { + packet_history_.CullAcknowledgedPackets(sequence_numbers); +} } // namespace webrtc diff --git a/modules/rtp_rtcp/source/rtp_sender.h b/modules/rtp_rtcp/source/rtp_sender.h index 4d7e72b7b7..832a570a98 100644 --- a/modules/rtp_rtcp/source/rtp_sender.h +++ b/modules/rtp_rtcp/source/rtp_sender.h @@ -42,7 +42,7 @@ class RateLimiter; class RtcEventLog; class RtpPacketToSend; -class RTPSender { +class RTPSender : public AcknowledgedPacketsObserver { public: RTPSender(bool audio, Clock* clock, @@ -173,6 +173,9 @@ class RTPSender { void SetRtt(int64_t rtt_ms); + void OnPacketsAcknowledged( + rtc::ArrayView sequence_numbers) override; + private: // Maps capture time in milliseconds to send-side delay in milliseconds. // Send-side delay is the difference between transmission time and capture