2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
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.
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"
26 using namespace webrtc;
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;
36 class VerifyingRtxReceiver : public NullRtpData
39 VerifyingRtxReceiver() {}
41 virtual int32_t OnReceivedPayloadData(
44 const webrtc::WebRtcRTPHeader* rtp_header) OVERRIDE {
45 if (!sequence_numbers_.empty())
46 EXPECT_EQ(kTestSsrc, rtp_header->header.ssrc);
47 sequence_numbers_.push_back(rtp_header->header.sequenceNumber);
50 std::list<uint16_t> sequence_numbers_;
53 class TestRtpFeedback : public NullRtpFeedback {
55 TestRtpFeedback(RtpRtcp* rtp_rtcp) : rtp_rtcp_(rtp_rtcp) {}
56 virtual ~TestRtpFeedback() {}
58 virtual void OnIncomingSSRCChanged(const int32_t id,
59 const uint32_t ssrc) OVERRIDE {
60 rtp_rtcp_->SetRemoteSSRC(ssrc);
67 class RtxLoopBackTransport : public webrtc::Transport {
69 explicit RtxLoopBackTransport(uint32_t rtx_ssrc)
72 consecutive_drop_start_(0),
73 consecutive_drop_end_(0),
76 rtp_payload_registry_(NULL),
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;
88 void DropEveryNthPacket(int n) {
92 void DropConsecutivePackets(int start, int total) {
93 consecutive_drop_start_ = start;
94 consecutive_drop_end_ = start + total;
98 virtual int SendPacket(int channel, const void *data, int len) OVERRIDE {
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(),
106 if (packet_loss_ > 0) {
107 if ((count_ % packet_loss_) == 0) {
110 } else if (count_ >= consecutive_drop_start_ &&
111 count_ < consecutive_drop_end_) {
114 int packet_length = len;
115 // TODO(pbos): Figure out why this needs to be initialized. Likely this
116 // is hiding a bug either in test setup or other code.
117 // https://code.google.com/p/webrtc/issues/detail?id=3183
118 uint8_t restored_packet[1500] = {0};
119 uint8_t* restored_packet_ptr = restored_packet;
121 scoped_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
122 if (!parser->Parse(ptr, len, &header)) {
125 if (rtp_payload_registry_->IsRtx(header)) {
126 // Remove the RTX header and parse the original RTP header.
127 EXPECT_TRUE(rtp_payload_registry_->RestoreOriginalPacket(
128 &restored_packet_ptr, ptr, &packet_length, rtp_receiver_->SSRC(),
130 if (!parser->Parse(restored_packet_ptr, packet_length, &header)) {
134 restored_packet_ptr += header.headerLength;
135 packet_length -= header.headerLength;
136 PayloadUnion payload_specific;
137 if (!rtp_payload_registry_->GetPayloadSpecifics(header.payloadType,
138 &payload_specific)) {
141 if (!rtp_receiver_->IncomingRtpPacket(header, restored_packet_ptr,
142 packet_length, payload_specific,
149 virtual int SendRTCPPacket(int channel, const void *data, int len) OVERRIDE {
150 if (module_->IncomingRtcpPacket((const uint8_t*)data, len) == 0) {
157 int consecutive_drop_start_;
158 int consecutive_drop_end_;
161 RTPPayloadRegistry* rtp_payload_registry_;
162 RtpReceiver* rtp_receiver_;
164 std::set<uint16_t> expected_sequence_numbers_;
167 class RtpRtcpRtxNackTest : public ::testing::Test {
170 : rtp_payload_registry_(RTPPayloadStrategy::CreateStrategy(false)),
171 rtp_rtcp_module_(NULL),
172 transport_(kTestSsrc + 1),
174 payload_data_length(sizeof(payload_data)),
175 fake_clock(123456) {}
176 ~RtpRtcpRtxNackTest() {}
178 virtual void SetUp() OVERRIDE {
179 RtpRtcp::Configuration configuration;
180 configuration.id = kTestId;
181 configuration.audio = false;
182 configuration.clock = &fake_clock;
183 receive_statistics_.reset(ReceiveStatistics::Create(&fake_clock));
184 configuration.receive_statistics = receive_statistics_.get();
185 configuration.outgoing_transport = &transport_;
186 rtp_rtcp_module_ = RtpRtcp::CreateRtpRtcp(configuration);
188 rtp_feedback_.reset(new TestRtpFeedback(rtp_rtcp_module_));
190 rtp_receiver_.reset(RtpReceiver::CreateVideoReceiver(
191 kTestId, &fake_clock, &receiver_, rtp_feedback_.get(),
192 &rtp_payload_registry_));
194 rtp_rtcp_module_->SetSSRC(kTestSsrc);
195 EXPECT_EQ(0, rtp_rtcp_module_->SetRTCPStatus(kRtcpCompound));
196 rtp_receiver_->SetNACKStatus(kNackRtcp);
197 EXPECT_EQ(0, rtp_rtcp_module_->SetStorePacketsStatus(true, 600));
198 EXPECT_EQ(0, rtp_rtcp_module_->SetSendingStatus(true));
199 EXPECT_EQ(0, rtp_rtcp_module_->SetSequenceNumber(kTestSequenceNumber));
200 EXPECT_EQ(0, rtp_rtcp_module_->SetStartTimestamp(111111));
202 transport_.SetSendModule(rtp_rtcp_module_, &rtp_payload_registry_,
203 rtp_receiver_.get());
205 VideoCodec video_codec;
206 memset(&video_codec, 0, sizeof(video_codec));
207 video_codec.plType = 123;
208 memcpy(video_codec.plName, "I420", 5);
210 EXPECT_EQ(0, rtp_rtcp_module_->RegisterSendPayload(video_codec));
211 EXPECT_EQ(0, rtp_receiver_->RegisterReceivePayload(video_codec.plName,
215 video_codec.maxBitrate));
217 for (int n = 0; n < payload_data_length; n++) {
218 payload_data[n] = n % 10;
222 int BuildNackList(uint16_t* nack_list) {
223 receiver_.sequence_numbers_.sort();
224 std::list<uint16_t> missing_sequence_numbers;
225 std::list<uint16_t>::iterator it =
226 receiver_.sequence_numbers_.begin();
228 while (it != receiver_.sequence_numbers_.end()) {
229 uint16_t sequence_number_1 = *it;
231 if (it != receiver_.sequence_numbers_.end()) {
232 uint16_t sequence_number_2 = *it;
233 // Add all missing sequence numbers to list
234 for (uint16_t i = sequence_number_1 + 1; i < sequence_number_2;
236 missing_sequence_numbers.push_back(i);
241 for (it = missing_sequence_numbers.begin();
242 it != missing_sequence_numbers.end(); ++it) {
243 nack_list[n++] = (*it);
248 bool ExpectedPacketsReceived() {
249 std::list<uint16_t> received_sorted;
250 std::copy(receiver_.sequence_numbers_.begin(),
251 receiver_.sequence_numbers_.end(),
252 std::back_inserter(received_sorted));
253 received_sorted.sort();
254 return std::equal(received_sorted.begin(), received_sorted.end(),
255 transport_.expected_sequence_numbers_.begin());
258 void RunRtxTest(RtxMode rtx_method, int loss) {
259 rtp_payload_registry_.SetRtxSsrc(kTestSsrc + 1);
260 rtp_rtcp_module_->SetRTXSendStatus(rtx_method);
261 rtp_rtcp_module_->SetRtxSsrc(kTestSsrc + 1);
262 transport_.DropEveryNthPacket(loss);
263 uint32_t timestamp = 3000;
264 uint16_t nack_list[kVideoNackListSize];
265 for (int frame = 0; frame < kNumFrames; ++frame) {
266 EXPECT_EQ(0, rtp_rtcp_module_->SendOutgoingData(webrtc::kVideoFrameDelta,
271 payload_data_length));
272 int length = BuildNackList(nack_list);
274 rtp_rtcp_module_->SendNACK(nack_list, length);
275 fake_clock.AdvanceTimeMilliseconds(33);
276 rtp_rtcp_module_->Process();
277 // Prepare next frame.
280 receiver_.sequence_numbers_.sort();
283 virtual void TearDown() OVERRIDE {
284 delete rtp_rtcp_module_;
287 scoped_ptr<ReceiveStatistics> receive_statistics_;
288 RTPPayloadRegistry rtp_payload_registry_;
289 scoped_ptr<RtpReceiver> rtp_receiver_;
290 RtpRtcp* rtp_rtcp_module_;
291 scoped_ptr<TestRtpFeedback> rtp_feedback_;
292 RtxLoopBackTransport transport_;
293 VerifyingRtxReceiver receiver_;
294 uint8_t payload_data[65000];
295 int payload_data_length;
296 SimulatedClock fake_clock;
299 TEST_F(RtpRtcpRtxNackTest, LongNackList) {
300 const int kNumPacketsToDrop = 900;
301 const int kNumRequiredRtcp = 4;
302 uint32_t timestamp = 3000;
303 uint16_t nack_list[kNumPacketsToDrop];
304 // Disable StorePackets to be able to set a larger packet history.
305 EXPECT_EQ(0, rtp_rtcp_module_->SetStorePacketsStatus(false, 0));
306 // Enable StorePackets with a packet history of 2000 packets.
307 EXPECT_EQ(0, rtp_rtcp_module_->SetStorePacketsStatus(true, 2000));
308 // Drop 900 packets from the second one so that we get a NACK list which is
309 // big enough to require 4 RTCP packets to be fully transmitted to the sender.
310 transport_.DropConsecutivePackets(2, kNumPacketsToDrop);
311 // Send 30 frames which at the default size is roughly what we need to get
313 for (int frame = 0; frame < kNumFrames; ++frame) {
314 EXPECT_EQ(0, rtp_rtcp_module_->SendOutgoingData(webrtc::kVideoFrameDelta,
319 payload_data_length));
320 // Prepare next frame.
322 fake_clock.AdvanceTimeMilliseconds(33);
323 rtp_rtcp_module_->Process();
325 EXPECT_FALSE(transport_.expected_sequence_numbers_.empty());
326 EXPECT_FALSE(receiver_.sequence_numbers_.empty());
327 size_t last_receive_count = receiver_.sequence_numbers_.size();
328 int length = BuildNackList(nack_list);
329 for (int i = 0; i < kNumRequiredRtcp - 1; ++i) {
330 rtp_rtcp_module_->SendNACK(nack_list, length);
331 EXPECT_GT(receiver_.sequence_numbers_.size(), last_receive_count);
332 last_receive_count = receiver_.sequence_numbers_.size();
333 EXPECT_FALSE(ExpectedPacketsReceived());
335 rtp_rtcp_module_->SendNACK(nack_list, length);
336 EXPECT_GT(receiver_.sequence_numbers_.size(), last_receive_count);
337 EXPECT_TRUE(ExpectedPacketsReceived());
340 TEST_F(RtpRtcpRtxNackTest, RtxNack) {
341 RunRtxTest(kRtxRetransmitted, 10);
342 EXPECT_EQ(kTestSequenceNumber, *(receiver_.sequence_numbers_.begin()));
343 EXPECT_EQ(kTestSequenceNumber + kTestNumberOfPackets - 1,
344 *(receiver_.sequence_numbers_.rbegin()));
345 EXPECT_EQ(kTestNumberOfPackets, receiver_.sequence_numbers_.size());
346 EXPECT_EQ(kTestNumberOfRtxPackets, transport_.count_rtx_ssrc_);
347 EXPECT_TRUE(ExpectedPacketsReceived());