Implement recieving NACK in RtcpTranceiver

Bug: webrtc:8239
Change-Id: I41d6c3252bbffeab66ded7ed294f82134351541a
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/254800
Reviewed-by: Emil Lundmark <lndmrk@webrtc.org>
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#36254}
This commit is contained in:
Danil Chapovalov
2022-03-18 14:49:12 +01:00
committed by WebRTC LUCI CQ
parent 16af378884
commit ef6b028c92
4 changed files with 63 additions and 4 deletions

View File

@ -97,6 +97,9 @@ class RtpStreamRtcpHandler {
int last_clock_rate_ = 90'000; int last_clock_rate_ = 90'000;
}; };
virtual RtpStats SentStats() = 0; virtual RtpStats SentStats() = 0;
virtual void OnNack(uint32_t sender_ssrc,
rtc::ArrayView<const uint16_t> sequence_numbers) {}
}; };
struct RtcpTransceiverConfig { struct RtcpTransceiverConfig {

View File

@ -351,10 +351,34 @@ void RtcpTransceiverImpl::HandlePayloadSpecificFeedback(
void RtcpTransceiverImpl::HandleRtpFeedback( void RtcpTransceiverImpl::HandleRtpFeedback(
const rtcp::CommonHeader& rtcp_packet_header, const rtcp::CommonHeader& rtcp_packet_header,
Timestamp now) { Timestamp now) {
// Transport feedback is the only message handled right now. switch (rtcp_packet_header.fmt()) {
if (rtcp_packet_header.fmt() != case rtcp::Nack::kFeedbackMessageType:
rtcp::TransportFeedback::kFeedbackMessageType || HandleNack(rtcp_packet_header);
config_.network_link_observer == nullptr) { break;
case rtcp::TransportFeedback::kFeedbackMessageType:
HandleTransportFeedback(rtcp_packet_header, now);
break;
}
}
void RtcpTransceiverImpl::HandleNack(
const rtcp::CommonHeader& rtcp_packet_header) {
rtcp::Nack nack;
if (local_senders_.empty() || !nack.Parse(rtcp_packet_header)) {
return;
}
auto it = local_senders_by_ssrc_.find(nack.media_ssrc());
if (it != local_senders_by_ssrc_.end()) {
it->second->handler->OnNack(nack.sender_ssrc(), nack.packet_ids());
}
}
void RtcpTransceiverImpl::HandleTransportFeedback(
const rtcp::CommonHeader& rtcp_packet_header,
Timestamp now) {
RTC_DCHECK_EQ(rtcp_packet_header.fmt(),
rtcp::TransportFeedback::kFeedbackMessageType);
if (config_.network_link_observer == nullptr) {
return; return;
} }
rtcp::TransportFeedback feedback; rtcp::TransportFeedback feedback;

View File

@ -105,6 +105,9 @@ class RtcpTransceiverImpl {
Timestamp now); Timestamp now);
void HandleRtpFeedback(const rtcp::CommonHeader& rtcp_packet_header, void HandleRtpFeedback(const rtcp::CommonHeader& rtcp_packet_header,
Timestamp now); Timestamp now);
void HandleNack(const rtcp::CommonHeader& rtcp_packet_header);
void HandleTransportFeedback(const rtcp::CommonHeader& rtcp_packet_header,
Timestamp now);
void HandleExtendedReports(const rtcp::CommonHeader& rtcp_packet_header, void HandleExtendedReports(const rtcp::CommonHeader& rtcp_packet_header,
Timestamp now); Timestamp now);
// Extended Reports blocks handlers. // Extended Reports blocks handlers.

View File

@ -40,6 +40,7 @@ namespace {
using ::testing::_; using ::testing::_;
using ::testing::ElementsAre; using ::testing::ElementsAre;
using ::testing::ElementsAreArray;
using ::testing::Ge; using ::testing::Ge;
using ::testing::NiceMock; using ::testing::NiceMock;
using ::testing::Return; using ::testing::Return;
@ -82,6 +83,10 @@ class MockRtpStreamRtcpHandler : public RtpStreamRtcpHandler {
} }
MOCK_METHOD(RtpStats, SentStats, (), (override)); MOCK_METHOD(RtpStats, SentStats, (), (override));
MOCK_METHOD(void,
OnNack,
(uint32_t, rtc::ArrayView<const uint16_t>),
(override));
private: private:
int num_calls_ = 0; int num_calls_ = 0;
@ -1044,6 +1049,30 @@ TEST(RtcpTransceiverImplTest, SendsNack) {
EXPECT_EQ(rtcp_parser.nack()->packet_ids(), kMissingSequenceNumbers); EXPECT_EQ(rtcp_parser.nack()->packet_ids(), kMissingSequenceNumbers);
} }
TEST(RtcpTransceiverImplTest, ReceivesNack) {
static constexpr uint32_t kRemoteSsrc = 4321;
static constexpr uint32_t kMediaSsrc1 = 1234;
static constexpr uint32_t kMediaSsrc2 = 1235;
std::vector<uint16_t> kMissingSequenceNumbers = {34, 37, 38};
RtcpTransceiverConfig config = DefaultTestConfig();
RtcpTransceiverImpl rtcp_transceiver(config);
MockRtpStreamRtcpHandler local_stream1;
MockRtpStreamRtcpHandler local_stream2;
EXPECT_CALL(local_stream1,
OnNack(kRemoteSsrc, ElementsAreArray(kMissingSequenceNumbers)));
EXPECT_CALL(local_stream2, OnNack).Times(0);
EXPECT_TRUE(rtcp_transceiver.AddMediaSender(kMediaSsrc1, &local_stream1));
EXPECT_TRUE(rtcp_transceiver.AddMediaSender(kMediaSsrc2, &local_stream2));
rtcp::Nack nack;
nack.SetSenderSsrc(kRemoteSsrc);
nack.SetMediaSsrc(kMediaSsrc1);
nack.SetPacketIds(kMissingSequenceNumbers);
rtcp_transceiver.ReceivePacket(nack.Build(), config.clock->CurrentTime());
}
TEST(RtcpTransceiverImplTest, RequestKeyFrameWithPictureLossIndication) { TEST(RtcpTransceiverImplTest, RequestKeyFrameWithPictureLossIndication) {
const uint32_t kSenderSsrc = 1234; const uint32_t kSenderSsrc = 1234;
const uint32_t kRemoteSsrc = 4321; const uint32_t kRemoteSsrc = 4321;