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/common_types.h"
     18 #include "webrtc/modules/rtp_rtcp/interface/receive_statistics.h"
     19 #include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
     20 #include "webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h"
     21 #include "webrtc/modules/rtp_rtcp/interface/rtp_receiver.h"
     22 #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h"
     23 #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h"
     24 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
     25 
     26 using namespace webrtc;
     27 
     28 const int kVideoNackListSize = 30;
     29 const int kTestId = 123;
     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 
     36 class VerifyingRtxReceiver : public NullRtpData
     37 {
     38  public:
     39   VerifyingRtxReceiver() {}
     40 
     41   virtual int32_t OnReceivedPayloadData(
     42       const uint8_t* data,
     43       const uint16_t size,
     44       const webrtc::WebRtcRTPHeader* rtp_header) {
     45     if (!sequence_numbers_.empty())
     46       EXPECT_EQ(kTestSsrc, rtp_header->header.ssrc);
     47     sequence_numbers_.push_back(rtp_header->header.sequenceNumber);
     48     return 0;
     49   }
     50   std::list<uint16_t> sequence_numbers_;
     51 };
     52 
     53 class TestRtpFeedback : public NullRtpFeedback {
     54  public:
     55   TestRtpFeedback(RtpRtcp* rtp_rtcp) : rtp_rtcp_(rtp_rtcp) {}
     56   virtual ~TestRtpFeedback() {}
     57 
     58   virtual void OnIncomingSSRCChanged(const int32_t id,
     59                                      const uint32_t ssrc) {
     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) {
     89     packet_loss_ = n;
     90   }
     91 
     92   void DropConsecutivePackets(int start, int total) {
     93     consecutive_drop_start_ = start;
     94     consecutive_drop_end_ = start + total;
     95     packet_loss_ = 0;
     96   }
     97 
     98   virtual int SendPacket(int channel, const void *data, int len) {
     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_) count_rtx_ssrc_++;
    103     uint16_t sequence_number = (ptr[2] << 8) + ptr[3];
    104     expected_sequence_numbers_.insert(expected_sequence_numbers_.end(),
    105         sequence_number);
    106     if (packet_loss_ > 0) {
    107       if ((count_ % packet_loss_) == 0) {
    108         return len;
    109       }
    110     } else if (count_ >= consecutive_drop_start_ &&
    111         count_ < consecutive_drop_end_) {
    112       return len;
    113     }
    114     int packet_length = len;
    115     uint8_t restored_packet[1500];
    116     uint8_t* restored_packet_ptr = restored_packet;
    117     RTPHeader header;
    118     scoped_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
    119     if (!parser->Parse(ptr, len, &header)) {
    120       return -1;
    121     }
    122     if (rtp_payload_registry_->IsRtx(header)) {
    123       // Remove the RTX header and parse the original RTP header.
    124       EXPECT_TRUE(rtp_payload_registry_->RestoreOriginalPacket(
    125           &restored_packet_ptr, ptr, &packet_length, rtp_receiver_->SSRC(),
    126           header));
    127       if (!parser->Parse(restored_packet_ptr, packet_length, &header)) {
    128         return -1;
    129       }
    130     }
    131     restored_packet_ptr += header.headerLength;
    132     packet_length -= header.headerLength;
    133     PayloadUnion payload_specific;
    134     if (!rtp_payload_registry_->GetPayloadSpecifics(header.payloadType,
    135                                                     &payload_specific)) {
    136       return -1;
    137     }
    138     if (!rtp_receiver_->IncomingRtpPacket(header, restored_packet_ptr,
    139                                           packet_length, payload_specific,
    140                                           true)) {
    141       return -1;
    142     }
    143     return len;
    144   }
    145 
    146   virtual int SendRTCPPacket(int channel, const void *data, int len) {
    147     if (module_->IncomingRtcpPacket((const uint8_t*)data, len) == 0) {
    148       return len;
    149     }
    150     return -1;
    151   }
    152   int count_;
    153   int packet_loss_;
    154   int consecutive_drop_start_;
    155   int consecutive_drop_end_;
    156   uint32_t rtx_ssrc_;
    157   int count_rtx_ssrc_;
    158   RTPPayloadRegistry* rtp_payload_registry_;
    159   RtpReceiver* rtp_receiver_;
    160   RtpRtcp* module_;
    161   std::set<uint16_t> expected_sequence_numbers_;
    162 };
    163 
    164 class RtpRtcpRtxNackTest : public ::testing::Test {
    165  protected:
    166   RtpRtcpRtxNackTest()
    167       : rtp_payload_registry_(RTPPayloadStrategy::CreateStrategy(false)),
    168         rtp_rtcp_module_(NULL),
    169         transport_(kTestSsrc + 1),
    170         receiver_(),
    171         payload_data_length(sizeof(payload_data)),
    172         fake_clock(123456) {}
    173   ~RtpRtcpRtxNackTest() {}
    174 
    175   virtual void SetUp() {
    176     RtpRtcp::Configuration configuration;
    177     configuration.id = kTestId;
    178     configuration.audio = false;
    179     configuration.clock = &fake_clock;
    180     receive_statistics_.reset(ReceiveStatistics::Create(&fake_clock));
    181     configuration.receive_statistics = receive_statistics_.get();
    182     configuration.outgoing_transport = &transport_;
    183     rtp_rtcp_module_ = RtpRtcp::CreateRtpRtcp(configuration);
    184 
    185     rtp_feedback_.reset(new TestRtpFeedback(rtp_rtcp_module_));
    186 
    187     rtp_receiver_.reset(RtpReceiver::CreateVideoReceiver(
    188         kTestId, &fake_clock, &receiver_, rtp_feedback_.get(),
    189         &rtp_payload_registry_));
    190 
    191     rtp_rtcp_module_->SetSSRC(kTestSsrc);
    192     EXPECT_EQ(0, rtp_rtcp_module_->SetRTCPStatus(kRtcpCompound));
    193     rtp_receiver_->SetNACKStatus(kNackRtcp);
    194     EXPECT_EQ(0, rtp_rtcp_module_->SetStorePacketsStatus(true, 600));
    195     EXPECT_EQ(0, rtp_rtcp_module_->SetSendingStatus(true));
    196     EXPECT_EQ(0, rtp_rtcp_module_->SetSequenceNumber(kTestSequenceNumber));
    197     EXPECT_EQ(0, rtp_rtcp_module_->SetStartTimestamp(111111));
    198 
    199     transport_.SetSendModule(rtp_rtcp_module_, &rtp_payload_registry_,
    200                              rtp_receiver_.get());
    201 
    202     VideoCodec video_codec;
    203     memset(&video_codec, 0, sizeof(video_codec));
    204     video_codec.plType = 123;
    205     memcpy(video_codec.plName, "I420", 5);
    206 
    207     EXPECT_EQ(0, rtp_rtcp_module_->RegisterSendPayload(video_codec));
    208     EXPECT_EQ(0, rtp_receiver_->RegisterReceivePayload(video_codec.plName,
    209                                                        video_codec.plType,
    210                                                        90000,
    211                                                        0,
    212                                                        video_codec.maxBitrate));
    213 
    214     for (int n = 0; n < payload_data_length; n++) {
    215       payload_data[n] = n % 10;
    216     }
    217   }
    218 
    219   int BuildNackList(uint16_t* nack_list) {
    220     receiver_.sequence_numbers_.sort();
    221     std::list<uint16_t> missing_sequence_numbers;
    222     std::list<uint16_t>::iterator it =
    223         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;
    232             ++i) {
    233           missing_sequence_numbers.push_back(i);
    234         }
    235       }
    236     }
    237     int n = 0;
    238     for (it = missing_sequence_numbers.begin();
    239         it != missing_sequence_numbers.end(); ++it) {
    240       nack_list[n++] = (*it);
    241     }
    242     return n;
    243   }
    244 
    245   bool ExpectedPacketsReceived() {
    246     std::list<uint16_t> received_sorted;
    247     std::copy(receiver_.sequence_numbers_.begin(),
    248               receiver_.sequence_numbers_.end(),
    249               std::back_inserter(received_sorted));
    250     received_sorted.sort();
    251     return std::equal(received_sorted.begin(), received_sorted.end(),
    252                       transport_.expected_sequence_numbers_.begin());
    253   }
    254 
    255   void RunRtxTest(RtxMode rtx_method, int loss) {
    256     rtp_payload_registry_.SetRtxSsrc(kTestSsrc + 1);
    257     rtp_rtcp_module_->SetRTXSendStatus(rtx_method);
    258     rtp_rtcp_module_->SetRtxSsrc(kTestSsrc + 1);
    259     transport_.DropEveryNthPacket(loss);
    260     uint32_t timestamp = 3000;
    261     uint16_t nack_list[kVideoNackListSize];
    262     for (int frame = 0; frame < kNumFrames; ++frame) {
    263       EXPECT_EQ(0, rtp_rtcp_module_->SendOutgoingData(webrtc::kVideoFrameDelta,
    264                                                       123,
    265                                                       timestamp,
    266                                                       timestamp / 90,
    267                                                       payload_data,
    268                                                       payload_data_length));
    269       int length = BuildNackList(nack_list);
    270       if (length > 0)
    271         rtp_rtcp_module_->SendNACK(nack_list, length);
    272       fake_clock.AdvanceTimeMilliseconds(33);
    273       rtp_rtcp_module_->Process();
    274       // Prepare next frame.
    275       timestamp += 3000;
    276     }
    277     receiver_.sequence_numbers_.sort();
    278   }
    279 
    280   virtual void TearDown() {
    281     delete rtp_rtcp_module_;
    282   }
    283 
    284   scoped_ptr<ReceiveStatistics> receive_statistics_;
    285   RTPPayloadRegistry rtp_payload_registry_;
    286   scoped_ptr<RtpReceiver> rtp_receiver_;
    287   RtpRtcp* rtp_rtcp_module_;
    288   scoped_ptr<TestRtpFeedback> rtp_feedback_;
    289   RtxLoopBackTransport transport_;
    290   VerifyingRtxReceiver receiver_;
    291   uint8_t  payload_data[65000];
    292   int payload_data_length;
    293   SimulatedClock fake_clock;
    294 };
    295 
    296 TEST_F(RtpRtcpRtxNackTest, LongNackList) {
    297   const int kNumPacketsToDrop = 900;
    298   const int kNumRequiredRtcp = 4;
    299   uint32_t timestamp = 3000;
    300   uint16_t nack_list[kNumPacketsToDrop];
    301   // Disable StorePackets to be able to set a larger packet history.
    302   EXPECT_EQ(0, rtp_rtcp_module_->SetStorePacketsStatus(false, 0));
    303   // Enable StorePackets with a packet history of 2000 packets.
    304   EXPECT_EQ(0, rtp_rtcp_module_->SetStorePacketsStatus(true, 2000));
    305   // Drop 900 packets from the second one so that we get a NACK list which is
    306   // big enough to require 4 RTCP packets to be fully transmitted to the sender.
    307   transport_.DropConsecutivePackets(2, kNumPacketsToDrop);
    308   // Send 30 frames which at the default size is roughly what we need to get
    309   // enough packets.
    310   for (int frame = 0; frame < kNumFrames; ++frame) {
    311     EXPECT_EQ(0, rtp_rtcp_module_->SendOutgoingData(webrtc::kVideoFrameDelta,
    312                                                     123,
    313                                                     timestamp,
    314                                                     timestamp / 90,
    315                                                     payload_data,
    316                                                     payload_data_length));
    317     // Prepare next frame.
    318     timestamp += 3000;
    319     fake_clock.AdvanceTimeMilliseconds(33);
    320     rtp_rtcp_module_->Process();
    321   }
    322   EXPECT_FALSE(transport_.expected_sequence_numbers_.empty());
    323   EXPECT_FALSE(receiver_.sequence_numbers_.empty());
    324   size_t last_receive_count = receiver_.sequence_numbers_.size();
    325   int length = BuildNackList(nack_list);
    326   for (int i = 0; i < kNumRequiredRtcp - 1; ++i) {
    327     rtp_rtcp_module_->SendNACK(nack_list, length);
    328     EXPECT_GT(receiver_.sequence_numbers_.size(), last_receive_count);
    329     last_receive_count = receiver_.sequence_numbers_.size();
    330     EXPECT_FALSE(ExpectedPacketsReceived());
    331   }
    332   rtp_rtcp_module_->SendNACK(nack_list, length);
    333   EXPECT_GT(receiver_.sequence_numbers_.size(), last_receive_count);
    334   EXPECT_TRUE(ExpectedPacketsReceived());
    335 }
    336 
    337 TEST_F(RtpRtcpRtxNackTest, RtxNack) {
    338   RunRtxTest(kRtxRetransmitted, 10);
    339   EXPECT_EQ(kTestSequenceNumber, *(receiver_.sequence_numbers_.begin()));
    340   EXPECT_EQ(kTestSequenceNumber + kTestNumberOfPackets - 1,
    341       *(receiver_.sequence_numbers_.rbegin()));
    342   EXPECT_EQ(kTestNumberOfPackets, receiver_.sequence_numbers_.size());
    343   EXPECT_EQ(kTestNumberOfRtxPackets, transport_.count_rtx_ssrc_);
    344   EXPECT_TRUE(ExpectedPacketsReceived());
    345 }
    346