blob: 378cf7d6dff61a23af4db48a117fab339b8fa29f [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"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "test/gmock.h"
20#include "test/gtest.h"
brandtra8b38552016-10-10 16:44:57 -070021
22namespace webrtc {
23
24namespace {
25
26using ::testing::_;
27using ::testing::Args;
28using ::testing::ElementsAreArray;
29using ::testing::Return;
30
31using test::fec::FlexfecPacketGenerator;
32using Packet = ForwardErrorCorrection::Packet;
33using PacketList = ForwardErrorCorrection::PacketList;
34
35constexpr size_t kPayloadLength = 500;
36constexpr uint32_t kFlexfecSsrc = 42984;
37constexpr uint32_t kMediaSsrc = 8353;
38
brandtrb29e6522016-12-21 06:37:18 -080039RtpPacketReceived ParsePacket(const Packet& packet) {
40 RtpPacketReceived parsed_packet;
41 EXPECT_TRUE(parsed_packet.Parse(packet.data, packet.length));
42 return parsed_packet;
43}
44
brandtra8b38552016-10-10 16:44:57 -070045} // namespace
46
nisse5c29a7a2017-02-16 06:52:32 -080047class FlexfecReceiverForTest : public FlexfecReceiver {
48 public:
49 FlexfecReceiverForTest(uint32_t ssrc,
50 uint32_t protected_media_ssrc,
51 RecoveredPacketReceiver* recovered_packet_receiver)
52 : FlexfecReceiver(ssrc, protected_media_ssrc, recovered_packet_receiver) {
53 }
54 // Expose methods for tests.
55 using FlexfecReceiver::AddReceivedPacket;
nissea5f043f2017-09-18 07:58:59 -070056 using FlexfecReceiver::ProcessReceivedPacket;
nisse5c29a7a2017-02-16 06:52:32 -080057};
58
brandtra8b38552016-10-10 16:44:57 -070059class FlexfecReceiverTest : public ::testing::Test {
60 protected:
61 FlexfecReceiverTest()
brandtr0a4c1612016-11-03 08:18:27 -070062 : receiver_(kFlexfecSsrc, kMediaSsrc, &recovered_packet_receiver_),
brandtrd726a3f2017-06-29 02:45:35 -070063 erasure_code_(
64 ForwardErrorCorrection::CreateFlexfec(kFlexfecSsrc, kMediaSsrc)),
brandtra8b38552016-10-10 16:44:57 -070065 packet_generator_(kMediaSsrc, kFlexfecSsrc) {}
66
67 // Generates |num_media_packets| corresponding to a single frame.
68 void PacketizeFrame(size_t num_media_packets,
69 size_t frame_offset,
70 PacketList* media_packets);
71
72 // Generates |num_fec_packets| FEC packets, given |media_packets|.
73 std::list<Packet*> EncodeFec(const PacketList& media_packets,
74 size_t num_fec_packets);
75
nisse5c29a7a2017-02-16 06:52:32 -080076 FlexfecReceiverForTest receiver_;
brandtra8b38552016-10-10 16:44:57 -070077 std::unique_ptr<ForwardErrorCorrection> erasure_code_;
78
79 FlexfecPacketGenerator packet_generator_;
80 testing::StrictMock<MockRecoveredPacketReceiver> recovered_packet_receiver_;
81};
82
83void FlexfecReceiverTest::PacketizeFrame(size_t num_media_packets,
84 size_t frame_offset,
85 PacketList* media_packets) {
86 packet_generator_.NewFrame(num_media_packets);
87 for (size_t i = 0; i < num_media_packets; ++i) {
88 std::unique_ptr<Packet> next_packet(
89 packet_generator_.NextPacket(frame_offset + i, kPayloadLength));
90 media_packets->push_back(std::move(next_packet));
91 }
92}
93
94std::list<Packet*> FlexfecReceiverTest::EncodeFec(
95 const PacketList& media_packets,
96 size_t num_fec_packets) {
97 const uint8_t protection_factor =
98 num_fec_packets * 255 / media_packets.size();
99 constexpr int kNumImportantPackets = 0;
100 constexpr bool kUseUnequalProtection = false;
101 constexpr FecMaskType kFecMaskType = kFecMaskRandom;
102 std::list<Packet*> fec_packets;
103 EXPECT_EQ(0, erasure_code_->EncodeFec(
104 media_packets, protection_factor, kNumImportantPackets,
105 kUseUnequalProtection, kFecMaskType, &fec_packets));
106 EXPECT_EQ(num_fec_packets, fec_packets.size());
107 return fec_packets;
108}
109
110TEST_F(FlexfecReceiverTest, ReceivesMediaPacket) {
111 packet_generator_.NewFrame(1);
112 std::unique_ptr<Packet> media_packet(
113 packet_generator_.NextPacket(0, kPayloadLength));
114
nissea5f043f2017-09-18 07:58:59 -0700115 std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet =
116 receiver_.AddReceivedPacket(ParsePacket(*media_packet));
117 ASSERT_TRUE(received_packet);
118 receiver_.ProcessReceivedPacket(*received_packet);
brandtra8b38552016-10-10 16:44:57 -0700119}
120
121TEST_F(FlexfecReceiverTest, ReceivesMediaAndFecPackets) {
122 const size_t kNumMediaPackets = 1;
123 const size_t kNumFecPackets = 1;
124
125 PacketList media_packets;
126 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
127 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
brandtrb29e6522016-12-21 06:37:18 -0800128 const auto& media_packet = media_packets.front();
brandtra8b38552016-10-10 16:44:57 -0700129 auto fec_packet = packet_generator_.BuildFlexfecPacket(*fec_packets.front());
130
nissea5f043f2017-09-18 07:58:59 -0700131 std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet =
132 receiver_.AddReceivedPacket(ParsePacket(*media_packet));
133 ASSERT_TRUE(received_packet);
134 receiver_.ProcessReceivedPacket(*received_packet);
135 received_packet = receiver_.AddReceivedPacket(ParsePacket(*fec_packet));
136 ASSERT_TRUE(received_packet);
137 receiver_.ProcessReceivedPacket(*received_packet);
brandtra8b38552016-10-10 16:44:57 -0700138}
139
140TEST_F(FlexfecReceiverTest, FailsOnTruncatedFecPacket) {
141 const size_t kNumMediaPackets = 1;
142 const size_t kNumFecPackets = 1;
143
144 PacketList media_packets;
145 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
146 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
brandtrb29e6522016-12-21 06:37:18 -0800147 const auto& media_packet = media_packets.front();
brandtra8b38552016-10-10 16:44:57 -0700148 // Simulate truncated FlexFEC payload.
149 fec_packets.front()->length = 1;
150 auto fec_packet = packet_generator_.BuildFlexfecPacket(*fec_packets.front());
151
nissea5f043f2017-09-18 07:58:59 -0700152 std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet =
153 receiver_.AddReceivedPacket(ParsePacket(*media_packet));
154 ASSERT_TRUE(received_packet);
155 receiver_.ProcessReceivedPacket(*received_packet);
nisse5c29a7a2017-02-16 06:52:32 -0800156 EXPECT_FALSE(receiver_.AddReceivedPacket(ParsePacket(*fec_packet)));
brandtra8b38552016-10-10 16:44:57 -0700157}
158
159TEST_F(FlexfecReceiverTest, FailsOnUnknownMediaSsrc) {
160 const size_t kNumMediaPackets = 1;
161
162 PacketList media_packets;
163 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
brandtrb29e6522016-12-21 06:37:18 -0800164 auto& media_packet = media_packets.front();
brandtra8b38552016-10-10 16:44:57 -0700165 // Corrupt the SSRC.
166 media_packet->data[8] = 0;
167 media_packet->data[9] = 1;
168 media_packet->data[10] = 2;
169 media_packet->data[11] = 3;
170
nisse5c29a7a2017-02-16 06:52:32 -0800171 EXPECT_FALSE(receiver_.AddReceivedPacket(ParsePacket(*media_packet)));
brandtra8b38552016-10-10 16:44:57 -0700172}
173
174TEST_F(FlexfecReceiverTest, FailsOnUnknownFecSsrc) {
175 const size_t kNumMediaPackets = 1;
176 const size_t kNumFecPackets = 1;
177
178 PacketList media_packets;
179 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
180 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
brandtrb29e6522016-12-21 06:37:18 -0800181 const auto& media_packet = media_packets.front();
brandtra8b38552016-10-10 16:44:57 -0700182 auto fec_packet = packet_generator_.BuildFlexfecPacket(*fec_packets.front());
183 // Corrupt the SSRC.
184 fec_packet->data[8] = 4;
185 fec_packet->data[9] = 5;
186 fec_packet->data[10] = 6;
187 fec_packet->data[11] = 7;
188
nissea5f043f2017-09-18 07:58:59 -0700189 std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet =
190 receiver_.AddReceivedPacket(ParsePacket(*media_packet));
191 ASSERT_TRUE(received_packet);
192 receiver_.ProcessReceivedPacket(*received_packet);
nisse5c29a7a2017-02-16 06:52:32 -0800193 EXPECT_FALSE(receiver_.AddReceivedPacket(ParsePacket(*fec_packet)));
brandtra8b38552016-10-10 16:44:57 -0700194}
195
196TEST_F(FlexfecReceiverTest, ReceivesMultiplePackets) {
197 const size_t kNumMediaPackets = 2;
198 const size_t kNumFecPackets = 1;
199
200 PacketList media_packets;
201 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
202 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
203
204 // Receive all media packets.
205 for (const auto& media_packet : media_packets) {
nissea5f043f2017-09-18 07:58:59 -0700206 std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet =
207 receiver_.AddReceivedPacket(ParsePacket(*media_packet));
208 ASSERT_TRUE(received_packet);
209 receiver_.ProcessReceivedPacket(*received_packet);
brandtra8b38552016-10-10 16:44:57 -0700210 }
211
212 // Receive FEC packet.
Danil Chapovalovdd7e2842018-03-09 15:37:03 +0000213 auto* fec_packet = fec_packets.front();
brandtra8b38552016-10-10 16:44:57 -0700214 std::unique_ptr<Packet> packet_with_rtp_header =
215 packet_generator_.BuildFlexfecPacket(*fec_packet);
nissea5f043f2017-09-18 07:58:59 -0700216 std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet =
217 receiver_.AddReceivedPacket(ParsePacket(*packet_with_rtp_header));
218 ASSERT_TRUE(received_packet);
219 receiver_.ProcessReceivedPacket(*received_packet);
brandtra8b38552016-10-10 16:44:57 -0700220}
221
222TEST_F(FlexfecReceiverTest, RecoversFromSingleMediaLoss) {
223 const size_t kNumMediaPackets = 2;
224 const size_t kNumFecPackets = 1;
225
226 PacketList media_packets;
227 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
228 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
229
230 // Receive first media packet but drop second.
231 auto media_it = media_packets.begin();
nisse5c29a7a2017-02-16 06:52:32 -0800232 receiver_.OnRtpPacket(ParsePacket(**media_it));
brandtra8b38552016-10-10 16:44:57 -0700233
234 // Receive FEC packet and ensure recovery of lost media packet.
235 auto fec_it = fec_packets.begin();
236 std::unique_ptr<Packet> packet_with_rtp_header =
237 packet_generator_.BuildFlexfecPacket(**fec_it);
238 media_it++;
239 EXPECT_CALL(recovered_packet_receiver_,
240 OnRecoveredPacket(_, (*media_it)->length))
241 .With(
nissed2ef3142017-05-11 08:00:58 -0700242 Args<0, 1>(ElementsAreArray((*media_it)->data, (*media_it)->length)));
nisse5c29a7a2017-02-16 06:52:32 -0800243 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700244}
245
246TEST_F(FlexfecReceiverTest, RecoversFromDoubleMediaLoss) {
247 const size_t kNumMediaPackets = 2;
248 const size_t kNumFecPackets = 2;
249
250 PacketList media_packets;
251 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
252 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
253
254 // Drop both media packets.
255
256 // Receive first FEC packet and recover first lost media packet.
257 auto fec_it = fec_packets.begin();
258 std::unique_ptr<Packet> packet_with_rtp_header =
259 packet_generator_.BuildFlexfecPacket(**fec_it);
260 auto media_it = media_packets.begin();
261 EXPECT_CALL(recovered_packet_receiver_,
262 OnRecoveredPacket(_, (*media_it)->length))
263 .With(
nissed2ef3142017-05-11 08:00:58 -0700264 Args<0, 1>(ElementsAreArray((*media_it)->data, (*media_it)->length)));
nisse5c29a7a2017-02-16 06:52:32 -0800265 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700266
267 // Receive second FEC packet and recover second lost media packet.
268 fec_it++;
269 packet_with_rtp_header = packet_generator_.BuildFlexfecPacket(**fec_it);
270 media_it++;
271 EXPECT_CALL(recovered_packet_receiver_,
272 OnRecoveredPacket(_, (*media_it)->length))
273 .With(
nissed2ef3142017-05-11 08:00:58 -0700274 Args<0, 1>(ElementsAreArray((*media_it)->data, (*media_it)->length)));
nisse5c29a7a2017-02-16 06:52:32 -0800275 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700276}
277
278TEST_F(FlexfecReceiverTest, DoesNotRecoverFromMediaAndFecLoss) {
279 const size_t kNumMediaPackets = 2;
280 const size_t kNumFecPackets = 1;
281
282 PacketList media_packets;
283 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
284 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
285
286 // Receive first media packet.
287 auto media_it = media_packets.begin();
nisse5c29a7a2017-02-16 06:52:32 -0800288 receiver_.OnRtpPacket(ParsePacket(**media_it));
brandtra8b38552016-10-10 16:44:57 -0700289
290 // Drop second media packet and FEC packet. Do not expect call back.
291}
292
293TEST_F(FlexfecReceiverTest, DoesNotCallbackTwice) {
294 const size_t kNumMediaPackets = 2;
295 const size_t kNumFecPackets = 1;
296
297 PacketList media_packets;
298 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
299 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
300
301 // Receive first media packet but drop second.
302 auto media_it = media_packets.begin();
nisse5c29a7a2017-02-16 06:52:32 -0800303 receiver_.OnRtpPacket(ParsePacket(**media_it));
brandtra8b38552016-10-10 16:44:57 -0700304
305 // Receive FEC packet and ensure recovery of lost media packet.
306 auto fec_it = fec_packets.begin();
307 std::unique_ptr<Packet> packet_with_rtp_header =
308 packet_generator_.BuildFlexfecPacket(**fec_it);
309 media_it++;
310 EXPECT_CALL(recovered_packet_receiver_,
311 OnRecoveredPacket(_, (*media_it)->length))
312 .With(
nissed2ef3142017-05-11 08:00:58 -0700313 Args<0, 1>(ElementsAreArray((*media_it)->data, (*media_it)->length)));
nisse5c29a7a2017-02-16 06:52:32 -0800314 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700315
brandtrf27c5b82017-05-23 08:38:43 -0700316 // Receive the FEC packet again, but do not call back.
nisse5c29a7a2017-02-16 06:52:32 -0800317 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700318
brandtrf27c5b82017-05-23 08:38:43 -0700319 // Receive the first media packet again, but do not call back.
320 media_it = media_packets.begin();
321 receiver_.OnRtpPacket(ParsePacket(**media_it));
322
323 // Receive the second media packet again (the one recovered above),
324 // but do not call back again.
325 media_it++;
326 receiver_.OnRtpPacket(ParsePacket(**media_it));
brandtra8b38552016-10-10 16:44:57 -0700327}
328
329// Here we are implicitly assuming packet masks that are suitable for
330// this type of 50% correlated loss. If we are changing our precomputed
331// packet masks, this test might need to be updated.
332TEST_F(FlexfecReceiverTest, RecoversFrom50PercentLoss) {
333 const size_t kNumFecPackets = 5;
334 const size_t kNumFrames = 2 * kNumFecPackets;
335 const size_t kNumMediaPacketsPerFrame = 1;
336
337 PacketList media_packets;
338 for (size_t i = 0; i < kNumFrames; ++i) {
339 PacketizeFrame(kNumMediaPacketsPerFrame, i, &media_packets);
340 }
341 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
342
343 // Drop every second media packet.
344 auto media_it = media_packets.begin();
345 while (media_it != media_packets.end()) {
nisse5c29a7a2017-02-16 06:52:32 -0800346 receiver_.OnRtpPacket(ParsePacket(**media_it));
brandtra8b38552016-10-10 16:44:57 -0700347 ++media_it;
348 if (media_it == media_packets.end()) {
349 break;
350 }
351 ++media_it;
352 }
353
354 // Receive all FEC packets.
355 media_it = media_packets.begin();
Danil Chapovalovdd7e2842018-03-09 15:37:03 +0000356 for (const auto* fec_packet : fec_packets) {
brandtra8b38552016-10-10 16:44:57 -0700357 std::unique_ptr<Packet> fec_packet_with_rtp_header =
358 packet_generator_.BuildFlexfecPacket(*fec_packet);
359 ++media_it;
360 if (media_it == media_packets.end()) {
361 break;
362 }
363 EXPECT_CALL(recovered_packet_receiver_,
364 OnRecoveredPacket(_, (*media_it)->length))
365 .With(Args<0, 1>(
nissed2ef3142017-05-11 08:00:58 -0700366 ElementsAreArray((*media_it)->data, (*media_it)->length)));
nisse5c29a7a2017-02-16 06:52:32 -0800367 receiver_.OnRtpPacket(ParsePacket(*fec_packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700368 ++media_it;
369 }
370}
371
372TEST_F(FlexfecReceiverTest, DelayedFecPacketDoesHelp) {
373 // These values need to be updated if the underlying erasure code
374 // implementation changes.
375 const size_t kNumFrames = 48;
376 const size_t kNumMediaPacketsPerFrame = 1;
377 const size_t kNumFecPackets = 1;
378
379 PacketList media_packets;
380 PacketizeFrame(kNumMediaPacketsPerFrame, 0, &media_packets);
381 PacketizeFrame(kNumMediaPacketsPerFrame, 1, &media_packets);
382 // Protect two first frames.
383 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
384 for (size_t i = 2; i < kNumFrames; ++i) {
385 PacketizeFrame(kNumMediaPacketsPerFrame, i, &media_packets);
386 }
387
388 // Drop first media packet and delay FEC packet.
389 auto media_it = media_packets.begin();
390 ++media_it;
391
392 // Receive all other media packets.
393 while (media_it != media_packets.end()) {
nisse5c29a7a2017-02-16 06:52:32 -0800394 receiver_.OnRtpPacket(ParsePacket(**media_it));
brandtra8b38552016-10-10 16:44:57 -0700395 ++media_it;
396 }
397
398 // Receive FEC packet and recover first media packet.
399 auto fec_it = fec_packets.begin();
400 std::unique_ptr<Packet> packet_with_rtp_header =
401 packet_generator_.BuildFlexfecPacket(**fec_it);
402 media_it = media_packets.begin();
403 EXPECT_CALL(recovered_packet_receiver_,
404 OnRecoveredPacket(_, (*media_it)->length))
405 .With(
nissed2ef3142017-05-11 08:00:58 -0700406 Args<0, 1>(ElementsAreArray((*media_it)->data, (*media_it)->length)));
nisse5c29a7a2017-02-16 06:52:32 -0800407 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700408}
409
410TEST_F(FlexfecReceiverTest, TooDelayedFecPacketDoesNotHelp) {
411 // These values need to be updated if the underlying erasure code
412 // implementation changes.
413 const size_t kNumFrames = 49;
414 const size_t kNumMediaPacketsPerFrame = 1;
415 const size_t kNumFecPackets = 1;
416
417 PacketList media_packets;
418 PacketizeFrame(kNumMediaPacketsPerFrame, 0, &media_packets);
419 PacketizeFrame(kNumMediaPacketsPerFrame, 1, &media_packets);
420 // Protect two first frames.
421 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
422 for (size_t i = 2; i < kNumFrames; ++i) {
423 PacketizeFrame(kNumMediaPacketsPerFrame, i, &media_packets);
424 }
425
426 // Drop first media packet and delay FEC packet.
427 auto media_it = media_packets.begin();
428 ++media_it;
429
430 // Receive all other media packets.
431 while (media_it != media_packets.end()) {
nisse5c29a7a2017-02-16 06:52:32 -0800432 receiver_.OnRtpPacket(ParsePacket(**media_it));
brandtra8b38552016-10-10 16:44:57 -0700433 ++media_it;
434 }
435
436 // Receive FEC packet.
437 auto fec_it = fec_packets.begin();
438 std::unique_ptr<Packet> packet_with_rtp_header =
439 packet_generator_.BuildFlexfecPacket(**fec_it);
nisse5c29a7a2017-02-16 06:52:32 -0800440 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700441
442 // Do not expect a call back.
443}
444
Rasmus Brandta00137c2017-12-12 10:01:20 +0100445TEST_F(FlexfecReceiverTest, SurvivesOldRecoveredPacketBeingReinserted) {
446 // Simulates the behaviour of the
447 // Call->FlexfecReceiveStream->FlexfecReceiver->Call loop in production code.
448 class LoopbackRecoveredPacketReceiver : public RecoveredPacketReceiver {
449 public:
450 LoopbackRecoveredPacketReceiver() : receiver_(nullptr) {}
451
452 void SetReceiver(FlexfecReceiver* receiver) { receiver_ = receiver; }
453
454 // Implements RecoveredPacketReceiver.
Danil Chapovalovdd7e2842018-03-09 15:37:03 +0000455 void OnRecoveredPacket(const uint8_t* packet, size_t length) override {
Rasmus Brandta00137c2017-12-12 10:01:20 +0100456 RtpPacketReceived parsed_packet;
457 EXPECT_TRUE(parsed_packet.Parse(packet, length));
458 parsed_packet.set_recovered(true);
459
460 RTC_DCHECK(receiver_);
461 receiver_->OnRtpPacket(parsed_packet);
462 }
463
464 private:
465 FlexfecReceiver* receiver_;
466 } loopback_recovered_packet_receiver;
467
468 // Feed recovered packets back into |receiver|.
469 FlexfecReceiver receiver(kFlexfecSsrc, kMediaSsrc,
470 &loopback_recovered_packet_receiver);
471 loopback_recovered_packet_receiver.SetReceiver(&receiver);
472
473 // Receive first set of packets.
474 PacketList first_media_packets;
475 for (int i = 0; i < 46; ++i) {
476 PacketizeFrame(1, 0, &first_media_packets);
477 }
478 for (const auto& media_packet : first_media_packets) {
479 receiver.OnRtpPacket(ParsePacket(*media_packet));
480 }
481
482 // Protect one media packet. Lose the media packet,
483 // but do not receive FEC packet yet.
484 PacketList protected_media_packet;
485 PacketizeFrame(1, 0, &protected_media_packet);
486 const std::list<Packet*> fec_packets = EncodeFec(protected_media_packet, 1);
487 EXPECT_EQ(1u, fec_packets.size());
488 std::unique_ptr<Packet> fec_packet_with_rtp_header =
489 packet_generator_.BuildFlexfecPacket(*fec_packets.front());
490
491 // Lose some packets, thus introducing a sequence number gap.
492 PacketList lost_packets;
493 for (int i = 0; i < 100; ++i) {
494 PacketizeFrame(1, 0, &lost_packets);
495 }
496
497 // Receive one more packet.
498 PacketList second_media_packets;
499 PacketizeFrame(1, 0, &second_media_packets);
500 for (const auto& media_packet : second_media_packets) {
501 receiver.OnRtpPacket(ParsePacket(*media_packet));
502 }
503
504 // Receive delayed FEC packet.
505 receiver.OnRtpPacket(ParsePacket(*fec_packet_with_rtp_header));
506
507 // Expect no crash.
508}
509
brandtra8b38552016-10-10 16:44:57 -0700510TEST_F(FlexfecReceiverTest, RecoversWithMediaPacketsOutOfOrder) {
511 const size_t kNumMediaPackets = 6;
512 const size_t kNumFecPackets = 2;
513
514 PacketList media_packets;
515 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
516 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
517
518 // Lose two media packets, and receive the others out of order.
519 auto media_it = media_packets.begin();
520 auto media_packet0 = media_it++;
521 auto media_packet1 = media_it++;
522 auto media_packet2 = media_it++;
523 auto media_packet3 = media_it++;
524 auto media_packet4 = media_it++;
525 auto media_packet5 = media_it++;
nisse5c29a7a2017-02-16 06:52:32 -0800526 receiver_.OnRtpPacket(ParsePacket(**media_packet5));
527 receiver_.OnRtpPacket(ParsePacket(**media_packet2));
528 receiver_.OnRtpPacket(ParsePacket(**media_packet3));
529 receiver_.OnRtpPacket(ParsePacket(**media_packet0));
brandtra8b38552016-10-10 16:44:57 -0700530
531 // Expect to recover lost media packets.
532 EXPECT_CALL(recovered_packet_receiver_,
533 OnRecoveredPacket(_, (*media_packet1)->length))
534 .With(Args<0, 1>(
nissed2ef3142017-05-11 08:00:58 -0700535 ElementsAreArray((*media_packet1)->data, (*media_packet1)->length)));
brandtra8b38552016-10-10 16:44:57 -0700536 EXPECT_CALL(recovered_packet_receiver_,
537 OnRecoveredPacket(_, (*media_packet4)->length))
538 .With(Args<0, 1>(
nissed2ef3142017-05-11 08:00:58 -0700539 ElementsAreArray((*media_packet4)->data, (*media_packet4)->length)));
brandtra8b38552016-10-10 16:44:57 -0700540
541 // Add FEC packets.
542 auto fec_it = fec_packets.begin();
543 std::unique_ptr<Packet> packet_with_rtp_header;
544 while (fec_it != fec_packets.end()) {
545 packet_with_rtp_header = packet_generator_.BuildFlexfecPacket(**fec_it);
nisse5c29a7a2017-02-16 06:52:32 -0800546 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700547 ++fec_it;
548 }
549}
550
brandtrf27c5b82017-05-23 08:38:43 -0700551// Recovered media packets may be fed back into the FlexfecReceiver by the
552// callback. This test ensures the idempotency of such a situation.
553TEST_F(FlexfecReceiverTest, RecoveryCallbackDoesNotLoopInfinitely) {
554 class LoopbackRecoveredPacketReceiver : public RecoveredPacketReceiver {
555 public:
556 const int kMaxRecursionDepth = 10;
557
558 LoopbackRecoveredPacketReceiver()
559 : receiver_(nullptr),
560 did_receive_call_back_(false),
561 recursion_depth_(0),
562 deep_recursion_(false) {}
563
564 void SetReceiver(FlexfecReceiver* receiver) { receiver_ = receiver; }
565 bool DidReceiveCallback() const { return did_receive_call_back_; }
566 bool DeepRecursion() const { return deep_recursion_; }
567
568 // Implements RecoveredPacketReceiver.
Danil Chapovalovdd7e2842018-03-09 15:37:03 +0000569 void OnRecoveredPacket(const uint8_t* packet, size_t length) override {
brandtrf27c5b82017-05-23 08:38:43 -0700570 RtpPacketReceived parsed_packet;
571 EXPECT_TRUE(parsed_packet.Parse(packet, length));
572
573 did_receive_call_back_ = true;
574
575 if (recursion_depth_ > kMaxRecursionDepth) {
576 deep_recursion_ = true;
577 return;
578 }
579 ++recursion_depth_;
580 RTC_DCHECK(receiver_);
581 receiver_->OnRtpPacket(parsed_packet);
582 --recursion_depth_;
583 }
584
585 private:
586 FlexfecReceiver* receiver_;
587 bool did_receive_call_back_;
588 int recursion_depth_;
589 bool deep_recursion_;
590 } loopback_recovered_packet_receiver;
591
592 // Feed recovered packets back into |receiver|.
593 FlexfecReceiver receiver(kFlexfecSsrc, kMediaSsrc,
594 &loopback_recovered_packet_receiver);
595 loopback_recovered_packet_receiver.SetReceiver(&receiver);
596
597 const size_t kNumMediaPackets = 2;
598 const size_t kNumFecPackets = 1;
599
600 PacketList media_packets;
601 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
602 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
603
604 // Receive first media packet but drop second.
605 auto media_it = media_packets.begin();
606 receiver.OnRtpPacket(ParsePacket(**media_it));
607
608 // Receive FEC packet and verify that a packet was recovered.
609 auto fec_it = fec_packets.begin();
610 std::unique_ptr<Packet> packet_with_rtp_header =
611 packet_generator_.BuildFlexfecPacket(**fec_it);
612 receiver.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
613 EXPECT_TRUE(loopback_recovered_packet_receiver.DidReceiveCallback());
614 EXPECT_FALSE(loopback_recovered_packet_receiver.DeepRecursion());
615}
616
brandtra8b38552016-10-10 16:44:57 -0700617TEST_F(FlexfecReceiverTest, CalculatesNumberOfPackets) {
618 const size_t kNumMediaPackets = 2;
619 const size_t kNumFecPackets = 1;
620
621 PacketList media_packets;
622 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
623 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
624
625 // Receive first media packet but drop second.
626 auto media_it = media_packets.begin();
nisse5c29a7a2017-02-16 06:52:32 -0800627 receiver_.OnRtpPacket(ParsePacket(**media_it));
brandtra8b38552016-10-10 16:44:57 -0700628
629 // Receive FEC packet and ensure recovery of lost media packet.
630 auto fec_it = fec_packets.begin();
631 std::unique_ptr<Packet> packet_with_rtp_header =
632 packet_generator_.BuildFlexfecPacket(**fec_it);
633 media_it++;
634 EXPECT_CALL(recovered_packet_receiver_,
635 OnRecoveredPacket(_, (*media_it)->length))
636 .With(
nissed2ef3142017-05-11 08:00:58 -0700637 Args<0, 1>(ElementsAreArray((*media_it)->data, (*media_it)->length)));
nisse5c29a7a2017-02-16 06:52:32 -0800638 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700639
640 // Check stats calculations.
brandtr0a4c1612016-11-03 08:18:27 -0700641 FecPacketCounter packet_counter = receiver_.GetPacketCounter();
brandtra8b38552016-10-10 16:44:57 -0700642 EXPECT_EQ(2U, packet_counter.num_packets);
643 EXPECT_EQ(1U, packet_counter.num_fec_packets);
644 EXPECT_EQ(1U, packet_counter.num_recovered_packets);
645}
646
647} // namespace webrtc