summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormikhal@webrtc.org <mikhal@webrtc.org@4adac7df-926f-26a2-2b94-8c16560cd09d>2013-05-15 20:17:43 +0000
committermikhal@webrtc.org <mikhal@webrtc.org@4adac7df-926f-26a2-2b94-8c16560cd09d>2013-05-15 20:17:43 +0000
commitb960975dbc6d2d0e9691b63631698f8968d76cfa (patch)
treeffdc443140ace2cf283c990f0a93052df9c233f5
parent9c946517600e79044a369a6866754c3c17be1024 (diff)
downloadwebrtc-b960975dbc6d2d0e9691b63631698f8968d76cfa.tar.gz
Updating NACK RTX test
BUG=1513 R=holmer@google.com, stefan@webrtc.org Review URL: https://webrtc-codereview.appspot.com/1274006 git-svn-id: http://webrtc.googlecode.com/svn/trunk/webrtc@4036 4adac7df-926f-26a2-2b94-8c16560cd09d
-rw-r--r--modules/rtp_rtcp/source/nack_rtx_unittest.cc318
-rw-r--r--modules/rtp_rtcp/source/rtp_rtcp_tests.gypi1
-rw-r--r--modules/rtp_rtcp/test/testAPI/test_api_nack.cc278
3 files changed, 135 insertions, 462 deletions
diff --git a/modules/rtp_rtcp/source/nack_rtx_unittest.cc b/modules/rtp_rtcp/source/nack_rtx_unittest.cc
index b1d494c6..2d1306a2 100644
--- a/modules/rtp_rtcp/source/nack_rtx_unittest.cc
+++ b/modules/rtp_rtcp/source/nack_rtx_unittest.cc
@@ -1,30 +1,35 @@
/*
- * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
+* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+*
+* Use of this source code is governed by a BSD-style license
+* that can be found in the LICENSE file in the root of the source
+* tree. An additional intellectual property rights grant can be found
+* in the file PATENTS. All contributing project authors may
+* be found in the AUTHORS file in the root of the source tree.
+*/
#include <algorithm>
-#include <vector>
+#include <iterator>
+#include <list>
+#include <set>
#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/common_types.h"
#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h"
#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h"
-namespace webrtc {
-const int kVideoNackListSize = 10;
+using namespace webrtc;
+
+const int kVideoNackListSize = 30;
const int kTestId = 123;
const uint32_t kTestSsrc = 3456;
const uint16_t kTestSequenceNumber = 2345;
-const uint32_t kTestNumberOfPackets = 450;
-const int kTestNumberOfRtxPackets = 49;
+const uint32_t kTestNumberOfPackets = 1350;
+const int kTestNumberOfRtxPackets = 149;
+const int kNumFrames = 30;
-class VerifyingRtxReceiver : public RtpData {
+class VerifyingRtxReceiver : public RtpData
+{
public:
VerifyingRtxReceiver() {}
@@ -32,13 +37,12 @@ class VerifyingRtxReceiver : public RtpData {
const uint8_t* data,
const uint16_t size,
const webrtc::WebRtcRTPHeader* rtp_header) {
- if (!sequence_numbers_.empty()) {
+ if (!sequence_numbers_.empty())
EXPECT_EQ(kTestSsrc, rtp_header->header.ssrc);
- }
sequence_numbers_.push_back(rtp_header->header.sequenceNumber);
return 0;
}
- std::vector<uint16_t > sequence_numbers_;
+ std::list<uint16_t> sequence_numbers_;
};
class RtxLoopBackTransport : public webrtc::Transport {
@@ -46,31 +50,49 @@ class RtxLoopBackTransport : public webrtc::Transport {
explicit RtxLoopBackTransport(uint32_t rtx_ssrc)
: count_(0),
packet_loss_(0),
+ consecutive_drop_start_(0),
+ consecutive_drop_end_(0),
rtx_ssrc_(rtx_ssrc),
count_rtx_ssrc_(0),
module_(NULL) {
}
+
void SetSendModule(RtpRtcp* rtpRtcpModule) {
module_ = rtpRtcpModule;
}
+
void DropEveryNthPacket(int n) {
packet_loss_ = n;
}
+
+ void DropConsecutivePackets(int start, int total) {
+ consecutive_drop_start_ = start;
+ consecutive_drop_end_ = start + total;
+ packet_loss_ = 0;
+ }
+
virtual int SendPacket(int channel, const void *data, int len) {
count_++;
const unsigned char* ptr = static_cast<const unsigned char*>(data);
uint32_t ssrc = (ptr[8] << 24) + (ptr[9] << 16) + (ptr[10] << 8) + ptr[11];
if (ssrc == rtx_ssrc_) count_rtx_ssrc_++;
+ uint16_t sequence_number = (ptr[2] << 8) + ptr[3];
+ expected_sequence_numbers_.insert(expected_sequence_numbers_.end(),
+ sequence_number);
if (packet_loss_ > 0) {
if ((count_ % packet_loss_) == 0) {
return len;
}
+ } else if (count_ >= consecutive_drop_start_ &&
+ count_ < consecutive_drop_end_) {
+ return len;
}
if (module_->IncomingPacket((const uint8_t*)data, len) == 0) {
return len;
}
return -1;
}
+
virtual int SendRTCPPacket(int channel, const void *data, int len) {
if (module_->IncomingPacket((const uint8_t*)data, len) == 0) {
return len;
@@ -79,9 +101,12 @@ class RtxLoopBackTransport : public webrtc::Transport {
}
int count_;
int packet_loss_;
+ int consecutive_drop_start_;
+ int consecutive_drop_end_;
uint32_t rtx_ssrc_;
int count_rtx_ssrc_;
RtpRtcp* module_;
+ std::set<uint16_t> expected_sequence_numbers_;
};
class RtpRtcpRtxNackTest : public ::testing::Test {
@@ -126,36 +151,10 @@ class RtpRtcpRtxNackTest : public ::testing::Test {
}
}
- virtual void TearDown() {
- delete rtp_rtcp_module_;
- }
-
- RtpRtcp* rtp_rtcp_module_;
- RtxLoopBackTransport transport_;
- VerifyingRtxReceiver receiver_;
- uint8_t payload_data[65000];
- int payload_data_length;
- SimulatedClock fake_clock;
-};
-
-TEST_F(RtpRtcpRtxNackTest, RTCP) {
- uint32_t timestamp = 3000;
- uint16_t nack_list[kVideoNackListSize];
- transport_.DropEveryNthPacket(10);
-
- for (int frame = 0; frame < 10; ++frame) {
- EXPECT_EQ(0, rtp_rtcp_module_->SendOutgoingData(webrtc::kVideoFrameDelta,
- 123,
- timestamp,
- timestamp / 90,
- payload_data,
- payload_data_length));
-
- std::sort(receiver_.sequence_numbers_.begin(),
- receiver_.sequence_numbers_.end());
-
- std::vector<uint16_t> missing_sequence_numbers;
- std::vector<uint16_t>::iterator it =
+ int BuildNackList(uint16_t* nack_list) {
+ receiver_.sequence_numbers_.sort();
+ std::list<uint16_t> missing_sequence_numbers;
+ std::list<uint16_t>::iterator it =
receiver_.sequence_numbers_.begin();
while (it != receiver_.sequence_numbers_.end()) {
@@ -163,7 +162,7 @@ TEST_F(RtpRtcpRtxNackTest, RTCP) {
++it;
if (it != receiver_.sequence_numbers_.end()) {
uint16_t sequence_number_2 = *it;
- // Add all missing sequence numbers to list.
+ // Add all missing sequence numbers to list
for (uint16_t i = sequence_number_1 + 1; i < sequence_number_2;
++i) {
missing_sequence_numbers.push_back(i);
@@ -175,109 +174,112 @@ TEST_F(RtpRtcpRtxNackTest, RTCP) {
it != missing_sequence_numbers.end(); ++it) {
nack_list[n++] = (*it);
}
- rtp_rtcp_module_->SendNACK(nack_list, n);
- fake_clock.AdvanceTimeMilliseconds(33);
- rtp_rtcp_module_->Process();
+ return n;
+ }
- // Prepare next frame.
- timestamp += 3000;
+ bool ExpectedPacketsReceived() {
+ std::list<uint16_t> received_sorted;
+ std::copy(receiver_.sequence_numbers_.begin(),
+ receiver_.sequence_numbers_.end(),
+ std::back_inserter(received_sorted));
+ received_sorted.sort();
+ return std::equal(received_sorted.begin(), received_sorted.end(),
+ transport_.expected_sequence_numbers_.begin());
}
- std::sort(receiver_.sequence_numbers_.begin(),
- receiver_.sequence_numbers_.end());
- EXPECT_EQ(kTestSequenceNumber, *(receiver_.sequence_numbers_.begin()));
- EXPECT_EQ(kTestSequenceNumber + kTestNumberOfPackets - 1,
- *(receiver_.sequence_numbers_.rbegin()));
- EXPECT_EQ(kTestNumberOfPackets, receiver_.sequence_numbers_.size());
- EXPECT_EQ(0, transport_.count_rtx_ssrc_);
-}
-TEST_F(RtpRtcpRtxNackTest, RTXNack) {
- EXPECT_EQ(0, rtp_rtcp_module_->SetRTXReceiveStatus(true, kTestSsrc + 1));
- rtp_rtcp_module_->SetRtxReceivePayloadType(119);
- EXPECT_EQ(0, rtp_rtcp_module_->SetRTXSendStatus(kRtxRetransmitted, true,
- kTestSsrc + 1));
- rtp_rtcp_module_->SetRtxSendPayloadType(119);
+ void RunRtxTest(RtxMode rtx_method, int loss) {
+ EXPECT_EQ(0, rtp_rtcp_module_->SetRTXReceiveStatus(true, kTestSsrc + 1));
+ EXPECT_EQ(0, rtp_rtcp_module_->SetRTXSendStatus(rtx_method, true,
+ kTestSsrc + 1));
+ transport_.DropEveryNthPacket(loss);
+ uint32_t timestamp = 3000;
+ uint16_t nack_list[kVideoNackListSize];
+ for (int frame = 0; frame < kNumFrames; ++frame) {
+ EXPECT_EQ(0, rtp_rtcp_module_->SendOutgoingData(webrtc::kVideoFrameDelta,
+ 123,
+ timestamp,
+ timestamp / 90,
+ payload_data,
+ payload_data_length));
+ int length = BuildNackList(nack_list);
+ if (length > 0)
+ rtp_rtcp_module_->SendNACK(nack_list, length);
+ fake_clock.AdvanceTimeMilliseconds(33);
+ rtp_rtcp_module_->Process();
+ // Prepare next frame.
+ timestamp += 3000;
+ }
+ receiver_.sequence_numbers_.sort();
+ }
- transport_.DropEveryNthPacket(10);
+ virtual void TearDown() {
+ delete rtp_rtcp_module_;
+ }
- uint32_t timestamp = 3000;
- uint16_t nack_list[kVideoNackListSize];
+ RtpRtcp* rtp_rtcp_module_;
+ RtxLoopBackTransport transport_;
+ VerifyingRtxReceiver receiver_;
+ uint8_t payload_data[65000];
+ int payload_data_length;
+ SimulatedClock fake_clock;
+};
- for (int frame = 0; frame < 10; ++frame) {
+TEST_F(RtpRtcpRtxNackTest, LongNackList) {
+ const int kNumPacketsToDrop = 900;
+ const int kNumRequiredRtcp = 4;
+ uint32_t timestamp = 3000;
+ uint16_t nack_list[kNumPacketsToDrop];
+ // Disable StorePackets to be able to set a larger packet history.
+ EXPECT_EQ(0, rtp_rtcp_module_->SetStorePacketsStatus(false, 0));
+ // Enable StorePackets with a packet history of 2000 packets.
+ EXPECT_EQ(0, rtp_rtcp_module_->SetStorePacketsStatus(true, 2000));
+ // Drop 900 packets from the second one so that we get a NACK list which is
+ // big enough to require 4 RTCP packets to be fully transmitted to the sender.
+ transport_.DropConsecutivePackets(2, kNumPacketsToDrop);
+ // Send 30 frames which at the default size is roughly what we need to get
+ // enough packets.
+ for (int frame = 0; frame < kNumFrames; ++frame) {
EXPECT_EQ(0, rtp_rtcp_module_->SendOutgoingData(webrtc::kVideoFrameDelta,
123,
timestamp,
timestamp / 90,
payload_data,
payload_data_length));
-
- std::sort(receiver_.sequence_numbers_.begin(),
- receiver_.sequence_numbers_.end());
-
- std::vector<uint16_t> missing_sequence_numbers;
-
-
- std::vector<uint16_t>::iterator it =
- receiver_.sequence_numbers_.begin();
- while (it != receiver_.sequence_numbers_.end()) {
- int sequence_number_1 = *it;
- ++it;
- if (it != receiver_.sequence_numbers_.end()) {
- int sequence_number_2 = *it;
- // Add all missing sequence numbers to list.
- for (int i = sequence_number_1 + 1; i < sequence_number_2; ++i) {
- missing_sequence_numbers.push_back(i);
- }
- }
- }
- int n = 0;
- for (it = missing_sequence_numbers.begin();
- it != missing_sequence_numbers.end(); ++it) {
- nack_list[n++] = (*it);
- }
- rtp_rtcp_module_->SendNACK(nack_list, n);
- fake_clock.AdvanceTimeMilliseconds(33);
- rtp_rtcp_module_->Process();
-
// Prepare next frame.
timestamp += 3000;
+ fake_clock.AdvanceTimeMilliseconds(33);
+ rtp_rtcp_module_->Process();
}
- std::sort(receiver_.sequence_numbers_.begin(),
- receiver_.sequence_numbers_.end());
+ EXPECT_FALSE(transport_.expected_sequence_numbers_.empty());
+ EXPECT_FALSE(receiver_.sequence_numbers_.empty());
+ size_t last_receive_count = receiver_.sequence_numbers_.size();
+ int length = BuildNackList(nack_list);
+ for (int i = 0; i < kNumRequiredRtcp - 1; ++i) {
+ rtp_rtcp_module_->SendNACK(nack_list, length);
+ EXPECT_GT(receiver_.sequence_numbers_.size(), last_receive_count);
+ last_receive_count = receiver_.sequence_numbers_.size();
+ EXPECT_FALSE(ExpectedPacketsReceived());
+ }
+ rtp_rtcp_module_->SendNACK(nack_list, length);
+ EXPECT_GT(receiver_.sequence_numbers_.size(), last_receive_count);
+ EXPECT_TRUE(ExpectedPacketsReceived());
+}
+
+TEST_F(RtpRtcpRtxNackTest, RtxNack) {
+ RunRtxTest(kRtxRetransmitted, 10);
EXPECT_EQ(kTestSequenceNumber, *(receiver_.sequence_numbers_.begin()));
EXPECT_EQ(kTestSequenceNumber + kTestNumberOfPackets - 1,
- *(receiver_.sequence_numbers_.rbegin()));
+ *(receiver_.sequence_numbers_.rbegin()));
EXPECT_EQ(kTestNumberOfPackets, receiver_.sequence_numbers_.size());
EXPECT_EQ(kTestNumberOfRtxPackets, transport_.count_rtx_ssrc_);
+ EXPECT_TRUE(ExpectedPacketsReceived());
}
TEST_F(RtpRtcpRtxNackTest, RTXAllNoLoss) {
- EXPECT_EQ(0, rtp_rtcp_module_->SetRTXReceiveStatus(true, kTestSsrc + 1));
- EXPECT_EQ(0, rtp_rtcp_module_->SetRTXSendStatus(kRtxAll, true,
- kTestSsrc + 1));
- transport_.DropEveryNthPacket(0);
-
- uint32_t timestamp = 3000;
-
- for (int frame = 0; frame < 10; ++frame) {
- EXPECT_EQ(0, rtp_rtcp_module_->SendOutgoingData(webrtc::kVideoFrameDelta,
- 123,
- timestamp,
- timestamp / 90,
- payload_data,
- payload_data_length));
-
- fake_clock.AdvanceTimeMilliseconds(33);
- rtp_rtcp_module_->Process();
-
- // Prepare next frame.
- timestamp += 3000;
- }
- std::sort(receiver_.sequence_numbers_.begin(),
- receiver_.sequence_numbers_.end());
+ RunRtxTest(kRtxAll, 0);
EXPECT_EQ(kTestSequenceNumber, *(receiver_.sequence_numbers_.begin()));
EXPECT_EQ(kTestSequenceNumber + kTestNumberOfPackets - 1,
- *(receiver_.sequence_numbers_.rbegin()));
+ *(receiver_.sequence_numbers_.rbegin()));
// We have transmitted all packets twice, and loss was set to 0.
EXPECT_EQ(kTestNumberOfPackets * 2u, receiver_.sequence_numbers_.size());
// Half of the packets should be via RTX.
@@ -286,63 +288,13 @@ TEST_F(RtpRtcpRtxNackTest, RTXAllNoLoss) {
}
TEST_F(RtpRtcpRtxNackTest, RTXAllWithLoss) {
- EXPECT_EQ(0, rtp_rtcp_module_->SetRTXReceiveStatus(true, kTestSsrc + 1));
- EXPECT_EQ(0, rtp_rtcp_module_->SetRTXSendStatus(kRtxAll, true,
- kTestSsrc + 1));
-
int loss = 10;
- transport_.DropEveryNthPacket(loss);
-
- uint32_t timestamp = 3000;
- uint16_t nack_list[kVideoNackListSize];
-
- for (int frame = 0; frame < 10; ++frame) {
- EXPECT_EQ(0, rtp_rtcp_module_->SendOutgoingData(webrtc::kVideoFrameDelta,
- 123,
- timestamp,
- timestamp / 90,
- payload_data,
- payload_data_length));
- std::sort(receiver_.sequence_numbers_.begin(),
- receiver_.sequence_numbers_.end());
- std::vector<uint16_t> missing_sequence_numbers;
-
- std::vector<uint16_t>::iterator it =
- receiver_.sequence_numbers_.begin();
- while (it != receiver_.sequence_numbers_.end()) {
- int sequence_number_1 = *it;
- ++it;
- if (it != receiver_.sequence_numbers_.end()) {
- int sequence_number_2 = *it;
- // Add all missing sequence numbers to list.
- for (int i = sequence_number_1 + 1; i < sequence_number_2; ++i) {
- missing_sequence_numbers.push_back(i);
- }
- }
- }
- int n = 0;
- for (it = missing_sequence_numbers.begin();
- it != missing_sequence_numbers.end(); ++it) {
- nack_list[n++] = (*it);
- }
- if (n > 0)
- rtp_rtcp_module_->SendNACK(nack_list, n);
- fake_clock.AdvanceTimeMilliseconds(33);
- rtp_rtcp_module_->Process();
-
- // Prepare next frame.
- timestamp += 3000;
- }
- std::sort(receiver_.sequence_numbers_.begin(),
- receiver_.sequence_numbers_.end());
+ RunRtxTest(kRtxAll, loss);
EXPECT_EQ(kTestSequenceNumber, *(receiver_.sequence_numbers_.begin()));
EXPECT_EQ(kTestSequenceNumber + kTestNumberOfPackets - 1,
- *(receiver_.sequence_numbers_.rbegin()));
- // Got everything but 10% loss.
- EXPECT_EQ(2u * (kTestNumberOfPackets - kTestNumberOfPackets / 10),
- receiver_.sequence_numbers_.size());
- EXPECT_EQ(static_cast<int>(kTestNumberOfPackets),
- transport_.count_rtx_ssrc_);
+ *(receiver_.sequence_numbers_.rbegin()));
+ // Got everything but lost packets.
+ EXPECT_EQ(2u * (kTestNumberOfPackets - kTestNumberOfPackets / loss),
+ receiver_.sequence_numbers_.size());
+ EXPECT_EQ(static_cast<int>(kTestNumberOfPackets), transport_.count_rtx_ssrc_);
}
-
-} // namespace webrtc
diff --git a/modules/rtp_rtcp/source/rtp_rtcp_tests.gypi b/modules/rtp_rtcp/source/rtp_rtcp_tests.gypi
index addf2e27..c1818cf8 100644
--- a/modules/rtp_rtcp/source/rtp_rtcp_tests.gypi
+++ b/modules/rtp_rtcp/source/rtp_rtcp_tests.gypi
@@ -25,7 +25,6 @@
'../test/testAPI/test_api.cc',
'../test/testAPI/test_api.h',
'../test/testAPI/test_api_audio.cc',
- '../test/testAPI/test_api_nack.cc',
'../test/testAPI/test_api_rtcp.cc',
'../test/testAPI/test_api_video.cc',
'mock/mock_rtp_payload_strategy.h',
diff --git a/modules/rtp_rtcp/test/testAPI/test_api_nack.cc b/modules/rtp_rtcp/test/testAPI/test_api_nack.cc
deleted file mode 100644
index 92663fac..00000000
--- a/modules/rtp_rtcp/test/testAPI/test_api_nack.cc
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-
-#include <algorithm>
-#include <iterator>
-#include <list>
-#include <set>
-#include <gtest/gtest.h>
-
-#include "test_api.h"
-
-#include "common_types.h"
-#include "rtp_rtcp.h"
-#include "rtp_rtcp_defines.h"
-
-using namespace webrtc;
-
-const int kVideoNackListSize = 10;
-const int kTestId = 123;
-const uint32_t kTestSsrc = 3456;
-const uint16_t kTestSequenceNumber = 2345;
-const uint32_t kTestNumberOfPackets = 450;
-const int kTestNumberOfRtxPackets = 49;
-
-class VerifyingNackReceiver : public RtpData
-{
- public:
- VerifyingNackReceiver() {}
-
- virtual int32_t OnReceivedPayloadData(
- const uint8_t* data,
- const uint16_t size,
- const webrtc::WebRtcRTPHeader* rtp_header) {
-
- EXPECT_EQ(kTestSsrc, rtp_header->header.ssrc);
- bool already_received = std::find(
- sequence_numbers_.begin(), sequence_numbers_.end(),
- rtp_header->header.sequenceNumber) != sequence_numbers_.end();
- EXPECT_FALSE(already_received);
- sequence_numbers_.push_back(rtp_header->header.sequenceNumber);
- return 0;
- }
- std::list<uint16_t> sequence_numbers_;
-};
-
-class NackLoopBackTransport : public webrtc::Transport {
- public:
- NackLoopBackTransport(uint32_t rtx_ssrc)
- : count_(0),
- packet_loss_(0),
- consecutive_drop_start_(0),
- consecutive_drop_end_(0),
- rtx_ssrc_(rtx_ssrc),
- count_rtx_ssrc_(0),
- module_(NULL) {
- }
- void SetSendModule(RtpRtcp* rtpRtcpModule) {
- module_ = rtpRtcpModule;
- }
- void DropEveryNthPacket(int n) {
- packet_loss_ = n;
- consecutive_drop_start_ = 0;
- consecutive_drop_end_ = 0;
- }
- void DropConsecutivePackets(int start, int total) {
- consecutive_drop_start_ = start;
- consecutive_drop_end_ = start + total;
- packet_loss_ = 0;
- }
- virtual int SendPacket(int channel, const void *data, int len) {
- count_++;
- const unsigned char* ptr = static_cast<const unsigned char*>(data);
- uint32_t ssrc = (ptr[8] << 24) + (ptr[9] << 16) + (ptr[10] << 8) + ptr[11];
- if (ssrc == rtx_ssrc_) count_rtx_ssrc_++;
- uint16_t sequence_number = (ptr[2] << 8) + ptr[3];
- expected_sequence_numbers_.insert(expected_sequence_numbers_.end(),
- sequence_number);
-
- if (packet_loss_ > 0) {
- if ((count_ % packet_loss_) == 0) {
- return len;
- }
- } else if (count_ >= consecutive_drop_start_ &&
- count_ < consecutive_drop_end_) {
- return len;
- }
- if (module_->IncomingPacket((const uint8_t*)data, len) == 0) {
- return len;
- }
- return -1;
- }
- virtual int SendRTCPPacket(int channel, const void *data, int len) {
- if (module_->IncomingPacket((const uint8_t*)data, len) == 0) {
- return len;
- }
- return -1;
- }
- int count_;
- int packet_loss_;
- int consecutive_drop_start_;
- int consecutive_drop_end_;
- uint32_t rtx_ssrc_;
- int count_rtx_ssrc_;
- RtpRtcp* module_;
- std::set<uint16_t> expected_sequence_numbers_;
-};
-
-class RtpRtcpNackTest : public ::testing::Test {
- protected:
- RtpRtcpNackTest()
- : video_module_(NULL),
- transport_(NULL),
- nack_receiver_(NULL),
- payload_data_length(sizeof(payload_data)),
- fake_clock(123456) {}
- ~RtpRtcpNackTest() {}
-
- virtual void SetUp() {
- transport_ = new NackLoopBackTransport(kTestSsrc + 1);
- nack_receiver_ = new VerifyingNackReceiver();
-
- RtpRtcp::Configuration configuration;
- configuration.id = kTestId;
- configuration.audio = false;
- configuration.clock = &fake_clock;
- configuration.incoming_data = nack_receiver_;
- configuration.outgoing_transport = transport_;
- video_module_ = RtpRtcp::CreateRtpRtcp(configuration);
-
- EXPECT_EQ(0, video_module_->SetRTCPStatus(kRtcpCompound));
- EXPECT_EQ(0, video_module_->SetSSRC(kTestSsrc));
- EXPECT_EQ(0, video_module_->SetNACKStatus(kNackRtcp, 450));
- EXPECT_EQ(0, video_module_->SetStorePacketsStatus(true, 600));
- EXPECT_EQ(0, video_module_->SetSendingStatus(true));
- EXPECT_EQ(0, video_module_->SetSequenceNumber(kTestSequenceNumber));
- EXPECT_EQ(0, video_module_->SetStartTimestamp(111111));
-
- transport_->SetSendModule(video_module_);
-
- VideoCodec video_codec;
- memset(&video_codec, 0, sizeof(video_codec));
- video_codec.plType = 123;
- memcpy(video_codec.plName, "I420", 5);
-
- EXPECT_EQ(0, video_module_->RegisterSendPayload(video_codec));
- EXPECT_EQ(0, video_module_->RegisterReceivePayload(video_codec));
-
- for (int n = 0; n < payload_data_length; n++) {
- payload_data[n] = n % 10;
- }
- }
-
- virtual void TearDown() {
- delete video_module_;
- delete transport_;
- delete nack_receiver_;
- }
-
- int BuildNackList(uint16_t* nack_list) const {
- nack_receiver_->sequence_numbers_.sort();
-
- std::list<uint16_t> missing_sequence_numbers;
- std::list<uint16_t>::iterator it =
- nack_receiver_->sequence_numbers_.begin();
-
- while (it != nack_receiver_->sequence_numbers_.end()) {
- uint16_t sequence_number_1 = *it;
- ++it;
- if (it != nack_receiver_->sequence_numbers_.end()) {
- uint16_t sequence_number_2 = *it;
- // Add all missing sequence numbers to list
- for (uint16_t i = sequence_number_1 + 1; i < sequence_number_2;
- ++i) {
- missing_sequence_numbers.push_back(i);
- }
- }
- }
- int n = 0;
- for (it = missing_sequence_numbers.begin();
- it != missing_sequence_numbers.end(); ++it) {
- nack_list[n++] = (*it);
- }
- return n;
- }
-
- bool ExpectedPacketsReceived() {
- std::list<uint16_t> received_sorted;
- std::copy(nack_receiver_->sequence_numbers_.begin(),
- nack_receiver_->sequence_numbers_.end(),
- std::back_inserter(received_sorted));
- received_sorted.sort();
- return std::equal(received_sorted.begin(), received_sorted.end(),
- transport_->expected_sequence_numbers_.begin());
- }
-
- RtpRtcp* video_module_;
- NackLoopBackTransport* transport_;
- VerifyingNackReceiver* nack_receiver_;
- uint8_t payload_data[65000];
- int payload_data_length;
- SimulatedClock fake_clock;
-};
-
-TEST_F(RtpRtcpNackTest, RTCP) {
- uint32_t timestamp = 3000;
- uint16_t nack_list[kVideoNackListSize];
- transport_->DropEveryNthPacket(10);
-
- for (int frame = 0; frame < 10; ++frame) {
- EXPECT_EQ(0, video_module_->SendOutgoingData(webrtc::kVideoFrameDelta, 123,
- timestamp,
- timestamp / 90,
- payload_data,
- payload_data_length));
-
- int length = BuildNackList(nack_list);
- video_module_->SendNACK(nack_list, length);
- fake_clock.AdvanceTimeMilliseconds(33);
- video_module_->Process();
-
- // Prepare next frame.
- timestamp += 3000;
- }
- nack_receiver_->sequence_numbers_.sort();
- EXPECT_EQ(kTestSequenceNumber, *(nack_receiver_->sequence_numbers_.begin()));
- EXPECT_EQ(kTestSequenceNumber + kTestNumberOfPackets - 1,
- *(nack_receiver_->sequence_numbers_.rbegin()));
- EXPECT_EQ(kTestNumberOfPackets, nack_receiver_->sequence_numbers_.size());
- EXPECT_EQ(0, transport_->count_rtx_ssrc_);
-}
-
-TEST_F(RtpRtcpNackTest, LongNackList) {
- const int kNumPacketsToDrop = 900;
- const int kNumFrames = 30;
- const int kNumRequiredRtcp = 4;
- uint32_t timestamp = 3000;
- uint16_t nack_list[kNumPacketsToDrop];
- // Disable StorePackets to be able to set a larger packet history.
- EXPECT_EQ(0, video_module_->SetStorePacketsStatus(false, 0));
- // Enable StorePackets with a packet history of 2000 packets.
- EXPECT_EQ(0, video_module_->SetStorePacketsStatus(true, 2000));
- // Drop 900 packets from the second one so that we get a NACK list which is
- // big enough to require 4 RTCP packets to be fully transmitted to the sender.
- transport_->DropConsecutivePackets(2, kNumPacketsToDrop);
- // Send 30 frames which at the default size is roughly what we need to get
- // enough packets.
- for (int frame = 0; frame < kNumFrames; ++frame) {
- EXPECT_EQ(0, video_module_->SendOutgoingData(webrtc::kVideoFrameDelta, 123,
- timestamp,
- timestamp / 90,
- payload_data,
- payload_data_length));
- // Prepare next frame.
- timestamp += 3000;
- fake_clock.AdvanceTimeMilliseconds(33);
- video_module_->Process();
- }
- EXPECT_FALSE(transport_->expected_sequence_numbers_.empty());
- EXPECT_FALSE(nack_receiver_->sequence_numbers_.empty());
- size_t last_receive_count = nack_receiver_->sequence_numbers_.size();
- int length = BuildNackList(nack_list);
- for (int i = 0; i < kNumRequiredRtcp - 1; ++i) {
- video_module_->SendNACK(nack_list, length);
- EXPECT_GT(nack_receiver_->sequence_numbers_.size(), last_receive_count);
- last_receive_count = nack_receiver_->sequence_numbers_.size();
- EXPECT_FALSE(ExpectedPacketsReceived());
- }
- video_module_->SendNACK(nack_list, length);
- EXPECT_GT(nack_receiver_->sequence_numbers_.size(), last_receive_count);
- EXPECT_TRUE(ExpectedPacketsReceived());
-}