diff --git a/modules/rtp_rtcp/source/rtcp_packet/nack.cc b/modules/rtp_rtcp/source/rtcp_packet/nack.cc index c196e29dc1..ba5a12b03a 100644 --- a/modules/rtp_rtcp/source/rtcp_packet/nack.cc +++ b/modules/rtp_rtcp/source/rtcp_packet/nack.cc @@ -11,6 +11,7 @@ #include "modules/rtp_rtcp/source/rtcp_packet/nack.h" #include +#include #include "modules/rtp_rtcp/source/byte_io.h" #include "modules/rtp_rtcp/source/rtcp_packet/common_header.h" @@ -123,9 +124,13 @@ bool Nack::Create(uint8_t* packet, void Nack::SetPacketIds(const uint16_t* nack_list, size_t length) { RTC_DCHECK(nack_list); + SetPacketIds(std::vector(nack_list, nack_list + length)); +} + +void Nack::SetPacketIds(std::vector nack_list) { RTC_DCHECK(packet_ids_.empty()); RTC_DCHECK(packed_.empty()); - packet_ids_.assign(nack_list, nack_list + length); + packet_ids_ = std::move(nack_list); Pack(); } diff --git a/modules/rtp_rtcp/source/rtcp_packet/nack.h b/modules/rtp_rtcp/source/rtcp_packet/nack.h index 3f6330d717..13a590f6c5 100644 --- a/modules/rtp_rtcp/source/rtcp_packet/nack.h +++ b/modules/rtp_rtcp/source/rtcp_packet/nack.h @@ -30,6 +30,7 @@ class Nack : public Rtpfb { bool Parse(const CommonHeader& packet); void SetPacketIds(const uint16_t* nack_list, size_t length); + void SetPacketIds(std::vector nack_list); const std::vector& packet_ids() const { return packet_ids_; } size_t BlockLength() const override; diff --git a/modules/rtp_rtcp/source/rtcp_transceiver.cc b/modules/rtp_rtcp/source/rtcp_transceiver.cc index 7feca3fb90..c0b829c53e 100644 --- a/modules/rtp_rtcp/source/rtcp_transceiver.cc +++ b/modules/rtp_rtcp/source/rtcp_transceiver.cc @@ -90,6 +90,22 @@ void RtcpTransceiver::UnsetRemb() { }); } +void RtcpTransceiver::SendNack(uint32_t ssrc, + std::vector sequence_numbers) { + // TODO(danilchap): Replace with lambda with move capture when available. + struct Closure { + void operator()() { + if (ptr) + ptr->SendNack(ssrc, std::move(sequence_numbers)); + } + + rtc::WeakPtr ptr; + uint32_t ssrc; + std::vector sequence_numbers; + }; + task_queue_->PostTask(Closure{ptr_, ssrc, std::move(sequence_numbers)}); +} + void RtcpTransceiver::SendPictureLossIndication(std::vector ssrcs) { // TODO(danilchap): Replace with lambda with move capture when available. struct Closure { diff --git a/modules/rtp_rtcp/source/rtcp_transceiver.h b/modules/rtp_rtcp/source/rtcp_transceiver.h index 9d695451a1..417943a164 100644 --- a/modules/rtp_rtcp/source/rtcp_transceiver.h +++ b/modules/rtp_rtcp/source/rtcp_transceiver.h @@ -44,7 +44,10 @@ class RtcpTransceiver { // Stops sending REMB in following compound packets. void UnsetRemb(); - // Request new key frame. + // Reports missing packets, https://tools.ietf.org/html/rfc4585#section-6.2.1 + void SendNack(uint32_t ssrc, std::vector sequence_numbers); + + // Requests new key frame. // using PLI, https://tools.ietf.org/html/rfc4585#section-6.3.1.1 void SendPictureLossIndication(std::vector ssrcs); // using FIR, https://tools.ietf.org/html/rfc5104#section-4.3.1.2 diff --git a/modules/rtp_rtcp/source/rtcp_transceiver_impl.cc b/modules/rtp_rtcp/source/rtcp_transceiver_impl.cc index b870dd103f..fbe1717c2a 100644 --- a/modules/rtp_rtcp/source/rtcp_transceiver_impl.cc +++ b/modules/rtp_rtcp/source/rtcp_transceiver_impl.cc @@ -18,6 +18,7 @@ #include "modules/rtp_rtcp/source/rtcp_packet.h" #include "modules/rtp_rtcp/source/rtcp_packet/common_header.h" #include "modules/rtp_rtcp/source/rtcp_packet/fir.h" +#include "modules/rtp_rtcp/source/rtcp_packet/nack.h" #include "modules/rtp_rtcp/source/rtcp_packet/pli.h" #include "modules/rtp_rtcp/source/rtcp_packet/receiver_report.h" #include "modules/rtp_rtcp/source/rtcp_packet/report_block.h" @@ -130,6 +131,18 @@ void RtcpTransceiverImpl::UnsetRemb() { remb_.reset(); } +void RtcpTransceiverImpl::SendNack(uint32_t ssrc, + std::vector sequence_numbers) { + RTC_DCHECK(!sequence_numbers.empty()); + SendImmediateFeedback([&](PacketSender* sender) { + rtcp::Nack nack; + nack.SetSenderSsrc(config_.feedback_ssrc); + nack.SetMediaSsrc(ssrc); + nack.SetPacketIds(std::move(sequence_numbers)); + sender->AppendPacket(nack); + }); +} + void RtcpTransceiverImpl::SendPictureLossIndication( rtc::ArrayView ssrcs) { RTC_DCHECK(!ssrcs.empty()); diff --git a/modules/rtp_rtcp/source/rtcp_transceiver_impl.h b/modules/rtp_rtcp/source/rtcp_transceiver_impl.h index a89f3e106a..8cde921213 100644 --- a/modules/rtp_rtcp/source/rtcp_transceiver_impl.h +++ b/modules/rtp_rtcp/source/rtcp_transceiver_impl.h @@ -44,6 +44,8 @@ class RtcpTransceiverImpl { void SetRemb(int bitrate_bps, std::vector ssrcs); void UnsetRemb(); + void SendNack(uint32_t ssrc, std::vector sequence_numbers); + void SendPictureLossIndication(rtc::ArrayView ssrcs); void SendFullIntraRequest(rtc::ArrayView ssrcs); diff --git a/modules/rtp_rtcp/source/rtcp_transceiver_impl_unittest.cc b/modules/rtp_rtcp/source/rtcp_transceiver_impl_unittest.cc index c7f7482f8c..2d291b2a1e 100644 --- a/modules/rtp_rtcp/source/rtcp_transceiver_impl_unittest.cc +++ b/modules/rtp_rtcp/source/rtcp_transceiver_impl_unittest.cc @@ -447,6 +447,28 @@ TEST(RtcpTransceiverImplTest, EXPECT_EQ(CompactNtpRttToMs(report_blocks[1].delay_since_last_sr()), 100); } +TEST(RtcpTransceiverImplTest, SendsNack) { + const uint32_t kSenderSsrc = 1234; + const uint32_t kRemoteSsrc = 4321; + std::vector kMissingSequenceNumbers = {34, 37, 38}; + MockTransport outgoing_transport; + RtcpTransceiverConfig config; + config.feedback_ssrc = kSenderSsrc; + config.schedule_periodic_compound_packets = false; + config.outgoing_transport = &outgoing_transport; + RtcpTransceiverImpl rtcp_transceiver(config); + RtcpPacketParser rtcp_parser; + EXPECT_CALL(outgoing_transport, SendRtcp(_, _)) + .WillOnce(Invoke(&rtcp_parser, &RtcpPacketParser::Parse)); + + rtcp_transceiver.SendNack(kRemoteSsrc, kMissingSequenceNumbers); + + EXPECT_EQ(rtcp_parser.nack()->num_packets(), 1); + EXPECT_EQ(rtcp_parser.nack()->sender_ssrc(), kSenderSsrc); + EXPECT_EQ(rtcp_parser.nack()->media_ssrc(), kRemoteSsrc); + EXPECT_EQ(rtcp_parser.nack()->packet_ids(), kMissingSequenceNumbers); +} + TEST(RtcpTransceiverImplTest, RequestKeyFrameWithPictureLossIndication) { const uint32_t kSenderSsrc = 1234; const uint32_t kRemoteSsrcs[] = {4321, 5321};