blob: 5cdcdf59d6d0007efe378742c781bbd4345c5a5f [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.
Danil Chapovalovdd7e2842018-03-09 15:37:03 +0000214 auto* fec_packet = fec_packets.front();
brandtra8b38552016-10-10 16:44:57 -0700215 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();
Danil Chapovalovdd7e2842018-03-09 15:37:03 +0000357 for (const auto* fec_packet : fec_packets) {
brandtra8b38552016-10-10 16:44:57 -0700358 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
Rasmus Brandta00137c2017-12-12 10:01:20 +0100446TEST_F(FlexfecReceiverTest, SurvivesOldRecoveredPacketBeingReinserted) {
447 // Simulates the behaviour of the
448 // Call->FlexfecReceiveStream->FlexfecReceiver->Call loop in production code.
449 class LoopbackRecoveredPacketReceiver : public RecoveredPacketReceiver {
450 public:
451 LoopbackRecoveredPacketReceiver() : receiver_(nullptr) {}
452
453 void SetReceiver(FlexfecReceiver* receiver) { receiver_ = receiver; }
454
455 // Implements RecoveredPacketReceiver.
Danil Chapovalovdd7e2842018-03-09 15:37:03 +0000456 void OnRecoveredPacket(const uint8_t* packet, size_t length) override {
Rasmus Brandta00137c2017-12-12 10:01:20 +0100457 RtpPacketReceived parsed_packet;
458 EXPECT_TRUE(parsed_packet.Parse(packet, length));
459 parsed_packet.set_recovered(true);
460
461 RTC_DCHECK(receiver_);
462 receiver_->OnRtpPacket(parsed_packet);
463 }
464
465 private:
466 FlexfecReceiver* receiver_;
467 } loopback_recovered_packet_receiver;
468
469 // Feed recovered packets back into |receiver|.
470 FlexfecReceiver receiver(kFlexfecSsrc, kMediaSsrc,
471 &loopback_recovered_packet_receiver);
472 loopback_recovered_packet_receiver.SetReceiver(&receiver);
473
474 // Receive first set of packets.
475 PacketList first_media_packets;
476 for (int i = 0; i < 46; ++i) {
477 PacketizeFrame(1, 0, &first_media_packets);
478 }
479 for (const auto& media_packet : first_media_packets) {
480 receiver.OnRtpPacket(ParsePacket(*media_packet));
481 }
482
483 // Protect one media packet. Lose the media packet,
484 // but do not receive FEC packet yet.
485 PacketList protected_media_packet;
486 PacketizeFrame(1, 0, &protected_media_packet);
487 const std::list<Packet*> fec_packets = EncodeFec(protected_media_packet, 1);
488 EXPECT_EQ(1u, fec_packets.size());
489 std::unique_ptr<Packet> fec_packet_with_rtp_header =
490 packet_generator_.BuildFlexfecPacket(*fec_packets.front());
491
492 // Lose some packets, thus introducing a sequence number gap.
493 PacketList lost_packets;
494 for (int i = 0; i < 100; ++i) {
495 PacketizeFrame(1, 0, &lost_packets);
496 }
497
498 // Receive one more packet.
499 PacketList second_media_packets;
500 PacketizeFrame(1, 0, &second_media_packets);
501 for (const auto& media_packet : second_media_packets) {
502 receiver.OnRtpPacket(ParsePacket(*media_packet));
503 }
504
505 // Receive delayed FEC packet.
506 receiver.OnRtpPacket(ParsePacket(*fec_packet_with_rtp_header));
507
508 // Expect no crash.
509}
510
brandtra8b38552016-10-10 16:44:57 -0700511TEST_F(FlexfecReceiverTest, RecoversWithMediaPacketsOutOfOrder) {
512 const size_t kNumMediaPackets = 6;
513 const size_t kNumFecPackets = 2;
514
515 PacketList media_packets;
516 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
517 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
518
519 // Lose two media packets, and receive the others out of order.
520 auto media_it = media_packets.begin();
521 auto media_packet0 = media_it++;
522 auto media_packet1 = media_it++;
523 auto media_packet2 = media_it++;
524 auto media_packet3 = media_it++;
525 auto media_packet4 = media_it++;
526 auto media_packet5 = media_it++;
nisse5c29a7a2017-02-16 06:52:32 -0800527 receiver_.OnRtpPacket(ParsePacket(**media_packet5));
528 receiver_.OnRtpPacket(ParsePacket(**media_packet2));
529 receiver_.OnRtpPacket(ParsePacket(**media_packet3));
530 receiver_.OnRtpPacket(ParsePacket(**media_packet0));
brandtra8b38552016-10-10 16:44:57 -0700531
532 // Expect to recover lost media packets.
533 EXPECT_CALL(recovered_packet_receiver_,
534 OnRecoveredPacket(_, (*media_packet1)->length))
535 .With(Args<0, 1>(
nissed2ef3142017-05-11 08:00:58 -0700536 ElementsAreArray((*media_packet1)->data, (*media_packet1)->length)));
brandtra8b38552016-10-10 16:44:57 -0700537 EXPECT_CALL(recovered_packet_receiver_,
538 OnRecoveredPacket(_, (*media_packet4)->length))
539 .With(Args<0, 1>(
nissed2ef3142017-05-11 08:00:58 -0700540 ElementsAreArray((*media_packet4)->data, (*media_packet4)->length)));
brandtra8b38552016-10-10 16:44:57 -0700541
542 // Add FEC packets.
543 auto fec_it = fec_packets.begin();
544 std::unique_ptr<Packet> packet_with_rtp_header;
545 while (fec_it != fec_packets.end()) {
546 packet_with_rtp_header = packet_generator_.BuildFlexfecPacket(**fec_it);
nisse5c29a7a2017-02-16 06:52:32 -0800547 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700548 ++fec_it;
549 }
550}
551
brandtrf27c5b82017-05-23 08:38:43 -0700552// Recovered media packets may be fed back into the FlexfecReceiver by the
553// callback. This test ensures the idempotency of such a situation.
554TEST_F(FlexfecReceiverTest, RecoveryCallbackDoesNotLoopInfinitely) {
555 class LoopbackRecoveredPacketReceiver : public RecoveredPacketReceiver {
556 public:
557 const int kMaxRecursionDepth = 10;
558
559 LoopbackRecoveredPacketReceiver()
560 : receiver_(nullptr),
561 did_receive_call_back_(false),
562 recursion_depth_(0),
563 deep_recursion_(false) {}
564
565 void SetReceiver(FlexfecReceiver* receiver) { receiver_ = receiver; }
566 bool DidReceiveCallback() const { return did_receive_call_back_; }
567 bool DeepRecursion() const { return deep_recursion_; }
568
569 // Implements RecoveredPacketReceiver.
Danil Chapovalovdd7e2842018-03-09 15:37:03 +0000570 void OnRecoveredPacket(const uint8_t* packet, size_t length) override {
brandtrf27c5b82017-05-23 08:38:43 -0700571 RtpPacketReceived parsed_packet;
572 EXPECT_TRUE(parsed_packet.Parse(packet, length));
573
574 did_receive_call_back_ = true;
575
576 if (recursion_depth_ > kMaxRecursionDepth) {
577 deep_recursion_ = true;
578 return;
579 }
580 ++recursion_depth_;
581 RTC_DCHECK(receiver_);
582 receiver_->OnRtpPacket(parsed_packet);
583 --recursion_depth_;
584 }
585
586 private:
587 FlexfecReceiver* receiver_;
588 bool did_receive_call_back_;
589 int recursion_depth_;
590 bool deep_recursion_;
591 } loopback_recovered_packet_receiver;
592
593 // Feed recovered packets back into |receiver|.
594 FlexfecReceiver receiver(kFlexfecSsrc, kMediaSsrc,
595 &loopback_recovered_packet_receiver);
596 loopback_recovered_packet_receiver.SetReceiver(&receiver);
597
598 const size_t kNumMediaPackets = 2;
599 const size_t kNumFecPackets = 1;
600
601 PacketList media_packets;
602 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
603 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
604
605 // Receive first media packet but drop second.
606 auto media_it = media_packets.begin();
607 receiver.OnRtpPacket(ParsePacket(**media_it));
608
609 // Receive FEC packet and verify that a packet was recovered.
610 auto fec_it = fec_packets.begin();
611 std::unique_ptr<Packet> packet_with_rtp_header =
612 packet_generator_.BuildFlexfecPacket(**fec_it);
613 receiver.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
614 EXPECT_TRUE(loopback_recovered_packet_receiver.DidReceiveCallback());
615 EXPECT_FALSE(loopback_recovered_packet_receiver.DeepRecursion());
616}
617
brandtra8b38552016-10-10 16:44:57 -0700618TEST_F(FlexfecReceiverTest, CalculatesNumberOfPackets) {
619 const size_t kNumMediaPackets = 2;
620 const size_t kNumFecPackets = 1;
621
622 PacketList media_packets;
623 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
624 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
625
626 // Receive first media packet but drop second.
627 auto media_it = media_packets.begin();
nisse5c29a7a2017-02-16 06:52:32 -0800628 receiver_.OnRtpPacket(ParsePacket(**media_it));
brandtra8b38552016-10-10 16:44:57 -0700629
630 // Receive FEC packet and ensure recovery of lost media packet.
631 auto fec_it = fec_packets.begin();
632 std::unique_ptr<Packet> packet_with_rtp_header =
633 packet_generator_.BuildFlexfecPacket(**fec_it);
634 media_it++;
635 EXPECT_CALL(recovered_packet_receiver_,
636 OnRecoveredPacket(_, (*media_it)->length))
637 .With(
nissed2ef3142017-05-11 08:00:58 -0700638 Args<0, 1>(ElementsAreArray((*media_it)->data, (*media_it)->length)));
nisse5c29a7a2017-02-16 06:52:32 -0800639 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700640
641 // Check stats calculations.
brandtr0a4c1612016-11-03 08:18:27 -0700642 FecPacketCounter packet_counter = receiver_.GetPacketCounter();
brandtra8b38552016-10-10 16:44:57 -0700643 EXPECT_EQ(2U, packet_counter.num_packets);
644 EXPECT_EQ(1U, packet_counter.num_fec_packets);
645 EXPECT_EQ(1U, packet_counter.num_recovered_packets);
646}
647
648} // namespace webrtc