1 /* 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include <algorithm> 12 #include <iterator> 13 #include <list> 14 #include <set> 15 16 #include "testing/gtest/include/gtest/gtest.h" 17 #include "webrtc/base/scoped_ptr.h" 18 #include "webrtc/common_types.h" 19 #include "webrtc/modules/rtp_rtcp/include/receive_statistics.h" 20 #include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h" 21 #include "webrtc/modules/rtp_rtcp/include/rtp_payload_registry.h" 22 #include "webrtc/modules/rtp_rtcp/include/rtp_receiver.h" 23 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h" 24 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" 25 #include "webrtc/transport.h" 26 27 namespace webrtc { 28 29 const int kVideoNackListSize = 30; 30 const uint32_t kTestSsrc = 3456; 31 const uint16_t kTestSequenceNumber = 2345; 32 const uint32_t kTestNumberOfPackets = 1350; 33 const int kTestNumberOfRtxPackets = 149; 34 const int kNumFrames = 30; 35 const int kPayloadType = 123; 36 const int kRtxPayloadType = 98; 37 38 class VerifyingRtxReceiver : public NullRtpData { 39 public: 40 VerifyingRtxReceiver() {} 41 42 int32_t OnReceivedPayloadData( 43 const uint8_t* data, 44 const size_t size, 45 const webrtc::WebRtcRTPHeader* rtp_header) override { 46 if (!sequence_numbers_.empty()) 47 EXPECT_EQ(kTestSsrc, rtp_header->header.ssrc); 48 sequence_numbers_.push_back(rtp_header->header.sequenceNumber); 49 return 0; 50 } 51 std::list<uint16_t> sequence_numbers_; 52 }; 53 54 class TestRtpFeedback : public NullRtpFeedback { 55 public: 56 explicit TestRtpFeedback(RtpRtcp* rtp_rtcp) : rtp_rtcp_(rtp_rtcp) {} 57 virtual ~TestRtpFeedback() {} 58 59 void OnIncomingSSRCChanged(const uint32_t ssrc) override { 60 rtp_rtcp_->SetRemoteSSRC(ssrc); 61 } 62 63 private: 64 RtpRtcp* rtp_rtcp_; 65 }; 66 67 class RtxLoopBackTransport : public webrtc::Transport { 68 public: 69 explicit RtxLoopBackTransport(uint32_t rtx_ssrc) 70 : count_(0), 71 packet_loss_(0), 72 consecutive_drop_start_(0), 73 consecutive_drop_end_(0), 74 rtx_ssrc_(rtx_ssrc), 75 count_rtx_ssrc_(0), 76 rtp_payload_registry_(NULL), 77 rtp_receiver_(NULL), 78 module_(NULL) {} 79 80 void SetSendModule(RtpRtcp* rtpRtcpModule, 81 RTPPayloadRegistry* rtp_payload_registry, 82 RtpReceiver* receiver) { 83 module_ = rtpRtcpModule; 84 rtp_payload_registry_ = rtp_payload_registry; 85 rtp_receiver_ = receiver; 86 } 87 88 void DropEveryNthPacket(int n) { packet_loss_ = n; } 89 90 void DropConsecutivePackets(int start, int total) { 91 consecutive_drop_start_ = start; 92 consecutive_drop_end_ = start + total; 93 packet_loss_ = 0; 94 } 95 96 bool SendRtp(const uint8_t* data, 97 size_t len, 98 const PacketOptions& options) override { 99 count_++; 100 const unsigned char* ptr = static_cast<const unsigned char*>(data); 101 uint32_t ssrc = (ptr[8] << 24) + (ptr[9] << 16) + (ptr[10] << 8) + ptr[11]; 102 if (ssrc == rtx_ssrc_) 103 count_rtx_ssrc_++; 104 uint16_t sequence_number = (ptr[2] << 8) + ptr[3]; 105 size_t packet_length = len; 106 uint8_t restored_packet[1500]; 107 RTPHeader header; 108 rtc::scoped_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create()); 109 if (!parser->Parse(ptr, len, &header)) { 110 return false; 111 } 112 113 if (!rtp_payload_registry_->IsRtx(header)) { 114 // Don't store retransmitted packets since we compare it to the list 115 // created by the receiver. 116 expected_sequence_numbers_.insert(expected_sequence_numbers_.end(), 117 sequence_number); 118 } 119 if (packet_loss_ > 0) { 120 if ((count_ % packet_loss_) == 0) { 121 return true; 122 } 123 } else if (count_ >= consecutive_drop_start_ && 124 count_ < consecutive_drop_end_) { 125 return true; 126 } 127 if (rtp_payload_registry_->IsRtx(header)) { 128 // Remove the RTX header and parse the original RTP header. 129 EXPECT_TRUE(rtp_payload_registry_->RestoreOriginalPacket( 130 restored_packet, ptr, &packet_length, rtp_receiver_->SSRC(), header)); 131 if (!parser->Parse(restored_packet, packet_length, &header)) { 132 return false; 133 } 134 ptr = restored_packet; 135 } else { 136 rtp_payload_registry_->SetIncomingPayloadType(header); 137 } 138 139 PayloadUnion payload_specific; 140 if (!rtp_payload_registry_->GetPayloadSpecifics(header.payloadType, 141 &payload_specific)) { 142 return false; 143 } 144 if (!rtp_receiver_->IncomingRtpPacket(header, ptr + header.headerLength, 145 packet_length - header.headerLength, 146 payload_specific, true)) { 147 return false; 148 } 149 return true; 150 } 151 152 bool SendRtcp(const uint8_t* data, size_t len) override { 153 return module_->IncomingRtcpPacket((const uint8_t*)data, len) == 0; 154 } 155 int count_; 156 int packet_loss_; 157 int consecutive_drop_start_; 158 int consecutive_drop_end_; 159 uint32_t rtx_ssrc_; 160 int count_rtx_ssrc_; 161 RTPPayloadRegistry* rtp_payload_registry_; 162 RtpReceiver* rtp_receiver_; 163 RtpRtcp* module_; 164 std::set<uint16_t> expected_sequence_numbers_; 165 }; 166 167 class RtpRtcpRtxNackTest : public ::testing::Test { 168 protected: 169 RtpRtcpRtxNackTest() 170 : rtp_payload_registry_(RTPPayloadStrategy::CreateStrategy(false)), 171 rtp_rtcp_module_(NULL), 172 transport_(kTestSsrc + 1), 173 receiver_(), 174 payload_data_length(sizeof(payload_data)), 175 fake_clock(123456) {} 176 ~RtpRtcpRtxNackTest() {} 177 178 void SetUp() override { 179 RtpRtcp::Configuration configuration; 180 configuration.audio = false; 181 configuration.clock = &fake_clock; 182 receive_statistics_.reset(ReceiveStatistics::Create(&fake_clock)); 183 configuration.receive_statistics = receive_statistics_.get(); 184 configuration.outgoing_transport = &transport_; 185 rtp_rtcp_module_ = RtpRtcp::CreateRtpRtcp(configuration); 186 187 rtp_feedback_.reset(new TestRtpFeedback(rtp_rtcp_module_)); 188 189 rtp_receiver_.reset(RtpReceiver::CreateVideoReceiver( 190 &fake_clock, &receiver_, rtp_feedback_.get(), &rtp_payload_registry_)); 191 192 rtp_rtcp_module_->SetSSRC(kTestSsrc); 193 rtp_rtcp_module_->SetRTCPStatus(RtcpMode::kCompound); 194 rtp_receiver_->SetNACKStatus(kNackRtcp); 195 rtp_rtcp_module_->SetStorePacketsStatus(true, 600); 196 EXPECT_EQ(0, rtp_rtcp_module_->SetSendingStatus(true)); 197 rtp_rtcp_module_->SetSequenceNumber(kTestSequenceNumber); 198 rtp_rtcp_module_->SetStartTimestamp(111111); 199 200 transport_.SetSendModule(rtp_rtcp_module_, &rtp_payload_registry_, 201 rtp_receiver_.get()); 202 203 VideoCodec video_codec; 204 memset(&video_codec, 0, sizeof(video_codec)); 205 video_codec.plType = kPayloadType; 206 memcpy(video_codec.plName, "I420", 5); 207 208 EXPECT_EQ(0, rtp_rtcp_module_->RegisterSendPayload(video_codec)); 209 rtp_rtcp_module_->SetRtxSendPayloadType(kRtxPayloadType, kPayloadType); 210 EXPECT_EQ(0, rtp_receiver_->RegisterReceivePayload( 211 video_codec.plName, video_codec.plType, 90000, 0, 212 video_codec.maxBitrate)); 213 rtp_payload_registry_.SetRtxPayloadType(kRtxPayloadType, kPayloadType); 214 215 for (size_t n = 0; n < payload_data_length; n++) { 216 payload_data[n] = n % 10; 217 } 218 } 219 220 int BuildNackList(uint16_t* nack_list) { 221 receiver_.sequence_numbers_.sort(); 222 std::list<uint16_t> missing_sequence_numbers; 223 std::list<uint16_t>::iterator it = receiver_.sequence_numbers_.begin(); 224 225 while (it != receiver_.sequence_numbers_.end()) { 226 uint16_t sequence_number_1 = *it; 227 ++it; 228 if (it != receiver_.sequence_numbers_.end()) { 229 uint16_t sequence_number_2 = *it; 230 // Add all missing sequence numbers to list 231 for (uint16_t i = sequence_number_1 + 1; i < sequence_number_2; ++i) { 232 missing_sequence_numbers.push_back(i); 233 } 234 } 235 } 236 int n = 0; 237 for (it = missing_sequence_numbers.begin(); 238 it != missing_sequence_numbers.end(); ++it) { 239 nack_list[n++] = (*it); 240 } 241 return n; 242 } 243 244 bool ExpectedPacketsReceived() { 245 std::list<uint16_t> received_sorted; 246 std::copy(receiver_.sequence_numbers_.begin(), 247 receiver_.sequence_numbers_.end(), 248 std::back_inserter(received_sorted)); 249 received_sorted.sort(); 250 return received_sorted.size() == 251 transport_.expected_sequence_numbers_.size() && 252 std::equal(received_sorted.begin(), received_sorted.end(), 253 transport_.expected_sequence_numbers_.begin()); 254 } 255 256 void RunRtxTest(RtxMode rtx_method, int loss) { 257 rtp_payload_registry_.SetRtxSsrc(kTestSsrc + 1); 258 rtp_rtcp_module_->SetRtxSendStatus(rtx_method); 259 rtp_rtcp_module_->SetRtxSsrc(kTestSsrc + 1); 260 transport_.DropEveryNthPacket(loss); 261 uint32_t timestamp = 3000; 262 uint16_t nack_list[kVideoNackListSize]; 263 for (int frame = 0; frame < kNumFrames; ++frame) { 264 EXPECT_EQ(0, rtp_rtcp_module_->SendOutgoingData( 265 webrtc::kVideoFrameDelta, kPayloadType, timestamp, 266 timestamp / 90, payload_data, payload_data_length)); 267 // Min required delay until retransmit = 5 + RTT ms (RTT = 0). 268 fake_clock.AdvanceTimeMilliseconds(5); 269 int length = BuildNackList(nack_list); 270 if (length > 0) 271 rtp_rtcp_module_->SendNACK(nack_list, length); 272 fake_clock.AdvanceTimeMilliseconds(28); // 33ms - 5ms delay. 273 rtp_rtcp_module_->Process(); 274 // Prepare next frame. 275 timestamp += 3000; 276 } 277 receiver_.sequence_numbers_.sort(); 278 } 279 280 void TearDown() override { delete rtp_rtcp_module_; } 281 282 rtc::scoped_ptr<ReceiveStatistics> receive_statistics_; 283 RTPPayloadRegistry rtp_payload_registry_; 284 rtc::scoped_ptr<RtpReceiver> rtp_receiver_; 285 RtpRtcp* rtp_rtcp_module_; 286 rtc::scoped_ptr<TestRtpFeedback> rtp_feedback_; 287 RtxLoopBackTransport transport_; 288 VerifyingRtxReceiver receiver_; 289 uint8_t payload_data[65000]; 290 size_t payload_data_length; 291 SimulatedClock fake_clock; 292 }; 293 294 TEST_F(RtpRtcpRtxNackTest, LongNackList) { 295 const int kNumPacketsToDrop = 900; 296 const int kNumRequiredRtcp = 4; 297 uint32_t timestamp = 3000; 298 uint16_t nack_list[kNumPacketsToDrop]; 299 // Disable StorePackets to be able to set a larger packet history. 300 rtp_rtcp_module_->SetStorePacketsStatus(false, 0); 301 // Enable StorePackets with a packet history of 2000 packets. 302 rtp_rtcp_module_->SetStorePacketsStatus(true, 2000); 303 // Drop 900 packets from the second one so that we get a NACK list which is 304 // big enough to require 4 RTCP packets to be fully transmitted to the sender. 305 transport_.DropConsecutivePackets(2, kNumPacketsToDrop); 306 // Send 30 frames which at the default size is roughly what we need to get 307 // enough packets. 308 for (int frame = 0; frame < kNumFrames; ++frame) { 309 EXPECT_EQ(0, rtp_rtcp_module_->SendOutgoingData( 310 webrtc::kVideoFrameDelta, kPayloadType, timestamp, 311 timestamp / 90, payload_data, payload_data_length)); 312 // Prepare next frame. 313 timestamp += 3000; 314 fake_clock.AdvanceTimeMilliseconds(33); 315 rtp_rtcp_module_->Process(); 316 } 317 EXPECT_FALSE(transport_.expected_sequence_numbers_.empty()); 318 EXPECT_FALSE(receiver_.sequence_numbers_.empty()); 319 size_t last_receive_count = receiver_.sequence_numbers_.size(); 320 int length = BuildNackList(nack_list); 321 for (int i = 0; i < kNumRequiredRtcp - 1; ++i) { 322 rtp_rtcp_module_->SendNACK(nack_list, length); 323 EXPECT_GT(receiver_.sequence_numbers_.size(), last_receive_count); 324 last_receive_count = receiver_.sequence_numbers_.size(); 325 EXPECT_FALSE(ExpectedPacketsReceived()); 326 } 327 rtp_rtcp_module_->SendNACK(nack_list, length); 328 EXPECT_GT(receiver_.sequence_numbers_.size(), last_receive_count); 329 EXPECT_TRUE(ExpectedPacketsReceived()); 330 } 331 332 TEST_F(RtpRtcpRtxNackTest, RtxNack) { 333 RunRtxTest(kRtxRetransmitted, 10); 334 EXPECT_EQ(kTestSequenceNumber, *(receiver_.sequence_numbers_.begin())); 335 EXPECT_EQ(kTestSequenceNumber + kTestNumberOfPackets - 1, 336 *(receiver_.sequence_numbers_.rbegin())); 337 EXPECT_EQ(kTestNumberOfPackets, receiver_.sequence_numbers_.size()); 338 EXPECT_EQ(kTestNumberOfRtxPackets, transport_.count_rtx_ssrc_); 339 EXPECT_TRUE(ExpectedPacketsReceived()); 340 } 341 342 } // namespace webrtc 343