blob: ae2ec1dca53a1a7737532a9b3344e6cbe2690af4 [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;
57 using FlexfecReceiver::ProcessReceivedPackets;
58};
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
nisse5c29a7a2017-02-16 06:52:32 -0800116 EXPECT_TRUE(receiver_.AddReceivedPacket(ParsePacket(*media_packet)));
117 EXPECT_TRUE(receiver_.ProcessReceivedPackets());
brandtra8b38552016-10-10 16:44:57 -0700118}
119
120TEST_F(FlexfecReceiverTest, ReceivesMediaAndFecPackets) {
121 const size_t kNumMediaPackets = 1;
122 const size_t kNumFecPackets = 1;
123
124 PacketList media_packets;
125 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
126 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
brandtrb29e6522016-12-21 06:37:18 -0800127 const auto& media_packet = media_packets.front();
brandtra8b38552016-10-10 16:44:57 -0700128 auto fec_packet = packet_generator_.BuildFlexfecPacket(*fec_packets.front());
129
nisse5c29a7a2017-02-16 06:52:32 -0800130 EXPECT_TRUE(receiver_.AddReceivedPacket(ParsePacket(*media_packet)));
131 EXPECT_TRUE(receiver_.ProcessReceivedPackets());
132 EXPECT_TRUE(receiver_.AddReceivedPacket(ParsePacket(*fec_packet)));
133 EXPECT_TRUE(receiver_.ProcessReceivedPackets());
brandtra8b38552016-10-10 16:44:57 -0700134}
135
136TEST_F(FlexfecReceiverTest, FailsOnTruncatedFecPacket) {
137 const size_t kNumMediaPackets = 1;
138 const size_t kNumFecPackets = 1;
139
140 PacketList media_packets;
141 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
142 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
brandtrb29e6522016-12-21 06:37:18 -0800143 const auto& media_packet = media_packets.front();
brandtra8b38552016-10-10 16:44:57 -0700144 // Simulate truncated FlexFEC payload.
145 fec_packets.front()->length = 1;
146 auto fec_packet = packet_generator_.BuildFlexfecPacket(*fec_packets.front());
147
nisse5c29a7a2017-02-16 06:52:32 -0800148 EXPECT_TRUE(receiver_.AddReceivedPacket(ParsePacket(*media_packet)));
149 EXPECT_TRUE(receiver_.ProcessReceivedPackets());
150 EXPECT_FALSE(receiver_.AddReceivedPacket(ParsePacket(*fec_packet)));
brandtra8b38552016-10-10 16:44:57 -0700151}
152
153TEST_F(FlexfecReceiverTest, FailsOnUnknownMediaSsrc) {
154 const size_t kNumMediaPackets = 1;
155
156 PacketList media_packets;
157 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
brandtrb29e6522016-12-21 06:37:18 -0800158 auto& media_packet = media_packets.front();
brandtra8b38552016-10-10 16:44:57 -0700159 // Corrupt the SSRC.
160 media_packet->data[8] = 0;
161 media_packet->data[9] = 1;
162 media_packet->data[10] = 2;
163 media_packet->data[11] = 3;
164
nisse5c29a7a2017-02-16 06:52:32 -0800165 EXPECT_FALSE(receiver_.AddReceivedPacket(ParsePacket(*media_packet)));
brandtra8b38552016-10-10 16:44:57 -0700166}
167
168TEST_F(FlexfecReceiverTest, FailsOnUnknownFecSsrc) {
169 const size_t kNumMediaPackets = 1;
170 const size_t kNumFecPackets = 1;
171
172 PacketList media_packets;
173 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
174 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
brandtrb29e6522016-12-21 06:37:18 -0800175 const auto& media_packet = media_packets.front();
brandtra8b38552016-10-10 16:44:57 -0700176 auto fec_packet = packet_generator_.BuildFlexfecPacket(*fec_packets.front());
177 // Corrupt the SSRC.
178 fec_packet->data[8] = 4;
179 fec_packet->data[9] = 5;
180 fec_packet->data[10] = 6;
181 fec_packet->data[11] = 7;
182
nisse5c29a7a2017-02-16 06:52:32 -0800183 EXPECT_TRUE(receiver_.AddReceivedPacket(ParsePacket(*media_packet)));
184 EXPECT_TRUE(receiver_.ProcessReceivedPackets());
185 EXPECT_FALSE(receiver_.AddReceivedPacket(ParsePacket(*fec_packet)));
brandtra8b38552016-10-10 16:44:57 -0700186}
187
188TEST_F(FlexfecReceiverTest, ReceivesMultiplePackets) {
189 const size_t kNumMediaPackets = 2;
190 const size_t kNumFecPackets = 1;
191
192 PacketList media_packets;
193 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
194 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
195
196 // Receive all media packets.
197 for (const auto& media_packet : media_packets) {
nisse5c29a7a2017-02-16 06:52:32 -0800198 EXPECT_TRUE(receiver_.AddReceivedPacket(ParsePacket(*media_packet)));
199 EXPECT_TRUE(receiver_.ProcessReceivedPackets());
brandtra8b38552016-10-10 16:44:57 -0700200 }
201
202 // Receive FEC packet.
203 auto fec_packet = fec_packets.front();
204 std::unique_ptr<Packet> packet_with_rtp_header =
205 packet_generator_.BuildFlexfecPacket(*fec_packet);
nisse5c29a7a2017-02-16 06:52:32 -0800206 EXPECT_TRUE(
207 receiver_.AddReceivedPacket(ParsePacket(*packet_with_rtp_header)));
208 EXPECT_TRUE(receiver_.ProcessReceivedPackets());
brandtra8b38552016-10-10 16:44:57 -0700209}
210
211TEST_F(FlexfecReceiverTest, RecoversFromSingleMediaLoss) {
212 const size_t kNumMediaPackets = 2;
213 const size_t kNumFecPackets = 1;
214
215 PacketList media_packets;
216 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
217 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
218
219 // Receive first media packet but drop second.
220 auto media_it = media_packets.begin();
nisse5c29a7a2017-02-16 06:52:32 -0800221 receiver_.OnRtpPacket(ParsePacket(**media_it));
brandtra8b38552016-10-10 16:44:57 -0700222
223 // Receive FEC packet and ensure recovery of lost media packet.
224 auto fec_it = fec_packets.begin();
225 std::unique_ptr<Packet> packet_with_rtp_header =
226 packet_generator_.BuildFlexfecPacket(**fec_it);
227 media_it++;
228 EXPECT_CALL(recovered_packet_receiver_,
229 OnRecoveredPacket(_, (*media_it)->length))
230 .With(
nissed2ef3142017-05-11 08:00:58 -0700231 Args<0, 1>(ElementsAreArray((*media_it)->data, (*media_it)->length)));
nisse5c29a7a2017-02-16 06:52:32 -0800232 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700233}
234
235TEST_F(FlexfecReceiverTest, RecoversFromDoubleMediaLoss) {
236 const size_t kNumMediaPackets = 2;
237 const size_t kNumFecPackets = 2;
238
239 PacketList media_packets;
240 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
241 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
242
243 // Drop both media packets.
244
245 // Receive first FEC packet and recover first lost media packet.
246 auto fec_it = fec_packets.begin();
247 std::unique_ptr<Packet> packet_with_rtp_header =
248 packet_generator_.BuildFlexfecPacket(**fec_it);
249 auto media_it = media_packets.begin();
250 EXPECT_CALL(recovered_packet_receiver_,
251 OnRecoveredPacket(_, (*media_it)->length))
252 .With(
nissed2ef3142017-05-11 08:00:58 -0700253 Args<0, 1>(ElementsAreArray((*media_it)->data, (*media_it)->length)));
nisse5c29a7a2017-02-16 06:52:32 -0800254 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700255
256 // Receive second FEC packet and recover second lost media packet.
257 fec_it++;
258 packet_with_rtp_header = packet_generator_.BuildFlexfecPacket(**fec_it);
259 media_it++;
260 EXPECT_CALL(recovered_packet_receiver_,
261 OnRecoveredPacket(_, (*media_it)->length))
262 .With(
nissed2ef3142017-05-11 08:00:58 -0700263 Args<0, 1>(ElementsAreArray((*media_it)->data, (*media_it)->length)));
nisse5c29a7a2017-02-16 06:52:32 -0800264 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700265}
266
267TEST_F(FlexfecReceiverTest, DoesNotRecoverFromMediaAndFecLoss) {
268 const size_t kNumMediaPackets = 2;
269 const size_t kNumFecPackets = 1;
270
271 PacketList media_packets;
272 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
273 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
274
275 // Receive first media packet.
276 auto media_it = media_packets.begin();
nisse5c29a7a2017-02-16 06:52:32 -0800277 receiver_.OnRtpPacket(ParsePacket(**media_it));
brandtra8b38552016-10-10 16:44:57 -0700278
279 // Drop second media packet and FEC packet. Do not expect call back.
280}
281
282TEST_F(FlexfecReceiverTest, DoesNotCallbackTwice) {
283 const size_t kNumMediaPackets = 2;
284 const size_t kNumFecPackets = 1;
285
286 PacketList media_packets;
287 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
288 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
289
290 // Receive first media packet but drop second.
291 auto media_it = media_packets.begin();
nisse5c29a7a2017-02-16 06:52:32 -0800292 receiver_.OnRtpPacket(ParsePacket(**media_it));
brandtra8b38552016-10-10 16:44:57 -0700293
294 // Receive FEC packet and ensure recovery of lost media packet.
295 auto fec_it = fec_packets.begin();
296 std::unique_ptr<Packet> packet_with_rtp_header =
297 packet_generator_.BuildFlexfecPacket(**fec_it);
298 media_it++;
299 EXPECT_CALL(recovered_packet_receiver_,
300 OnRecoveredPacket(_, (*media_it)->length))
301 .With(
nissed2ef3142017-05-11 08:00:58 -0700302 Args<0, 1>(ElementsAreArray((*media_it)->data, (*media_it)->length)));
nisse5c29a7a2017-02-16 06:52:32 -0800303 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700304
brandtrf27c5b82017-05-23 08:38:43 -0700305 // Receive the FEC packet again, but do not call back.
nisse5c29a7a2017-02-16 06:52:32 -0800306 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700307
brandtrf27c5b82017-05-23 08:38:43 -0700308 // Receive the first media packet again, but do not call back.
309 media_it = media_packets.begin();
310 receiver_.OnRtpPacket(ParsePacket(**media_it));
311
312 // Receive the second media packet again (the one recovered above),
313 // but do not call back again.
314 media_it++;
315 receiver_.OnRtpPacket(ParsePacket(**media_it));
brandtra8b38552016-10-10 16:44:57 -0700316}
317
318// Here we are implicitly assuming packet masks that are suitable for
319// this type of 50% correlated loss. If we are changing our precomputed
320// packet masks, this test might need to be updated.
321TEST_F(FlexfecReceiverTest, RecoversFrom50PercentLoss) {
322 const size_t kNumFecPackets = 5;
323 const size_t kNumFrames = 2 * kNumFecPackets;
324 const size_t kNumMediaPacketsPerFrame = 1;
325
326 PacketList media_packets;
327 for (size_t i = 0; i < kNumFrames; ++i) {
328 PacketizeFrame(kNumMediaPacketsPerFrame, i, &media_packets);
329 }
330 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
331
332 // Drop every second media packet.
333 auto media_it = media_packets.begin();
334 while (media_it != media_packets.end()) {
nisse5c29a7a2017-02-16 06:52:32 -0800335 receiver_.OnRtpPacket(ParsePacket(**media_it));
brandtra8b38552016-10-10 16:44:57 -0700336 ++media_it;
337 if (media_it == media_packets.end()) {
338 break;
339 }
340 ++media_it;
341 }
342
343 // Receive all FEC packets.
344 media_it = media_packets.begin();
345 for (const auto& fec_packet : fec_packets) {
346 std::unique_ptr<Packet> fec_packet_with_rtp_header =
347 packet_generator_.BuildFlexfecPacket(*fec_packet);
348 ++media_it;
349 if (media_it == media_packets.end()) {
350 break;
351 }
352 EXPECT_CALL(recovered_packet_receiver_,
353 OnRecoveredPacket(_, (*media_it)->length))
354 .With(Args<0, 1>(
nissed2ef3142017-05-11 08:00:58 -0700355 ElementsAreArray((*media_it)->data, (*media_it)->length)));
nisse5c29a7a2017-02-16 06:52:32 -0800356 receiver_.OnRtpPacket(ParsePacket(*fec_packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700357 ++media_it;
358 }
359}
360
361TEST_F(FlexfecReceiverTest, DelayedFecPacketDoesHelp) {
362 // These values need to be updated if the underlying erasure code
363 // implementation changes.
364 const size_t kNumFrames = 48;
365 const size_t kNumMediaPacketsPerFrame = 1;
366 const size_t kNumFecPackets = 1;
367
368 PacketList media_packets;
369 PacketizeFrame(kNumMediaPacketsPerFrame, 0, &media_packets);
370 PacketizeFrame(kNumMediaPacketsPerFrame, 1, &media_packets);
371 // Protect two first frames.
372 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
373 for (size_t i = 2; i < kNumFrames; ++i) {
374 PacketizeFrame(kNumMediaPacketsPerFrame, i, &media_packets);
375 }
376
377 // Drop first media packet and delay FEC packet.
378 auto media_it = media_packets.begin();
379 ++media_it;
380
381 // Receive all other media packets.
382 while (media_it != media_packets.end()) {
nisse5c29a7a2017-02-16 06:52:32 -0800383 receiver_.OnRtpPacket(ParsePacket(**media_it));
brandtra8b38552016-10-10 16:44:57 -0700384 ++media_it;
385 }
386
387 // Receive FEC packet and recover first media packet.
388 auto fec_it = fec_packets.begin();
389 std::unique_ptr<Packet> packet_with_rtp_header =
390 packet_generator_.BuildFlexfecPacket(**fec_it);
391 media_it = media_packets.begin();
392 EXPECT_CALL(recovered_packet_receiver_,
393 OnRecoveredPacket(_, (*media_it)->length))
394 .With(
nissed2ef3142017-05-11 08:00:58 -0700395 Args<0, 1>(ElementsAreArray((*media_it)->data, (*media_it)->length)));
nisse5c29a7a2017-02-16 06:52:32 -0800396 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700397}
398
399TEST_F(FlexfecReceiverTest, TooDelayedFecPacketDoesNotHelp) {
400 // These values need to be updated if the underlying erasure code
401 // implementation changes.
402 const size_t kNumFrames = 49;
403 const size_t kNumMediaPacketsPerFrame = 1;
404 const size_t kNumFecPackets = 1;
405
406 PacketList media_packets;
407 PacketizeFrame(kNumMediaPacketsPerFrame, 0, &media_packets);
408 PacketizeFrame(kNumMediaPacketsPerFrame, 1, &media_packets);
409 // Protect two first frames.
410 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
411 for (size_t i = 2; i < kNumFrames; ++i) {
412 PacketizeFrame(kNumMediaPacketsPerFrame, i, &media_packets);
413 }
414
415 // Drop first media packet and delay FEC packet.
416 auto media_it = media_packets.begin();
417 ++media_it;
418
419 // Receive all other media packets.
420 while (media_it != media_packets.end()) {
nisse5c29a7a2017-02-16 06:52:32 -0800421 receiver_.OnRtpPacket(ParsePacket(**media_it));
brandtra8b38552016-10-10 16:44:57 -0700422 ++media_it;
423 }
424
425 // Receive FEC packet.
426 auto fec_it = fec_packets.begin();
427 std::unique_ptr<Packet> packet_with_rtp_header =
428 packet_generator_.BuildFlexfecPacket(**fec_it);
nisse5c29a7a2017-02-16 06:52:32 -0800429 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700430
431 // Do not expect a call back.
432}
433
434TEST_F(FlexfecReceiverTest, RecoversWithMediaPacketsOutOfOrder) {
435 const size_t kNumMediaPackets = 6;
436 const size_t kNumFecPackets = 2;
437
438 PacketList media_packets;
439 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
440 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
441
442 // Lose two media packets, and receive the others out of order.
443 auto media_it = media_packets.begin();
444 auto media_packet0 = media_it++;
445 auto media_packet1 = media_it++;
446 auto media_packet2 = media_it++;
447 auto media_packet3 = media_it++;
448 auto media_packet4 = media_it++;
449 auto media_packet5 = media_it++;
nisse5c29a7a2017-02-16 06:52:32 -0800450 receiver_.OnRtpPacket(ParsePacket(**media_packet5));
451 receiver_.OnRtpPacket(ParsePacket(**media_packet2));
452 receiver_.OnRtpPacket(ParsePacket(**media_packet3));
453 receiver_.OnRtpPacket(ParsePacket(**media_packet0));
brandtra8b38552016-10-10 16:44:57 -0700454
455 // Expect to recover lost media packets.
456 EXPECT_CALL(recovered_packet_receiver_,
457 OnRecoveredPacket(_, (*media_packet1)->length))
458 .With(Args<0, 1>(
nissed2ef3142017-05-11 08:00:58 -0700459 ElementsAreArray((*media_packet1)->data, (*media_packet1)->length)));
brandtra8b38552016-10-10 16:44:57 -0700460 EXPECT_CALL(recovered_packet_receiver_,
461 OnRecoveredPacket(_, (*media_packet4)->length))
462 .With(Args<0, 1>(
nissed2ef3142017-05-11 08:00:58 -0700463 ElementsAreArray((*media_packet4)->data, (*media_packet4)->length)));
brandtra8b38552016-10-10 16:44:57 -0700464
465 // Add FEC packets.
466 auto fec_it = fec_packets.begin();
467 std::unique_ptr<Packet> packet_with_rtp_header;
468 while (fec_it != fec_packets.end()) {
469 packet_with_rtp_header = packet_generator_.BuildFlexfecPacket(**fec_it);
nisse5c29a7a2017-02-16 06:52:32 -0800470 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700471 ++fec_it;
472 }
473}
474
brandtrf27c5b82017-05-23 08:38:43 -0700475// Recovered media packets may be fed back into the FlexfecReceiver by the
476// callback. This test ensures the idempotency of such a situation.
477TEST_F(FlexfecReceiverTest, RecoveryCallbackDoesNotLoopInfinitely) {
478 class LoopbackRecoveredPacketReceiver : public RecoveredPacketReceiver {
479 public:
480 const int kMaxRecursionDepth = 10;
481
482 LoopbackRecoveredPacketReceiver()
483 : receiver_(nullptr),
484 did_receive_call_back_(false),
485 recursion_depth_(0),
486 deep_recursion_(false) {}
487
488 void SetReceiver(FlexfecReceiver* receiver) { receiver_ = receiver; }
489 bool DidReceiveCallback() const { return did_receive_call_back_; }
490 bool DeepRecursion() const { return deep_recursion_; }
491
492 // Implements RecoveredPacketReceiver.
493 void OnRecoveredPacket(const uint8_t* packet, size_t length) {
494 RtpPacketReceived parsed_packet;
495 EXPECT_TRUE(parsed_packet.Parse(packet, length));
496
497 did_receive_call_back_ = true;
498
499 if (recursion_depth_ > kMaxRecursionDepth) {
500 deep_recursion_ = true;
501 return;
502 }
503 ++recursion_depth_;
504 RTC_DCHECK(receiver_);
505 receiver_->OnRtpPacket(parsed_packet);
506 --recursion_depth_;
507 }
508
509 private:
510 FlexfecReceiver* receiver_;
511 bool did_receive_call_back_;
512 int recursion_depth_;
513 bool deep_recursion_;
514 } loopback_recovered_packet_receiver;
515
516 // Feed recovered packets back into |receiver|.
517 FlexfecReceiver receiver(kFlexfecSsrc, kMediaSsrc,
518 &loopback_recovered_packet_receiver);
519 loopback_recovered_packet_receiver.SetReceiver(&receiver);
520
521 const size_t kNumMediaPackets = 2;
522 const size_t kNumFecPackets = 1;
523
524 PacketList media_packets;
525 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
526 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
527
528 // Receive first media packet but drop second.
529 auto media_it = media_packets.begin();
530 receiver.OnRtpPacket(ParsePacket(**media_it));
531
532 // Receive FEC packet and verify that a packet was recovered.
533 auto fec_it = fec_packets.begin();
534 std::unique_ptr<Packet> packet_with_rtp_header =
535 packet_generator_.BuildFlexfecPacket(**fec_it);
536 receiver.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
537 EXPECT_TRUE(loopback_recovered_packet_receiver.DidReceiveCallback());
538 EXPECT_FALSE(loopback_recovered_packet_receiver.DeepRecursion());
539}
540
brandtra8b38552016-10-10 16:44:57 -0700541TEST_F(FlexfecReceiverTest, CalculatesNumberOfPackets) {
542 const size_t kNumMediaPackets = 2;
543 const size_t kNumFecPackets = 1;
544
545 PacketList media_packets;
546 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
547 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
548
549 // Receive first media packet but drop second.
550 auto media_it = media_packets.begin();
nisse5c29a7a2017-02-16 06:52:32 -0800551 receiver_.OnRtpPacket(ParsePacket(**media_it));
brandtra8b38552016-10-10 16:44:57 -0700552
553 // Receive FEC packet and ensure recovery of lost media packet.
554 auto fec_it = fec_packets.begin();
555 std::unique_ptr<Packet> packet_with_rtp_header =
556 packet_generator_.BuildFlexfecPacket(**fec_it);
557 media_it++;
558 EXPECT_CALL(recovered_packet_receiver_,
559 OnRecoveredPacket(_, (*media_it)->length))
560 .With(
nissed2ef3142017-05-11 08:00:58 -0700561 Args<0, 1>(ElementsAreArray((*media_it)->data, (*media_it)->length)));
nisse5c29a7a2017-02-16 06:52:32 -0800562 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700563
564 // Check stats calculations.
brandtr0a4c1612016-11-03 08:18:27 -0700565 FecPacketCounter packet_counter = receiver_.GetPacketCounter();
brandtra8b38552016-10-10 16:44:57 -0700566 EXPECT_EQ(2U, packet_counter.num_packets);
567 EXPECT_EQ(1U, packet_counter.num_fec_packets);
568 EXPECT_EQ(1U, packet_counter.num_recovered_packets);
569}
570
571} // namespace webrtc