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