1 /*
2 * Copyright (c) 2016 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/flexfec_receiver.h"
12
13 #include <algorithm>
14 #include <memory>
15
16 #include "modules/rtp_rtcp/mocks/mock_recovered_packet_receiver.h"
17 #include "modules/rtp_rtcp/source/fec_test_helper.h"
18 #include "modules/rtp_rtcp/source/forward_error_correction.h"
19 #include "modules/rtp_rtcp/source/rtp_packet_received.h"
20 #include "test/gmock.h"
21 #include "test/gtest.h"
22
23 namespace webrtc {
24
25 namespace {
26
27 using ::testing::_;
28 using ::testing::Args;
29 using ::testing::ElementsAreArray;
30
31 using test::fec::FlexfecPacketGenerator;
32 using Packet = ForwardErrorCorrection::Packet;
33 using PacketList = ForwardErrorCorrection::PacketList;
34
35 constexpr size_t kPayloadLength = 500;
36 constexpr uint32_t kFlexfecSsrc = 42984;
37 constexpr uint32_t kMediaSsrc = 8353;
38
ParsePacket(const Packet & packet)39 RtpPacketReceived ParsePacket(const Packet& packet) {
40 RtpPacketReceived parsed_packet;
41 EXPECT_TRUE(parsed_packet.Parse(packet.data));
42 return parsed_packet;
43 }
44
45 } // namespace
46
47 class FlexfecReceiverForTest : public FlexfecReceiver {
48 public:
FlexfecReceiverForTest(uint32_t ssrc,uint32_t protected_media_ssrc,RecoveredPacketReceiver * recovered_packet_receiver)49 FlexfecReceiverForTest(uint32_t ssrc,
50 uint32_t protected_media_ssrc,
51 RecoveredPacketReceiver* recovered_packet_receiver)
52 : FlexfecReceiver(Clock::GetRealTimeClock(),
53 ssrc,
54 protected_media_ssrc,
55 recovered_packet_receiver) {}
56 // Expose methods for tests.
57 using FlexfecReceiver::AddReceivedPacket;
58 using FlexfecReceiver::ProcessReceivedPacket;
59 };
60
61 class FlexfecReceiverTest : public ::testing::Test {
62 protected:
FlexfecReceiverTest()63 FlexfecReceiverTest()
64 : receiver_(kFlexfecSsrc, kMediaSsrc, &recovered_packet_receiver_),
65 erasure_code_(
66 ForwardErrorCorrection::CreateFlexfec(kFlexfecSsrc, kMediaSsrc)),
67 packet_generator_(kMediaSsrc, kFlexfecSsrc) {}
68
69 // Generates |num_media_packets| corresponding to a single frame.
70 void PacketizeFrame(size_t num_media_packets,
71 size_t frame_offset,
72 PacketList* media_packets);
73
74 // Generates |num_fec_packets| FEC packets, given |media_packets|.
75 std::list<Packet*> EncodeFec(const PacketList& media_packets,
76 size_t num_fec_packets);
77
78 FlexfecReceiverForTest receiver_;
79 std::unique_ptr<ForwardErrorCorrection> erasure_code_;
80
81 FlexfecPacketGenerator packet_generator_;
82 ::testing::StrictMock<MockRecoveredPacketReceiver> recovered_packet_receiver_;
83 };
84
PacketizeFrame(size_t num_media_packets,size_t frame_offset,PacketList * media_packets)85 void FlexfecReceiverTest::PacketizeFrame(size_t num_media_packets,
86 size_t frame_offset,
87 PacketList* media_packets) {
88 packet_generator_.NewFrame(num_media_packets);
89 for (size_t i = 0; i < num_media_packets; ++i) {
90 std::unique_ptr<Packet> next_packet(
91 packet_generator_.NextPacket(frame_offset + i, kPayloadLength));
92 media_packets->push_back(std::move(next_packet));
93 }
94 }
95
EncodeFec(const PacketList & media_packets,size_t num_fec_packets)96 std::list<Packet*> FlexfecReceiverTest::EncodeFec(
97 const PacketList& media_packets,
98 size_t num_fec_packets) {
99 const uint8_t protection_factor =
100 num_fec_packets * 255 / media_packets.size();
101 constexpr int kNumImportantPackets = 0;
102 constexpr bool kUseUnequalProtection = false;
103 constexpr FecMaskType kFecMaskType = kFecMaskRandom;
104 std::list<Packet*> fec_packets;
105 EXPECT_EQ(0, erasure_code_->EncodeFec(
106 media_packets, protection_factor, kNumImportantPackets,
107 kUseUnequalProtection, kFecMaskType, &fec_packets));
108 EXPECT_EQ(num_fec_packets, fec_packets.size());
109 return fec_packets;
110 }
111
TEST_F(FlexfecReceiverTest,ReceivesMediaPacket)112 TEST_F(FlexfecReceiverTest, ReceivesMediaPacket) {
113 packet_generator_.NewFrame(1);
114 std::unique_ptr<Packet> media_packet(
115 packet_generator_.NextPacket(0, kPayloadLength));
116
117 std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet =
118 receiver_.AddReceivedPacket(ParsePacket(*media_packet));
119 ASSERT_TRUE(received_packet);
120 receiver_.ProcessReceivedPacket(*received_packet);
121 }
122
TEST_F(FlexfecReceiverTest,ReceivesMediaAndFecPackets)123 TEST_F(FlexfecReceiverTest, ReceivesMediaAndFecPackets) {
124 const size_t kNumMediaPackets = 1;
125 const size_t kNumFecPackets = 1;
126
127 PacketList media_packets;
128 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
129 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
130 const auto& media_packet = media_packets.front();
131 auto fec_packet = packet_generator_.BuildFlexfecPacket(*fec_packets.front());
132
133 std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet =
134 receiver_.AddReceivedPacket(ParsePacket(*media_packet));
135 ASSERT_TRUE(received_packet);
136 receiver_.ProcessReceivedPacket(*received_packet);
137 received_packet = receiver_.AddReceivedPacket(ParsePacket(*fec_packet));
138 ASSERT_TRUE(received_packet);
139 receiver_.ProcessReceivedPacket(*received_packet);
140 }
141
TEST_F(FlexfecReceiverTest,FailsOnTruncatedFecPacket)142 TEST_F(FlexfecReceiverTest, FailsOnTruncatedFecPacket) {
143 const size_t kNumMediaPackets = 1;
144 const size_t kNumFecPackets = 1;
145
146 PacketList media_packets;
147 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
148 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
149 const auto& media_packet = media_packets.front();
150 // Simulate truncated FlexFEC payload.
151 fec_packets.front()->data.SetSize(1);
152 auto fec_packet = packet_generator_.BuildFlexfecPacket(*fec_packets.front());
153
154 std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet =
155 receiver_.AddReceivedPacket(ParsePacket(*media_packet));
156 ASSERT_TRUE(received_packet);
157 receiver_.ProcessReceivedPacket(*received_packet);
158 EXPECT_FALSE(receiver_.AddReceivedPacket(ParsePacket(*fec_packet)));
159 }
160
TEST_F(FlexfecReceiverTest,FailsOnUnknownMediaSsrc)161 TEST_F(FlexfecReceiverTest, FailsOnUnknownMediaSsrc) {
162 const size_t kNumMediaPackets = 1;
163
164 PacketList media_packets;
165 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
166 auto& media_packet = media_packets.front();
167 // Corrupt the SSRC.
168 media_packet->data[8] = 0;
169 media_packet->data[9] = 1;
170 media_packet->data[10] = 2;
171 media_packet->data[11] = 3;
172
173 EXPECT_FALSE(receiver_.AddReceivedPacket(ParsePacket(*media_packet)));
174 }
175
TEST_F(FlexfecReceiverTest,FailsOnUnknownFecSsrc)176 TEST_F(FlexfecReceiverTest, FailsOnUnknownFecSsrc) {
177 const size_t kNumMediaPackets = 1;
178 const size_t kNumFecPackets = 1;
179
180 PacketList media_packets;
181 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
182 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
183 const auto& media_packet = media_packets.front();
184 auto fec_packet = packet_generator_.BuildFlexfecPacket(*fec_packets.front());
185 // Corrupt the SSRC.
186 fec_packet->data[8] = 4;
187 fec_packet->data[9] = 5;
188 fec_packet->data[10] = 6;
189 fec_packet->data[11] = 7;
190
191 std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet =
192 receiver_.AddReceivedPacket(ParsePacket(*media_packet));
193 ASSERT_TRUE(received_packet);
194 receiver_.ProcessReceivedPacket(*received_packet);
195 EXPECT_FALSE(receiver_.AddReceivedPacket(ParsePacket(*fec_packet)));
196 }
197
TEST_F(FlexfecReceiverTest,ReceivesMultiplePackets)198 TEST_F(FlexfecReceiverTest, ReceivesMultiplePackets) {
199 const size_t kNumMediaPackets = 2;
200 const size_t kNumFecPackets = 1;
201
202 PacketList media_packets;
203 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
204 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
205
206 // Receive all media packets.
207 for (const auto& media_packet : media_packets) {
208 std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet =
209 receiver_.AddReceivedPacket(ParsePacket(*media_packet));
210 ASSERT_TRUE(received_packet);
211 receiver_.ProcessReceivedPacket(*received_packet);
212 }
213
214 // Receive FEC packet.
215 auto* fec_packet = fec_packets.front();
216 std::unique_ptr<Packet> packet_with_rtp_header =
217 packet_generator_.BuildFlexfecPacket(*fec_packet);
218 std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet =
219 receiver_.AddReceivedPacket(ParsePacket(*packet_with_rtp_header));
220 ASSERT_TRUE(received_packet);
221 receiver_.ProcessReceivedPacket(*received_packet);
222 }
223
TEST_F(FlexfecReceiverTest,RecoversFromSingleMediaLoss)224 TEST_F(FlexfecReceiverTest, RecoversFromSingleMediaLoss) {
225 const size_t kNumMediaPackets = 2;
226 const size_t kNumFecPackets = 1;
227
228 PacketList media_packets;
229 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
230 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
231
232 // Receive first media packet but drop second.
233 auto media_it = media_packets.begin();
234 receiver_.OnRtpPacket(ParsePacket(**media_it));
235
236 // Receive FEC packet and ensure recovery of lost media packet.
237 auto fec_it = fec_packets.begin();
238 std::unique_ptr<Packet> packet_with_rtp_header =
239 packet_generator_.BuildFlexfecPacket(**fec_it);
240 media_it++;
241 EXPECT_CALL(recovered_packet_receiver_,
242 OnRecoveredPacket(_, (*media_it)->data.size()))
243 .With(Args<0, 1>(ElementsAreArray((*media_it)->data.cdata(),
244 (*media_it)->data.size())));
245 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
246 }
247
TEST_F(FlexfecReceiverTest,RecoversFromDoubleMediaLoss)248 TEST_F(FlexfecReceiverTest, RecoversFromDoubleMediaLoss) {
249 const size_t kNumMediaPackets = 2;
250 const size_t kNumFecPackets = 2;
251
252 PacketList media_packets;
253 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
254 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
255
256 // Drop both media packets.
257
258 // Receive first FEC packet and recover first lost media packet.
259 auto fec_it = fec_packets.begin();
260 std::unique_ptr<Packet> packet_with_rtp_header =
261 packet_generator_.BuildFlexfecPacket(**fec_it);
262 auto media_it = media_packets.begin();
263 EXPECT_CALL(recovered_packet_receiver_,
264 OnRecoveredPacket(_, (*media_it)->data.size()))
265 .With(Args<0, 1>(ElementsAreArray((*media_it)->data.cdata(),
266 (*media_it)->data.size())));
267 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
268
269 // Receive second FEC packet and recover second lost media packet.
270 fec_it++;
271 packet_with_rtp_header = packet_generator_.BuildFlexfecPacket(**fec_it);
272 media_it++;
273 EXPECT_CALL(recovered_packet_receiver_,
274 OnRecoveredPacket(_, (*media_it)->data.size()))
275 .With(Args<0, 1>(ElementsAreArray((*media_it)->data.cdata(),
276 (*media_it)->data.size())));
277 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
278 }
279
TEST_F(FlexfecReceiverTest,DoesNotRecoverFromMediaAndFecLoss)280 TEST_F(FlexfecReceiverTest, DoesNotRecoverFromMediaAndFecLoss) {
281 const size_t kNumMediaPackets = 2;
282 const size_t kNumFecPackets = 1;
283
284 PacketList media_packets;
285 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
286 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
287
288 // Receive first media packet.
289 auto media_it = media_packets.begin();
290 receiver_.OnRtpPacket(ParsePacket(**media_it));
291
292 // Drop second media packet and FEC packet. Do not expect call back.
293 }
294
TEST_F(FlexfecReceiverTest,DoesNotCallbackTwice)295 TEST_F(FlexfecReceiverTest, DoesNotCallbackTwice) {
296 const size_t kNumMediaPackets = 2;
297 const size_t kNumFecPackets = 1;
298
299 PacketList media_packets;
300 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
301 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
302
303 // Receive first media packet but drop second.
304 auto media_it = media_packets.begin();
305 receiver_.OnRtpPacket(ParsePacket(**media_it));
306
307 // Receive FEC packet and ensure recovery of lost media packet.
308 auto fec_it = fec_packets.begin();
309 std::unique_ptr<Packet> packet_with_rtp_header =
310 packet_generator_.BuildFlexfecPacket(**fec_it);
311 media_it++;
312 EXPECT_CALL(recovered_packet_receiver_,
313 OnRecoveredPacket(_, (*media_it)->data.size()))
314 .With(Args<0, 1>(ElementsAreArray((*media_it)->data.cdata(),
315 (*media_it)->data.size())));
316 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
317
318 // Receive the FEC packet again, but do not call back.
319 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
320
321 // Receive the first media packet again, but do not call back.
322 media_it = media_packets.begin();
323 receiver_.OnRtpPacket(ParsePacket(**media_it));
324
325 // Receive the second media packet again (the one recovered above),
326 // but do not call back again.
327 media_it++;
328 receiver_.OnRtpPacket(ParsePacket(**media_it));
329 }
330
331 // Here we are implicitly assuming packet masks that are suitable for
332 // this type of 50% correlated loss. If we are changing our precomputed
333 // packet masks, this test might need to be updated.
TEST_F(FlexfecReceiverTest,RecoversFrom50PercentLoss)334 TEST_F(FlexfecReceiverTest, RecoversFrom50PercentLoss) {
335 const size_t kNumFecPackets = 5;
336 const size_t kNumFrames = 2 * kNumFecPackets;
337 const size_t kNumMediaPacketsPerFrame = 1;
338
339 PacketList media_packets;
340 for (size_t i = 0; i < kNumFrames; ++i) {
341 PacketizeFrame(kNumMediaPacketsPerFrame, i, &media_packets);
342 }
343 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
344
345 // Drop every second media packet.
346 auto media_it = media_packets.begin();
347 while (media_it != media_packets.end()) {
348 receiver_.OnRtpPacket(ParsePacket(**media_it));
349 ++media_it;
350 if (media_it == media_packets.end()) {
351 break;
352 }
353 ++media_it;
354 }
355
356 // Receive all FEC packets.
357 media_it = media_packets.begin();
358 for (const auto* fec_packet : fec_packets) {
359 std::unique_ptr<Packet> fec_packet_with_rtp_header =
360 packet_generator_.BuildFlexfecPacket(*fec_packet);
361 ++media_it;
362 if (media_it == media_packets.end()) {
363 break;
364 }
365 EXPECT_CALL(recovered_packet_receiver_,
366 OnRecoveredPacket(_, (*media_it)->data.size()))
367 .With(Args<0, 1>(ElementsAreArray((*media_it)->data.cdata(),
368 (*media_it)->data.size())));
369 receiver_.OnRtpPacket(ParsePacket(*fec_packet_with_rtp_header));
370 ++media_it;
371 }
372 }
373
TEST_F(FlexfecReceiverTest,DelayedFecPacketDoesHelp)374 TEST_F(FlexfecReceiverTest, DelayedFecPacketDoesHelp) {
375 // These values need to be updated if the underlying erasure code
376 // implementation changes.
377 const size_t kNumFrames = 48;
378 const size_t kNumMediaPacketsPerFrame = 1;
379 const size_t kNumFecPackets = 1;
380
381 PacketList media_packets;
382 PacketizeFrame(kNumMediaPacketsPerFrame, 0, &media_packets);
383 PacketizeFrame(kNumMediaPacketsPerFrame, 1, &media_packets);
384 // Protect two first frames.
385 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
386 for (size_t i = 2; i < kNumFrames; ++i) {
387 PacketizeFrame(kNumMediaPacketsPerFrame, i, &media_packets);
388 }
389
390 // Drop first media packet and delay FEC packet.
391 auto media_it = media_packets.begin();
392 ++media_it;
393
394 // Receive all other media packets.
395 while (media_it != media_packets.end()) {
396 receiver_.OnRtpPacket(ParsePacket(**media_it));
397 ++media_it;
398 }
399
400 // Receive FEC packet and recover first media packet.
401 auto fec_it = fec_packets.begin();
402 std::unique_ptr<Packet> packet_with_rtp_header =
403 packet_generator_.BuildFlexfecPacket(**fec_it);
404 media_it = media_packets.begin();
405 EXPECT_CALL(recovered_packet_receiver_,
406 OnRecoveredPacket(_, (*media_it)->data.size()))
407 .With(Args<0, 1>(ElementsAreArray((*media_it)->data.cdata(),
408 (*media_it)->data.size())));
409 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
410 }
411
TEST_F(FlexfecReceiverTest,TooDelayedFecPacketDoesNotHelp)412 TEST_F(FlexfecReceiverTest, TooDelayedFecPacketDoesNotHelp) {
413 // These values need to be updated if the underlying erasure code
414 // implementation changes.
415 const size_t kNumFrames = 49;
416 const size_t kNumMediaPacketsPerFrame = 1;
417 const size_t kNumFecPackets = 1;
418
419 PacketList media_packets;
420 PacketizeFrame(kNumMediaPacketsPerFrame, 0, &media_packets);
421 PacketizeFrame(kNumMediaPacketsPerFrame, 1, &media_packets);
422 // Protect two first frames.
423 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
424 for (size_t i = 2; i < kNumFrames; ++i) {
425 PacketizeFrame(kNumMediaPacketsPerFrame, i, &media_packets);
426 }
427
428 // Drop first media packet and delay FEC packet.
429 auto media_it = media_packets.begin();
430 ++media_it;
431
432 // Receive all other media packets.
433 while (media_it != media_packets.end()) {
434 receiver_.OnRtpPacket(ParsePacket(**media_it));
435 ++media_it;
436 }
437
438 // Receive FEC packet.
439 auto fec_it = fec_packets.begin();
440 std::unique_ptr<Packet> packet_with_rtp_header =
441 packet_generator_.BuildFlexfecPacket(**fec_it);
442 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
443
444 // Do not expect a call back.
445 }
446
TEST_F(FlexfecReceiverTest,SurvivesOldRecoveredPacketBeingReinserted)447 TEST_F(FlexfecReceiverTest, SurvivesOldRecoveredPacketBeingReinserted) {
448 // Simulates the behaviour of the
449 // Call->FlexfecReceiveStream->FlexfecReceiver->Call loop in production code.
450 class LoopbackRecoveredPacketReceiver : public RecoveredPacketReceiver {
451 public:
452 LoopbackRecoveredPacketReceiver() : receiver_(nullptr) {}
453
454 void SetReceiver(FlexfecReceiver* receiver) { receiver_ = receiver; }
455
456 // Implements RecoveredPacketReceiver.
457 void OnRecoveredPacket(const uint8_t* packet, size_t length) override {
458 RtpPacketReceived parsed_packet;
459 EXPECT_TRUE(parsed_packet.Parse(packet, length));
460 parsed_packet.set_recovered(true);
461
462 RTC_DCHECK(receiver_);
463 receiver_->OnRtpPacket(parsed_packet);
464 }
465
466 private:
467 FlexfecReceiver* receiver_;
468 } loopback_recovered_packet_receiver;
469
470 // Feed recovered packets back into |receiver|.
471 FlexfecReceiver receiver(Clock::GetRealTimeClock(), kFlexfecSsrc, kMediaSsrc,
472 &loopback_recovered_packet_receiver);
473 loopback_recovered_packet_receiver.SetReceiver(&receiver);
474
475 // Receive first set of packets.
476 PacketList first_media_packets;
477 for (int i = 0; i < 46; ++i) {
478 PacketizeFrame(1, 0, &first_media_packets);
479 }
480 for (const auto& media_packet : first_media_packets) {
481 receiver.OnRtpPacket(ParsePacket(*media_packet));
482 }
483
484 // Protect one media packet. Lose the media packet,
485 // but do not receive FEC packet yet.
486 PacketList protected_media_packet;
487 PacketizeFrame(1, 0, &protected_media_packet);
488 const std::list<Packet*> fec_packets = EncodeFec(protected_media_packet, 1);
489 EXPECT_EQ(1u, fec_packets.size());
490 std::unique_ptr<Packet> fec_packet_with_rtp_header =
491 packet_generator_.BuildFlexfecPacket(*fec_packets.front());
492
493 // Lose some packets, thus introducing a sequence number gap.
494 PacketList lost_packets;
495 for (int i = 0; i < 100; ++i) {
496 PacketizeFrame(1, 0, &lost_packets);
497 }
498
499 // Receive one more packet.
500 PacketList second_media_packets;
501 PacketizeFrame(1, 0, &second_media_packets);
502 for (const auto& media_packet : second_media_packets) {
503 receiver.OnRtpPacket(ParsePacket(*media_packet));
504 }
505
506 // Receive delayed FEC packet.
507 receiver.OnRtpPacket(ParsePacket(*fec_packet_with_rtp_header));
508
509 // Expect no crash.
510 }
511
TEST_F(FlexfecReceiverTest,RecoversWithMediaPacketsOutOfOrder)512 TEST_F(FlexfecReceiverTest, RecoversWithMediaPacketsOutOfOrder) {
513 const size_t kNumMediaPackets = 6;
514 const size_t kNumFecPackets = 2;
515
516 PacketList media_packets;
517 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
518 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
519
520 // Lose two media packets, and receive the others out of order.
521 auto media_it = media_packets.begin();
522 auto media_packet0 = media_it++;
523 auto media_packet1 = media_it++;
524 auto media_packet2 = media_it++;
525 auto media_packet3 = media_it++;
526 auto media_packet4 = media_it++;
527 auto media_packet5 = media_it++;
528 receiver_.OnRtpPacket(ParsePacket(**media_packet5));
529 receiver_.OnRtpPacket(ParsePacket(**media_packet2));
530 receiver_.OnRtpPacket(ParsePacket(**media_packet3));
531 receiver_.OnRtpPacket(ParsePacket(**media_packet0));
532
533 // Expect to recover lost media packets.
534 EXPECT_CALL(recovered_packet_receiver_,
535 OnRecoveredPacket(_, (*media_packet1)->data.size()))
536 .With(Args<0, 1>(ElementsAreArray((*media_packet1)->data.cdata(),
537 (*media_packet1)->data.size())));
538 EXPECT_CALL(recovered_packet_receiver_,
539 OnRecoveredPacket(_, (*media_packet4)->data.size()))
540 .With(Args<0, 1>(ElementsAreArray((*media_packet4)->data.cdata(),
541 (*media_packet4)->data.size())));
542
543 // Add FEC packets.
544 auto fec_it = fec_packets.begin();
545 std::unique_ptr<Packet> packet_with_rtp_header;
546 while (fec_it != fec_packets.end()) {
547 packet_with_rtp_header = packet_generator_.BuildFlexfecPacket(**fec_it);
548 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
549 ++fec_it;
550 }
551 }
552
553 // Recovered media packets may be fed back into the FlexfecReceiver by the
554 // callback. This test ensures the idempotency of such a situation.
TEST_F(FlexfecReceiverTest,RecoveryCallbackDoesNotLoopInfinitely)555 TEST_F(FlexfecReceiverTest, RecoveryCallbackDoesNotLoopInfinitely) {
556 class LoopbackRecoveredPacketReceiver : public RecoveredPacketReceiver {
557 public:
558 const int kMaxRecursionDepth = 10;
559
560 LoopbackRecoveredPacketReceiver()
561 : receiver_(nullptr),
562 did_receive_call_back_(false),
563 recursion_depth_(0),
564 deep_recursion_(false) {}
565
566 void SetReceiver(FlexfecReceiver* receiver) { receiver_ = receiver; }
567 bool DidReceiveCallback() const { return did_receive_call_back_; }
568 bool DeepRecursion() const { return deep_recursion_; }
569
570 // Implements RecoveredPacketReceiver.
571 void OnRecoveredPacket(const uint8_t* packet, size_t length) override {
572 RtpPacketReceived parsed_packet;
573 EXPECT_TRUE(parsed_packet.Parse(packet, length));
574
575 did_receive_call_back_ = true;
576
577 if (recursion_depth_ > kMaxRecursionDepth) {
578 deep_recursion_ = true;
579 return;
580 }
581 ++recursion_depth_;
582 RTC_DCHECK(receiver_);
583 receiver_->OnRtpPacket(parsed_packet);
584 --recursion_depth_;
585 }
586
587 private:
588 FlexfecReceiver* receiver_;
589 bool did_receive_call_back_;
590 int recursion_depth_;
591 bool deep_recursion_;
592 } loopback_recovered_packet_receiver;
593
594 // Feed recovered packets back into |receiver|.
595 FlexfecReceiver receiver(Clock::GetRealTimeClock(), kFlexfecSsrc, kMediaSsrc,
596 &loopback_recovered_packet_receiver);
597 loopback_recovered_packet_receiver.SetReceiver(&receiver);
598
599 const size_t kNumMediaPackets = 2;
600 const size_t kNumFecPackets = 1;
601
602 PacketList media_packets;
603 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
604 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
605
606 // Receive first media packet but drop second.
607 auto media_it = media_packets.begin();
608 receiver.OnRtpPacket(ParsePacket(**media_it));
609
610 // Receive FEC packet and verify that a packet was recovered.
611 auto fec_it = fec_packets.begin();
612 std::unique_ptr<Packet> packet_with_rtp_header =
613 packet_generator_.BuildFlexfecPacket(**fec_it);
614 receiver.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
615 EXPECT_TRUE(loopback_recovered_packet_receiver.DidReceiveCallback());
616 EXPECT_FALSE(loopback_recovered_packet_receiver.DeepRecursion());
617 }
618
TEST_F(FlexfecReceiverTest,CalculatesNumberOfPackets)619 TEST_F(FlexfecReceiverTest, CalculatesNumberOfPackets) {
620 const size_t kNumMediaPackets = 2;
621 const size_t kNumFecPackets = 1;
622
623 PacketList media_packets;
624 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
625 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
626
627 // Receive first media packet but drop second.
628 auto media_it = media_packets.begin();
629 receiver_.OnRtpPacket(ParsePacket(**media_it));
630
631 // Receive FEC packet and ensure recovery of lost media packet.
632 auto fec_it = fec_packets.begin();
633 std::unique_ptr<Packet> packet_with_rtp_header =
634 packet_generator_.BuildFlexfecPacket(**fec_it);
635 media_it++;
636 EXPECT_CALL(recovered_packet_receiver_,
637 OnRecoveredPacket(_, (*media_it)->data.size()))
638 .With(Args<0, 1>(ElementsAreArray((*media_it)->data.cdata(),
639 (*media_it)->data.size())));
640 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
641
642 // Check stats calculations.
643 FecPacketCounter packet_counter = receiver_.GetPacketCounter();
644 EXPECT_EQ(2U, packet_counter.num_packets);
645 EXPECT_EQ(1U, packet_counter.num_fec_packets);
646 EXPECT_EQ(1U, packet_counter.num_recovered_packets);
647 }
648
649 } // namespace webrtc
650