tor-browser

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

ulpfec_receiver_unittest.cc (22116B)


      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 "modules/rtp_rtcp/source/ulpfec_receiver.h"
     12 
     13 #include <cstdint>
     14 #include <cstring>
     15 #include <iterator>
     16 #include <list>
     17 #include <memory>
     18 #include <utility>
     19 
     20 #include "api/units/timestamp.h"
     21 #include "modules/include/module_fec_types.h"
     22 #include "modules/rtp_rtcp/include/recovered_packet_receiver.h"
     23 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
     24 #include "modules/rtp_rtcp/mocks/mock_recovered_packet_receiver.h"
     25 #include "modules/rtp_rtcp/source/byte_io.h"
     26 #include "modules/rtp_rtcp/source/fec_test_helper.h"
     27 #include "modules/rtp_rtcp/source/forward_error_correction.h"
     28 #include "modules/rtp_rtcp/source/rtp_packet_received.h"
     29 #include "system_wrappers/include/clock.h"
     30 #include "test/gmock.h"
     31 #include "test/gtest.h"
     32 
     33 namespace webrtc {
     34 
     35 namespace {
     36 using ::testing::_;
     37 using ::testing::Eq;
     38 using ::testing::Property;
     39 
     40 using Packet = ForwardErrorCorrection::Packet;
     41 using test::fec::UlpfecPacketGenerator;
     42 
     43 constexpr int kFecPayloadType = 96;
     44 constexpr uint32_t kMediaSsrc = 835424;
     45 
     46 class NullRecoveredPacketReceiver : public RecoveredPacketReceiver {
     47 public:
     48  void OnRecoveredPacket(const RtpPacketReceived& /* packet */) override {}
     49 };
     50 
     51 }  // namespace
     52 
     53 class UlpfecReceiverTest : public ::testing::Test {
     54 protected:
     55  UlpfecReceiverTest()
     56      : fec_(ForwardErrorCorrection::CreateUlpfec(kMediaSsrc)),
     57        receiver_fec_(kMediaSsrc,
     58                      kFecPayloadType,
     59                      &recovered_packet_receiver_,
     60                      Clock::GetRealTimeClock()),
     61        packet_generator_(kMediaSsrc) {}
     62 
     63  // Generates `num_fec_packets` FEC packets, given `media_packets`.
     64  void EncodeFec(const ForwardErrorCorrection::PacketList& media_packets,
     65                 size_t num_fec_packets,
     66                 std::list<ForwardErrorCorrection::Packet*>* fec_packets);
     67 
     68  // Generates `num_media_packets` corresponding to a single frame.
     69  void PacketizeFrame(size_t num_media_packets,
     70                      size_t frame_offset,
     71                      std::list<RtpPacketReceived>* augmented_packets,
     72                      ForwardErrorCorrection::PacketList* packets);
     73 
     74  // Build a media packet using `packet_generator_` and add it
     75  // to the receiver.
     76  void BuildAndAddRedMediaPacket(const RtpPacketReceived& packet,
     77                                 bool is_recovered = false);
     78 
     79  // Build a FEC packet using `packet_generator_` and add it
     80  // to the receiver.
     81  void BuildAndAddRedFecPacket(Packet* packet);
     82 
     83  // Ensure that `recovered_packet_receiver_` will be called correctly
     84  // and that the recovered packet will be identical to the lost packet.
     85  void VerifyReconstructedMediaPacket(const RtpPacket& packet, size_t times);
     86 
     87  void InjectGarbagePacketLength(size_t fec_garbage_offset);
     88 
     89  static void SurvivesMaliciousPacket(const uint8_t* data,
     90                                      size_t length,
     91                                      uint8_t ulpfec_payload_type);
     92 
     93  MockRecoveredPacketReceiver recovered_packet_receiver_;
     94  std::unique_ptr<ForwardErrorCorrection> fec_;
     95  UlpfecReceiver receiver_fec_;
     96  UlpfecPacketGenerator packet_generator_;
     97 };
     98 
     99 void UlpfecReceiverTest::EncodeFec(
    100    const ForwardErrorCorrection::PacketList& media_packets,
    101    size_t num_fec_packets,
    102    std::list<ForwardErrorCorrection::Packet*>* fec_packets) {
    103  const uint8_t protection_factor =
    104      num_fec_packets * 255 / media_packets.size();
    105  // Unequal protection is turned off, and the number of important
    106  // packets is thus irrelevant.
    107  constexpr int kNumImportantPackets = 0;
    108  constexpr bool kUseUnequalProtection = false;
    109  constexpr FecMaskType kFecMaskType = kFecMaskBursty;
    110  EXPECT_EQ(
    111      0, fec_->EncodeFec(media_packets, protection_factor, kNumImportantPackets,
    112                         kUseUnequalProtection, kFecMaskType, fec_packets));
    113  ASSERT_EQ(num_fec_packets, fec_packets->size());
    114 }
    115 
    116 void UlpfecReceiverTest::PacketizeFrame(
    117    size_t num_media_packets,
    118    size_t frame_offset,
    119    std::list<RtpPacketReceived>* augmented_packets,
    120    ForwardErrorCorrection::PacketList* packets) {
    121  packet_generator_.NewFrame(num_media_packets);
    122  for (size_t i = 0; i < num_media_packets; ++i) {
    123    RtpPacketReceived next_packet =
    124        packet_generator_.NextPacket<RtpPacketReceived>(frame_offset + i,
    125                                                        kRtpHeaderSize + 10);
    126    auto packet = std::make_unique<Packet>();
    127    packet->data = next_packet.Buffer();
    128    augmented_packets->push_back(std::move(next_packet));
    129    packets->push_back(std::move(packet));
    130  }
    131 }
    132 
    133 void UlpfecReceiverTest::BuildAndAddRedMediaPacket(
    134    const RtpPacketReceived& packet,
    135    bool is_recovered) {
    136  EXPECT_TRUE(receiver_fec_.AddReceivedRedPacket(
    137      packet_generator_.BuildMediaRedPacket(packet, is_recovered)));
    138 }
    139 
    140 void UlpfecReceiverTest::BuildAndAddRedFecPacket(Packet* packet) {
    141  RtpPacketReceived red_packet =
    142      packet_generator_.BuildUlpfecRedPacket(*packet);
    143  EXPECT_TRUE(receiver_fec_.AddReceivedRedPacket(red_packet));
    144 }
    145 
    146 void UlpfecReceiverTest::VerifyReconstructedMediaPacket(const RtpPacket& packet,
    147                                                        size_t times) {
    148  // Verify that the content of the reconstructed packet is equal to the
    149  // content of `packet`, and that the same content is received `times` number
    150  // of times in a row.
    151  EXPECT_CALL(recovered_packet_receiver_,
    152              OnRecoveredPacket(
    153                  Property(&RtpPacketReceived::Buffer, Eq(packet.Buffer()))))
    154      .Times(times);
    155 }
    156 
    157 void UlpfecReceiverTest::InjectGarbagePacketLength(size_t fec_garbage_offset) {
    158  EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_));
    159 
    160  const size_t kNumFecPackets = 1;
    161  std::list<RtpPacketReceived> augmented_media_packets;
    162  ForwardErrorCorrection::PacketList media_packets;
    163  PacketizeFrame(2, 0, &augmented_media_packets, &media_packets);
    164  std::list<ForwardErrorCorrection::Packet*> fec_packets;
    165  EncodeFec(media_packets, kNumFecPackets, &fec_packets);
    166  ByteWriter<uint16_t>::WriteBigEndian(
    167      fec_packets.front()->data.MutableData() + fec_garbage_offset, 0x4711);
    168 
    169  // Inject first media packet, then first FEC packet, skipping the second media
    170  // packet to cause a recovery from the FEC packet.
    171  BuildAndAddRedMediaPacket(augmented_media_packets.front());
    172  BuildAndAddRedFecPacket(fec_packets.front());
    173  receiver_fec_.ProcessReceivedFec();
    174 
    175  FecPacketCounter counter = receiver_fec_.GetPacketCounter();
    176  EXPECT_EQ(2U, counter.num_packets);
    177  EXPECT_EQ(1U, counter.num_fec_packets);
    178  EXPECT_EQ(0U, counter.num_recovered_packets);
    179 }
    180 
    181 void UlpfecReceiverTest::SurvivesMaliciousPacket(const uint8_t* data,
    182                                                 size_t length,
    183                                                 uint8_t ulpfec_payload_type) {
    184  NullRecoveredPacketReceiver null_callback;
    185  UlpfecReceiver receiver_fec(kMediaSsrc, ulpfec_payload_type, &null_callback,
    186                              Clock::GetRealTimeClock());
    187 
    188  RtpPacketReceived rtp_packet;
    189  ASSERT_TRUE(rtp_packet.Parse(data, length));
    190  receiver_fec.AddReceivedRedPacket(rtp_packet);
    191 }
    192 
    193 TEST_F(UlpfecReceiverTest, TwoMediaOneFec) {
    194  constexpr size_t kNumFecPackets = 1u;
    195  std::list<RtpPacketReceived> augmented_media_packets;
    196  ForwardErrorCorrection::PacketList media_packets;
    197  PacketizeFrame(2, 0, &augmented_media_packets, &media_packets);
    198  std::list<ForwardErrorCorrection::Packet*> fec_packets;
    199  EncodeFec(media_packets, kNumFecPackets, &fec_packets);
    200 
    201  FecPacketCounter counter = receiver_fec_.GetPacketCounter();
    202  EXPECT_EQ(0u, counter.num_packets);
    203  EXPECT_EQ(Timestamp::MinusInfinity(), counter.first_packet_time);
    204 
    205  // Recovery
    206  auto it = augmented_media_packets.begin();
    207  BuildAndAddRedMediaPacket(*it);
    208  VerifyReconstructedMediaPacket(*it, 1);
    209 
    210  receiver_fec_.ProcessReceivedFec();
    211  counter = receiver_fec_.GetPacketCounter();
    212  EXPECT_EQ(1u, counter.num_packets);
    213  EXPECT_EQ(0u, counter.num_fec_packets);
    214  EXPECT_EQ(0u, counter.num_recovered_packets);
    215  const Timestamp first_packet_time = counter.first_packet_time;
    216  EXPECT_NE(Timestamp::MinusInfinity(), first_packet_time);
    217 
    218  // Drop one media packet.
    219  auto fec_it = fec_packets.begin();
    220  BuildAndAddRedFecPacket(*fec_it);
    221  ++it;
    222  VerifyReconstructedMediaPacket(*it, 1);
    223  receiver_fec_.ProcessReceivedFec();
    224 
    225  counter = receiver_fec_.GetPacketCounter();
    226  EXPECT_EQ(2u, counter.num_packets);
    227  EXPECT_EQ(1u, counter.num_fec_packets);
    228  EXPECT_EQ(1u, counter.num_recovered_packets);
    229  EXPECT_EQ(first_packet_time, counter.first_packet_time);
    230 }
    231 
    232 TEST_F(UlpfecReceiverTest, TwoMediaOneFecNotUsesRecoveredPackets) {
    233  constexpr size_t kNumFecPackets = 1u;
    234  std::list<RtpPacketReceived> augmented_media_packets;
    235  ForwardErrorCorrection::PacketList media_packets;
    236  PacketizeFrame(2, 0, &augmented_media_packets, &media_packets);
    237  std::list<ForwardErrorCorrection::Packet*> fec_packets;
    238  EncodeFec(media_packets, kNumFecPackets, &fec_packets);
    239 
    240  FecPacketCounter counter = receiver_fec_.GetPacketCounter();
    241  EXPECT_EQ(0u, counter.num_packets);
    242  EXPECT_EQ(Timestamp::MinusInfinity(), counter.first_packet_time);
    243 
    244  // Recovery
    245  auto it = augmented_media_packets.begin();
    246  BuildAndAddRedMediaPacket(*it, /*is_recovered=*/true);
    247  VerifyReconstructedMediaPacket(*it, 1);
    248  receiver_fec_.ProcessReceivedFec();
    249  counter = receiver_fec_.GetPacketCounter();
    250  EXPECT_EQ(1u, counter.num_packets);
    251  EXPECT_EQ(0u, counter.num_fec_packets);
    252  EXPECT_EQ(0u, counter.num_recovered_packets);
    253  const Timestamp first_packet_time = counter.first_packet_time;
    254  EXPECT_NE(Timestamp::MinusInfinity(), first_packet_time);
    255 
    256  // Drop one media packet.
    257  auto fec_it = fec_packets.begin();
    258  BuildAndAddRedFecPacket(*fec_it);
    259  ++it;
    260  receiver_fec_.ProcessReceivedFec();
    261 
    262  counter = receiver_fec_.GetPacketCounter();
    263  EXPECT_EQ(2u, counter.num_packets);
    264  EXPECT_EQ(1u, counter.num_fec_packets);
    265  EXPECT_EQ(0u, counter.num_recovered_packets);
    266  EXPECT_EQ(first_packet_time, counter.first_packet_time);
    267 }
    268 
    269 TEST_F(UlpfecReceiverTest, InjectGarbageFecHeaderLengthRecovery) {
    270  // Byte offset 8 is the 'length recovery' field of the FEC header.
    271  InjectGarbagePacketLength(8);
    272 }
    273 
    274 TEST_F(UlpfecReceiverTest, InjectGarbageFecLevelHeaderProtectionLength) {
    275  // Byte offset 10 is the 'protection length' field in the first FEC level
    276  // header.
    277  InjectGarbagePacketLength(10);
    278 }
    279 
    280 TEST_F(UlpfecReceiverTest, TwoMediaTwoFec) {
    281  const size_t kNumFecPackets = 2;
    282  std::list<RtpPacketReceived> augmented_media_packets;
    283  ForwardErrorCorrection::PacketList media_packets;
    284  PacketizeFrame(2, 0, &augmented_media_packets, &media_packets);
    285  std::list<ForwardErrorCorrection::Packet*> fec_packets;
    286  EncodeFec(media_packets, kNumFecPackets, &fec_packets);
    287 
    288  // Recovery
    289  // Drop both media packets.
    290  auto it = augmented_media_packets.begin();
    291  auto fec_it = fec_packets.begin();
    292  BuildAndAddRedFecPacket(*fec_it);
    293  VerifyReconstructedMediaPacket(*it, 1);
    294  receiver_fec_.ProcessReceivedFec();
    295  ++fec_it;
    296  BuildAndAddRedFecPacket(*fec_it);
    297  ++it;
    298  VerifyReconstructedMediaPacket(*it, 1);
    299  receiver_fec_.ProcessReceivedFec();
    300 }
    301 
    302 TEST_F(UlpfecReceiverTest, TwoFramesOneFec) {
    303  const size_t kNumFecPackets = 1;
    304  std::list<RtpPacketReceived> augmented_media_packets;
    305  ForwardErrorCorrection::PacketList media_packets;
    306  PacketizeFrame(1, 0, &augmented_media_packets, &media_packets);
    307  PacketizeFrame(1, 1, &augmented_media_packets, &media_packets);
    308  std::list<ForwardErrorCorrection::Packet*> fec_packets;
    309  EncodeFec(media_packets, kNumFecPackets, &fec_packets);
    310 
    311  // Recovery
    312  auto it = augmented_media_packets.begin();
    313  BuildAndAddRedMediaPacket(augmented_media_packets.front());
    314  VerifyReconstructedMediaPacket(*it, 1);
    315  receiver_fec_.ProcessReceivedFec();
    316  // Drop one media packet.
    317  BuildAndAddRedFecPacket(fec_packets.front());
    318  ++it;
    319  VerifyReconstructedMediaPacket(*it, 1);
    320  receiver_fec_.ProcessReceivedFec();
    321 }
    322 
    323 TEST_F(UlpfecReceiverTest, OneCompleteOneUnrecoverableFrame) {
    324  const size_t kNumFecPackets = 1;
    325  std::list<RtpPacketReceived> augmented_media_packets;
    326  ForwardErrorCorrection::PacketList media_packets;
    327  PacketizeFrame(1, 0, &augmented_media_packets, &media_packets);
    328  PacketizeFrame(2, 1, &augmented_media_packets, &media_packets);
    329 
    330  std::list<ForwardErrorCorrection::Packet*> fec_packets;
    331  EncodeFec(media_packets, kNumFecPackets, &fec_packets);
    332 
    333  // Recovery
    334  auto it = augmented_media_packets.begin();
    335  BuildAndAddRedMediaPacket(*it);  // First frame: one packet.
    336  VerifyReconstructedMediaPacket(*it, 1);
    337  receiver_fec_.ProcessReceivedFec();
    338  ++it;
    339  BuildAndAddRedMediaPacket(*it);  // First packet of second frame.
    340  VerifyReconstructedMediaPacket(*it, 1);
    341  receiver_fec_.ProcessReceivedFec();
    342 }
    343 
    344 TEST_F(UlpfecReceiverTest, MaxFramesOneFec) {
    345  const size_t kNumFecPackets = 1;
    346  const size_t kNumMediaPackets = 48;
    347  std::list<RtpPacketReceived> augmented_media_packets;
    348  ForwardErrorCorrection::PacketList media_packets;
    349  for (size_t i = 0; i < kNumMediaPackets; ++i) {
    350    PacketizeFrame(1, i, &augmented_media_packets, &media_packets);
    351  }
    352  std::list<ForwardErrorCorrection::Packet*> fec_packets;
    353  EncodeFec(media_packets, kNumFecPackets, &fec_packets);
    354 
    355  // Recovery
    356  auto it = augmented_media_packets.begin();
    357  ++it;  // Drop first packet.
    358  for (; it != augmented_media_packets.end(); ++it) {
    359    BuildAndAddRedMediaPacket(*it);
    360    VerifyReconstructedMediaPacket(*it, 1);
    361    receiver_fec_.ProcessReceivedFec();
    362  }
    363  BuildAndAddRedFecPacket(fec_packets.front());
    364  it = augmented_media_packets.begin();
    365  VerifyReconstructedMediaPacket(*it, 1);
    366  receiver_fec_.ProcessReceivedFec();
    367 }
    368 
    369 TEST_F(UlpfecReceiverTest, TooManyFrames) {
    370  const size_t kNumFecPackets = 1;
    371  const size_t kNumMediaPackets = 49;
    372  std::list<RtpPacketReceived> augmented_media_packets;
    373  ForwardErrorCorrection::PacketList media_packets;
    374  for (size_t i = 0; i < kNumMediaPackets; ++i) {
    375    PacketizeFrame(1, i, &augmented_media_packets, &media_packets);
    376  }
    377  std::list<ForwardErrorCorrection::Packet*> fec_packets;
    378  EXPECT_EQ(-1, fec_->EncodeFec(media_packets,
    379                                kNumFecPackets * 255 / kNumMediaPackets, 0,
    380                                false, kFecMaskBursty, &fec_packets));
    381 }
    382 
    383 TEST_F(UlpfecReceiverTest, PacketNotDroppedTooEarly) {
    384  // 1 frame with 2 media packets and one FEC packet. One media packet missing.
    385  // Delay the FEC packet.
    386  Packet* delayed_fec = nullptr;
    387  const size_t kNumFecPacketsBatch1 = 1;
    388  const size_t kNumMediaPacketsBatch1 = 2;
    389  std::list<RtpPacketReceived> augmented_media_packets_batch1;
    390  ForwardErrorCorrection::PacketList media_packets_batch1;
    391  PacketizeFrame(kNumMediaPacketsBatch1, 0, &augmented_media_packets_batch1,
    392                 &media_packets_batch1);
    393  std::list<ForwardErrorCorrection::Packet*> fec_packets;
    394  EncodeFec(media_packets_batch1, kNumFecPacketsBatch1, &fec_packets);
    395 
    396  BuildAndAddRedMediaPacket(augmented_media_packets_batch1.front());
    397  EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_)).Times(1);
    398  receiver_fec_.ProcessReceivedFec();
    399  delayed_fec = fec_packets.front();
    400 
    401  // Fill the FEC decoder. No packets should be dropped.
    402  const size_t kNumMediaPacketsBatch2 = 191;
    403  std::list<RtpPacketReceived> augmented_media_packets_batch2;
    404  ForwardErrorCorrection::PacketList media_packets_batch2;
    405  for (size_t i = 0; i < kNumMediaPacketsBatch2; ++i) {
    406    PacketizeFrame(1, i, &augmented_media_packets_batch2,
    407                   &media_packets_batch2);
    408  }
    409  for (auto it = augmented_media_packets_batch2.begin();
    410       it != augmented_media_packets_batch2.end(); ++it) {
    411    BuildAndAddRedMediaPacket(*it);
    412    EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_)).Times(1);
    413    receiver_fec_.ProcessReceivedFec();
    414  }
    415 
    416  // Add the delayed FEC packet. One packet should be reconstructed.
    417  BuildAndAddRedFecPacket(delayed_fec);
    418  EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_)).Times(1);
    419  receiver_fec_.ProcessReceivedFec();
    420 }
    421 
    422 TEST_F(UlpfecReceiverTest, PacketDroppedWhenTooOld) {
    423  // 1 frame with 2 media packets and one FEC packet. One media packet missing.
    424  // Delay the FEC packet.
    425  Packet* delayed_fec = nullptr;
    426  const size_t kNumFecPacketsBatch1 = 1;
    427  const size_t kNumMediaPacketsBatch1 = 2;
    428  std::list<RtpPacketReceived> augmented_media_packets_batch1;
    429  ForwardErrorCorrection::PacketList media_packets_batch1;
    430  PacketizeFrame(kNumMediaPacketsBatch1, 0, &augmented_media_packets_batch1,
    431                 &media_packets_batch1);
    432  std::list<ForwardErrorCorrection::Packet*> fec_packets;
    433  EncodeFec(media_packets_batch1, kNumFecPacketsBatch1, &fec_packets);
    434 
    435  BuildAndAddRedMediaPacket(augmented_media_packets_batch1.front());
    436  EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_)).Times(1);
    437  receiver_fec_.ProcessReceivedFec();
    438  delayed_fec = fec_packets.front();
    439 
    440  // Fill the FEC decoder and force the last packet to be dropped.
    441  const size_t kNumMediaPacketsBatch2 = 192;
    442  std::list<RtpPacketReceived> augmented_media_packets_batch2;
    443  ForwardErrorCorrection::PacketList media_packets_batch2;
    444  for (size_t i = 0; i < kNumMediaPacketsBatch2; ++i) {
    445    PacketizeFrame(1, i, &augmented_media_packets_batch2,
    446                   &media_packets_batch2);
    447  }
    448  for (auto it = augmented_media_packets_batch2.begin();
    449       it != augmented_media_packets_batch2.end(); ++it) {
    450    BuildAndAddRedMediaPacket(*it);
    451    EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_)).Times(1);
    452    receiver_fec_.ProcessReceivedFec();
    453  }
    454 
    455  // Add the delayed FEC packet. No packet should be reconstructed since the
    456  // first media packet of that frame has been dropped due to being too old.
    457  BuildAndAddRedFecPacket(delayed_fec);
    458  EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_)).Times(0);
    459  receiver_fec_.ProcessReceivedFec();
    460 }
    461 
    462 TEST_F(UlpfecReceiverTest, OldFecPacketDropped) {
    463  // 49 frames with 2 media packets and one FEC packet. All media packets
    464  // missing.
    465  const size_t kNumMediaPackets = 49 * 2;
    466  std::list<RtpPacketReceived> augmented_media_packets;
    467  ForwardErrorCorrection::PacketList media_packets;
    468  for (size_t i = 0; i < kNumMediaPackets / 2; ++i) {
    469    std::list<RtpPacketReceived> frame_augmented_media_packets;
    470    ForwardErrorCorrection::PacketList frame_media_packets;
    471    std::list<ForwardErrorCorrection::Packet*> fec_packets;
    472    PacketizeFrame(2, 0, &frame_augmented_media_packets, &frame_media_packets);
    473    EncodeFec(frame_media_packets, 1, &fec_packets);
    474    for (auto it = fec_packets.begin(); it != fec_packets.end(); ++it) {
    475      // Only FEC packets inserted. No packets recoverable at this time.
    476      BuildAndAddRedFecPacket(*it);
    477      EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_)).Times(0);
    478      receiver_fec_.ProcessReceivedFec();
    479    }
    480    // Move unique_ptr's to media_packets for lifetime management.
    481    media_packets.insert(media_packets.end(),
    482                         std::make_move_iterator(frame_media_packets.begin()),
    483                         std::make_move_iterator(frame_media_packets.end()));
    484    augmented_media_packets.insert(augmented_media_packets.end(),
    485                                   frame_augmented_media_packets.begin(),
    486                                   frame_augmented_media_packets.end());
    487  }
    488  // Insert the oldest media packet. The corresponding FEC packet is too old
    489  // and should have been dropped. Only the media packet we inserted will be
    490  // returned.
    491  BuildAndAddRedMediaPacket(augmented_media_packets.front());
    492  EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_)).Times(1);
    493  receiver_fec_.ProcessReceivedFec();
    494 }
    495 
    496 TEST_F(UlpfecReceiverTest, TruncatedPacketWithFBitSet) {
    497  const uint8_t kTruncatedPacket[] = {0x80, 0x2a, 0x68, 0x71, 0x29, 0xa1, 0x27,
    498                                      0x3a, 0x29, 0x12, 0x2a, 0x98, 0xe0, 0x29};
    499 
    500  SurvivesMaliciousPacket(kTruncatedPacket, sizeof(kTruncatedPacket), 100);
    501 }
    502 
    503 TEST_F(UlpfecReceiverTest,
    504       TruncatedPacketWithFBitSetEndingAfterFirstRedHeader) {
    505  const uint8_t kPacket[] = {
    506      0x89, 0x27, 0x3a, 0x83, 0x27, 0x3a, 0x3a, 0xf3, 0x67, 0xbe, 0x2a,
    507      0xa9, 0x27, 0x54, 0x3a, 0x3a, 0x2a, 0x67, 0x3a, 0xf3, 0x67, 0xbe,
    508      0x2a, 0x27, 0xe6, 0xf6, 0x03, 0x3e, 0x29, 0x27, 0x21, 0x27, 0x2a,
    509      0x29, 0x21, 0x4b, 0x29, 0x3a, 0x28, 0x29, 0xbf, 0x29, 0x2a, 0x26,
    510      0x29, 0xae, 0x27, 0xa6, 0xf6, 0x00, 0x03, 0x3e};
    511  SurvivesMaliciousPacket(kPacket, sizeof(kPacket), 100);
    512 }
    513 
    514 TEST_F(UlpfecReceiverTest, TruncatedPacketWithoutDataPastFirstBlock) {
    515  const uint8_t kPacket[] = {
    516      0x82, 0x38, 0x92, 0x38, 0x92, 0x38, 0xde, 0x2a, 0x11, 0xc8, 0xa3, 0xc4,
    517      0x82, 0x38, 0x2a, 0x21, 0x2a, 0x28, 0x92, 0x38, 0x92, 0x00, 0x00, 0x0a,
    518      0x3a, 0xc8, 0xa3, 0x3a, 0x27, 0xc4, 0x2a, 0x21, 0x2a, 0x28};
    519  SurvivesMaliciousPacket(kPacket, sizeof(kPacket), 100);
    520 }
    521 
    522 TEST_F(UlpfecReceiverTest, MediaWithPadding) {
    523  const size_t kNumFecPackets = 1;
    524  std::list<RtpPacketReceived> augmented_media_packets;
    525  ForwardErrorCorrection::PacketList media_packets;
    526  PacketizeFrame(2, 0, &augmented_media_packets, &media_packets);
    527 
    528  augmented_media_packets.front().SetPadding(/*padding_size=*/4);
    529  media_packets.front()->data = augmented_media_packets.front().Buffer();
    530 
    531  std::list<ForwardErrorCorrection::Packet*> fec_packets;
    532  EncodeFec(media_packets, kNumFecPackets, &fec_packets);
    533 
    534  auto it = augmented_media_packets.begin();
    535  BuildAndAddRedMediaPacket(augmented_media_packets.front());
    536 
    537  VerifyReconstructedMediaPacket(*it, 1);
    538  receiver_fec_.ProcessReceivedFec();
    539 
    540  BuildAndAddRedFecPacket(fec_packets.front());
    541  ++it;
    542  VerifyReconstructedMediaPacket(*it, 1);
    543  receiver_fec_.ProcessReceivedFec();
    544 }
    545 
    546 }  // namespace webrtc