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