tor-browser

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

rtp_fec_unittest.cc (46198B)


      1 /*
      2 *  Copyright (c) 2012 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 <cstddef>
     12 #include <cstdint>
     13 #include <cstring>
     14 #include <list>
     15 #include <memory>
     16 #include <utility>
     17 #include <vector>
     18 
     19 #include "absl/algorithm/container.h"
     20 #include "modules/include/module_fec_types.h"
     21 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
     22 #include "modules/rtp_rtcp/source/byte_io.h"
     23 #include "modules/rtp_rtcp/source/fec_test_helper.h"
     24 #include "modules/rtp_rtcp/source/flexfec_03_header_reader_writer.h"
     25 #include "modules/rtp_rtcp/source/forward_error_correction.h"
     26 #include "modules/rtp_rtcp/source/forward_error_correction_internal.h"
     27 #include "modules/rtp_rtcp/source/ulpfec_header_reader_writer.h"
     28 #include "rtc_base/checks.h"
     29 #include "rtc_base/random.h"
     30 #include "test/gtest.h"
     31 
     32 namespace webrtc {
     33 
     34 namespace {
     35 
     36 // Transport header size in bytes. Assume UDP/IPv4 as a reasonable minimum.
     37 constexpr size_t kTransportOverhead = 28;
     38 
     39 constexpr uint32_t kMediaSsrc = 83542;
     40 constexpr uint32_t kFlexfecSsrc = 43245;
     41 
     42 constexpr size_t kMaxMediaPackets = 48;
     43 
     44 // Deep copies `src` to `dst`, but only keeps every Nth packet.
     45 void DeepCopyEveryNthPacket(const ForwardErrorCorrection::PacketList& src,
     46                            int n,
     47                            ForwardErrorCorrection::PacketList* dst) {
     48  RTC_DCHECK_GT(n, 0);
     49  int i = 0;
     50  for (const auto& packet : src) {
     51    if (i % n == 0) {
     52      dst->emplace_back(new ForwardErrorCorrection::Packet(*packet));
     53    }
     54    ++i;
     55  }
     56 }
     57 
     58 }  // namespace
     59 
     60 using ::testing::Types;
     61 
     62 template <typename ForwardErrorCorrectionType>
     63 class RtpFecTest : public ::testing::Test {
     64 protected:
     65  RtpFecTest()
     66      : random_(0xabcdef123456),
     67        media_packet_generator_(
     68            kRtpHeaderSize,  // Minimum packet size.
     69            IP_PACKET_SIZE - kRtpHeaderSize - kTransportOverhead -
     70                fec_.MaxPacketOverhead(),  // Maximum packet size.
     71            kMediaSsrc,
     72            &random_) {}
     73 
     74  // Construct `received_packets_`: a subset of the media and FEC packets.
     75  //
     76  // Media packet "i" is lost if media_loss_mask_[i] = 1, received if
     77  // media_loss_mask_[i] = 0.
     78  // FEC packet "i" is lost if fec_loss_mask_[i] = 1, received if
     79  // fec_loss_mask_[i] = 0.
     80  void NetworkReceivedPackets(int* media_loss_mask, int* fec_loss_mask);
     81 
     82  // Add packet from `packet_list` to list of received packets, using the
     83  // `loss_mask`.
     84  // The `packet_list` may be a media packet list (is_fec = false), or a
     85  // FEC packet list (is_fec = true).
     86  template <typename T>
     87  void ReceivedPackets(const T& packet_list, int* loss_mask, bool is_fec);
     88 
     89  // Check for complete recovery after FEC decoding.
     90  bool IsRecoveryComplete();
     91 
     92  ForwardErrorCorrectionType fec_;
     93 
     94  Random random_;
     95  test::fec::MediaPacketGenerator media_packet_generator_;
     96 
     97  ForwardErrorCorrection::PacketList media_packets_;
     98  std::list<ForwardErrorCorrection::Packet*> generated_fec_packets_;
     99  std::vector<std::unique_ptr<ForwardErrorCorrection::ReceivedPacket>>
    100      received_packets_;
    101  ForwardErrorCorrection::RecoveredPacketList recovered_packets_;
    102 
    103  int media_loss_mask_[kUlpfecMaxMediaPackets];
    104  int fec_loss_mask_[kUlpfecMaxMediaPackets];
    105 };
    106 
    107 template <typename ForwardErrorCorrectionType>
    108 void RtpFecTest<ForwardErrorCorrectionType>::NetworkReceivedPackets(
    109    int* media_loss_mask,
    110    int* fec_loss_mask) {
    111  constexpr bool kFecPacket = true;
    112  this->received_packets_.clear();
    113  ReceivedPackets(media_packets_, media_loss_mask, !kFecPacket);
    114  ReceivedPackets(generated_fec_packets_, fec_loss_mask, kFecPacket);
    115 }
    116 
    117 template <typename ForwardErrorCorrectionType>
    118 template <typename PacketListType>
    119 void RtpFecTest<ForwardErrorCorrectionType>::ReceivedPackets(
    120    const PacketListType& packet_list,
    121    int* loss_mask,
    122    bool is_fec) {
    123  uint16_t fec_seq_num = ForwardErrorCorrectionType::GetFirstFecSeqNum(
    124      media_packet_generator_.GetNextSeqNum());
    125  int packet_idx = 0;
    126 
    127  for (const auto& packet : packet_list) {
    128    if (loss_mask[packet_idx] == 0) {
    129      std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet(
    130          new ForwardErrorCorrection::ReceivedPacket());
    131      received_packet->pkt = new ForwardErrorCorrection::Packet();
    132      received_packet->pkt->data = packet->data;
    133      received_packet->is_fec = is_fec;
    134      if (!is_fec) {
    135        received_packet->ssrc = kMediaSsrc;
    136        // For media packets, the sequence number is obtained from the
    137        // RTP header as written by MediaPacketGenerator::ConstructMediaPackets.
    138        received_packet->seq_num =
    139            ByteReader<uint16_t>::ReadBigEndian(packet->data.data() + 2);
    140      } else {
    141        received_packet->ssrc = ForwardErrorCorrectionType::kFecSsrc;
    142        // For FEC packets, we simulate the sequence numbers differently
    143        // depending on if ULPFEC or FlexFEC is used. See the definition of
    144        // ForwardErrorCorrectionType::GetFirstFecSeqNum.
    145        received_packet->seq_num = fec_seq_num;
    146      }
    147      received_packets_.push_back(std::move(received_packet));
    148    }
    149    packet_idx++;
    150    // Sequence number of FEC packets are defined as increment by 1 from
    151    // last media packet in frame.
    152    if (is_fec)
    153      fec_seq_num++;
    154  }
    155 }
    156 
    157 template <typename ForwardErrorCorrectionType>
    158 bool RtpFecTest<ForwardErrorCorrectionType>::IsRecoveryComplete() {
    159  // We must have equally many recovered packets as original packets and all
    160  // recovered packets must be identical to the corresponding original packets.
    161  return absl::c_equal(
    162      media_packets_, recovered_packets_,
    163      [](const std::unique_ptr<ForwardErrorCorrection::Packet>& media_packet,
    164         const std::unique_ptr<ForwardErrorCorrection::RecoveredPacket>&
    165             recovered_packet) {
    166        if (media_packet->data.size() != recovered_packet->pkt->data.size()) {
    167          return false;
    168        }
    169        if (memcmp(media_packet->data.cdata(),
    170                   recovered_packet->pkt->data.cdata(),
    171                   media_packet->data.size()) != 0) {
    172          return false;
    173        }
    174        return true;
    175      });
    176 }
    177 
    178 // Define gTest typed test to loop over both ULPFEC and FlexFEC.
    179 // Since the tests now are parameterized, we need to access
    180 // member variables using `this`, thereby enforcing runtime
    181 // resolution.
    182 
    183 class FlexfecForwardErrorCorrection : public ForwardErrorCorrection {
    184 public:
    185  static constexpr uint32_t kFecSsrc = kFlexfecSsrc;
    186 
    187  FlexfecForwardErrorCorrection()
    188      : ForwardErrorCorrection(
    189            std::unique_ptr<FecHeaderReader>(new Flexfec03HeaderReader()),
    190            std::unique_ptr<FecHeaderWriter>(new Flexfec03HeaderWriter()),
    191            kFecSsrc,
    192            kMediaSsrc) {}
    193 
    194  // For FlexFEC we let the FEC packet sequence numbers be independent of
    195  // the media packet sequence numbers.
    196  static uint16_t GetFirstFecSeqNum(uint16_t /* next_media_seq_num */) {
    197    Random random(0xbe110);
    198    return random.Rand<uint16_t>();
    199  }
    200 };
    201 
    202 class UlpfecForwardErrorCorrection : public ForwardErrorCorrection {
    203 public:
    204  static constexpr uint32_t kFecSsrc = kMediaSsrc;
    205 
    206  UlpfecForwardErrorCorrection()
    207      : ForwardErrorCorrection(
    208            std::unique_ptr<FecHeaderReader>(new UlpfecHeaderReader()),
    209            std::unique_ptr<FecHeaderWriter>(new UlpfecHeaderWriter()),
    210            kFecSsrc,
    211            kMediaSsrc) {}
    212 
    213  // For ULPFEC we assume that the FEC packets are subsequent to the media
    214  // packets in terms of sequence number.
    215  static uint16_t GetFirstFecSeqNum(uint16_t next_media_seq_num) {
    216    return next_media_seq_num;
    217  }
    218 };
    219 
    220 using FecTypes =
    221    Types<FlexfecForwardErrorCorrection, UlpfecForwardErrorCorrection>;
    222 TYPED_TEST_SUITE(RtpFecTest, FecTypes);
    223 
    224 TYPED_TEST(RtpFecTest, WillProtectMediaPacketsWithLargeSequenceNumberGap) {
    225  constexpr int kNumImportantPackets = 0;
    226  constexpr bool kUseUnequalProtection = false;
    227  constexpr int kNumMediaPackets = 2;
    228  constexpr uint8_t kProtectionFactor = 127;
    229 
    230  this->media_packets_ =
    231      this->media_packet_generator_.ConstructMediaPackets(kNumMediaPackets);
    232 
    233  // Create |kMaxMediaPackets - 1| sequence number difference.
    234  ByteWriter<uint16_t>::WriteBigEndian(
    235      this->media_packets_.front()->data.MutableData() + 2, 1);
    236  ByteWriter<uint16_t>::WriteBigEndian(
    237      this->media_packets_.back()->data.MutableData() + 2, kMaxMediaPackets);
    238 
    239  EXPECT_EQ(
    240      0, this->fec_.EncodeFec(this->media_packets_, kProtectionFactor,
    241                              kNumImportantPackets, kUseUnequalProtection,
    242                              kFecMaskBursty, &this->generated_fec_packets_));
    243  EXPECT_EQ(1u, this->generated_fec_packets_.size());
    244 }
    245 
    246 TYPED_TEST(RtpFecTest,
    247           WillNotProtectMediaPacketsWithTooLargeSequenceNumberGap) {
    248  constexpr int kNumImportantPackets = 0;
    249  constexpr bool kUseUnequalProtection = false;
    250  constexpr int kNumMediaPackets = 2;
    251  constexpr uint8_t kProtectionFactor = 127;
    252 
    253  this->media_packets_ =
    254      this->media_packet_generator_.ConstructMediaPackets(kNumMediaPackets);
    255 
    256  // Create `kMaxMediaPackets` sequence number difference.
    257  ByteWriter<uint16_t>::WriteBigEndian(
    258      this->media_packets_.front()->data.MutableData() + 2, 1);
    259  ByteWriter<uint16_t>::WriteBigEndian(
    260      this->media_packets_.back()->data.MutableData() + 2,
    261      kMaxMediaPackets + 1);
    262 
    263  EXPECT_EQ(
    264      -1, this->fec_.EncodeFec(this->media_packets_, kProtectionFactor,
    265                               kNumImportantPackets, kUseUnequalProtection,
    266                               kFecMaskBursty, &this->generated_fec_packets_));
    267  EXPECT_TRUE(this->generated_fec_packets_.empty());
    268 }
    269 
    270 TYPED_TEST(RtpFecTest, FecRecoveryNoLoss) {
    271  constexpr int kNumImportantPackets = 0;
    272  constexpr bool kUseUnequalProtection = false;
    273  constexpr int kNumMediaPackets = 4;
    274  constexpr uint8_t kProtectionFactor = 60;
    275 
    276  this->media_packets_ =
    277      this->media_packet_generator_.ConstructMediaPackets(kNumMediaPackets);
    278 
    279  EXPECT_EQ(
    280      0, this->fec_.EncodeFec(this->media_packets_, kProtectionFactor,
    281                              kNumImportantPackets, kUseUnequalProtection,
    282                              kFecMaskBursty, &this->generated_fec_packets_));
    283 
    284  // Expect 1 FEC packet.
    285  EXPECT_EQ(1u, this->generated_fec_packets_.size());
    286 
    287  // No packets lost.
    288  memset(this->media_loss_mask_, 0, sizeof(this->media_loss_mask_));
    289  memset(this->fec_loss_mask_, 0, sizeof(this->fec_loss_mask_));
    290  this->NetworkReceivedPackets(this->media_loss_mask_, this->fec_loss_mask_);
    291 
    292  for (const auto& received_packet : this->received_packets_) {
    293    this->fec_.DecodeFec(*received_packet, &this->recovered_packets_);
    294  }
    295 
    296  // No packets lost, expect complete recovery.
    297  EXPECT_TRUE(this->IsRecoveryComplete());
    298 }
    299 
    300 TYPED_TEST(RtpFecTest, FecRecoveryWithLoss) {
    301  constexpr int kNumImportantPackets = 0;
    302  constexpr bool kUseUnequalProtection = false;
    303  constexpr int kNumMediaPackets = 4;
    304  constexpr uint8_t kProtectionFactor = 60;
    305 
    306  this->media_packets_ =
    307      this->media_packet_generator_.ConstructMediaPackets(kNumMediaPackets);
    308 
    309  EXPECT_EQ(
    310      0, this->fec_.EncodeFec(this->media_packets_, kProtectionFactor,
    311                              kNumImportantPackets, kUseUnequalProtection,
    312                              kFecMaskBursty, &this->generated_fec_packets_));
    313 
    314  // Expect 1 FEC packet.
    315  EXPECT_EQ(1u, this->generated_fec_packets_.size());
    316 
    317  // 1 media packet lost
    318  memset(this->media_loss_mask_, 0, sizeof(this->media_loss_mask_));
    319  memset(this->fec_loss_mask_, 0, sizeof(this->fec_loss_mask_));
    320  this->media_loss_mask_[3] = 1;
    321  this->NetworkReceivedPackets(this->media_loss_mask_, this->fec_loss_mask_);
    322 
    323  for (const auto& received_packet : this->received_packets_) {
    324    this->fec_.DecodeFec(*received_packet, &this->recovered_packets_);
    325  }
    326 
    327  // One packet lost, one FEC packet, expect complete recovery.
    328  EXPECT_TRUE(this->IsRecoveryComplete());
    329  this->recovered_packets_.clear();
    330 
    331  // 2 media packets lost.
    332  memset(this->media_loss_mask_, 0, sizeof(this->media_loss_mask_));
    333  memset(this->fec_loss_mask_, 0, sizeof(this->fec_loss_mask_));
    334  this->media_loss_mask_[1] = 1;
    335  this->media_loss_mask_[3] = 1;
    336  this->NetworkReceivedPackets(this->media_loss_mask_, this->fec_loss_mask_);
    337 
    338  for (const auto& received_packet : this->received_packets_) {
    339    this->fec_.DecodeFec(*received_packet, &this->recovered_packets_);
    340  }
    341 
    342  // 2 packets lost, one FEC packet, cannot get complete recovery.
    343  EXPECT_FALSE(this->IsRecoveryComplete());
    344 }
    345 
    346 // Verify that we don't use an old FEC packet for FEC decoding.
    347 TYPED_TEST(RtpFecTest, NoFecRecoveryWithOldFecPacket) {
    348  constexpr int kNumImportantPackets = 0;
    349  constexpr bool kUseUnequalProtection = false;
    350  constexpr uint8_t kProtectionFactor = 20;
    351 
    352  // Two frames: first frame (old) with two media packets and 1 FEC packet.
    353  // Third frame (new) with 3 media packets, and no FEC packets.
    354  //
    355  //  #0(media) #1(media) #2(FEC)              ----Frame 1-----
    356  //  #32767(media) 32768(media) 32769(media)  ----Frame 2-----
    357  //  #65535(media) #0(media) #1(media).       ----Frame 3-----
    358  // If we lose either packet 0 or 1 of third frame, FEC decoding should not
    359  // try to decode using "old" FEC packet #2.
    360 
    361  // Construct media packets for first frame, starting at sequence number 0.
    362  this->media_packets_ =
    363      this->media_packet_generator_.ConstructMediaPackets(2, 0);
    364 
    365  EXPECT_EQ(
    366      0, this->fec_.EncodeFec(this->media_packets_, kProtectionFactor,
    367                              kNumImportantPackets, kUseUnequalProtection,
    368                              kFecMaskBursty, &this->generated_fec_packets_));
    369  // Expect 1 FEC packet.
    370  EXPECT_EQ(1u, this->generated_fec_packets_.size());
    371  // Add FEC packet (seq#2) of this first frame to received list (i.e., assume
    372  // the two media packet were lost).
    373  memset(this->fec_loss_mask_, 0, sizeof(this->fec_loss_mask_));
    374  this->ReceivedPackets(this->generated_fec_packets_, this->fec_loss_mask_,
    375                        true);
    376 
    377  // Construct media packets for second frame, with sequence number wrap.
    378  this->media_packets_ =
    379      this->media_packet_generator_.ConstructMediaPackets(3, 32767);
    380 
    381  // Expect 3 media packets for this frame.
    382  EXPECT_EQ(3u, this->media_packets_.size());
    383 
    384  // No packets lost
    385  memset(this->media_loss_mask_, 0, sizeof(this->media_loss_mask_));
    386  this->ReceivedPackets(this->media_packets_, this->media_loss_mask_, false);
    387 
    388  // Construct media packets for third frame, with sequence number wrap.
    389  this->media_packets_ =
    390      this->media_packet_generator_.ConstructMediaPackets(3, 65535);
    391 
    392  // Expect 3 media packets for this frame.
    393  EXPECT_EQ(3u, this->media_packets_.size());
    394 
    395  // Second media packet lost (seq#0).
    396  memset(this->media_loss_mask_, 0, sizeof(this->media_loss_mask_));
    397  this->media_loss_mask_[1] = 1;
    398  // Add packets #65535, and #1 to received list.
    399  this->ReceivedPackets(this->media_packets_, this->media_loss_mask_, false);
    400 
    401  for (const auto& received_packet : this->received_packets_) {
    402    this->fec_.DecodeFec(*received_packet, &this->recovered_packets_);
    403  }
    404 
    405  // Expect that no decoding is done to get missing packet (seq#0) of third
    406  // frame, using old FEC packet (seq#2) from first (old) frame. So number of
    407  // recovered packets is 5 (0 from first frame, three from second frame, and 2
    408  // for the third frame, with no packets recovered via FEC).
    409  EXPECT_EQ(5u, this->recovered_packets_.size());
    410  EXPECT_TRUE(this->recovered_packets_.size() != this->media_packets_.size());
    411 }
    412 
    413 // Verify we can still recover frame if sequence number wrap occurs within
    414 // the frame and FEC packet following wrap is received after media packets.
    415 TYPED_TEST(RtpFecTest, FecRecoveryWithSeqNumGapOneFrameRecovery) {
    416  constexpr int kNumImportantPackets = 0;
    417  constexpr bool kUseUnequalProtection = false;
    418  constexpr uint8_t kProtectionFactor = 20;
    419 
    420  // One frame, with sequence number wrap in media packets.
    421  //         -----Frame 1----
    422  //  #65534(media) #65535(media) #0(media) #1(FEC).
    423  this->media_packets_ =
    424      this->media_packet_generator_.ConstructMediaPackets(3, 65534);
    425 
    426  EXPECT_EQ(
    427      0, this->fec_.EncodeFec(this->media_packets_, kProtectionFactor,
    428                              kNumImportantPackets, kUseUnequalProtection,
    429                              kFecMaskBursty, &this->generated_fec_packets_));
    430 
    431  // Expect 1 FEC packet.
    432  EXPECT_EQ(1u, this->generated_fec_packets_.size());
    433 
    434  // Lose one media packet (seq# 65535).
    435  memset(this->media_loss_mask_, 0, sizeof(this->media_loss_mask_));
    436  memset(this->fec_loss_mask_, 0, sizeof(this->fec_loss_mask_));
    437  this->media_loss_mask_[1] = 1;
    438  this->ReceivedPackets(this->media_packets_, this->media_loss_mask_, false);
    439  // Add FEC packet to received list following the media packets.
    440  this->ReceivedPackets(this->generated_fec_packets_, this->fec_loss_mask_,
    441                        true);
    442 
    443  for (const auto& received_packet : this->received_packets_) {
    444    this->fec_.DecodeFec(*received_packet, &this->recovered_packets_);
    445  }
    446 
    447  // Expect 3 media packets in recovered list, and complete recovery.
    448  // Wrap-around won't remove FEC packet, as it follows the wrap.
    449  EXPECT_EQ(3u, this->recovered_packets_.size());
    450  EXPECT_TRUE(this->IsRecoveryComplete());
    451 }
    452 
    453 // Sequence number wrap occurs within the ULPFEC packets for the frame.
    454 // Same problem will occur if wrap is within media packets but ULPFEC packet is
    455 // received before the media packets. This may be improved if timing information
    456 // is used to detect old ULPFEC packets.
    457 
    458 // TODO(nisse): There's some logic to discard ULPFEC packets at wrap-around,
    459 // however, that is not actually exercised by this test: When the first FEC
    460 // packet is processed, it results in full recovery of one media packet and the
    461 // FEC packet is forgotten. And then the wraparound isn't noticed when the next
    462 // FEC packet is received. We should fix wraparound handling, which currently
    463 // appears broken, and then figure out how to test it properly.
    464 using RtpFecTestUlpfecOnly = RtpFecTest<UlpfecForwardErrorCorrection>;
    465 TEST_F(RtpFecTestUlpfecOnly, FecRecoveryWithSeqNumGapOneFrameRecovery) {
    466  constexpr int kNumImportantPackets = 0;
    467  constexpr bool kUseUnequalProtection = false;
    468  constexpr uint8_t kProtectionFactor = 200;
    469 
    470  // 1 frame: 3 media packets and 2 FEC packets.
    471  // Sequence number wrap in FEC packets.
    472  //           -----Frame 1----
    473  // #65532(media) #65533(media) #65534(media) #65535(FEC) #0(FEC).
    474  this->media_packets_ =
    475      this->media_packet_generator_.ConstructMediaPackets(3, 65532);
    476 
    477  EXPECT_EQ(
    478      0, this->fec_.EncodeFec(this->media_packets_, kProtectionFactor,
    479                              kNumImportantPackets, kUseUnequalProtection,
    480                              kFecMaskBursty, &this->generated_fec_packets_));
    481 
    482  // Expect 2 FEC packets.
    483  EXPECT_EQ(2u, this->generated_fec_packets_.size());
    484 
    485  // Lose the last two media packets (seq# 65533, 65534).
    486  memset(this->media_loss_mask_, 0, sizeof(this->media_loss_mask_));
    487  memset(this->fec_loss_mask_, 0, sizeof(this->fec_loss_mask_));
    488  this->media_loss_mask_[1] = 1;
    489  this->media_loss_mask_[2] = 1;
    490  this->ReceivedPackets(this->media_packets_, this->media_loss_mask_, false);
    491  this->ReceivedPackets(this->generated_fec_packets_, this->fec_loss_mask_,
    492                        true);
    493 
    494  for (const auto& received_packet : this->received_packets_) {
    495    this->fec_.DecodeFec(*received_packet, &this->recovered_packets_);
    496  }
    497 
    498  // The two FEC packets are received and should allow for complete recovery,
    499  // but because of the wrap the first FEC packet will be discarded, and only
    500  // one media packet is recoverable. So expect 2 media packets on recovered
    501  // list and no complete recovery.
    502  EXPECT_EQ(3u, this->recovered_packets_.size());
    503  EXPECT_EQ(this->recovered_packets_.size(), this->media_packets_.size());
    504  EXPECT_TRUE(this->IsRecoveryComplete());
    505 }
    506 
    507 // TODO(brandtr): This test mimics the one above, ensuring that the recovery
    508 // strategy of FlexFEC matches the recovery strategy of ULPFEC. Since FlexFEC
    509 // does not share the sequence number space with the media, however, having a
    510 // matching recovery strategy may be suboptimal. Study this further.
    511 // TODO(nisse): In this test, recovery based on the first FEC packet fails with
    512 // the log message "The recovered packet had a length larger than a typical IP
    513 // packet, and is thus dropped." This is probably not intended, and needs
    514 // investigation.
    515 using RtpFecTestFlexfecOnly = RtpFecTest<FlexfecForwardErrorCorrection>;
    516 TEST_F(RtpFecTestFlexfecOnly, FecRecoveryWithSeqNumGapOneFrameNoRecovery) {
    517  constexpr int kNumImportantPackets = 0;
    518  constexpr bool kUseUnequalProtection = false;
    519  constexpr uint8_t kProtectionFactor = 200;
    520 
    521  // 1 frame: 3 media packets and 2 FEC packets.
    522  // Sequence number wrap in FEC packets.
    523  //           -----Frame 1----
    524  // #65532(media) #65533(media) #65534(media) #65535(FEC) #0(FEC).
    525  this->media_packets_ =
    526      this->media_packet_generator_.ConstructMediaPackets(3, 65532);
    527 
    528  EXPECT_EQ(
    529      0, this->fec_.EncodeFec(this->media_packets_, kProtectionFactor,
    530                              kNumImportantPackets, kUseUnequalProtection,
    531                              kFecMaskBursty, &this->generated_fec_packets_));
    532 
    533  // Expect 2 FEC packets.
    534  EXPECT_EQ(2u, this->generated_fec_packets_.size());
    535 
    536  // Overwrite the sequence numbers generated by ConstructMediaPackets,
    537  // to make sure that we do have a wrap.
    538  auto it = this->generated_fec_packets_.begin();
    539  ByteWriter<uint16_t>::WriteBigEndian(&(*it)->data.MutableData()[2], 65535);
    540  ++it;
    541  ByteWriter<uint16_t>::WriteBigEndian(&(*it)->data.MutableData()[2], 0);
    542 
    543  // Lose the last two media packets (seq# 65533, 65534).
    544  memset(this->media_loss_mask_, 0, sizeof(this->media_loss_mask_));
    545  memset(this->fec_loss_mask_, 0, sizeof(this->fec_loss_mask_));
    546  this->media_loss_mask_[1] = 1;
    547  this->media_loss_mask_[2] = 1;
    548  this->ReceivedPackets(this->media_packets_, this->media_loss_mask_, false);
    549  this->ReceivedPackets(this->generated_fec_packets_, this->fec_loss_mask_,
    550                        true);
    551 
    552  for (const auto& received_packet : this->received_packets_) {
    553    this->fec_.DecodeFec(*received_packet, &this->recovered_packets_);
    554  }
    555 
    556  // The two FEC packets are received and should allow for complete recovery,
    557  // but because of the wrap the first FEC packet will be discarded, and only
    558  // one media packet is recoverable. So expect 2 media packets on recovered
    559  // list and no complete recovery.
    560  EXPECT_EQ(2u, this->recovered_packets_.size());
    561  EXPECT_TRUE(this->recovered_packets_.size() != this->media_packets_.size());
    562  EXPECT_FALSE(this->IsRecoveryComplete());
    563 }
    564 
    565 // Verify we can still recover frame if media packets are reordered.
    566 TYPED_TEST(RtpFecTest, FecRecoveryWithMediaOutOfOrder) {
    567  constexpr int kNumImportantPackets = 0;
    568  constexpr bool kUseUnequalProtection = false;
    569  constexpr uint8_t kProtectionFactor = 20;
    570 
    571  // One frame: 3 media packets, 1 FEC packet.
    572  //         -----Frame 1----
    573  //  #0(media) #1(media) #2(media) #3(FEC).
    574  this->media_packets_ =
    575      this->media_packet_generator_.ConstructMediaPackets(3, 0);
    576 
    577  EXPECT_EQ(
    578      0, this->fec_.EncodeFec(this->media_packets_, kProtectionFactor,
    579                              kNumImportantPackets, kUseUnequalProtection,
    580                              kFecMaskBursty, &this->generated_fec_packets_));
    581 
    582  // Expect 1 FEC packet.
    583  EXPECT_EQ(1u, this->generated_fec_packets_.size());
    584 
    585  // Lose one media packet (seq# 1).
    586  memset(this->media_loss_mask_, 0, sizeof(this->media_loss_mask_));
    587  memset(this->fec_loss_mask_, 0, sizeof(this->fec_loss_mask_));
    588  this->media_loss_mask_[1] = 1;
    589  this->NetworkReceivedPackets(this->media_loss_mask_, this->fec_loss_mask_);
    590 
    591  // Reorder received media packets.
    592  auto it0 = this->received_packets_.begin();
    593  auto it1 = this->received_packets_.begin();
    594  it1++;
    595  std::swap(*it0, *it1);
    596 
    597  for (const auto& received_packet : this->received_packets_) {
    598    this->fec_.DecodeFec(*received_packet, &this->recovered_packets_);
    599  }
    600 
    601  // Expect 3 media packets in recovered list, and complete recovery.
    602  EXPECT_EQ(3u, this->recovered_packets_.size());
    603  EXPECT_TRUE(this->IsRecoveryComplete());
    604 }
    605 
    606 // Verify we can still recover frame if FEC is received before media packets.
    607 TYPED_TEST(RtpFecTest, FecRecoveryWithFecOutOfOrder) {
    608  constexpr int kNumImportantPackets = 0;
    609  constexpr bool kUseUnequalProtection = false;
    610  constexpr uint8_t kProtectionFactor = 20;
    611 
    612  // One frame: 3 media packets, 1 FEC packet.
    613  //         -----Frame 1----
    614  //  #0(media) #1(media) #2(media) #3(FEC).
    615  this->media_packets_ =
    616      this->media_packet_generator_.ConstructMediaPackets(3, 0);
    617 
    618  EXPECT_EQ(
    619      0, this->fec_.EncodeFec(this->media_packets_, kProtectionFactor,
    620                              kNumImportantPackets, kUseUnequalProtection,
    621                              kFecMaskBursty, &this->generated_fec_packets_));
    622 
    623  // Expect 1 FEC packet.
    624  EXPECT_EQ(1u, this->generated_fec_packets_.size());
    625 
    626  // Lose one media packet (seq# 1).
    627  memset(this->media_loss_mask_, 0, sizeof(this->media_loss_mask_));
    628  memset(this->fec_loss_mask_, 0, sizeof(this->fec_loss_mask_));
    629  this->media_loss_mask_[1] = 1;
    630  // Add FEC packet to received list before the media packets.
    631  this->ReceivedPackets(this->generated_fec_packets_, this->fec_loss_mask_,
    632                        true);
    633  // Add media packets to received list.
    634  this->ReceivedPackets(this->media_packets_, this->media_loss_mask_, false);
    635 
    636  for (const auto& received_packet : this->received_packets_) {
    637    this->fec_.DecodeFec(*received_packet, &this->recovered_packets_);
    638  }
    639 
    640  // Expect 3 media packets in recovered list, and complete recovery.
    641  EXPECT_EQ(3u, this->recovered_packets_.size());
    642  EXPECT_TRUE(this->IsRecoveryComplete());
    643 }
    644 
    645 // Test 50% protection with random mask type: Two cases are considered:
    646 // a 50% non-consecutive loss which can be fully recovered, and a 50%
    647 // consecutive loss which cannot be fully recovered.
    648 TYPED_TEST(RtpFecTest, FecRecoveryWithLoss50percRandomMask) {
    649  constexpr int kNumImportantPackets = 0;
    650  constexpr bool kUseUnequalProtection = false;
    651  constexpr int kNumMediaPackets = 4;
    652  constexpr uint8_t kProtectionFactor = 255;
    653 
    654  // Packet Mask for (4,4,0) code, from random mask table.
    655  // (kNumMediaPackets = 4; num_fec_packets = 4, kNumImportantPackets = 0)
    656 
    657  //         media#0   media#1  media#2    media#3
    658  // fec#0:    1          1        0          0
    659  // fec#1:    1          0        1          0
    660  // fec#2:    0          0        1          1
    661  // fec#3:    0          1        0          1
    662  //
    663 
    664  this->media_packets_ =
    665      this->media_packet_generator_.ConstructMediaPackets(kNumMediaPackets);
    666 
    667  EXPECT_EQ(
    668      0, this->fec_.EncodeFec(this->media_packets_, kProtectionFactor,
    669                              kNumImportantPackets, kUseUnequalProtection,
    670                              kFecMaskRandom, &this->generated_fec_packets_));
    671 
    672  // Expect 4 FEC packets.
    673  EXPECT_EQ(4u, this->generated_fec_packets_.size());
    674 
    675  // 4 packets lost: 3 media packets (0, 2, 3), and one FEC packet (0) lost.
    676  memset(this->media_loss_mask_, 0, sizeof(this->media_loss_mask_));
    677  memset(this->fec_loss_mask_, 0, sizeof(this->fec_loss_mask_));
    678  this->fec_loss_mask_[0] = 1;
    679  this->media_loss_mask_[0] = 1;
    680  this->media_loss_mask_[2] = 1;
    681  this->media_loss_mask_[3] = 1;
    682  this->NetworkReceivedPackets(this->media_loss_mask_, this->fec_loss_mask_);
    683 
    684  for (const auto& received_packet : this->received_packets_) {
    685    this->fec_.DecodeFec(*received_packet, &this->recovered_packets_);
    686  }
    687 
    688  // With media packet#1 and FEC packets #1, #2, #3, expect complete recovery.
    689  EXPECT_TRUE(this->IsRecoveryComplete());
    690  this->recovered_packets_.clear();
    691 
    692  // 4 consecutive packets lost: media packets 0, 1, 2, 3.
    693  memset(this->media_loss_mask_, 0, sizeof(this->media_loss_mask_));
    694  memset(this->fec_loss_mask_, 0, sizeof(this->fec_loss_mask_));
    695  this->media_loss_mask_[0] = 1;
    696  this->media_loss_mask_[1] = 1;
    697  this->media_loss_mask_[2] = 1;
    698  this->media_loss_mask_[3] = 1;
    699  this->NetworkReceivedPackets(this->media_loss_mask_, this->fec_loss_mask_);
    700 
    701  for (const auto& received_packet : this->received_packets_) {
    702    this->fec_.DecodeFec(*received_packet, &this->recovered_packets_);
    703  }
    704 
    705  // Cannot get complete recovery for this loss configuration with random mask.
    706  EXPECT_FALSE(this->IsRecoveryComplete());
    707 }
    708 
    709 // Test 50% protection with bursty type: Three cases are considered:
    710 // two 50% consecutive losses which can be fully recovered, and one
    711 // non-consecutive which cannot be fully recovered.
    712 TYPED_TEST(RtpFecTest, FecRecoveryWithLoss50percBurstyMask) {
    713  constexpr int kNumImportantPackets = 0;
    714  constexpr bool kUseUnequalProtection = false;
    715  constexpr int kNumMediaPackets = 4;
    716  constexpr uint8_t kProtectionFactor = 255;
    717 
    718  // Packet Mask for (4,4,0) code, from bursty mask table.
    719  // (kNumMediaPackets = 4; num_fec_packets = 4, kNumImportantPackets = 0)
    720 
    721  //         media#0   media#1  media#2    media#3
    722  // fec#0:    1          0        0          0
    723  // fec#1:    1          1        0          0
    724  // fec#2:    0          1        1          0
    725  // fec#3:    0          0        1          1
    726  //
    727 
    728  this->media_packets_ =
    729      this->media_packet_generator_.ConstructMediaPackets(kNumMediaPackets);
    730 
    731  EXPECT_EQ(
    732      0, this->fec_.EncodeFec(this->media_packets_, kProtectionFactor,
    733                              kNumImportantPackets, kUseUnequalProtection,
    734                              kFecMaskBursty, &this->generated_fec_packets_));
    735 
    736  // Expect 4 FEC packets.
    737  EXPECT_EQ(4u, this->generated_fec_packets_.size());
    738 
    739  // 4 consecutive packets lost: media packets 0,1,2,3.
    740  memset(this->media_loss_mask_, 0, sizeof(this->media_loss_mask_));
    741  memset(this->fec_loss_mask_, 0, sizeof(this->fec_loss_mask_));
    742  this->media_loss_mask_[0] = 1;
    743  this->media_loss_mask_[1] = 1;
    744  this->media_loss_mask_[2] = 1;
    745  this->media_loss_mask_[3] = 1;
    746  this->NetworkReceivedPackets(this->media_loss_mask_, this->fec_loss_mask_);
    747 
    748  for (const auto& received_packet : this->received_packets_) {
    749    this->fec_.DecodeFec(*received_packet, &this->recovered_packets_);
    750  }
    751 
    752  // Expect complete recovery for consecutive packet loss <= 50%.
    753  EXPECT_TRUE(this->IsRecoveryComplete());
    754  this->recovered_packets_.clear();
    755 
    756  // 4 consecutive packets lost: media packets 1,2, 3, and FEC packet 0.
    757  memset(this->media_loss_mask_, 0, sizeof(this->media_loss_mask_));
    758  memset(this->fec_loss_mask_, 0, sizeof(this->fec_loss_mask_));
    759  this->fec_loss_mask_[0] = 1;
    760  this->media_loss_mask_[1] = 1;
    761  this->media_loss_mask_[2] = 1;
    762  this->media_loss_mask_[3] = 1;
    763  this->NetworkReceivedPackets(this->media_loss_mask_, this->fec_loss_mask_);
    764 
    765  for (const auto& received_packet : this->received_packets_) {
    766    this->fec_.DecodeFec(*received_packet, &this->recovered_packets_);
    767  }
    768 
    769  // Expect complete recovery for consecutive packet loss <= 50%.
    770  EXPECT_TRUE(this->IsRecoveryComplete());
    771  this->recovered_packets_.clear();
    772 
    773  // 4 packets lost (non-consecutive loss): media packets 0, 3, and FEC# 0, 3.
    774  memset(this->media_loss_mask_, 0, sizeof(this->media_loss_mask_));
    775  memset(this->fec_loss_mask_, 0, sizeof(this->fec_loss_mask_));
    776  this->fec_loss_mask_[0] = 1;
    777  this->fec_loss_mask_[3] = 1;
    778  this->media_loss_mask_[0] = 1;
    779  this->media_loss_mask_[3] = 1;
    780  this->NetworkReceivedPackets(this->media_loss_mask_, this->fec_loss_mask_);
    781 
    782  for (const auto& received_packet : this->received_packets_) {
    783    this->fec_.DecodeFec(*received_packet, &this->recovered_packets_);
    784  }
    785 
    786  // Cannot get complete recovery for this loss configuration.
    787  EXPECT_FALSE(this->IsRecoveryComplete());
    788 }
    789 
    790 TYPED_TEST(RtpFecTest, FecRecoveryNoLossUep) {
    791  constexpr int kNumImportantPackets = 2;
    792  constexpr bool kUseUnequalProtection = true;
    793  constexpr int kNumMediaPackets = 4;
    794  constexpr uint8_t kProtectionFactor = 60;
    795 
    796  this->media_packets_ =
    797      this->media_packet_generator_.ConstructMediaPackets(kNumMediaPackets);
    798 
    799  EXPECT_EQ(
    800      0, this->fec_.EncodeFec(this->media_packets_, kProtectionFactor,
    801                              kNumImportantPackets, kUseUnequalProtection,
    802                              kFecMaskBursty, &this->generated_fec_packets_));
    803 
    804  // Expect 1 FEC packet.
    805  EXPECT_EQ(1u, this->generated_fec_packets_.size());
    806 
    807  // No packets lost.
    808  memset(this->media_loss_mask_, 0, sizeof(this->media_loss_mask_));
    809  memset(this->fec_loss_mask_, 0, sizeof(this->fec_loss_mask_));
    810  this->NetworkReceivedPackets(this->media_loss_mask_, this->fec_loss_mask_);
    811 
    812  for (const auto& received_packet : this->received_packets_) {
    813    this->fec_.DecodeFec(*received_packet, &this->recovered_packets_);
    814  }
    815 
    816  // No packets lost, expect complete recovery.
    817  EXPECT_TRUE(this->IsRecoveryComplete());
    818 }
    819 
    820 TYPED_TEST(RtpFecTest, FecRecoveryWithLossUep) {
    821  constexpr int kNumImportantPackets = 2;
    822  constexpr bool kUseUnequalProtection = true;
    823  constexpr int kNumMediaPackets = 4;
    824  constexpr uint8_t kProtectionFactor = 60;
    825 
    826  this->media_packets_ =
    827      this->media_packet_generator_.ConstructMediaPackets(kNumMediaPackets);
    828 
    829  EXPECT_EQ(
    830      0, this->fec_.EncodeFec(this->media_packets_, kProtectionFactor,
    831                              kNumImportantPackets, kUseUnequalProtection,
    832                              kFecMaskBursty, &this->generated_fec_packets_));
    833 
    834  // Expect 1 FEC packet.
    835  EXPECT_EQ(1u, this->generated_fec_packets_.size());
    836 
    837  // 1 media packet lost.
    838  memset(this->media_loss_mask_, 0, sizeof(this->media_loss_mask_));
    839  memset(this->fec_loss_mask_, 0, sizeof(this->fec_loss_mask_));
    840  this->media_loss_mask_[3] = 1;
    841  this->NetworkReceivedPackets(this->media_loss_mask_, this->fec_loss_mask_);
    842 
    843  for (const auto& received_packet : this->received_packets_) {
    844    this->fec_.DecodeFec(*received_packet, &this->recovered_packets_);
    845  }
    846 
    847  // One packet lost, one FEC packet, expect complete recovery.
    848  EXPECT_TRUE(this->IsRecoveryComplete());
    849  this->recovered_packets_.clear();
    850 
    851  // 2 media packets lost.
    852  memset(this->media_loss_mask_, 0, sizeof(this->media_loss_mask_));
    853  memset(this->fec_loss_mask_, 0, sizeof(this->fec_loss_mask_));
    854  this->media_loss_mask_[1] = 1;
    855  this->media_loss_mask_[3] = 1;
    856  this->NetworkReceivedPackets(this->media_loss_mask_, this->fec_loss_mask_);
    857 
    858  for (const auto& received_packet : this->received_packets_) {
    859    this->fec_.DecodeFec(*received_packet, &this->recovered_packets_);
    860  }
    861 
    862  // 2 packets lost, one FEC packet, cannot get complete recovery.
    863  EXPECT_FALSE(this->IsRecoveryComplete());
    864 }
    865 
    866 // Test 50% protection with random mask type for UEP on.
    867 TYPED_TEST(RtpFecTest, FecRecoveryWithLoss50percUepRandomMask) {
    868  constexpr int kNumImportantPackets = 1;
    869  constexpr bool kUseUnequalProtection = true;
    870  constexpr int kNumMediaPackets = 4;
    871  constexpr uint8_t kProtectionFactor = 255;
    872 
    873  // Packet Mask for (4,4,1) code, from random mask table.
    874  // (kNumMediaPackets = 4; num_fec_packets = 4, kNumImportantPackets = 1)
    875 
    876  //         media#0   media#1  media#2    media#3
    877  // fec#0:    1          0        0          0
    878  // fec#1:    1          1        0          0
    879  // fec#2:    1          0        1          1
    880  // fec#3:    0          1        1          0
    881  //
    882 
    883  this->media_packets_ =
    884      this->media_packet_generator_.ConstructMediaPackets(kNumMediaPackets);
    885 
    886  EXPECT_EQ(
    887      0, this->fec_.EncodeFec(this->media_packets_, kProtectionFactor,
    888                              kNumImportantPackets, kUseUnequalProtection,
    889                              kFecMaskRandom, &this->generated_fec_packets_));
    890 
    891  // Expect 4 FEC packets.
    892  EXPECT_EQ(4u, this->generated_fec_packets_.size());
    893 
    894  // 4 packets lost: 3 media packets and FEC packet#1 lost.
    895  memset(this->media_loss_mask_, 0, sizeof(this->media_loss_mask_));
    896  memset(this->fec_loss_mask_, 0, sizeof(this->fec_loss_mask_));
    897  this->fec_loss_mask_[1] = 1;
    898  this->media_loss_mask_[0] = 1;
    899  this->media_loss_mask_[2] = 1;
    900  this->media_loss_mask_[3] = 1;
    901  this->NetworkReceivedPackets(this->media_loss_mask_, this->fec_loss_mask_);
    902 
    903  for (const auto& received_packet : this->received_packets_) {
    904    this->fec_.DecodeFec(*received_packet, &this->recovered_packets_);
    905  }
    906 
    907  // With media packet#3 and FEC packets #0, #1, #3, expect complete recovery.
    908  EXPECT_TRUE(this->IsRecoveryComplete());
    909  this->recovered_packets_.clear();
    910 
    911  // 5 packets lost: 4 media packets and one FEC packet#2 lost.
    912  memset(this->media_loss_mask_, 0, sizeof(this->media_loss_mask_));
    913  memset(this->fec_loss_mask_, 0, sizeof(this->fec_loss_mask_));
    914  this->fec_loss_mask_[2] = 1;
    915  this->media_loss_mask_[0] = 1;
    916  this->media_loss_mask_[1] = 1;
    917  this->media_loss_mask_[2] = 1;
    918  this->media_loss_mask_[3] = 1;
    919  this->NetworkReceivedPackets(this->media_loss_mask_, this->fec_loss_mask_);
    920 
    921  for (const auto& received_packet : this->received_packets_) {
    922    this->fec_.DecodeFec(*received_packet, &this->recovered_packets_);
    923  }
    924 
    925  // Cannot get complete recovery for this loss configuration.
    926  EXPECT_FALSE(this->IsRecoveryComplete());
    927 }
    928 
    929 TYPED_TEST(RtpFecTest, FecRecoveryNonConsecutivePackets) {
    930  constexpr int kNumImportantPackets = 0;
    931  constexpr bool kUseUnequalProtection = false;
    932  constexpr int kNumMediaPackets = 5;
    933  constexpr uint8_t kProtectionFactor = 60;
    934 
    935  this->media_packets_ =
    936      this->media_packet_generator_.ConstructMediaPackets(kNumMediaPackets);
    937 
    938  // Create a new temporary packet list for generating FEC packets.
    939  // This list should have every other packet removed.
    940  ForwardErrorCorrection::PacketList protected_media_packets;
    941  DeepCopyEveryNthPacket(this->media_packets_, 2, &protected_media_packets);
    942 
    943  EXPECT_EQ(
    944      0, this->fec_.EncodeFec(protected_media_packets, kProtectionFactor,
    945                              kNumImportantPackets, kUseUnequalProtection,
    946                              kFecMaskBursty, &this->generated_fec_packets_));
    947 
    948  // Expect 1 FEC packet.
    949  EXPECT_EQ(1u, this->generated_fec_packets_.size());
    950 
    951  // 1 protected media packet lost
    952  memset(this->media_loss_mask_, 0, sizeof(this->media_loss_mask_));
    953  memset(this->fec_loss_mask_, 0, sizeof(this->fec_loss_mask_));
    954  this->media_loss_mask_[2] = 1;
    955  this->NetworkReceivedPackets(this->media_loss_mask_, this->fec_loss_mask_);
    956 
    957  for (const auto& received_packet : this->received_packets_) {
    958    this->fec_.DecodeFec(*received_packet, &this->recovered_packets_);
    959  }
    960 
    961  // One packet lost, one FEC packet, expect complete recovery.
    962  EXPECT_TRUE(this->IsRecoveryComplete());
    963  this->recovered_packets_.clear();
    964 
    965  // Unprotected packet lost.
    966  memset(this->media_loss_mask_, 0, sizeof(this->media_loss_mask_));
    967  memset(this->fec_loss_mask_, 0, sizeof(this->fec_loss_mask_));
    968  this->media_loss_mask_[1] = 1;
    969  this->NetworkReceivedPackets(this->media_loss_mask_, this->fec_loss_mask_);
    970 
    971  for (const auto& received_packet : this->received_packets_) {
    972    this->fec_.DecodeFec(*received_packet, &this->recovered_packets_);
    973  }
    974 
    975  // Unprotected packet lost. Recovery not possible.
    976  EXPECT_FALSE(this->IsRecoveryComplete());
    977  this->recovered_packets_.clear();
    978 
    979  // 2 media packets lost.
    980  memset(this->media_loss_mask_, 0, sizeof(this->media_loss_mask_));
    981  memset(this->fec_loss_mask_, 0, sizeof(this->fec_loss_mask_));
    982  this->media_loss_mask_[0] = 1;
    983  this->media_loss_mask_[2] = 1;
    984  this->NetworkReceivedPackets(this->media_loss_mask_, this->fec_loss_mask_);
    985 
    986  for (const auto& received_packet : this->received_packets_) {
    987    this->fec_.DecodeFec(*received_packet, &this->recovered_packets_);
    988  }
    989 
    990  // 2 protected packets lost, one FEC packet, cannot get complete recovery.
    991  EXPECT_FALSE(this->IsRecoveryComplete());
    992 }
    993 
    994 TYPED_TEST(RtpFecTest, FecRecoveryNonConsecutivePacketsExtension) {
    995  constexpr int kNumImportantPackets = 0;
    996  constexpr bool kUseUnequalProtection = false;
    997  constexpr int kNumMediaPackets = 21;
    998  uint8_t kProtectionFactor = 127;
    999 
   1000  this->media_packets_ =
   1001      this->media_packet_generator_.ConstructMediaPackets(kNumMediaPackets);
   1002 
   1003  // Create a new temporary packet list for generating FEC packets.
   1004  // This list should have every other packet removed.
   1005  ForwardErrorCorrection::PacketList protected_media_packets;
   1006  DeepCopyEveryNthPacket(this->media_packets_, 2, &protected_media_packets);
   1007 
   1008  // Zero column insertion will have to extend the size of the packet
   1009  // mask since the number of actual packets are 21, while the number
   1010  // of protected packets are 11.
   1011  EXPECT_EQ(
   1012      0, this->fec_.EncodeFec(protected_media_packets, kProtectionFactor,
   1013                              kNumImportantPackets, kUseUnequalProtection,
   1014                              kFecMaskBursty, &this->generated_fec_packets_));
   1015 
   1016  // Expect 5 FEC packet.
   1017  EXPECT_EQ(5u, this->generated_fec_packets_.size());
   1018 
   1019  // Last protected media packet lost
   1020  memset(this->media_loss_mask_, 0, sizeof(this->media_loss_mask_));
   1021  memset(this->fec_loss_mask_, 0, sizeof(this->fec_loss_mask_));
   1022  this->media_loss_mask_[kNumMediaPackets - 1] = 1;
   1023  this->NetworkReceivedPackets(this->media_loss_mask_, this->fec_loss_mask_);
   1024 
   1025  for (const auto& received_packet : this->received_packets_) {
   1026    this->fec_.DecodeFec(*received_packet, &this->recovered_packets_);
   1027  }
   1028 
   1029  // One packet lost, one FEC packet, expect complete recovery.
   1030  EXPECT_TRUE(this->IsRecoveryComplete());
   1031  this->recovered_packets_.clear();
   1032 
   1033  // Last unprotected packet lost.
   1034  memset(this->media_loss_mask_, 0, sizeof(this->media_loss_mask_));
   1035  memset(this->fec_loss_mask_, 0, sizeof(this->fec_loss_mask_));
   1036  this->media_loss_mask_[kNumMediaPackets - 2] = 1;
   1037  this->NetworkReceivedPackets(this->media_loss_mask_, this->fec_loss_mask_);
   1038 
   1039  for (const auto& received_packet : this->received_packets_) {
   1040    this->fec_.DecodeFec(*received_packet, &this->recovered_packets_);
   1041  }
   1042 
   1043  // Unprotected packet lost. Recovery not possible.
   1044  EXPECT_FALSE(this->IsRecoveryComplete());
   1045  this->recovered_packets_.clear();
   1046 
   1047  // 6 media packets lost.
   1048  memset(this->media_loss_mask_, 0, sizeof(this->media_loss_mask_));
   1049  memset(this->fec_loss_mask_, 0, sizeof(this->fec_loss_mask_));
   1050  this->media_loss_mask_[kNumMediaPackets - 11] = 1;
   1051  this->media_loss_mask_[kNumMediaPackets - 9] = 1;
   1052  this->media_loss_mask_[kNumMediaPackets - 7] = 1;
   1053  this->media_loss_mask_[kNumMediaPackets - 5] = 1;
   1054  this->media_loss_mask_[kNumMediaPackets - 3] = 1;
   1055  this->media_loss_mask_[kNumMediaPackets - 1] = 1;
   1056  this->NetworkReceivedPackets(this->media_loss_mask_, this->fec_loss_mask_);
   1057 
   1058  for (const auto& received_packet : this->received_packets_) {
   1059    this->fec_.DecodeFec(*received_packet, &this->recovered_packets_);
   1060  }
   1061 
   1062  // 5 protected packets lost, one FEC packet, cannot get complete recovery.
   1063  EXPECT_FALSE(this->IsRecoveryComplete());
   1064 }
   1065 
   1066 TYPED_TEST(RtpFecTest, FecRecoveryNonConsecutivePacketsWrap) {
   1067  constexpr int kNumImportantPackets = 0;
   1068  constexpr bool kUseUnequalProtection = false;
   1069  constexpr int kNumMediaPackets = 21;
   1070  uint8_t kProtectionFactor = 127;
   1071 
   1072  this->media_packets_ = this->media_packet_generator_.ConstructMediaPackets(
   1073      kNumMediaPackets, 0xFFFF - 5);
   1074 
   1075  // Create a new temporary packet list for generating FEC packets.
   1076  // This list should have every other packet removed.
   1077  ForwardErrorCorrection::PacketList protected_media_packets;
   1078  DeepCopyEveryNthPacket(this->media_packets_, 2, &protected_media_packets);
   1079 
   1080  // Zero column insertion will have to extend the size of the packet
   1081  // mask since the number of actual packets are 21, while the number
   1082  // of protected packets are 11.
   1083  EXPECT_EQ(
   1084      0, this->fec_.EncodeFec(protected_media_packets, kProtectionFactor,
   1085                              kNumImportantPackets, kUseUnequalProtection,
   1086                              kFecMaskBursty, &this->generated_fec_packets_));
   1087 
   1088  // Expect 5 FEC packet.
   1089  EXPECT_EQ(5u, this->generated_fec_packets_.size());
   1090 
   1091  // Last protected media packet lost
   1092  memset(this->media_loss_mask_, 0, sizeof(this->media_loss_mask_));
   1093  memset(this->fec_loss_mask_, 0, sizeof(this->fec_loss_mask_));
   1094  this->media_loss_mask_[kNumMediaPackets - 1] = 1;
   1095  this->NetworkReceivedPackets(this->media_loss_mask_, this->fec_loss_mask_);
   1096 
   1097  for (const auto& received_packet : this->received_packets_) {
   1098    this->fec_.DecodeFec(*received_packet, &this->recovered_packets_);
   1099  }
   1100 
   1101  // One packet lost, one FEC packet, expect complete recovery.
   1102  EXPECT_TRUE(this->IsRecoveryComplete());
   1103  this->recovered_packets_.clear();
   1104 
   1105  // Last unprotected packet lost.
   1106  memset(this->media_loss_mask_, 0, sizeof(this->media_loss_mask_));
   1107  memset(this->fec_loss_mask_, 0, sizeof(this->fec_loss_mask_));
   1108  this->media_loss_mask_[kNumMediaPackets - 2] = 1;
   1109  this->NetworkReceivedPackets(this->media_loss_mask_, this->fec_loss_mask_);
   1110 
   1111  for (const auto& received_packet : this->received_packets_) {
   1112    this->fec_.DecodeFec(*received_packet, &this->recovered_packets_);
   1113  }
   1114 
   1115  // Unprotected packet lost. Recovery not possible.
   1116  EXPECT_FALSE(this->IsRecoveryComplete());
   1117  this->recovered_packets_.clear();
   1118 
   1119  // 6 media packets lost.
   1120  memset(this->media_loss_mask_, 0, sizeof(this->media_loss_mask_));
   1121  memset(this->fec_loss_mask_, 0, sizeof(this->fec_loss_mask_));
   1122  this->media_loss_mask_[kNumMediaPackets - 11] = 1;
   1123  this->media_loss_mask_[kNumMediaPackets - 9] = 1;
   1124  this->media_loss_mask_[kNumMediaPackets - 7] = 1;
   1125  this->media_loss_mask_[kNumMediaPackets - 5] = 1;
   1126  this->media_loss_mask_[kNumMediaPackets - 3] = 1;
   1127  this->media_loss_mask_[kNumMediaPackets - 1] = 1;
   1128  this->NetworkReceivedPackets(this->media_loss_mask_, this->fec_loss_mask_);
   1129 
   1130  for (const auto& received_packet : this->received_packets_) {
   1131    this->fec_.DecodeFec(*received_packet, &this->recovered_packets_);
   1132  }
   1133 
   1134  // 5 protected packets lost, one FEC packet, cannot get complete recovery.
   1135  EXPECT_FALSE(this->IsRecoveryComplete());
   1136 }
   1137 
   1138 }  // namespace webrtc