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