• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
VerifyingRtxReceiver()39   VerifyingRtxReceiver() {}
40 
OnReceivedPayloadData(const uint8_t * data,const uint16_t size,const webrtc::WebRtcRTPHeader * rtp_header)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:
TestRtpFeedback(RtpRtcp * rtp_rtcp)55   TestRtpFeedback(RtpRtcp* rtp_rtcp) : rtp_rtcp_(rtp_rtcp) {}
~TestRtpFeedback()56   virtual ~TestRtpFeedback() {}
57 
OnIncomingSSRCChanged(const int32_t id,const uint32_t ssrc)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:
RtxLoopBackTransport(uint32_t rtx_ssrc)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 
SetSendModule(RtpRtcp * rtpRtcpModule,RTPPayloadRegistry * rtp_payload_registry,RtpReceiver * receiver)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 
DropEveryNthPacket(int n)88   void DropEveryNthPacket(int n) {
89     packet_loss_ = n;
90   }
91 
DropConsecutivePackets(int start,int total)92   void DropConsecutivePackets(int start, int total) {
93     consecutive_drop_start_ = start;
94     consecutive_drop_end_ = start + total;
95     packet_loss_ = 0;
96   }
97 
SendPacket(int channel,const void * data,int len)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 
SendRTCPPacket(int channel,const void * data,int len)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:
RtpRtcpRtxNackTest()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) {}
~RtpRtcpRtxNackTest()173   ~RtpRtcpRtxNackTest() {}
174 
SetUp()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 
BuildNackList(uint16_t * nack_list)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 
ExpectedPacketsReceived()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 
RunRtxTest(RtxMode rtx_method,int loss)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 
TearDown()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 
TEST_F(RtpRtcpRtxNackTest,LongNackList)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 
TEST_F(RtpRtcpRtxNackTest,RtxNack)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