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