tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

flexfec_receiver_unittest.cc (25329B)


      1 /*
      2 *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
      3 *
      4 *  Use of this source code is governed by a BSD-style license
      5 *  that can be found in the LICENSE file in the root of the source
      6 *  tree. An additional intellectual property rights grant can be found
      7 *  in the file PATENTS.  All contributing project authors may
      8 *  be found in the AUTHORS file in the root of the source tree.
      9 */
     10 
     11 #include "modules/rtp_rtcp/include/flexfec_receiver.h"
     12 
     13 #include <cstddef>
     14 #include <cstdint>
     15 #include <limits>
     16 #include <list>
     17 #include <memory>
     18 #include <utility>
     19 
     20 #include "modules/include/module_fec_types.h"
     21 #include "modules/rtp_rtcp/include/recovered_packet_receiver.h"
     22 #include "modules/rtp_rtcp/mocks/mock_recovered_packet_receiver.h"
     23 #include "modules/rtp_rtcp/source/fec_test_helper.h"
     24 #include "modules/rtp_rtcp/source/forward_error_correction.h"
     25 #include "modules/rtp_rtcp/source/rtp_packet_received.h"
     26 #include "modules/rtp_rtcp/source/ulpfec_receiver.h"
     27 #include "rtc_base/checks.h"
     28 #include "test/gmock.h"
     29 #include "test/gtest.h"
     30 
     31 namespace webrtc {
     32 
     33 namespace {
     34 
     35 using ::testing::Eq;
     36 using ::testing::Property;
     37 
     38 using test::fec::FlexfecPacketGenerator;
     39 using Packet = ForwardErrorCorrection::Packet;
     40 using PacketList = ForwardErrorCorrection::PacketList;
     41 
     42 constexpr size_t kPayloadLength = 500;
     43 constexpr uint32_t kFlexfecSsrc = 42984;
     44 constexpr uint32_t kMediaSsrc = 8353;
     45 
     46 RtpPacketReceived ParsePacket(const Packet& packet) {
     47  RtpPacketReceived parsed_packet;
     48  EXPECT_TRUE(parsed_packet.Parse(packet.data));
     49  return parsed_packet;
     50 }
     51 
     52 }  // namespace
     53 
     54 class FlexfecReceiverForTest : public FlexfecReceiver {
     55 public:
     56  FlexfecReceiverForTest(uint32_t ssrc,
     57                         uint32_t protected_media_ssrc,
     58                         RecoveredPacketReceiver* recovered_packet_receiver)
     59      : FlexfecReceiver(Clock::GetRealTimeClock(),
     60                        ssrc,
     61                        protected_media_ssrc,
     62                        recovered_packet_receiver) {}
     63  // Expose methods for tests.
     64  using FlexfecReceiver::AddReceivedPacket;
     65  using FlexfecReceiver::ProcessReceivedPacket;
     66 };
     67 
     68 class FlexfecReceiverTest : public ::testing::Test {
     69 protected:
     70  FlexfecReceiverTest()
     71      : receiver_(kFlexfecSsrc, kMediaSsrc, &recovered_packet_receiver_),
     72        erasure_code_(
     73            ForwardErrorCorrection::CreateFlexfec(kFlexfecSsrc, kMediaSsrc)),
     74        packet_generator_(kMediaSsrc, kFlexfecSsrc) {}
     75 
     76  // Generates `num_media_packets` corresponding to a single frame.
     77  void PacketizeFrame(size_t num_media_packets,
     78                      size_t frame_offset,
     79                      PacketList* media_packets);
     80 
     81  // Generates `num_fec_packets` FEC packets, given `media_packets`.
     82  std::list<Packet*> EncodeFec(const PacketList& media_packets,
     83                               size_t num_fec_packets);
     84 
     85  FlexfecReceiverForTest receiver_;
     86  std::unique_ptr<ForwardErrorCorrection> erasure_code_;
     87 
     88  FlexfecPacketGenerator packet_generator_;
     89  ::testing::StrictMock<MockRecoveredPacketReceiver> recovered_packet_receiver_;
     90 };
     91 
     92 void FlexfecReceiverTest::PacketizeFrame(size_t num_media_packets,
     93                                         size_t frame_offset,
     94                                         PacketList* media_packets) {
     95  packet_generator_.NewFrame(num_media_packets);
     96  for (size_t i = 0; i < num_media_packets; ++i) {
     97    auto next_packet = std::make_unique<Packet>();
     98    next_packet->data =
     99        packet_generator_.NextPacket(frame_offset + i, kPayloadLength).Buffer();
    100    media_packets->push_back(std::move(next_packet));
    101  }
    102 }
    103 
    104 std::list<Packet*> FlexfecReceiverTest::EncodeFec(
    105    const PacketList& media_packets,
    106    size_t num_fec_packets) {
    107  const uint8_t protection_factor =
    108      num_fec_packets * 255 / media_packets.size();
    109  constexpr int kNumImportantPackets = 0;
    110  constexpr bool kUseUnequalProtection = false;
    111  constexpr FecMaskType kFecMaskType = kFecMaskRandom;
    112  std::list<Packet*> fec_packets;
    113  EXPECT_EQ(0, erasure_code_->EncodeFec(
    114                   media_packets, protection_factor, kNumImportantPackets,
    115                   kUseUnequalProtection, kFecMaskType, &fec_packets));
    116  EXPECT_EQ(num_fec_packets, fec_packets.size());
    117  return fec_packets;
    118 }
    119 
    120 TEST_F(FlexfecReceiverTest, ReceivesMediaPacket) {
    121  packet_generator_.NewFrame(1);
    122  RtpPacketReceived media_packet =
    123      packet_generator_.NextPacket<RtpPacketReceived>(0, kPayloadLength);
    124 
    125  std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet =
    126      receiver_.AddReceivedPacket(media_packet);
    127  ASSERT_TRUE(received_packet);
    128  receiver_.ProcessReceivedPacket(*received_packet);
    129 }
    130 
    131 TEST_F(FlexfecReceiverTest, ReceivesMediaAndFecPackets) {
    132  const size_t kNumMediaPackets = 1;
    133  const size_t kNumFecPackets = 1;
    134 
    135  PacketList media_packets;
    136  PacketizeFrame(kNumMediaPackets, 0, &media_packets);
    137  std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
    138  const auto& media_packet = media_packets.front();
    139  auto fec_packet = packet_generator_.BuildFlexfecPacket(*fec_packets.front());
    140 
    141  std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet =
    142      receiver_.AddReceivedPacket(ParsePacket(*media_packet));
    143  ASSERT_TRUE(received_packet);
    144  receiver_.ProcessReceivedPacket(*received_packet);
    145  received_packet = receiver_.AddReceivedPacket(fec_packet);
    146  ASSERT_TRUE(received_packet);
    147  receiver_.ProcessReceivedPacket(*received_packet);
    148 }
    149 
    150 TEST_F(FlexfecReceiverTest, FailsOnTruncatedFecPacket) {
    151  const size_t kNumMediaPackets = 1;
    152  const size_t kNumFecPackets = 1;
    153 
    154  PacketList media_packets;
    155  PacketizeFrame(kNumMediaPackets, 0, &media_packets);
    156  std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
    157  const auto& media_packet = media_packets.front();
    158  // Simulate truncated FlexFEC payload.
    159  fec_packets.front()->data.SetSize(1);
    160  auto fec_packet = packet_generator_.BuildFlexfecPacket(*fec_packets.front());
    161 
    162  std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet =
    163      receiver_.AddReceivedPacket(ParsePacket(*media_packet));
    164  ASSERT_TRUE(received_packet);
    165  receiver_.ProcessReceivedPacket(*received_packet);
    166  EXPECT_FALSE(receiver_.AddReceivedPacket(fec_packet));
    167 }
    168 
    169 TEST_F(FlexfecReceiverTest, FailsOnUnknownMediaSsrc) {
    170  const size_t kNumMediaPackets = 1;
    171 
    172  PacketList media_packets;
    173  PacketizeFrame(kNumMediaPackets, 0, &media_packets);
    174  auto& media_packet = media_packets.front();
    175  // Corrupt the SSRC.
    176  media_packet->data.MutableData()[8] = 0;
    177  media_packet->data.MutableData()[9] = 1;
    178  media_packet->data.MutableData()[10] = 2;
    179  media_packet->data.MutableData()[11] = 3;
    180 
    181  EXPECT_FALSE(receiver_.AddReceivedPacket(ParsePacket(*media_packet)));
    182 }
    183 
    184 TEST_F(FlexfecReceiverTest, FailsOnUnknownFecSsrc) {
    185  const size_t kNumMediaPackets = 1;
    186  const size_t kNumFecPackets = 1;
    187 
    188  PacketList media_packets;
    189  PacketizeFrame(kNumMediaPackets, 0, &media_packets);
    190  std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
    191  const auto& media_packet = media_packets.front();
    192  auto fec_packet = packet_generator_.BuildFlexfecPacket(*fec_packets.front());
    193  // Corrupt the SSRC.
    194  fec_packet.SetSsrc(0x04050607);
    195 
    196  std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet =
    197      receiver_.AddReceivedPacket(ParsePacket(*media_packet));
    198  ASSERT_TRUE(received_packet);
    199  receiver_.ProcessReceivedPacket(*received_packet);
    200  EXPECT_FALSE(receiver_.AddReceivedPacket(fec_packet));
    201 }
    202 
    203 TEST_F(FlexfecReceiverTest, ReceivesMultiplePackets) {
    204  const size_t kNumMediaPackets = 2;
    205  const size_t kNumFecPackets = 1;
    206 
    207  PacketList media_packets;
    208  PacketizeFrame(kNumMediaPackets, 0, &media_packets);
    209  std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
    210 
    211  // Receive all media packets.
    212  for (const auto& media_packet : media_packets) {
    213    std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet =
    214        receiver_.AddReceivedPacket(ParsePacket(*media_packet));
    215    ASSERT_TRUE(received_packet);
    216    receiver_.ProcessReceivedPacket(*received_packet);
    217  }
    218 
    219  // Receive FEC packet.
    220  auto* fec_packet = fec_packets.front();
    221  RtpPacketReceived packet_with_rtp_header =
    222      packet_generator_.BuildFlexfecPacket(*fec_packet);
    223  std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet =
    224      receiver_.AddReceivedPacket(packet_with_rtp_header);
    225  ASSERT_TRUE(received_packet);
    226  receiver_.ProcessReceivedPacket(*received_packet);
    227 }
    228 
    229 TEST_F(FlexfecReceiverTest, RecoversFromSingleMediaLoss) {
    230  const size_t kNumMediaPackets = 2;
    231  const size_t kNumFecPackets = 1;
    232 
    233  PacketList media_packets;
    234  PacketizeFrame(kNumMediaPackets, 0, &media_packets);
    235  std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
    236 
    237  // Receive first media packet but drop second.
    238  auto media_it = media_packets.begin();
    239  receiver_.OnRtpPacket(ParsePacket(**media_it));
    240 
    241  // Receive FEC packet and ensure recovery of lost media packet.
    242  auto fec_it = fec_packets.begin();
    243  RtpPacketReceived packet_with_rtp_header =
    244      packet_generator_.BuildFlexfecPacket(**fec_it);
    245  media_it++;
    246  EXPECT_CALL(recovered_packet_receiver_,
    247              OnRecoveredPacket(
    248                  Property(&RtpPacketReceived::Buffer, Eq((*media_it)->data))));
    249  receiver_.OnRtpPacket(packet_with_rtp_header);
    250 }
    251 
    252 TEST_F(FlexfecReceiverTest, RecoversFromDoubleMediaLoss) {
    253  const size_t kNumMediaPackets = 2;
    254  const size_t kNumFecPackets = 2;
    255 
    256  PacketList media_packets;
    257  PacketizeFrame(kNumMediaPackets, 0, &media_packets);
    258  std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
    259 
    260  // Drop both media packets.
    261 
    262  // Receive first FEC packet and recover first lost media packet.
    263  auto fec_it = fec_packets.begin();
    264  RtpPacketReceived packet_with_rtp_header =
    265      packet_generator_.BuildFlexfecPacket(**fec_it);
    266  auto media_it = media_packets.begin();
    267  EXPECT_CALL(recovered_packet_receiver_,
    268              OnRecoveredPacket(
    269                  Property(&RtpPacketReceived::Buffer, Eq((*media_it)->data))));
    270  receiver_.OnRtpPacket(packet_with_rtp_header);
    271 
    272  // Receive second FEC packet and recover second lost media packet.
    273  fec_it++;
    274  packet_with_rtp_header = packet_generator_.BuildFlexfecPacket(**fec_it);
    275  media_it++;
    276  EXPECT_CALL(recovered_packet_receiver_,
    277              OnRecoveredPacket(
    278                  Property(&RtpPacketReceived::Buffer, Eq((*media_it)->data))));
    279 
    280  receiver_.OnRtpPacket(packet_with_rtp_header);
    281 }
    282 
    283 TEST_F(FlexfecReceiverTest, DoesNotRecoverFromMediaAndFecLoss) {
    284  const size_t kNumMediaPackets = 2;
    285  const size_t kNumFecPackets = 1;
    286 
    287  PacketList media_packets;
    288  PacketizeFrame(kNumMediaPackets, 0, &media_packets);
    289  std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
    290 
    291  // Receive first media packet.
    292  auto media_it = media_packets.begin();
    293  receiver_.OnRtpPacket(ParsePacket(**media_it));
    294 
    295  // Drop second media packet and FEC packet. Do not expect call back.
    296 }
    297 
    298 TEST_F(FlexfecReceiverTest, DoesNotCallbackTwice) {
    299  const size_t kNumMediaPackets = 2;
    300  const size_t kNumFecPackets = 1;
    301 
    302  PacketList media_packets;
    303  PacketizeFrame(kNumMediaPackets, 0, &media_packets);
    304  std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
    305 
    306  // Receive first media packet but drop second.
    307  auto media_it = media_packets.begin();
    308  receiver_.OnRtpPacket(ParsePacket(**media_it));
    309 
    310  // Receive FEC packet and ensure recovery of lost media packet.
    311  auto fec_it = fec_packets.begin();
    312  RtpPacketReceived packet_with_rtp_header =
    313      packet_generator_.BuildFlexfecPacket(**fec_it);
    314  media_it++;
    315  EXPECT_CALL(recovered_packet_receiver_,
    316              OnRecoveredPacket(
    317                  Property(&RtpPacketReceived::Buffer, Eq((*media_it)->data))));
    318  receiver_.OnRtpPacket(packet_with_rtp_header);
    319 
    320  // Receive the FEC packet again, but do not call back.
    321  receiver_.OnRtpPacket(packet_with_rtp_header);
    322 
    323  // Receive the first media packet again, but do not call back.
    324  media_it = media_packets.begin();
    325  receiver_.OnRtpPacket(ParsePacket(**media_it));
    326 
    327  // Receive the second media packet again (the one recovered above),
    328  // but do not call back again.
    329  media_it++;
    330  receiver_.OnRtpPacket(ParsePacket(**media_it));
    331 }
    332 
    333 // Here we are implicitly assuming packet masks that are suitable for
    334 // this type of 50% correlated loss. If we are changing our precomputed
    335 // packet masks, this test might need to be updated.
    336 TEST_F(FlexfecReceiverTest, RecoversFrom50PercentLoss) {
    337  const size_t kNumFecPackets = 5;
    338  const size_t kNumFrames = 2 * kNumFecPackets;
    339  const size_t kNumMediaPacketsPerFrame = 1;
    340 
    341  PacketList media_packets;
    342  for (size_t i = 0; i < kNumFrames; ++i) {
    343    PacketizeFrame(kNumMediaPacketsPerFrame, i, &media_packets);
    344  }
    345  std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
    346 
    347  // Drop every second media packet.
    348  auto media_it = media_packets.begin();
    349  while (media_it != media_packets.end()) {
    350    receiver_.OnRtpPacket(ParsePacket(**media_it));
    351    ++media_it;
    352    if (media_it == media_packets.end()) {
    353      break;
    354    }
    355    ++media_it;
    356  }
    357 
    358  // Receive all FEC packets.
    359  media_it = media_packets.begin();
    360  for (const auto* fec_packet : fec_packets) {
    361    RtpPacketReceived fec_packet_with_rtp_header =
    362        packet_generator_.BuildFlexfecPacket(*fec_packet);
    363    ++media_it;
    364    if (media_it == media_packets.end()) {
    365      break;
    366    }
    367    EXPECT_CALL(recovered_packet_receiver_,
    368                OnRecoveredPacket(Property(&RtpPacketReceived::Buffer,
    369                                           Eq((*media_it)->data))));
    370    receiver_.OnRtpPacket(fec_packet_with_rtp_header);
    371    ++media_it;
    372  }
    373 }
    374 
    375 TEST_F(FlexfecReceiverTest, DelayedFecPacketDoesHelp) {
    376  // These values need to be updated if the underlying erasure code
    377  // implementation changes.
    378  // Delay FEC packet by maximum number of media packets tracked by receiver.
    379  const size_t kNumFrames = 192;
    380  const size_t kNumMediaPacketsPerFrame = 1;
    381  const size_t kNumFecPackets = 1;
    382 
    383  PacketList media_packets;
    384  PacketizeFrame(kNumMediaPacketsPerFrame, 0, &media_packets);
    385  PacketizeFrame(kNumMediaPacketsPerFrame, 1, &media_packets);
    386  // Protect two first frames.
    387  std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
    388  for (size_t i = 2; i < kNumFrames; ++i) {
    389    PacketizeFrame(kNumMediaPacketsPerFrame, i, &media_packets);
    390  }
    391 
    392  // Drop first media packet and delay FEC packet.
    393  auto media_it = media_packets.begin();
    394  ++media_it;
    395 
    396  // Receive all other media packets.
    397  while (media_it != media_packets.end()) {
    398    receiver_.OnRtpPacket(ParsePacket(**media_it));
    399    ++media_it;
    400  }
    401 
    402  // Receive FEC packet and recover first media packet.
    403  auto fec_it = fec_packets.begin();
    404  RtpPacketReceived packet_with_rtp_header =
    405      packet_generator_.BuildFlexfecPacket(**fec_it);
    406  media_it = media_packets.begin();
    407  EXPECT_CALL(recovered_packet_receiver_,
    408              OnRecoveredPacket(
    409                  Property(&RtpPacketReceived::Buffer, Eq((*media_it)->data))));
    410  receiver_.OnRtpPacket(packet_with_rtp_header);
    411 }
    412 
    413 TEST_F(FlexfecReceiverTest, TooDelayedFecPacketDoesNotHelp) {
    414  // These values need to be updated if the underlying erasure code
    415  // implementation changes.
    416  // Delay FEC packet by one more than maximum number of media packets
    417  // tracked by receiver.
    418  const size_t kNumFrames = 193;
    419  const size_t kNumMediaPacketsPerFrame = 1;
    420  const size_t kNumFecPackets = 1;
    421 
    422  PacketList media_packets;
    423  PacketizeFrame(kNumMediaPacketsPerFrame, 0, &media_packets);
    424  PacketizeFrame(kNumMediaPacketsPerFrame, 1, &media_packets);
    425  // Protect first two frames.
    426  std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
    427  for (size_t i = 2; i < kNumFrames; ++i) {
    428    PacketizeFrame(kNumMediaPacketsPerFrame, i, &media_packets);
    429  }
    430 
    431  // Drop first media packet and delay FEC packet.
    432  auto media_it = media_packets.begin();
    433  ++media_it;
    434 
    435  // Receive all other media packets.
    436  while (media_it != media_packets.end()) {
    437    receiver_.OnRtpPacket(ParsePacket(**media_it));
    438    ++media_it;
    439  }
    440 
    441  // Receive FEC packet.
    442  auto fec_it = fec_packets.begin();
    443  RtpPacketReceived packet_with_rtp_header =
    444      packet_generator_.BuildFlexfecPacket(**fec_it);
    445  receiver_.OnRtpPacket(packet_with_rtp_header);
    446 
    447  // Do not expect a call back.
    448 }
    449 
    450 TEST_F(FlexfecReceiverTest, SurvivesOldRecoveredPacketBeingReinserted) {
    451  // Simulates the behaviour of the
    452  // Call->FlexfecReceiveStream->FlexfecReceiver->Call loop in production code.
    453  class LoopbackRecoveredPacketReceiver : public RecoveredPacketReceiver {
    454   public:
    455    LoopbackRecoveredPacketReceiver() : receiver_(nullptr) {}
    456 
    457    void SetReceiver(FlexfecReceiver* receiver) { receiver_ = receiver; }
    458 
    459    // Implements RecoveredPacketReceiver.
    460    void OnRecoveredPacket(const RtpPacketReceived& packet) override {
    461      EXPECT_TRUE(packet.recovered());
    462      RTC_DCHECK(receiver_);
    463      receiver_->OnRtpPacket(packet);
    464    }
    465 
    466   private:
    467    FlexfecReceiver* receiver_;
    468  } loopback_recovered_packet_receiver;
    469 
    470  // Feed recovered packets back into `receiver`.
    471  FlexfecReceiver receiver(Clock::GetRealTimeClock(), kFlexfecSsrc, kMediaSsrc,
    472                           &loopback_recovered_packet_receiver);
    473  loopback_recovered_packet_receiver.SetReceiver(&receiver);
    474 
    475  // Receive first set of packets.
    476  PacketList first_media_packets;
    477  for (int i = 0; i < 46; ++i) {
    478    PacketizeFrame(1, 0, &first_media_packets);
    479  }
    480  for (const auto& media_packet : first_media_packets) {
    481    receiver.OnRtpPacket(ParsePacket(*media_packet));
    482  }
    483 
    484  // Protect one media packet. Lose the media packet,
    485  // but do not receive FEC packet yet.
    486  PacketList protected_media_packet;
    487  PacketizeFrame(1, 0, &protected_media_packet);
    488  const std::list<Packet*> fec_packets = EncodeFec(protected_media_packet, 1);
    489  EXPECT_EQ(1u, fec_packets.size());
    490  RtpPacketReceived fec_packet_with_rtp_header =
    491      packet_generator_.BuildFlexfecPacket(*fec_packets.front());
    492 
    493  // Lose some packets, thus introducing a sequence number gap.
    494  PacketList lost_packets;
    495  for (int i = 0; i < 100; ++i) {
    496    PacketizeFrame(1, 0, &lost_packets);
    497  }
    498 
    499  // Receive one more packet.
    500  PacketList second_media_packets;
    501  PacketizeFrame(1, 0, &second_media_packets);
    502  for (const auto& media_packet : second_media_packets) {
    503    receiver.OnRtpPacket(ParsePacket(*media_packet));
    504  }
    505 
    506  // Receive delayed FEC packet.
    507  receiver.OnRtpPacket(fec_packet_with_rtp_header);
    508 
    509  // Expect no crash.
    510 }
    511 
    512 TEST_F(FlexfecReceiverTest, RecoversWithMediaPacketsOutOfOrder) {
    513  const size_t kNumMediaPackets = 6;
    514  const size_t kNumFecPackets = 2;
    515 
    516  PacketList media_packets;
    517  PacketizeFrame(kNumMediaPackets, 0, &media_packets);
    518  std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
    519 
    520  // Lose two media packets, and receive the others out of order.
    521  auto media_it = media_packets.begin();
    522  auto media_packet0 = media_it++;
    523  auto media_packet1 = media_it++;
    524  auto media_packet2 = media_it++;
    525  auto media_packet3 = media_it++;
    526  auto media_packet4 = media_it++;
    527  auto media_packet5 = media_it++;
    528  receiver_.OnRtpPacket(ParsePacket(**media_packet5));
    529  receiver_.OnRtpPacket(ParsePacket(**media_packet2));
    530  receiver_.OnRtpPacket(ParsePacket(**media_packet3));
    531  receiver_.OnRtpPacket(ParsePacket(**media_packet0));
    532 
    533  // Expect to recover lost media packets.
    534  EXPECT_CALL(recovered_packet_receiver_,
    535              OnRecoveredPacket(Property(&RtpPacketReceived::Buffer,
    536                                         Eq((*media_packet1)->data))));
    537  EXPECT_CALL(recovered_packet_receiver_,
    538              OnRecoveredPacket(Property(&RtpPacketReceived::Buffer,
    539                                         Eq((*media_packet4)->data))));
    540  // Add FEC packets.
    541  for (Packet* fec_packet : fec_packets) {
    542    receiver_.OnRtpPacket(packet_generator_.BuildFlexfecPacket(*fec_packet));
    543  }
    544 }
    545 
    546 // Recovered media packets may be fed back into the FlexfecReceiver by the
    547 // callback. This test ensures the idempotency of such a situation.
    548 TEST_F(FlexfecReceiverTest, RecoveryCallbackDoesNotLoopInfinitely) {
    549  class LoopbackRecoveredPacketReceiver : public RecoveredPacketReceiver {
    550   public:
    551    const int kMaxRecursionDepth = 10;
    552 
    553    LoopbackRecoveredPacketReceiver()
    554        : receiver_(nullptr),
    555          did_receive_call_back_(false),
    556          recursion_depth_(0),
    557          deep_recursion_(false) {}
    558 
    559    void SetReceiver(FlexfecReceiver* receiver) { receiver_ = receiver; }
    560    bool DidReceiveCallback() const { return did_receive_call_back_; }
    561    bool DeepRecursion() const { return deep_recursion_; }
    562 
    563    // Implements RecoveredPacketReceiver.
    564    void OnRecoveredPacket(const RtpPacketReceived& packet) override {
    565      did_receive_call_back_ = true;
    566 
    567      if (recursion_depth_ > kMaxRecursionDepth) {
    568        deep_recursion_ = true;
    569        return;
    570      }
    571      ++recursion_depth_;
    572      RTC_DCHECK(receiver_);
    573      receiver_->OnRtpPacket(packet);
    574      --recursion_depth_;
    575    }
    576 
    577   private:
    578    FlexfecReceiver* receiver_;
    579    bool did_receive_call_back_;
    580    int recursion_depth_;
    581    bool deep_recursion_;
    582  } loopback_recovered_packet_receiver;
    583 
    584  // Feed recovered packets back into `receiver`.
    585  FlexfecReceiver receiver(Clock::GetRealTimeClock(), kFlexfecSsrc, kMediaSsrc,
    586                           &loopback_recovered_packet_receiver);
    587  loopback_recovered_packet_receiver.SetReceiver(&receiver);
    588 
    589  const size_t kNumMediaPackets = 2;
    590  const size_t kNumFecPackets = 1;
    591 
    592  PacketList media_packets;
    593  PacketizeFrame(kNumMediaPackets, 0, &media_packets);
    594  std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
    595 
    596  // Receive first media packet but drop second.
    597  auto media_it = media_packets.begin();
    598  receiver.OnRtpPacket(ParsePacket(**media_it));
    599 
    600  // Receive FEC packet and verify that a packet was recovered.
    601  auto fec_it = fec_packets.begin();
    602  receiver.OnRtpPacket(packet_generator_.BuildFlexfecPacket(**fec_it));
    603  EXPECT_TRUE(loopback_recovered_packet_receiver.DidReceiveCallback());
    604  EXPECT_FALSE(loopback_recovered_packet_receiver.DeepRecursion());
    605 }
    606 
    607 TEST_F(FlexfecReceiverTest, CalculatesNumberOfPackets) {
    608  const size_t kNumMediaPackets = 2;
    609  const size_t kNumFecPackets = 1;
    610 
    611  PacketList media_packets;
    612  PacketizeFrame(kNumMediaPackets, 0, &media_packets);
    613  std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
    614 
    615  // Receive first media packet but drop second.
    616  auto media_it = media_packets.begin();
    617  receiver_.OnRtpPacket(ParsePacket(**media_it));
    618 
    619  // Receive FEC packet and ensure recovery of lost media packet.
    620  auto fec_it = fec_packets.begin();
    621  RtpPacketReceived packet_with_rtp_header =
    622      packet_generator_.BuildFlexfecPacket(**fec_it);
    623  media_it++;
    624  EXPECT_CALL(recovered_packet_receiver_,
    625              OnRecoveredPacket(
    626                  Property(&RtpPacketReceived::Buffer, Eq((*media_it)->data))));
    627  receiver_.OnRtpPacket(packet_with_rtp_header);
    628 
    629  // Check stats calculations.
    630  FecPacketCounter packet_counter = receiver_.GetPacketCounter();
    631  EXPECT_EQ(2U, packet_counter.num_packets);
    632  EXPECT_EQ(1U, packet_counter.num_fec_packets);
    633  EXPECT_EQ(1U, packet_counter.num_recovered_packets);
    634 }
    635 
    636 TEST_F(FlexfecReceiverTest, DoesNotDecodeWrappedMediaSequenceUsingOldFec) {
    637  const size_t kFirstFrameNumMediaPackets = 2;
    638  const size_t kFirstFrameNumFecPackets = 1;
    639 
    640  PacketList media_packets;
    641  PacketizeFrame(kFirstFrameNumMediaPackets, 0, &media_packets);
    642 
    643  // Protect first frame (sequences 0 and 1) with 1 FEC packet.
    644  std::list<Packet*> fec_packets =
    645      EncodeFec(media_packets, kFirstFrameNumFecPackets);
    646 
    647  // Generate enough media packets to simulate media sequence number wraparound.
    648  // Use no FEC for these frames to make sure old FEC is not purged due to age.
    649  const size_t kNumFramesSequenceWrapAround =
    650      std::numeric_limits<uint16_t>::max();
    651  const size_t kNumMediaPacketsPerFrame = 1;
    652 
    653  for (size_t i = 1; i <= kNumFramesSequenceWrapAround; ++i) {
    654    PacketizeFrame(kNumMediaPacketsPerFrame, i, &media_packets);
    655  }
    656 
    657  // Receive first (`kFirstFrameNumMediaPackets` + 192) media packets.
    658  // Simulate an old FEC packet by separating it from its encoded media
    659  // packets by at least 192 packets.
    660  auto media_it = media_packets.begin();
    661  for (size_t i = 0; i < (kFirstFrameNumMediaPackets + 192); i++) {
    662    if (i == 1) {
    663      // Drop the second packet of the first frame.
    664      media_it++;
    665    } else {
    666      receiver_.OnRtpPacket(ParsePacket(**media_it++));
    667    }
    668  }
    669 
    670  // Receive FEC packet. Although a protected packet was dropped,
    671  // expect no recovery callback since it is delayed from first frame
    672  // by more than 192 packets.
    673  auto fec_it = fec_packets.begin();
    674  receiver_.OnRtpPacket(packet_generator_.BuildFlexfecPacket(**fec_it));
    675 
    676  // Receive remaining media packets.
    677  // NOTE: Because we sent enough to simulate wrap around, sequence 0 is
    678  // received again, but is a different packet than the original first
    679  // packet of first frame.
    680  while (media_it != media_packets.end()) {
    681    receiver_.OnRtpPacket(ParsePacket(**media_it++));
    682  }
    683 
    684  // Do not expect a recovery callback, the FEC packet is old
    685  // and should not decode wrapped around media sequences.
    686 }
    687 
    688 }  // namespace webrtc