diff options
author | mikhal@webrtc.org <mikhal@webrtc.org@4adac7df-926f-26a2-2b94-8c16560cd09d> | 2013-05-15 20:17:43 +0000 |
---|---|---|
committer | mikhal@webrtc.org <mikhal@webrtc.org@4adac7df-926f-26a2-2b94-8c16560cd09d> | 2013-05-15 20:17:43 +0000 |
commit | b960975dbc6d2d0e9691b63631698f8968d76cfa (patch) | |
tree | ffdc443140ace2cf283c990f0a93052df9c233f5 | |
parent | 9c946517600e79044a369a6866754c3c17be1024 (diff) | |
download | webrtc-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.cc | 318 | ||||
-rw-r--r-- | modules/rtp_rtcp/source/rtp_rtcp_tests.gypi | 1 | ||||
-rw-r--r-- | modules/rtp_rtcp/test/testAPI/test_api_nack.cc | 278 |
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()); -} |