blob: 1761e1d4c523512b43979fbd40631747ac1c0cc9 [file] [log] [blame]
brandtra8b38552016-10-10 16:44:57 -07001/*
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 <algorithm>
12#include <memory>
13
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020014#include "modules/rtp_rtcp/include/flexfec_receiver.h"
15#include "modules/rtp_rtcp/mocks/mock_recovered_packet_receiver.h"
16#include "modules/rtp_rtcp/source/fec_test_helper.h"
17#include "modules/rtp_rtcp/source/forward_error_correction.h"
18#include "modules/rtp_rtcp/source/rtp_packet_received.h"
19#include "rtc_base/basictypes.h"
20#include "test/gmock.h"
21#include "test/gtest.h"
brandtra8b38552016-10-10 16:44:57 -070022
23namespace webrtc {
24
25namespace {
26
27using ::testing::_;
28using ::testing::Args;
29using ::testing::ElementsAreArray;
30using ::testing::Return;
31
32using test::fec::FlexfecPacketGenerator;
33using Packet = ForwardErrorCorrection::Packet;
34using PacketList = ForwardErrorCorrection::PacketList;
35
36constexpr size_t kPayloadLength = 500;
37constexpr uint32_t kFlexfecSsrc = 42984;
38constexpr uint32_t kMediaSsrc = 8353;
39
brandtrb29e6522016-12-21 06:37:18 -080040RtpPacketReceived ParsePacket(const Packet& packet) {
41 RtpPacketReceived parsed_packet;
42 EXPECT_TRUE(parsed_packet.Parse(packet.data, packet.length));
43 return parsed_packet;
44}
45
brandtra8b38552016-10-10 16:44:57 -070046} // namespace
47
nisse5c29a7a2017-02-16 06:52:32 -080048class FlexfecReceiverForTest : public FlexfecReceiver {
49 public:
50 FlexfecReceiverForTest(uint32_t ssrc,
51 uint32_t protected_media_ssrc,
52 RecoveredPacketReceiver* recovered_packet_receiver)
53 : FlexfecReceiver(ssrc, protected_media_ssrc, recovered_packet_receiver) {
54 }
55 // Expose methods for tests.
56 using FlexfecReceiver::AddReceivedPacket;
nissea5f043f2017-09-18 07:58:59 -070057 using FlexfecReceiver::ProcessReceivedPacket;
nisse5c29a7a2017-02-16 06:52:32 -080058};
59
brandtra8b38552016-10-10 16:44:57 -070060class FlexfecReceiverTest : public ::testing::Test {
61 protected:
62 FlexfecReceiverTest()
brandtr0a4c1612016-11-03 08:18:27 -070063 : receiver_(kFlexfecSsrc, kMediaSsrc, &recovered_packet_receiver_),
brandtrd726a3f2017-06-29 02:45:35 -070064 erasure_code_(
65 ForwardErrorCorrection::CreateFlexfec(kFlexfecSsrc, kMediaSsrc)),
brandtra8b38552016-10-10 16:44:57 -070066 packet_generator_(kMediaSsrc, kFlexfecSsrc) {}
67
68 // Generates |num_media_packets| corresponding to a single frame.
69 void PacketizeFrame(size_t num_media_packets,
70 size_t frame_offset,
71 PacketList* media_packets);
72
73 // Generates |num_fec_packets| FEC packets, given |media_packets|.
74 std::list<Packet*> EncodeFec(const PacketList& media_packets,
75 size_t num_fec_packets);
76
nisse5c29a7a2017-02-16 06:52:32 -080077 FlexfecReceiverForTest receiver_;
brandtra8b38552016-10-10 16:44:57 -070078 std::unique_ptr<ForwardErrorCorrection> erasure_code_;
79
80 FlexfecPacketGenerator packet_generator_;
81 testing::StrictMock<MockRecoveredPacketReceiver> recovered_packet_receiver_;
82};
83
84void FlexfecReceiverTest::PacketizeFrame(size_t num_media_packets,
85 size_t frame_offset,
86 PacketList* media_packets) {
87 packet_generator_.NewFrame(num_media_packets);
88 for (size_t i = 0; i < num_media_packets; ++i) {
89 std::unique_ptr<Packet> next_packet(
90 packet_generator_.NextPacket(frame_offset + i, kPayloadLength));
91 media_packets->push_back(std::move(next_packet));
92 }
93}
94
95std::list<Packet*> FlexfecReceiverTest::EncodeFec(
96 const PacketList& media_packets,
97 size_t num_fec_packets) {
98 const uint8_t protection_factor =
99 num_fec_packets * 255 / media_packets.size();
100 constexpr int kNumImportantPackets = 0;
101 constexpr bool kUseUnequalProtection = false;
102 constexpr FecMaskType kFecMaskType = kFecMaskRandom;
103 std::list<Packet*> fec_packets;
104 EXPECT_EQ(0, erasure_code_->EncodeFec(
105 media_packets, protection_factor, kNumImportantPackets,
106 kUseUnequalProtection, kFecMaskType, &fec_packets));
107 EXPECT_EQ(num_fec_packets, fec_packets.size());
108 return fec_packets;
109}
110
111TEST_F(FlexfecReceiverTest, ReceivesMediaPacket) {
112 packet_generator_.NewFrame(1);
113 std::unique_ptr<Packet> media_packet(
114 packet_generator_.NextPacket(0, kPayloadLength));
115
nissea5f043f2017-09-18 07:58:59 -0700116 std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet =
117 receiver_.AddReceivedPacket(ParsePacket(*media_packet));
118 ASSERT_TRUE(received_packet);
119 receiver_.ProcessReceivedPacket(*received_packet);
brandtra8b38552016-10-10 16:44:57 -0700120}
121
122TEST_F(FlexfecReceiverTest, ReceivesMediaAndFecPackets) {
123 const size_t kNumMediaPackets = 1;
124 const size_t kNumFecPackets = 1;
125
126 PacketList media_packets;
127 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
128 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
brandtrb29e6522016-12-21 06:37:18 -0800129 const auto& media_packet = media_packets.front();
brandtra8b38552016-10-10 16:44:57 -0700130 auto fec_packet = packet_generator_.BuildFlexfecPacket(*fec_packets.front());
131
nissea5f043f2017-09-18 07:58:59 -0700132 std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet =
133 receiver_.AddReceivedPacket(ParsePacket(*media_packet));
134 ASSERT_TRUE(received_packet);
135 receiver_.ProcessReceivedPacket(*received_packet);
136 received_packet = receiver_.AddReceivedPacket(ParsePacket(*fec_packet));
137 ASSERT_TRUE(received_packet);
138 receiver_.ProcessReceivedPacket(*received_packet);
brandtra8b38552016-10-10 16:44:57 -0700139}
140
141TEST_F(FlexfecReceiverTest, FailsOnTruncatedFecPacket) {
142 const size_t kNumMediaPackets = 1;
143 const size_t kNumFecPackets = 1;
144
145 PacketList media_packets;
146 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
147 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
brandtrb29e6522016-12-21 06:37:18 -0800148 const auto& media_packet = media_packets.front();
brandtra8b38552016-10-10 16:44:57 -0700149 // Simulate truncated FlexFEC payload.
150 fec_packets.front()->length = 1;
151 auto fec_packet = packet_generator_.BuildFlexfecPacket(*fec_packets.front());
152
nissea5f043f2017-09-18 07:58:59 -0700153 std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet =
154 receiver_.AddReceivedPacket(ParsePacket(*media_packet));
155 ASSERT_TRUE(received_packet);
156 receiver_.ProcessReceivedPacket(*received_packet);
nisse5c29a7a2017-02-16 06:52:32 -0800157 EXPECT_FALSE(receiver_.AddReceivedPacket(ParsePacket(*fec_packet)));
brandtra8b38552016-10-10 16:44:57 -0700158}
159
160TEST_F(FlexfecReceiverTest, FailsOnUnknownMediaSsrc) {
161 const size_t kNumMediaPackets = 1;
162
163 PacketList media_packets;
164 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
brandtrb29e6522016-12-21 06:37:18 -0800165 auto& media_packet = media_packets.front();
brandtra8b38552016-10-10 16:44:57 -0700166 // Corrupt the SSRC.
167 media_packet->data[8] = 0;
168 media_packet->data[9] = 1;
169 media_packet->data[10] = 2;
170 media_packet->data[11] = 3;
171
nisse5c29a7a2017-02-16 06:52:32 -0800172 EXPECT_FALSE(receiver_.AddReceivedPacket(ParsePacket(*media_packet)));
brandtra8b38552016-10-10 16:44:57 -0700173}
174
175TEST_F(FlexfecReceiverTest, FailsOnUnknownFecSsrc) {
176 const size_t kNumMediaPackets = 1;
177 const size_t kNumFecPackets = 1;
178
179 PacketList media_packets;
180 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
181 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
brandtrb29e6522016-12-21 06:37:18 -0800182 const auto& media_packet = media_packets.front();
brandtra8b38552016-10-10 16:44:57 -0700183 auto fec_packet = packet_generator_.BuildFlexfecPacket(*fec_packets.front());
184 // Corrupt the SSRC.
185 fec_packet->data[8] = 4;
186 fec_packet->data[9] = 5;
187 fec_packet->data[10] = 6;
188 fec_packet->data[11] = 7;
189
nissea5f043f2017-09-18 07:58:59 -0700190 std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet =
191 receiver_.AddReceivedPacket(ParsePacket(*media_packet));
192 ASSERT_TRUE(received_packet);
193 receiver_.ProcessReceivedPacket(*received_packet);
nisse5c29a7a2017-02-16 06:52:32 -0800194 EXPECT_FALSE(receiver_.AddReceivedPacket(ParsePacket(*fec_packet)));
brandtra8b38552016-10-10 16:44:57 -0700195}
196
197TEST_F(FlexfecReceiverTest, ReceivesMultiplePackets) {
198 const size_t kNumMediaPackets = 2;
199 const size_t kNumFecPackets = 1;
200
201 PacketList media_packets;
202 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
203 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
204
205 // Receive all media packets.
206 for (const auto& media_packet : media_packets) {
nissea5f043f2017-09-18 07:58:59 -0700207 std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet =
208 receiver_.AddReceivedPacket(ParsePacket(*media_packet));
209 ASSERT_TRUE(received_packet);
210 receiver_.ProcessReceivedPacket(*received_packet);
brandtra8b38552016-10-10 16:44:57 -0700211 }
212
213 // Receive FEC packet.
214 auto fec_packet = fec_packets.front();
215 std::unique_ptr<Packet> packet_with_rtp_header =
216 packet_generator_.BuildFlexfecPacket(*fec_packet);
nissea5f043f2017-09-18 07:58:59 -0700217 std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet =
218 receiver_.AddReceivedPacket(ParsePacket(*packet_with_rtp_header));
219 ASSERT_TRUE(received_packet);
220 receiver_.ProcessReceivedPacket(*received_packet);
brandtra8b38552016-10-10 16:44:57 -0700221}
222
223TEST_F(FlexfecReceiverTest, RecoversFromSingleMediaLoss) {
224 const size_t kNumMediaPackets = 2;
225 const size_t kNumFecPackets = 1;
226
227 PacketList media_packets;
228 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
229 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
230
231 // Receive first media packet but drop second.
232 auto media_it = media_packets.begin();
nisse5c29a7a2017-02-16 06:52:32 -0800233 receiver_.OnRtpPacket(ParsePacket(**media_it));
brandtra8b38552016-10-10 16:44:57 -0700234
235 // Receive FEC packet and ensure recovery of lost media packet.
236 auto fec_it = fec_packets.begin();
237 std::unique_ptr<Packet> packet_with_rtp_header =
238 packet_generator_.BuildFlexfecPacket(**fec_it);
239 media_it++;
240 EXPECT_CALL(recovered_packet_receiver_,
241 OnRecoveredPacket(_, (*media_it)->length))
242 .With(
nissed2ef3142017-05-11 08:00:58 -0700243 Args<0, 1>(ElementsAreArray((*media_it)->data, (*media_it)->length)));
nisse5c29a7a2017-02-16 06:52:32 -0800244 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700245}
246
247TEST_F(FlexfecReceiverTest, RecoversFromDoubleMediaLoss) {
248 const size_t kNumMediaPackets = 2;
249 const size_t kNumFecPackets = 2;
250
251 PacketList media_packets;
252 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
253 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
254
255 // Drop both media packets.
256
257 // Receive first FEC packet and recover first lost media packet.
258 auto fec_it = fec_packets.begin();
259 std::unique_ptr<Packet> packet_with_rtp_header =
260 packet_generator_.BuildFlexfecPacket(**fec_it);
261 auto media_it = media_packets.begin();
262 EXPECT_CALL(recovered_packet_receiver_,
263 OnRecoveredPacket(_, (*media_it)->length))
264 .With(
nissed2ef3142017-05-11 08:00:58 -0700265 Args<0, 1>(ElementsAreArray((*media_it)->data, (*media_it)->length)));
nisse5c29a7a2017-02-16 06:52:32 -0800266 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700267
268 // Receive second FEC packet and recover second lost media packet.
269 fec_it++;
270 packet_with_rtp_header = packet_generator_.BuildFlexfecPacket(**fec_it);
271 media_it++;
272 EXPECT_CALL(recovered_packet_receiver_,
273 OnRecoveredPacket(_, (*media_it)->length))
274 .With(
nissed2ef3142017-05-11 08:00:58 -0700275 Args<0, 1>(ElementsAreArray((*media_it)->data, (*media_it)->length)));
nisse5c29a7a2017-02-16 06:52:32 -0800276 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700277}
278
279TEST_F(FlexfecReceiverTest, DoesNotRecoverFromMediaAndFecLoss) {
280 const size_t kNumMediaPackets = 2;
281 const size_t kNumFecPackets = 1;
282
283 PacketList media_packets;
284 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
285 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
286
287 // Receive first media packet.
288 auto media_it = media_packets.begin();
nisse5c29a7a2017-02-16 06:52:32 -0800289 receiver_.OnRtpPacket(ParsePacket(**media_it));
brandtra8b38552016-10-10 16:44:57 -0700290
291 // Drop second media packet and FEC packet. Do not expect call back.
292}
293
294TEST_F(FlexfecReceiverTest, DoesNotCallbackTwice) {
295 const size_t kNumMediaPackets = 2;
296 const size_t kNumFecPackets = 1;
297
298 PacketList media_packets;
299 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
300 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
301
302 // Receive first media packet but drop second.
303 auto media_it = media_packets.begin();
nisse5c29a7a2017-02-16 06:52:32 -0800304 receiver_.OnRtpPacket(ParsePacket(**media_it));
brandtra8b38552016-10-10 16:44:57 -0700305
306 // Receive FEC packet and ensure recovery of lost media packet.
307 auto fec_it = fec_packets.begin();
308 std::unique_ptr<Packet> packet_with_rtp_header =
309 packet_generator_.BuildFlexfecPacket(**fec_it);
310 media_it++;
311 EXPECT_CALL(recovered_packet_receiver_,
312 OnRecoveredPacket(_, (*media_it)->length))
313 .With(
nissed2ef3142017-05-11 08:00:58 -0700314 Args<0, 1>(ElementsAreArray((*media_it)->data, (*media_it)->length)));
nisse5c29a7a2017-02-16 06:52:32 -0800315 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700316
brandtrf27c5b82017-05-23 08:38:43 -0700317 // Receive the FEC packet again, but do not call back.
nisse5c29a7a2017-02-16 06:52:32 -0800318 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700319
brandtrf27c5b82017-05-23 08:38:43 -0700320 // Receive the first media packet again, but do not call back.
321 media_it = media_packets.begin();
322 receiver_.OnRtpPacket(ParsePacket(**media_it));
323
324 // Receive the second media packet again (the one recovered above),
325 // but do not call back again.
326 media_it++;
327 receiver_.OnRtpPacket(ParsePacket(**media_it));
brandtra8b38552016-10-10 16:44:57 -0700328}
329
330// Here we are implicitly assuming packet masks that are suitable for
331// this type of 50% correlated loss. If we are changing our precomputed
332// packet masks, this test might need to be updated.
333TEST_F(FlexfecReceiverTest, RecoversFrom50PercentLoss) {
334 const size_t kNumFecPackets = 5;
335 const size_t kNumFrames = 2 * kNumFecPackets;
336 const size_t kNumMediaPacketsPerFrame = 1;
337
338 PacketList media_packets;
339 for (size_t i = 0; i < kNumFrames; ++i) {
340 PacketizeFrame(kNumMediaPacketsPerFrame, i, &media_packets);
341 }
342 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
343
344 // Drop every second media packet.
345 auto media_it = media_packets.begin();
346 while (media_it != media_packets.end()) {
nisse5c29a7a2017-02-16 06:52:32 -0800347 receiver_.OnRtpPacket(ParsePacket(**media_it));
brandtra8b38552016-10-10 16:44:57 -0700348 ++media_it;
349 if (media_it == media_packets.end()) {
350 break;
351 }
352 ++media_it;
353 }
354
355 // Receive all FEC packets.
356 media_it = media_packets.begin();
357 for (const auto& fec_packet : fec_packets) {
358 std::unique_ptr<Packet> fec_packet_with_rtp_header =
359 packet_generator_.BuildFlexfecPacket(*fec_packet);
360 ++media_it;
361 if (media_it == media_packets.end()) {
362 break;
363 }
364 EXPECT_CALL(recovered_packet_receiver_,
365 OnRecoveredPacket(_, (*media_it)->length))
366 .With(Args<0, 1>(
nissed2ef3142017-05-11 08:00:58 -0700367 ElementsAreArray((*media_it)->data, (*media_it)->length)));
nisse5c29a7a2017-02-16 06:52:32 -0800368 receiver_.OnRtpPacket(ParsePacket(*fec_packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700369 ++media_it;
370 }
371}
372
373TEST_F(FlexfecReceiverTest, DelayedFecPacketDoesHelp) {
374 // These values need to be updated if the underlying erasure code
375 // implementation changes.
376 const size_t kNumFrames = 48;
377 const size_t kNumMediaPacketsPerFrame = 1;
378 const size_t kNumFecPackets = 1;
379
380 PacketList media_packets;
381 PacketizeFrame(kNumMediaPacketsPerFrame, 0, &media_packets);
382 PacketizeFrame(kNumMediaPacketsPerFrame, 1, &media_packets);
383 // Protect two first frames.
384 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
385 for (size_t i = 2; i < kNumFrames; ++i) {
386 PacketizeFrame(kNumMediaPacketsPerFrame, i, &media_packets);
387 }
388
389 // Drop first media packet and delay FEC packet.
390 auto media_it = media_packets.begin();
391 ++media_it;
392
393 // Receive all other media packets.
394 while (media_it != media_packets.end()) {
nisse5c29a7a2017-02-16 06:52:32 -0800395 receiver_.OnRtpPacket(ParsePacket(**media_it));
brandtra8b38552016-10-10 16:44:57 -0700396 ++media_it;
397 }
398
399 // Receive FEC packet and recover first media packet.
400 auto fec_it = fec_packets.begin();
401 std::unique_ptr<Packet> packet_with_rtp_header =
402 packet_generator_.BuildFlexfecPacket(**fec_it);
403 media_it = media_packets.begin();
404 EXPECT_CALL(recovered_packet_receiver_,
405 OnRecoveredPacket(_, (*media_it)->length))
406 .With(
nissed2ef3142017-05-11 08:00:58 -0700407 Args<0, 1>(ElementsAreArray((*media_it)->data, (*media_it)->length)));
nisse5c29a7a2017-02-16 06:52:32 -0800408 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700409}
410
411TEST_F(FlexfecReceiverTest, TooDelayedFecPacketDoesNotHelp) {
412 // These values need to be updated if the underlying erasure code
413 // implementation changes.
414 const size_t kNumFrames = 49;
415 const size_t kNumMediaPacketsPerFrame = 1;
416 const size_t kNumFecPackets = 1;
417
418 PacketList media_packets;
419 PacketizeFrame(kNumMediaPacketsPerFrame, 0, &media_packets);
420 PacketizeFrame(kNumMediaPacketsPerFrame, 1, &media_packets);
421 // Protect two first frames.
422 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
423 for (size_t i = 2; i < kNumFrames; ++i) {
424 PacketizeFrame(kNumMediaPacketsPerFrame, i, &media_packets);
425 }
426
427 // Drop first media packet and delay FEC packet.
428 auto media_it = media_packets.begin();
429 ++media_it;
430
431 // Receive all other media packets.
432 while (media_it != media_packets.end()) {
nisse5c29a7a2017-02-16 06:52:32 -0800433 receiver_.OnRtpPacket(ParsePacket(**media_it));
brandtra8b38552016-10-10 16:44:57 -0700434 ++media_it;
435 }
436
437 // Receive FEC packet.
438 auto fec_it = fec_packets.begin();
439 std::unique_ptr<Packet> packet_with_rtp_header =
440 packet_generator_.BuildFlexfecPacket(**fec_it);
nisse5c29a7a2017-02-16 06:52:32 -0800441 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700442
443 // Do not expect a call back.
444}
445
446TEST_F(FlexfecReceiverTest, RecoversWithMediaPacketsOutOfOrder) {
447 const size_t kNumMediaPackets = 6;
448 const size_t kNumFecPackets = 2;
449
450 PacketList media_packets;
451 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
452 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
453
454 // Lose two media packets, and receive the others out of order.
455 auto media_it = media_packets.begin();
456 auto media_packet0 = media_it++;
457 auto media_packet1 = media_it++;
458 auto media_packet2 = media_it++;
459 auto media_packet3 = media_it++;
460 auto media_packet4 = media_it++;
461 auto media_packet5 = media_it++;
nisse5c29a7a2017-02-16 06:52:32 -0800462 receiver_.OnRtpPacket(ParsePacket(**media_packet5));
463 receiver_.OnRtpPacket(ParsePacket(**media_packet2));
464 receiver_.OnRtpPacket(ParsePacket(**media_packet3));
465 receiver_.OnRtpPacket(ParsePacket(**media_packet0));
brandtra8b38552016-10-10 16:44:57 -0700466
467 // Expect to recover lost media packets.
468 EXPECT_CALL(recovered_packet_receiver_,
469 OnRecoveredPacket(_, (*media_packet1)->length))
470 .With(Args<0, 1>(
nissed2ef3142017-05-11 08:00:58 -0700471 ElementsAreArray((*media_packet1)->data, (*media_packet1)->length)));
brandtra8b38552016-10-10 16:44:57 -0700472 EXPECT_CALL(recovered_packet_receiver_,
473 OnRecoveredPacket(_, (*media_packet4)->length))
474 .With(Args<0, 1>(
nissed2ef3142017-05-11 08:00:58 -0700475 ElementsAreArray((*media_packet4)->data, (*media_packet4)->length)));
brandtra8b38552016-10-10 16:44:57 -0700476
477 // Add FEC packets.
478 auto fec_it = fec_packets.begin();
479 std::unique_ptr<Packet> packet_with_rtp_header;
480 while (fec_it != fec_packets.end()) {
481 packet_with_rtp_header = packet_generator_.BuildFlexfecPacket(**fec_it);
nisse5c29a7a2017-02-16 06:52:32 -0800482 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700483 ++fec_it;
484 }
485}
486
brandtrf27c5b82017-05-23 08:38:43 -0700487// Recovered media packets may be fed back into the FlexfecReceiver by the
488// callback. This test ensures the idempotency of such a situation.
489TEST_F(FlexfecReceiverTest, RecoveryCallbackDoesNotLoopInfinitely) {
490 class LoopbackRecoveredPacketReceiver : public RecoveredPacketReceiver {
491 public:
492 const int kMaxRecursionDepth = 10;
493
494 LoopbackRecoveredPacketReceiver()
495 : receiver_(nullptr),
496 did_receive_call_back_(false),
497 recursion_depth_(0),
498 deep_recursion_(false) {}
499
500 void SetReceiver(FlexfecReceiver* receiver) { receiver_ = receiver; }
501 bool DidReceiveCallback() const { return did_receive_call_back_; }
502 bool DeepRecursion() const { return deep_recursion_; }
503
504 // Implements RecoveredPacketReceiver.
505 void OnRecoveredPacket(const uint8_t* packet, size_t length) {
506 RtpPacketReceived parsed_packet;
507 EXPECT_TRUE(parsed_packet.Parse(packet, length));
508
509 did_receive_call_back_ = true;
510
511 if (recursion_depth_ > kMaxRecursionDepth) {
512 deep_recursion_ = true;
513 return;
514 }
515 ++recursion_depth_;
516 RTC_DCHECK(receiver_);
517 receiver_->OnRtpPacket(parsed_packet);
518 --recursion_depth_;
519 }
520
521 private:
522 FlexfecReceiver* receiver_;
523 bool did_receive_call_back_;
524 int recursion_depth_;
525 bool deep_recursion_;
526 } loopback_recovered_packet_receiver;
527
528 // Feed recovered packets back into |receiver|.
529 FlexfecReceiver receiver(kFlexfecSsrc, kMediaSsrc,
530 &loopback_recovered_packet_receiver);
531 loopback_recovered_packet_receiver.SetReceiver(&receiver);
532
533 const size_t kNumMediaPackets = 2;
534 const size_t kNumFecPackets = 1;
535
536 PacketList media_packets;
537 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
538 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
539
540 // Receive first media packet but drop second.
541 auto media_it = media_packets.begin();
542 receiver.OnRtpPacket(ParsePacket(**media_it));
543
544 // Receive FEC packet and verify that a packet was recovered.
545 auto fec_it = fec_packets.begin();
546 std::unique_ptr<Packet> packet_with_rtp_header =
547 packet_generator_.BuildFlexfecPacket(**fec_it);
548 receiver.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
549 EXPECT_TRUE(loopback_recovered_packet_receiver.DidReceiveCallback());
550 EXPECT_FALSE(loopback_recovered_packet_receiver.DeepRecursion());
551}
552
brandtra8b38552016-10-10 16:44:57 -0700553TEST_F(FlexfecReceiverTest, CalculatesNumberOfPackets) {
554 const size_t kNumMediaPackets = 2;
555 const size_t kNumFecPackets = 1;
556
557 PacketList media_packets;
558 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
559 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
560
561 // Receive first media packet but drop second.
562 auto media_it = media_packets.begin();
nisse5c29a7a2017-02-16 06:52:32 -0800563 receiver_.OnRtpPacket(ParsePacket(**media_it));
brandtra8b38552016-10-10 16:44:57 -0700564
565 // Receive FEC packet and ensure recovery of lost media packet.
566 auto fec_it = fec_packets.begin();
567 std::unique_ptr<Packet> packet_with_rtp_header =
568 packet_generator_.BuildFlexfecPacket(**fec_it);
569 media_it++;
570 EXPECT_CALL(recovered_packet_receiver_,
571 OnRecoveredPacket(_, (*media_it)->length))
572 .With(
nissed2ef3142017-05-11 08:00:58 -0700573 Args<0, 1>(ElementsAreArray((*media_it)->data, (*media_it)->length)));
nisse5c29a7a2017-02-16 06:52:32 -0800574 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700575
576 // Check stats calculations.
brandtr0a4c1612016-11-03 08:18:27 -0700577 FecPacketCounter packet_counter = receiver_.GetPacketCounter();
brandtra8b38552016-10-10 16:44:57 -0700578 EXPECT_EQ(2U, packet_counter.num_packets);
579 EXPECT_EQ(1U, packet_counter.num_fec_packets);
580 EXPECT_EQ(1U, packet_counter.num_recovered_packets);
581}
582
583} // namespace webrtc