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