Home | History | Annotate | Download | only in source
      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