1bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org/* 26cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. 36cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org* 46cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org* Use of this source code is governed by a BSD-style license 56cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org* that can be found in the LICENSE file in the root of the source 66cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org* tree. An additional intellectual property rights grant can be found 76cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org* in the file PATENTS. All contributing project authors may 86cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org* be found in the AUTHORS file in the root of the source tree. 96cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org*/ 10bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org 11bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org#include <algorithm> 126cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org#include <iterator> 136cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org#include <list> 146cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org#include <set> 15bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org 16bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org#include "testing/gtest/include/gtest/gtest.h" 1700b8f6b3643332cce1ee711715f7fbb824d793cakwiberg@webrtc.org#include "webrtc/base/scoped_ptr.h" 18bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org#include "webrtc/common_types.h" 19ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander#include "webrtc/modules/rtp_rtcp/include/receive_statistics.h" 20ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander#include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h" 21ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander#include "webrtc/modules/rtp_rtcp/include/rtp_payload_registry.h" 22ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander#include "webrtc/modules/rtp_rtcp/include/rtp_receiver.h" 23ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h" 24ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" 252d566686a23fe93ada58f1c38a0d4b9a0d68556epbos#include "webrtc/transport.h" 26bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org 276a6f0893dd1e653410ba4b22e7f33947d15aeb65danilchapnamespace webrtc { 286cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org 296cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.orgconst int kVideoNackListSize = 30; 302f44673d665899ca788ae44247a9a7f4764f5e2bpbos@webrtc.orgconst uint32_t kTestSsrc = 3456; 312f44673d665899ca788ae44247a9a7f4764f5e2bpbos@webrtc.orgconst uint16_t kTestSequenceNumber = 2345; 326cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.orgconst uint32_t kTestNumberOfPackets = 1350; 336cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.orgconst int kTestNumberOfRtxPackets = 149; 346cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.orgconst int kNumFrames = 30; 35e62202fedf57b74cc263246c0586ee353978caf8Shao Changbinconst int kPayloadType = 123; 36e62202fedf57b74cc263246c0586ee353978caf8Shao Changbinconst int kRtxPayloadType = 98; 37bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org 38162abd3562d7b08ab36569800d757b52739b9249danilchapclass VerifyingRtxReceiver : public NullRtpData { 39bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org public: 40bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org VerifyingRtxReceiver() {} 41bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org 4214665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org int32_t OnReceivedPayloadData( 432f44673d665899ca788ae44247a9a7f4764f5e2bpbos@webrtc.org const uint8_t* data, 444591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org const size_t size, 4514665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org const webrtc::WebRtcRTPHeader* rtp_header) override { 466cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org if (!sequence_numbers_.empty()) 47bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org EXPECT_EQ(kTestSsrc, rtp_header->header.ssrc); 48bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org sequence_numbers_.push_back(rtp_header->header.sequenceNumber); 49bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org return 0; 50bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org } 516cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org std::list<uint16_t> sequence_numbers_; 52bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org}; 53bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org 54822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.orgclass TestRtpFeedback : public NullRtpFeedback { 55822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org public: 566db6cdc604f9a866991ecf8454eb7f7aa69918eadanilchap explicit TestRtpFeedback(RtpRtcp* rtp_rtcp) : rtp_rtcp_(rtp_rtcp) {} 57822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org virtual ~TestRtpFeedback() {} 58822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org 59ac547a653862744d0aae560713f8418ad2852085Peter Boström void OnIncomingSSRCChanged(const uint32_t ssrc) override { 60286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org rtp_rtcp_->SetRemoteSSRC(ssrc); 61822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org } 62822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org 63822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org private: 64822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org RtpRtcp* rtp_rtcp_; 65822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org}; 66822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org 67bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.orgclass RtxLoopBackTransport : public webrtc::Transport { 68bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org public: 69bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org explicit RtxLoopBackTransport(uint32_t rtx_ssrc) 70bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org : count_(0), 71bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org packet_loss_(0), 726cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org consecutive_drop_start_(0), 736cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org consecutive_drop_end_(0), 74bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org rtx_ssrc_(rtx_ssrc), 75bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org count_rtx_ssrc_(0), 76822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org rtp_payload_registry_(NULL), 77822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org rtp_receiver_(NULL), 787bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org module_(NULL) {} 796cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org 80822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org void SetSendModule(RtpRtcp* rtpRtcpModule, 81822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org RTPPayloadRegistry* rtp_payload_registry, 82822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org RtpReceiver* receiver) { 83bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org module_ = rtpRtcpModule; 84822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org rtp_payload_registry_ = rtp_payload_registry; 85822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org rtp_receiver_ = receiver; 86bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org } 876cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org 88162abd3562d7b08ab36569800d757b52739b9249danilchap void DropEveryNthPacket(int n) { packet_loss_ = n; } 896cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org 906cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org void DropConsecutivePackets(int start, int total) { 916cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org consecutive_drop_start_ = start; 926cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org consecutive_drop_end_ = start + total; 936cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org packet_loss_ = 0; 946cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org } 956cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org 961d8a506405734d0cef9653704b036ca4f1388960stefan bool SendRtp(const uint8_t* data, 971d8a506405734d0cef9653704b036ca4f1388960stefan size_t len, 981d8a506405734d0cef9653704b036ca4f1388960stefan const PacketOptions& options) override { 99bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org count_++; 100162abd3562d7b08ab36569800d757b52739b9249danilchap const unsigned char* ptr = static_cast<const unsigned char*>(data); 101bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org uint32_t ssrc = (ptr[8] << 24) + (ptr[9] << 16) + (ptr[10] << 8) + ptr[11]; 102162abd3562d7b08ab36569800d757b52739b9249danilchap if (ssrc == rtx_ssrc_) 103162abd3562d7b08ab36569800d757b52739b9249danilchap count_rtx_ssrc_++; 1046cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org uint16_t sequence_number = (ptr[2] << 8) + ptr[3]; 1054591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org size_t packet_length = len; 106740c4f11e0d3b409c5444b328859754d2a717e33pbos uint8_t restored_packet[1500]; 107a5cb98cbbd11e93cb6d0a6232387814aac168c7dstefan@webrtc.org RTPHeader header; 10800b8f6b3643332cce1ee711715f7fbb824d793cakwiberg@webrtc.org rtc::scoped_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create()); 1097bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org if (!parser->Parse(ptr, len, &header)) { 1102d566686a23fe93ada58f1c38a0d4b9a0d68556epbos return false; 111bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org } 112e64fbce0d92949b2928a1a7427b24f37ba90f526terelius 113e64fbce0d92949b2928a1a7427b24f37ba90f526terelius if (!rtp_payload_registry_->IsRtx(header)) { 114e64fbce0d92949b2928a1a7427b24f37ba90f526terelius // Don't store retransmitted packets since we compare it to the list 115e64fbce0d92949b2928a1a7427b24f37ba90f526terelius // created by the receiver. 116e64fbce0d92949b2928a1a7427b24f37ba90f526terelius expected_sequence_numbers_.insert(expected_sequence_numbers_.end(), 117e64fbce0d92949b2928a1a7427b24f37ba90f526terelius sequence_number); 118e64fbce0d92949b2928a1a7427b24f37ba90f526terelius } 119e64fbce0d92949b2928a1a7427b24f37ba90f526terelius if (packet_loss_ > 0) { 120e64fbce0d92949b2928a1a7427b24f37ba90f526terelius if ((count_ % packet_loss_) == 0) { 1212d566686a23fe93ada58f1c38a0d4b9a0d68556epbos return true; 122e64fbce0d92949b2928a1a7427b24f37ba90f526terelius } 123e64fbce0d92949b2928a1a7427b24f37ba90f526terelius } else if (count_ >= consecutive_drop_start_ && 124e64fbce0d92949b2928a1a7427b24f37ba90f526terelius count_ < consecutive_drop_end_) { 1252d566686a23fe93ada58f1c38a0d4b9a0d68556epbos return true; 126e64fbce0d92949b2928a1a7427b24f37ba90f526terelius } 1277bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org if (rtp_payload_registry_->IsRtx(header)) { 1287bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org // Remove the RTX header and parse the original RTP header. 1297bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org EXPECT_TRUE(rtp_payload_registry_->RestoreOriginalPacket( 13065220a70a38ffe252b587775c5e9104606ab7c2cnoahric restored_packet, ptr, &packet_length, rtp_receiver_->SSRC(), header)); 13165220a70a38ffe252b587775c5e9104606ab7c2cnoahric if (!parser->Parse(restored_packet, packet_length, &header)) { 1322d566686a23fe93ada58f1c38a0d4b9a0d68556epbos return false; 1337bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org } 134740c4f11e0d3b409c5444b328859754d2a717e33pbos ptr = restored_packet; 135e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin } else { 136e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin rtp_payload_registry_->SetIncomingPayloadType(header); 1377bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org } 138e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin 139822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org PayloadUnion payload_specific; 140822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org if (!rtp_payload_registry_->GetPayloadSpecifics(header.payloadType, 1417bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org &payload_specific)) { 1422d566686a23fe93ada58f1c38a0d4b9a0d68556epbos return false; 143822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org } 144740c4f11e0d3b409c5444b328859754d2a717e33pbos if (!rtp_receiver_->IncomingRtpPacket(header, ptr + header.headerLength, 145740c4f11e0d3b409c5444b328859754d2a717e33pbos packet_length - header.headerLength, 146740c4f11e0d3b409c5444b328859754d2a717e33pbos payload_specific, true)) { 1472d566686a23fe93ada58f1c38a0d4b9a0d68556epbos return false; 148a5cb98cbbd11e93cb6d0a6232387814aac168c7dstefan@webrtc.org } 1492d566686a23fe93ada58f1c38a0d4b9a0d68556epbos return true; 150bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org } 1516cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org 1522d566686a23fe93ada58f1c38a0d4b9a0d68556epbos bool SendRtcp(const uint8_t* data, size_t len) override { 1532d566686a23fe93ada58f1c38a0d4b9a0d68556epbos return module_->IncomingRtcpPacket((const uint8_t*)data, len) == 0; 154bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org } 155bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org int count_; 156bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org int packet_loss_; 1576cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org int consecutive_drop_start_; 1586cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org int consecutive_drop_end_; 159bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org uint32_t rtx_ssrc_; 160bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org int count_rtx_ssrc_; 161822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org RTPPayloadRegistry* rtp_payload_registry_; 162822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org RtpReceiver* rtp_receiver_; 163bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org RtpRtcp* module_; 1646cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org std::set<uint16_t> expected_sequence_numbers_; 165bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org}; 166bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org 16741211466d8b67769c8b3837d3401b2c824c6e337stefan@webrtc.orgclass RtpRtcpRtxNackTest : public ::testing::Test { 168bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org protected: 16941211466d8b67769c8b3837d3401b2c824c6e337stefan@webrtc.org RtpRtcpRtxNackTest() 170dc80bae2a62a1bdbe0d342b3260a7e5b2cb958dfandresp@webrtc.org : rtp_payload_registry_(RTPPayloadStrategy::CreateStrategy(false)), 171822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org rtp_rtcp_module_(NULL), 172bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org transport_(kTestSsrc + 1), 173bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org receiver_(), 174bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org payload_data_length(sizeof(payload_data)), 175bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org fake_clock(123456) {} 17641211466d8b67769c8b3837d3401b2c824c6e337stefan@webrtc.org ~RtpRtcpRtxNackTest() {} 177bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org 17814665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org void SetUp() override { 179bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org RtpRtcp::Configuration configuration; 180bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org configuration.audio = false; 181bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org configuration.clock = &fake_clock; 182822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org receive_statistics_.reset(ReceiveStatistics::Create(&fake_clock)); 183822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org configuration.receive_statistics = receive_statistics_.get(); 184bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org configuration.outgoing_transport = &transport_; 185bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org rtp_rtcp_module_ = RtpRtcp::CreateRtpRtcp(configuration); 186bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org 187822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org rtp_feedback_.reset(new TestRtpFeedback(rtp_rtcp_module_)); 188822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org 189822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org rtp_receiver_.reset(RtpReceiver::CreateVideoReceiver( 190162abd3562d7b08ab36569800d757b52739b9249danilchap &fake_clock, &receiver_, rtp_feedback_.get(), &rtp_payload_registry_)); 191822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org 192ef92755780253c6a7940c89598a206e58e05b810stefan@webrtc.org rtp_rtcp_module_->SetSSRC(kTestSsrc); 193da903eaabbb6c6830efcafc3c2ade1d36f511e43pbos rtp_rtcp_module_->SetRTCPStatus(RtcpMode::kCompound); 1947bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org rtp_receiver_->SetNACKStatus(kNackRtcp); 195d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org rtp_rtcp_module_->SetStorePacketsStatus(true, 600); 196bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org EXPECT_EQ(0, rtp_rtcp_module_->SetSendingStatus(true)); 197d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org rtp_rtcp_module_->SetSequenceNumber(kTestSequenceNumber); 198d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org rtp_rtcp_module_->SetStartTimestamp(111111); 199bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org 200822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org transport_.SetSendModule(rtp_rtcp_module_, &rtp_payload_registry_, 201822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org rtp_receiver_.get()); 202bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org 203bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org VideoCodec video_codec; 204bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org memset(&video_codec, 0, sizeof(video_codec)); 205e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin video_codec.plType = kPayloadType; 206bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org memcpy(video_codec.plName, "I420", 5); 207bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org 208bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org EXPECT_EQ(0, rtp_rtcp_module_->RegisterSendPayload(video_codec)); 209e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin rtp_rtcp_module_->SetRtxSendPayloadType(kRtxPayloadType, kPayloadType); 210162abd3562d7b08ab36569800d757b52739b9249danilchap EXPECT_EQ(0, rtp_receiver_->RegisterReceivePayload( 211162abd3562d7b08ab36569800d757b52739b9249danilchap video_codec.plName, video_codec.plType, 90000, 0, 212162abd3562d7b08ab36569800d757b52739b9249danilchap video_codec.maxBitrate)); 213e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin rtp_payload_registry_.SetRtxPayloadType(kRtxPayloadType, kPayloadType); 214bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org 2154591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org for (size_t n = 0; n < payload_data_length; n++) { 216bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org payload_data[n] = n % 10; 217bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org } 218bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org } 219bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org 2206cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org int BuildNackList(uint16_t* nack_list) { 2216cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org receiver_.sequence_numbers_.sort(); 2226cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org std::list<uint16_t> missing_sequence_numbers; 223162abd3562d7b08ab36569800d757b52739b9249danilchap std::list<uint16_t>::iterator it = receiver_.sequence_numbers_.begin(); 224bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org 225bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org while (it != receiver_.sequence_numbers_.end()) { 2262f44673d665899ca788ae44247a9a7f4764f5e2bpbos@webrtc.org uint16_t sequence_number_1 = *it; 227bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org ++it; 228bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org if (it != receiver_.sequence_numbers_.end()) { 2292f44673d665899ca788ae44247a9a7f4764f5e2bpbos@webrtc.org uint16_t sequence_number_2 = *it; 2306cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org // Add all missing sequence numbers to list 231162abd3562d7b08ab36569800d757b52739b9249danilchap for (uint16_t i = sequence_number_1 + 1; i < sequence_number_2; ++i) { 232bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org missing_sequence_numbers.push_back(i); 233bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org } 234bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org } 235bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org } 236bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org int n = 0; 237bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org for (it = missing_sequence_numbers.begin(); 238162abd3562d7b08ab36569800d757b52739b9249danilchap it != missing_sequence_numbers.end(); ++it) { 239bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org nack_list[n++] = (*it); 240bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org } 2416cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org return n; 2426cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org } 243bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org 2446cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org bool ExpectedPacketsReceived() { 2456cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org std::list<uint16_t> received_sorted; 2466cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org std::copy(receiver_.sequence_numbers_.begin(), 2476cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org receiver_.sequence_numbers_.end(), 2486cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org std::back_inserter(received_sorted)); 2496cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org received_sorted.sort(); 250e64fbce0d92949b2928a1a7427b24f37ba90f526terelius return received_sorted.size() == 251e64fbce0d92949b2928a1a7427b24f37ba90f526terelius transport_.expected_sequence_numbers_.size() && 252e64fbce0d92949b2928a1a7427b24f37ba90f526terelius std::equal(received_sorted.begin(), received_sorted.end(), 2536cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org transport_.expected_sequence_numbers_.begin()); 254bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org } 255bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org 2566cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org void RunRtxTest(RtxMode rtx_method, int loss) { 257ef92755780253c6a7940c89598a206e58e05b810stefan@webrtc.org rtp_payload_registry_.SetRtxSsrc(kTestSsrc + 1); 2580b0c24177bac6eaa27cd520595ba799e48e84a0cpbos@webrtc.org rtp_rtcp_module_->SetRtxSendStatus(rtx_method); 259ef92755780253c6a7940c89598a206e58e05b810stefan@webrtc.org rtp_rtcp_module_->SetRtxSsrc(kTestSsrc + 1); 2606cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org transport_.DropEveryNthPacket(loss); 2616cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org uint32_t timestamp = 3000; 2626cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org uint16_t nack_list[kVideoNackListSize]; 2636cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org for (int frame = 0; frame < kNumFrames; ++frame) { 264e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin EXPECT_EQ(0, rtp_rtcp_module_->SendOutgoingData( 265e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin webrtc::kVideoFrameDelta, kPayloadType, timestamp, 266e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin timestamp / 90, payload_data, payload_data_length)); 26743c883954f5edc84bd8e0e901ef770fead218ed5sprang@webrtc.org // Min required delay until retransmit = 5 + RTT ms (RTT = 0). 26843c883954f5edc84bd8e0e901ef770fead218ed5sprang@webrtc.org fake_clock.AdvanceTimeMilliseconds(5); 2696cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org int length = BuildNackList(nack_list); 2706cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org if (length > 0) 2716cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org rtp_rtcp_module_->SendNACK(nack_list, length); 27243c883954f5edc84bd8e0e901ef770fead218ed5sprang@webrtc.org fake_clock.AdvanceTimeMilliseconds(28); // 33ms - 5ms delay. 2736cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org rtp_rtcp_module_->Process(); 2746cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org // Prepare next frame. 2756cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org timestamp += 3000; 2766cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org } 2776cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org receiver_.sequence_numbers_.sort(); 2786cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org } 279bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org 28014665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org void TearDown() override { delete rtp_rtcp_module_; } 281bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org 28200b8f6b3643332cce1ee711715f7fbb824d793cakwiberg@webrtc.org rtc::scoped_ptr<ReceiveStatistics> receive_statistics_; 283822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org RTPPayloadRegistry rtp_payload_registry_; 28400b8f6b3643332cce1ee711715f7fbb824d793cakwiberg@webrtc.org rtc::scoped_ptr<RtpReceiver> rtp_receiver_; 2856cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org RtpRtcp* rtp_rtcp_module_; 28600b8f6b3643332cce1ee711715f7fbb824d793cakwiberg@webrtc.org rtc::scoped_ptr<TestRtpFeedback> rtp_feedback_; 2876cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org RtxLoopBackTransport transport_; 2886cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org VerifyingRtxReceiver receiver_; 289162abd3562d7b08ab36569800d757b52739b9249danilchap uint8_t payload_data[65000]; 2904591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org size_t payload_data_length; 2916cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org SimulatedClock fake_clock; 2926cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org}; 293bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org 2946cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.orgTEST_F(RtpRtcpRtxNackTest, LongNackList) { 2956cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org const int kNumPacketsToDrop = 900; 2966cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org const int kNumRequiredRtcp = 4; 2976cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org uint32_t timestamp = 3000; 2986cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org uint16_t nack_list[kNumPacketsToDrop]; 2996cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org // Disable StorePackets to be able to set a larger packet history. 300d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org rtp_rtcp_module_->SetStorePacketsStatus(false, 0); 3016cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org // Enable StorePackets with a packet history of 2000 packets. 302d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org rtp_rtcp_module_->SetStorePacketsStatus(true, 2000); 3036cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org // Drop 900 packets from the second one so that we get a NACK list which is 3046cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org // big enough to require 4 RTCP packets to be fully transmitted to the sender. 3056cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org transport_.DropConsecutivePackets(2, kNumPacketsToDrop); 3066cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org // Send 30 frames which at the default size is roughly what we need to get 3076cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org // enough packets. 3086cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org for (int frame = 0; frame < kNumFrames; ++frame) { 309e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin EXPECT_EQ(0, rtp_rtcp_module_->SendOutgoingData( 310e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin webrtc::kVideoFrameDelta, kPayloadType, timestamp, 311e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin timestamp / 90, payload_data, payload_data_length)); 312bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org // Prepare next frame. 313bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org timestamp += 3000; 3146cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org fake_clock.AdvanceTimeMilliseconds(33); 3156cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org rtp_rtcp_module_->Process(); 316bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org } 3176cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org EXPECT_FALSE(transport_.expected_sequence_numbers_.empty()); 3186cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org EXPECT_FALSE(receiver_.sequence_numbers_.empty()); 3196cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org size_t last_receive_count = receiver_.sequence_numbers_.size(); 3206cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org int length = BuildNackList(nack_list); 3216cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org for (int i = 0; i < kNumRequiredRtcp - 1; ++i) { 3226cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org rtp_rtcp_module_->SendNACK(nack_list, length); 3236cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org EXPECT_GT(receiver_.sequence_numbers_.size(), last_receive_count); 3246cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org last_receive_count = receiver_.sequence_numbers_.size(); 3256cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org EXPECT_FALSE(ExpectedPacketsReceived()); 3266cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org } 3276cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org rtp_rtcp_module_->SendNACK(nack_list, length); 3286cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org EXPECT_GT(receiver_.sequence_numbers_.size(), last_receive_count); 3296cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org EXPECT_TRUE(ExpectedPacketsReceived()); 3306cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org} 3316cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org 3326cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.orgTEST_F(RtpRtcpRtxNackTest, RtxNack) { 3336cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org RunRtxTest(kRtxRetransmitted, 10); 334bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org EXPECT_EQ(kTestSequenceNumber, *(receiver_.sequence_numbers_.begin())); 335bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org EXPECT_EQ(kTestSequenceNumber + kTestNumberOfPackets - 1, 336162abd3562d7b08ab36569800d757b52739b9249danilchap *(receiver_.sequence_numbers_.rbegin())); 337bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org EXPECT_EQ(kTestNumberOfPackets, receiver_.sequence_numbers_.size()); 338bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org EXPECT_EQ(kTestNumberOfRtxPackets, transport_.count_rtx_ssrc_); 3396cfa3907c8b4cff62f13e4fe8beb66f89b6c0912mikhal@webrtc.org EXPECT_TRUE(ExpectedPacketsReceived()); 340bda7f305c5d7d675f1c35813bd2b2a5732775bb9mikhal@webrtc.org} 3416a6f0893dd1e653410ba4b22e7f33947d15aeb65danilchap 3426a6f0893dd1e653410ba4b22e7f33947d15aeb65danilchap} // namespace webrtc 343