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