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