xref: /aosp_15_r20/external/webrtc/modules/rtp_rtcp/source/flexfec_receiver_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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.MutableData()[8] = 0;
169   media_packet->data.MutableData()[9] = 1;
170   media_packet->data.MutableData()[10] = 2;
171   media_packet->data.MutableData()[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.MutableData()[8] = 4;
187   fec_packet->data.MutableData()[9] = 5;
188   fec_packet->data.MutableData()[10] = 6;
189   fec_packet->data.MutableData()[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   // Delay FEC packet by maximum number of media packets tracked by receiver.
378   const size_t kNumFrames = 192;
379   const size_t kNumMediaPacketsPerFrame = 1;
380   const size_t kNumFecPackets = 1;
381 
382   PacketList media_packets;
383   PacketizeFrame(kNumMediaPacketsPerFrame, 0, &media_packets);
384   PacketizeFrame(kNumMediaPacketsPerFrame, 1, &media_packets);
385   // Protect two first frames.
386   std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
387   for (size_t i = 2; i < kNumFrames; ++i) {
388     PacketizeFrame(kNumMediaPacketsPerFrame, i, &media_packets);
389   }
390 
391   // Drop first media packet and delay FEC packet.
392   auto media_it = media_packets.begin();
393   ++media_it;
394 
395   // Receive all other media packets.
396   while (media_it != media_packets.end()) {
397     receiver_.OnRtpPacket(ParsePacket(**media_it));
398     ++media_it;
399   }
400 
401   // Receive FEC packet and recover first media packet.
402   auto fec_it = fec_packets.begin();
403   std::unique_ptr<Packet> packet_with_rtp_header =
404       packet_generator_.BuildFlexfecPacket(**fec_it);
405   media_it = media_packets.begin();
406   EXPECT_CALL(recovered_packet_receiver_,
407               OnRecoveredPacket(_, (*media_it)->data.size()))
408       .With(Args<0, 1>(ElementsAreArray((*media_it)->data.cdata(),
409                                         (*media_it)->data.size())));
410   receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
411 }
412 
TEST_F(FlexfecReceiverTest,TooDelayedFecPacketDoesNotHelp)413 TEST_F(FlexfecReceiverTest, TooDelayedFecPacketDoesNotHelp) {
414   // These values need to be updated if the underlying erasure code
415   // implementation changes.
416   // Delay FEC packet by one more than maximum number of media packets
417   // tracked by receiver.
418   const size_t kNumFrames = 193;
419   const size_t kNumMediaPacketsPerFrame = 1;
420   const size_t kNumFecPackets = 1;
421 
422   PacketList media_packets;
423   PacketizeFrame(kNumMediaPacketsPerFrame, 0, &media_packets);
424   PacketizeFrame(kNumMediaPacketsPerFrame, 1, &media_packets);
425   // Protect first two frames.
426   std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
427   for (size_t i = 2; i < kNumFrames; ++i) {
428     PacketizeFrame(kNumMediaPacketsPerFrame, i, &media_packets);
429   }
430 
431   // Drop first media packet and delay FEC packet.
432   auto media_it = media_packets.begin();
433   ++media_it;
434 
435   // Receive all other media packets.
436   while (media_it != media_packets.end()) {
437     receiver_.OnRtpPacket(ParsePacket(**media_it));
438     ++media_it;
439   }
440 
441   // Receive FEC packet.
442   auto fec_it = fec_packets.begin();
443   std::unique_ptr<Packet> packet_with_rtp_header =
444       packet_generator_.BuildFlexfecPacket(**fec_it);
445   receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
446 
447   // Do not expect a call back.
448 }
449 
TEST_F(FlexfecReceiverTest,SurvivesOldRecoveredPacketBeingReinserted)450 TEST_F(FlexfecReceiverTest, SurvivesOldRecoveredPacketBeingReinserted) {
451   // Simulates the behaviour of the
452   // Call->FlexfecReceiveStream->FlexfecReceiver->Call loop in production code.
453   class LoopbackRecoveredPacketReceiver : public RecoveredPacketReceiver {
454    public:
455     LoopbackRecoveredPacketReceiver() : receiver_(nullptr) {}
456 
457     void SetReceiver(FlexfecReceiver* receiver) { receiver_ = receiver; }
458 
459     // Implements RecoveredPacketReceiver.
460     void OnRecoveredPacket(const uint8_t* packet, size_t length) override {
461       RtpPacketReceived parsed_packet;
462       EXPECT_TRUE(parsed_packet.Parse(packet, length));
463       parsed_packet.set_recovered(true);
464 
465       RTC_DCHECK(receiver_);
466       receiver_->OnRtpPacket(parsed_packet);
467     }
468 
469    private:
470     FlexfecReceiver* receiver_;
471   } loopback_recovered_packet_receiver;
472 
473   // Feed recovered packets back into `receiver`.
474   FlexfecReceiver receiver(Clock::GetRealTimeClock(), kFlexfecSsrc, kMediaSsrc,
475                            &loopback_recovered_packet_receiver);
476   loopback_recovered_packet_receiver.SetReceiver(&receiver);
477 
478   // Receive first set of packets.
479   PacketList first_media_packets;
480   for (int i = 0; i < 46; ++i) {
481     PacketizeFrame(1, 0, &first_media_packets);
482   }
483   for (const auto& media_packet : first_media_packets) {
484     receiver.OnRtpPacket(ParsePacket(*media_packet));
485   }
486 
487   // Protect one media packet. Lose the media packet,
488   // but do not receive FEC packet yet.
489   PacketList protected_media_packet;
490   PacketizeFrame(1, 0, &protected_media_packet);
491   const std::list<Packet*> fec_packets = EncodeFec(protected_media_packet, 1);
492   EXPECT_EQ(1u, fec_packets.size());
493   std::unique_ptr<Packet> fec_packet_with_rtp_header =
494       packet_generator_.BuildFlexfecPacket(*fec_packets.front());
495 
496   // Lose some packets, thus introducing a sequence number gap.
497   PacketList lost_packets;
498   for (int i = 0; i < 100; ++i) {
499     PacketizeFrame(1, 0, &lost_packets);
500   }
501 
502   // Receive one more packet.
503   PacketList second_media_packets;
504   PacketizeFrame(1, 0, &second_media_packets);
505   for (const auto& media_packet : second_media_packets) {
506     receiver.OnRtpPacket(ParsePacket(*media_packet));
507   }
508 
509   // Receive delayed FEC packet.
510   receiver.OnRtpPacket(ParsePacket(*fec_packet_with_rtp_header));
511 
512   // Expect no crash.
513 }
514 
TEST_F(FlexfecReceiverTest,RecoversWithMediaPacketsOutOfOrder)515 TEST_F(FlexfecReceiverTest, RecoversWithMediaPacketsOutOfOrder) {
516   const size_t kNumMediaPackets = 6;
517   const size_t kNumFecPackets = 2;
518 
519   PacketList media_packets;
520   PacketizeFrame(kNumMediaPackets, 0, &media_packets);
521   std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
522 
523   // Lose two media packets, and receive the others out of order.
524   auto media_it = media_packets.begin();
525   auto media_packet0 = media_it++;
526   auto media_packet1 = media_it++;
527   auto media_packet2 = media_it++;
528   auto media_packet3 = media_it++;
529   auto media_packet4 = media_it++;
530   auto media_packet5 = media_it++;
531   receiver_.OnRtpPacket(ParsePacket(**media_packet5));
532   receiver_.OnRtpPacket(ParsePacket(**media_packet2));
533   receiver_.OnRtpPacket(ParsePacket(**media_packet3));
534   receiver_.OnRtpPacket(ParsePacket(**media_packet0));
535 
536   // Expect to recover lost media packets.
537   EXPECT_CALL(recovered_packet_receiver_,
538               OnRecoveredPacket(_, (*media_packet1)->data.size()))
539       .With(Args<0, 1>(ElementsAreArray((*media_packet1)->data.cdata(),
540                                         (*media_packet1)->data.size())));
541   EXPECT_CALL(recovered_packet_receiver_,
542               OnRecoveredPacket(_, (*media_packet4)->data.size()))
543       .With(Args<0, 1>(ElementsAreArray((*media_packet4)->data.cdata(),
544                                         (*media_packet4)->data.size())));
545 
546   // Add FEC packets.
547   auto fec_it = fec_packets.begin();
548   std::unique_ptr<Packet> packet_with_rtp_header;
549   while (fec_it != fec_packets.end()) {
550     packet_with_rtp_header = packet_generator_.BuildFlexfecPacket(**fec_it);
551     receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
552     ++fec_it;
553   }
554 }
555 
556 // Recovered media packets may be fed back into the FlexfecReceiver by the
557 // callback. This test ensures the idempotency of such a situation.
TEST_F(FlexfecReceiverTest,RecoveryCallbackDoesNotLoopInfinitely)558 TEST_F(FlexfecReceiverTest, RecoveryCallbackDoesNotLoopInfinitely) {
559   class LoopbackRecoveredPacketReceiver : public RecoveredPacketReceiver {
560    public:
561     const int kMaxRecursionDepth = 10;
562 
563     LoopbackRecoveredPacketReceiver()
564         : receiver_(nullptr),
565           did_receive_call_back_(false),
566           recursion_depth_(0),
567           deep_recursion_(false) {}
568 
569     void SetReceiver(FlexfecReceiver* receiver) { receiver_ = receiver; }
570     bool DidReceiveCallback() const { return did_receive_call_back_; }
571     bool DeepRecursion() const { return deep_recursion_; }
572 
573     // Implements RecoveredPacketReceiver.
574     void OnRecoveredPacket(const uint8_t* packet, size_t length) override {
575       RtpPacketReceived parsed_packet;
576       EXPECT_TRUE(parsed_packet.Parse(packet, length));
577 
578       did_receive_call_back_ = true;
579 
580       if (recursion_depth_ > kMaxRecursionDepth) {
581         deep_recursion_ = true;
582         return;
583       }
584       ++recursion_depth_;
585       RTC_DCHECK(receiver_);
586       receiver_->OnRtpPacket(parsed_packet);
587       --recursion_depth_;
588     }
589 
590    private:
591     FlexfecReceiver* receiver_;
592     bool did_receive_call_back_;
593     int recursion_depth_;
594     bool deep_recursion_;
595   } loopback_recovered_packet_receiver;
596 
597   // Feed recovered packets back into `receiver`.
598   FlexfecReceiver receiver(Clock::GetRealTimeClock(), kFlexfecSsrc, kMediaSsrc,
599                            &loopback_recovered_packet_receiver);
600   loopback_recovered_packet_receiver.SetReceiver(&receiver);
601 
602   const size_t kNumMediaPackets = 2;
603   const size_t kNumFecPackets = 1;
604 
605   PacketList media_packets;
606   PacketizeFrame(kNumMediaPackets, 0, &media_packets);
607   std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
608 
609   // Receive first media packet but drop second.
610   auto media_it = media_packets.begin();
611   receiver.OnRtpPacket(ParsePacket(**media_it));
612 
613   // Receive FEC packet and verify that a packet was recovered.
614   auto fec_it = fec_packets.begin();
615   std::unique_ptr<Packet> packet_with_rtp_header =
616       packet_generator_.BuildFlexfecPacket(**fec_it);
617   receiver.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
618   EXPECT_TRUE(loopback_recovered_packet_receiver.DidReceiveCallback());
619   EXPECT_FALSE(loopback_recovered_packet_receiver.DeepRecursion());
620 }
621 
TEST_F(FlexfecReceiverTest,CalculatesNumberOfPackets)622 TEST_F(FlexfecReceiverTest, CalculatesNumberOfPackets) {
623   const size_t kNumMediaPackets = 2;
624   const size_t kNumFecPackets = 1;
625 
626   PacketList media_packets;
627   PacketizeFrame(kNumMediaPackets, 0, &media_packets);
628   std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
629 
630   // Receive first media packet but drop second.
631   auto media_it = media_packets.begin();
632   receiver_.OnRtpPacket(ParsePacket(**media_it));
633 
634   // Receive FEC packet and ensure recovery of lost media packet.
635   auto fec_it = fec_packets.begin();
636   std::unique_ptr<Packet> packet_with_rtp_header =
637       packet_generator_.BuildFlexfecPacket(**fec_it);
638   media_it++;
639   EXPECT_CALL(recovered_packet_receiver_,
640               OnRecoveredPacket(_, (*media_it)->data.size()))
641       .With(Args<0, 1>(ElementsAreArray((*media_it)->data.cdata(),
642                                         (*media_it)->data.size())));
643   receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
644 
645   // Check stats calculations.
646   FecPacketCounter packet_counter = receiver_.GetPacketCounter();
647   EXPECT_EQ(2U, packet_counter.num_packets);
648   EXPECT_EQ(1U, packet_counter.num_fec_packets);
649   EXPECT_EQ(1U, packet_counter.num_recovered_packets);
650 }
651 
TEST_F(FlexfecReceiverTest,DoesNotDecodeWrappedMediaSequenceUsingOldFec)652 TEST_F(FlexfecReceiverTest, DoesNotDecodeWrappedMediaSequenceUsingOldFec) {
653   const size_t kFirstFrameNumMediaPackets = 2;
654   const size_t kFirstFrameNumFecPackets = 1;
655 
656   PacketList media_packets;
657   PacketizeFrame(kFirstFrameNumMediaPackets, 0, &media_packets);
658 
659   // Protect first frame (sequences 0 and 1) with 1 FEC packet.
660   std::list<Packet*> fec_packets =
661       EncodeFec(media_packets, kFirstFrameNumFecPackets);
662 
663   // Generate enough media packets to simulate media sequence number wraparound.
664   // Use no FEC for these frames to make sure old FEC is not purged due to age.
665   const size_t kNumFramesSequenceWrapAround =
666       std::numeric_limits<uint16_t>::max();
667   const size_t kNumMediaPacketsPerFrame = 1;
668 
669   for (size_t i = 1; i <= kNumFramesSequenceWrapAround; ++i) {
670     PacketizeFrame(kNumMediaPacketsPerFrame, i, &media_packets);
671   }
672 
673   // Receive first (`kFirstFrameNumMediaPackets` + 192) media packets.
674   // Simulate an old FEC packet by separating it from its encoded media
675   // packets by at least 192 packets.
676   auto media_it = media_packets.begin();
677   for (size_t i = 0; i < (kFirstFrameNumMediaPackets + 192); i++) {
678     if (i == 1) {
679       // Drop the second packet of the first frame.
680       media_it++;
681     } else {
682       receiver_.OnRtpPacket(ParsePacket(**media_it++));
683     }
684   }
685 
686   // Receive FEC packet. Although a protected packet was dropped,
687   // expect no recovery callback since it is delayed from first frame
688   // by more than 192 packets.
689   auto fec_it = fec_packets.begin();
690   std::unique_ptr<Packet> fec_packet_with_rtp_header =
691       packet_generator_.BuildFlexfecPacket(**fec_it);
692   receiver_.OnRtpPacket(ParsePacket(*fec_packet_with_rtp_header));
693 
694   // Receive remaining media packets.
695   // NOTE: Because we sent enough to simulate wrap around, sequence 0 is
696   // received again, but is a different packet than the original first
697   // packet of first frame.
698   while (media_it != media_packets.end()) {
699     receiver_.OnRtpPacket(ParsePacket(**media_it++));
700   }
701 
702   // Do not expect a recovery callback, the FEC packet is old
703   // and should not decode wrapped around media sequences.
704 }
705 
706 }  // namespace webrtc
707