blob: 224fee6aa075ab72f72c9ab9d63a5a7f1b5eed59 [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
Jonas Olssona4d87372019-07-05 19:08:33 +020011#include "modules/rtp_rtcp/include/flexfec_receiver.h"
12
brandtra8b38552016-10-10 16:44:57 -070013#include <algorithm>
14#include <memory>
15
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020016#include "modules/rtp_rtcp/mocks/mock_recovered_packet_receiver.h"
17#include "modules/rtp_rtcp/source/fec_test_helper.h"
18#include "modules/rtp_rtcp/source/forward_error_correction.h"
19#include "modules/rtp_rtcp/source/rtp_packet_received.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#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;
Ilya Nikolaevskiyeec5fff2019-09-02 13:58:49 +020042 EXPECT_TRUE(parsed_packet.Parse(packet.data));
brandtrb29e6522016-12-21 06:37:18 -080043 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)
Sebastian Jansson8026d602019-03-04 19:39:01 +010053 : FlexfecReceiver(Clock::GetRealTimeClock(),
54 ssrc,
55 protected_media_ssrc,
56 recovered_packet_receiver) {}
nisse5c29a7a2017-02-16 06:52:32 -080057 // Expose methods for tests.
58 using FlexfecReceiver::AddReceivedPacket;
nissea5f043f2017-09-18 07:58:59 -070059 using FlexfecReceiver::ProcessReceivedPacket;
nisse5c29a7a2017-02-16 06:52:32 -080060};
61
brandtra8b38552016-10-10 16:44:57 -070062class FlexfecReceiverTest : public ::testing::Test {
63 protected:
64 FlexfecReceiverTest()
brandtr0a4c1612016-11-03 08:18:27 -070065 : receiver_(kFlexfecSsrc, kMediaSsrc, &recovered_packet_receiver_),
brandtrd726a3f2017-06-29 02:45:35 -070066 erasure_code_(
67 ForwardErrorCorrection::CreateFlexfec(kFlexfecSsrc, kMediaSsrc)),
brandtra8b38552016-10-10 16:44:57 -070068 packet_generator_(kMediaSsrc, kFlexfecSsrc) {}
69
70 // Generates |num_media_packets| corresponding to a single frame.
71 void PacketizeFrame(size_t num_media_packets,
72 size_t frame_offset,
73 PacketList* media_packets);
74
75 // Generates |num_fec_packets| FEC packets, given |media_packets|.
76 std::list<Packet*> EncodeFec(const PacketList& media_packets,
77 size_t num_fec_packets);
78
nisse5c29a7a2017-02-16 06:52:32 -080079 FlexfecReceiverForTest receiver_;
brandtra8b38552016-10-10 16:44:57 -070080 std::unique_ptr<ForwardErrorCorrection> erasure_code_;
81
82 FlexfecPacketGenerator packet_generator_;
Mirko Bonadei6a489f22019-04-09 15:11:12 +020083 ::testing::StrictMock<MockRecoveredPacketReceiver> recovered_packet_receiver_;
brandtra8b38552016-10-10 16:44:57 -070084};
85
86void FlexfecReceiverTest::PacketizeFrame(size_t num_media_packets,
87 size_t frame_offset,
88 PacketList* media_packets) {
89 packet_generator_.NewFrame(num_media_packets);
90 for (size_t i = 0; i < num_media_packets; ++i) {
91 std::unique_ptr<Packet> next_packet(
92 packet_generator_.NextPacket(frame_offset + i, kPayloadLength));
93 media_packets->push_back(std::move(next_packet));
94 }
95}
96
97std::list<Packet*> FlexfecReceiverTest::EncodeFec(
98 const PacketList& media_packets,
99 size_t num_fec_packets) {
100 const uint8_t protection_factor =
101 num_fec_packets * 255 / media_packets.size();
102 constexpr int kNumImportantPackets = 0;
103 constexpr bool kUseUnequalProtection = false;
104 constexpr FecMaskType kFecMaskType = kFecMaskRandom;
105 std::list<Packet*> fec_packets;
106 EXPECT_EQ(0, erasure_code_->EncodeFec(
107 media_packets, protection_factor, kNumImportantPackets,
108 kUseUnequalProtection, kFecMaskType, &fec_packets));
109 EXPECT_EQ(num_fec_packets, fec_packets.size());
110 return fec_packets;
111}
112
113TEST_F(FlexfecReceiverTest, ReceivesMediaPacket) {
114 packet_generator_.NewFrame(1);
115 std::unique_ptr<Packet> media_packet(
116 packet_generator_.NextPacket(0, kPayloadLength));
117
nissea5f043f2017-09-18 07:58:59 -0700118 std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet =
119 receiver_.AddReceivedPacket(ParsePacket(*media_packet));
120 ASSERT_TRUE(received_packet);
121 receiver_.ProcessReceivedPacket(*received_packet);
brandtra8b38552016-10-10 16:44:57 -0700122}
123
124TEST_F(FlexfecReceiverTest, ReceivesMediaAndFecPackets) {
125 const size_t kNumMediaPackets = 1;
126 const size_t kNumFecPackets = 1;
127
128 PacketList media_packets;
129 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
130 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
brandtrb29e6522016-12-21 06:37:18 -0800131 const auto& media_packet = media_packets.front();
brandtra8b38552016-10-10 16:44:57 -0700132 auto fec_packet = packet_generator_.BuildFlexfecPacket(*fec_packets.front());
133
nissea5f043f2017-09-18 07:58:59 -0700134 std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet =
135 receiver_.AddReceivedPacket(ParsePacket(*media_packet));
136 ASSERT_TRUE(received_packet);
137 receiver_.ProcessReceivedPacket(*received_packet);
138 received_packet = receiver_.AddReceivedPacket(ParsePacket(*fec_packet));
139 ASSERT_TRUE(received_packet);
140 receiver_.ProcessReceivedPacket(*received_packet);
brandtra8b38552016-10-10 16:44:57 -0700141}
142
143TEST_F(FlexfecReceiverTest, FailsOnTruncatedFecPacket) {
144 const size_t kNumMediaPackets = 1;
145 const size_t kNumFecPackets = 1;
146
147 PacketList media_packets;
148 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
149 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
brandtrb29e6522016-12-21 06:37:18 -0800150 const auto& media_packet = media_packets.front();
brandtra8b38552016-10-10 16:44:57 -0700151 // Simulate truncated FlexFEC payload.
Ilya Nikolaevskiyeec5fff2019-09-02 13:58:49 +0200152 fec_packets.front()->data.SetSize(1);
brandtra8b38552016-10-10 16:44:57 -0700153 auto fec_packet = packet_generator_.BuildFlexfecPacket(*fec_packets.front());
154
nissea5f043f2017-09-18 07:58:59 -0700155 std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet =
156 receiver_.AddReceivedPacket(ParsePacket(*media_packet));
157 ASSERT_TRUE(received_packet);
158 receiver_.ProcessReceivedPacket(*received_packet);
nisse5c29a7a2017-02-16 06:52:32 -0800159 EXPECT_FALSE(receiver_.AddReceivedPacket(ParsePacket(*fec_packet)));
brandtra8b38552016-10-10 16:44:57 -0700160}
161
162TEST_F(FlexfecReceiverTest, FailsOnUnknownMediaSsrc) {
163 const size_t kNumMediaPackets = 1;
164
165 PacketList media_packets;
166 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
brandtrb29e6522016-12-21 06:37:18 -0800167 auto& media_packet = media_packets.front();
brandtra8b38552016-10-10 16:44:57 -0700168 // Corrupt the SSRC.
169 media_packet->data[8] = 0;
170 media_packet->data[9] = 1;
171 media_packet->data[10] = 2;
172 media_packet->data[11] = 3;
173
nisse5c29a7a2017-02-16 06:52:32 -0800174 EXPECT_FALSE(receiver_.AddReceivedPacket(ParsePacket(*media_packet)));
brandtra8b38552016-10-10 16:44:57 -0700175}
176
177TEST_F(FlexfecReceiverTest, FailsOnUnknownFecSsrc) {
178 const size_t kNumMediaPackets = 1;
179 const size_t kNumFecPackets = 1;
180
181 PacketList media_packets;
182 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
183 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
brandtrb29e6522016-12-21 06:37:18 -0800184 const auto& media_packet = media_packets.front();
brandtra8b38552016-10-10 16:44:57 -0700185 auto fec_packet = packet_generator_.BuildFlexfecPacket(*fec_packets.front());
186 // Corrupt the SSRC.
187 fec_packet->data[8] = 4;
188 fec_packet->data[9] = 5;
189 fec_packet->data[10] = 6;
190 fec_packet->data[11] = 7;
191
nissea5f043f2017-09-18 07:58:59 -0700192 std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet =
193 receiver_.AddReceivedPacket(ParsePacket(*media_packet));
194 ASSERT_TRUE(received_packet);
195 receiver_.ProcessReceivedPacket(*received_packet);
nisse5c29a7a2017-02-16 06:52:32 -0800196 EXPECT_FALSE(receiver_.AddReceivedPacket(ParsePacket(*fec_packet)));
brandtra8b38552016-10-10 16:44:57 -0700197}
198
199TEST_F(FlexfecReceiverTest, ReceivesMultiplePackets) {
200 const size_t kNumMediaPackets = 2;
201 const size_t kNumFecPackets = 1;
202
203 PacketList media_packets;
204 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
205 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
206
207 // Receive all media packets.
208 for (const auto& media_packet : media_packets) {
nissea5f043f2017-09-18 07:58:59 -0700209 std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet =
210 receiver_.AddReceivedPacket(ParsePacket(*media_packet));
211 ASSERT_TRUE(received_packet);
212 receiver_.ProcessReceivedPacket(*received_packet);
brandtra8b38552016-10-10 16:44:57 -0700213 }
214
215 // Receive FEC packet.
Danil Chapovalovdd7e2842018-03-09 15:37:03 +0000216 auto* fec_packet = fec_packets.front();
brandtra8b38552016-10-10 16:44:57 -0700217 std::unique_ptr<Packet> packet_with_rtp_header =
218 packet_generator_.BuildFlexfecPacket(*fec_packet);
nissea5f043f2017-09-18 07:58:59 -0700219 std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet =
220 receiver_.AddReceivedPacket(ParsePacket(*packet_with_rtp_header));
221 ASSERT_TRUE(received_packet);
222 receiver_.ProcessReceivedPacket(*received_packet);
brandtra8b38552016-10-10 16:44:57 -0700223}
224
225TEST_F(FlexfecReceiverTest, RecoversFromSingleMediaLoss) {
226 const size_t kNumMediaPackets = 2;
227 const size_t kNumFecPackets = 1;
228
229 PacketList media_packets;
230 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
231 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
232
233 // Receive first media packet but drop second.
234 auto media_it = media_packets.begin();
nisse5c29a7a2017-02-16 06:52:32 -0800235 receiver_.OnRtpPacket(ParsePacket(**media_it));
brandtra8b38552016-10-10 16:44:57 -0700236
237 // Receive FEC packet and ensure recovery of lost media packet.
238 auto fec_it = fec_packets.begin();
239 std::unique_ptr<Packet> packet_with_rtp_header =
240 packet_generator_.BuildFlexfecPacket(**fec_it);
241 media_it++;
242 EXPECT_CALL(recovered_packet_receiver_,
Ilya Nikolaevskiyeec5fff2019-09-02 13:58:49 +0200243 OnRecoveredPacket(_, (*media_it)->data.size()))
244 .With(Args<0, 1>(ElementsAreArray((*media_it)->data.cdata(),
245 (*media_it)->data.size())));
nisse5c29a7a2017-02-16 06:52:32 -0800246 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700247}
248
249TEST_F(FlexfecReceiverTest, RecoversFromDoubleMediaLoss) {
250 const size_t kNumMediaPackets = 2;
251 const size_t kNumFecPackets = 2;
252
253 PacketList media_packets;
254 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
255 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
256
257 // Drop both media packets.
258
259 // Receive first FEC packet and recover first lost media packet.
260 auto fec_it = fec_packets.begin();
261 std::unique_ptr<Packet> packet_with_rtp_header =
262 packet_generator_.BuildFlexfecPacket(**fec_it);
263 auto media_it = media_packets.begin();
264 EXPECT_CALL(recovered_packet_receiver_,
Ilya Nikolaevskiyeec5fff2019-09-02 13:58:49 +0200265 OnRecoveredPacket(_, (*media_it)->data.size()))
266 .With(Args<0, 1>(ElementsAreArray((*media_it)->data.cdata(),
267 (*media_it)->data.size())));
nisse5c29a7a2017-02-16 06:52:32 -0800268 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700269
270 // Receive second FEC packet and recover second lost media packet.
271 fec_it++;
272 packet_with_rtp_header = packet_generator_.BuildFlexfecPacket(**fec_it);
273 media_it++;
274 EXPECT_CALL(recovered_packet_receiver_,
Ilya Nikolaevskiyeec5fff2019-09-02 13:58:49 +0200275 OnRecoveredPacket(_, (*media_it)->data.size()))
276 .With(Args<0, 1>(ElementsAreArray((*media_it)->data.cdata(),
277 (*media_it)->data.size())));
nisse5c29a7a2017-02-16 06:52:32 -0800278 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700279}
280
281TEST_F(FlexfecReceiverTest, DoesNotRecoverFromMediaAndFecLoss) {
282 const size_t kNumMediaPackets = 2;
283 const size_t kNumFecPackets = 1;
284
285 PacketList media_packets;
286 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
287 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
288
289 // Receive first media packet.
290 auto media_it = media_packets.begin();
nisse5c29a7a2017-02-16 06:52:32 -0800291 receiver_.OnRtpPacket(ParsePacket(**media_it));
brandtra8b38552016-10-10 16:44:57 -0700292
293 // Drop second media packet and FEC packet. Do not expect call back.
294}
295
296TEST_F(FlexfecReceiverTest, DoesNotCallbackTwice) {
297 const size_t kNumMediaPackets = 2;
298 const size_t kNumFecPackets = 1;
299
300 PacketList media_packets;
301 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
302 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
303
304 // Receive first media packet but drop second.
305 auto media_it = media_packets.begin();
nisse5c29a7a2017-02-16 06:52:32 -0800306 receiver_.OnRtpPacket(ParsePacket(**media_it));
brandtra8b38552016-10-10 16:44:57 -0700307
308 // Receive FEC packet and ensure recovery of lost media packet.
309 auto fec_it = fec_packets.begin();
310 std::unique_ptr<Packet> packet_with_rtp_header =
311 packet_generator_.BuildFlexfecPacket(**fec_it);
312 media_it++;
313 EXPECT_CALL(recovered_packet_receiver_,
Ilya Nikolaevskiyeec5fff2019-09-02 13:58:49 +0200314 OnRecoveredPacket(_, (*media_it)->data.size()))
315 .With(Args<0, 1>(ElementsAreArray((*media_it)->data.cdata(),
316 (*media_it)->data.size())));
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 FEC packet again, but do not call back.
nisse5c29a7a2017-02-16 06:52:32 -0800320 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700321
brandtrf27c5b82017-05-23 08:38:43 -0700322 // Receive the first media packet again, but do not call back.
323 media_it = media_packets.begin();
324 receiver_.OnRtpPacket(ParsePacket(**media_it));
325
326 // Receive the second media packet again (the one recovered above),
327 // but do not call back again.
328 media_it++;
329 receiver_.OnRtpPacket(ParsePacket(**media_it));
brandtra8b38552016-10-10 16:44:57 -0700330}
331
332// Here we are implicitly assuming packet masks that are suitable for
333// this type of 50% correlated loss. If we are changing our precomputed
334// packet masks, this test might need to be updated.
335TEST_F(FlexfecReceiverTest, RecoversFrom50PercentLoss) {
336 const size_t kNumFecPackets = 5;
337 const size_t kNumFrames = 2 * kNumFecPackets;
338 const size_t kNumMediaPacketsPerFrame = 1;
339
340 PacketList media_packets;
341 for (size_t i = 0; i < kNumFrames; ++i) {
342 PacketizeFrame(kNumMediaPacketsPerFrame, i, &media_packets);
343 }
344 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
345
346 // Drop every second media packet.
347 auto media_it = media_packets.begin();
348 while (media_it != media_packets.end()) {
nisse5c29a7a2017-02-16 06:52:32 -0800349 receiver_.OnRtpPacket(ParsePacket(**media_it));
brandtra8b38552016-10-10 16:44:57 -0700350 ++media_it;
351 if (media_it == media_packets.end()) {
352 break;
353 }
354 ++media_it;
355 }
356
357 // Receive all FEC packets.
358 media_it = media_packets.begin();
Danil Chapovalovdd7e2842018-03-09 15:37:03 +0000359 for (const auto* fec_packet : fec_packets) {
brandtra8b38552016-10-10 16:44:57 -0700360 std::unique_ptr<Packet> fec_packet_with_rtp_header =
361 packet_generator_.BuildFlexfecPacket(*fec_packet);
362 ++media_it;
363 if (media_it == media_packets.end()) {
364 break;
365 }
366 EXPECT_CALL(recovered_packet_receiver_,
Ilya Nikolaevskiyeec5fff2019-09-02 13:58:49 +0200367 OnRecoveredPacket(_, (*media_it)->data.size()))
368 .With(Args<0, 1>(ElementsAreArray((*media_it)->data.cdata(),
369 (*media_it)->data.size())));
nisse5c29a7a2017-02-16 06:52:32 -0800370 receiver_.OnRtpPacket(ParsePacket(*fec_packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700371 ++media_it;
372 }
373}
374
375TEST_F(FlexfecReceiverTest, DelayedFecPacketDoesHelp) {
376 // These values need to be updated if the underlying erasure code
377 // implementation changes.
378 const size_t kNumFrames = 48;
379 const size_t kNumMediaPacketsPerFrame = 1;
380 const size_t kNumFecPackets = 1;
381
382 PacketList media_packets;
383 PacketizeFrame(kNumMediaPacketsPerFrame, 0, &media_packets);
384 PacketizeFrame(kNumMediaPacketsPerFrame, 1, &media_packets);
385 // Protect two first frames.
386 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
387 for (size_t i = 2; i < kNumFrames; ++i) {
388 PacketizeFrame(kNumMediaPacketsPerFrame, i, &media_packets);
389 }
390
391 // Drop first media packet and delay FEC packet.
392 auto media_it = media_packets.begin();
393 ++media_it;
394
395 // Receive all other media packets.
396 while (media_it != media_packets.end()) {
nisse5c29a7a2017-02-16 06:52:32 -0800397 receiver_.OnRtpPacket(ParsePacket(**media_it));
brandtra8b38552016-10-10 16:44:57 -0700398 ++media_it;
399 }
400
401 // Receive FEC packet and recover first media packet.
402 auto fec_it = fec_packets.begin();
403 std::unique_ptr<Packet> packet_with_rtp_header =
404 packet_generator_.BuildFlexfecPacket(**fec_it);
405 media_it = media_packets.begin();
406 EXPECT_CALL(recovered_packet_receiver_,
Ilya Nikolaevskiyeec5fff2019-09-02 13:58:49 +0200407 OnRecoveredPacket(_, (*media_it)->data.size()))
408 .With(Args<0, 1>(ElementsAreArray((*media_it)->data.cdata(),
409 (*media_it)->data.size())));
nisse5c29a7a2017-02-16 06:52:32 -0800410 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700411}
412
413TEST_F(FlexfecReceiverTest, TooDelayedFecPacketDoesNotHelp) {
414 // These values need to be updated if the underlying erasure code
415 // implementation changes.
416 const size_t kNumFrames = 49;
417 const size_t kNumMediaPacketsPerFrame = 1;
418 const size_t kNumFecPackets = 1;
419
420 PacketList media_packets;
421 PacketizeFrame(kNumMediaPacketsPerFrame, 0, &media_packets);
422 PacketizeFrame(kNumMediaPacketsPerFrame, 1, &media_packets);
423 // Protect two first frames.
424 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
425 for (size_t i = 2; i < kNumFrames; ++i) {
426 PacketizeFrame(kNumMediaPacketsPerFrame, i, &media_packets);
427 }
428
429 // Drop first media packet and delay FEC packet.
430 auto media_it = media_packets.begin();
431 ++media_it;
432
433 // Receive all other media packets.
434 while (media_it != media_packets.end()) {
nisse5c29a7a2017-02-16 06:52:32 -0800435 receiver_.OnRtpPacket(ParsePacket(**media_it));
brandtra8b38552016-10-10 16:44:57 -0700436 ++media_it;
437 }
438
439 // Receive FEC packet.
440 auto fec_it = fec_packets.begin();
441 std::unique_ptr<Packet> packet_with_rtp_header =
442 packet_generator_.BuildFlexfecPacket(**fec_it);
nisse5c29a7a2017-02-16 06:52:32 -0800443 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700444
445 // Do not expect a call back.
446}
447
Rasmus Brandta00137c2017-12-12 10:01:20 +0100448TEST_F(FlexfecReceiverTest, SurvivesOldRecoveredPacketBeingReinserted) {
449 // Simulates the behaviour of the
450 // Call->FlexfecReceiveStream->FlexfecReceiver->Call loop in production code.
451 class LoopbackRecoveredPacketReceiver : public RecoveredPacketReceiver {
452 public:
453 LoopbackRecoveredPacketReceiver() : receiver_(nullptr) {}
454
455 void SetReceiver(FlexfecReceiver* receiver) { receiver_ = receiver; }
456
457 // Implements RecoveredPacketReceiver.
Danil Chapovalovdd7e2842018-03-09 15:37:03 +0000458 void OnRecoveredPacket(const uint8_t* packet, size_t length) override {
Rasmus Brandta00137c2017-12-12 10:01:20 +0100459 RtpPacketReceived parsed_packet;
460 EXPECT_TRUE(parsed_packet.Parse(packet, length));
461 parsed_packet.set_recovered(true);
462
463 RTC_DCHECK(receiver_);
464 receiver_->OnRtpPacket(parsed_packet);
465 }
466
467 private:
468 FlexfecReceiver* receiver_;
469 } loopback_recovered_packet_receiver;
470
471 // Feed recovered packets back into |receiver|.
Sebastian Jansson8026d602019-03-04 19:39:01 +0100472 FlexfecReceiver receiver(Clock::GetRealTimeClock(), kFlexfecSsrc, kMediaSsrc,
Rasmus Brandta00137c2017-12-12 10:01:20 +0100473 &loopback_recovered_packet_receiver);
474 loopback_recovered_packet_receiver.SetReceiver(&receiver);
475
476 // Receive first set of packets.
477 PacketList first_media_packets;
478 for (int i = 0; i < 46; ++i) {
479 PacketizeFrame(1, 0, &first_media_packets);
480 }
481 for (const auto& media_packet : first_media_packets) {
482 receiver.OnRtpPacket(ParsePacket(*media_packet));
483 }
484
485 // Protect one media packet. Lose the media packet,
486 // but do not receive FEC packet yet.
487 PacketList protected_media_packet;
488 PacketizeFrame(1, 0, &protected_media_packet);
489 const std::list<Packet*> fec_packets = EncodeFec(protected_media_packet, 1);
490 EXPECT_EQ(1u, fec_packets.size());
491 std::unique_ptr<Packet> fec_packet_with_rtp_header =
492 packet_generator_.BuildFlexfecPacket(*fec_packets.front());
493
494 // Lose some packets, thus introducing a sequence number gap.
495 PacketList lost_packets;
496 for (int i = 0; i < 100; ++i) {
497 PacketizeFrame(1, 0, &lost_packets);
498 }
499
500 // Receive one more packet.
501 PacketList second_media_packets;
502 PacketizeFrame(1, 0, &second_media_packets);
503 for (const auto& media_packet : second_media_packets) {
504 receiver.OnRtpPacket(ParsePacket(*media_packet));
505 }
506
507 // Receive delayed FEC packet.
508 receiver.OnRtpPacket(ParsePacket(*fec_packet_with_rtp_header));
509
510 // Expect no crash.
511}
512
brandtra8b38552016-10-10 16:44:57 -0700513TEST_F(FlexfecReceiverTest, RecoversWithMediaPacketsOutOfOrder) {
514 const size_t kNumMediaPackets = 6;
515 const size_t kNumFecPackets = 2;
516
517 PacketList media_packets;
518 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
519 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
520
521 // Lose two media packets, and receive the others out of order.
522 auto media_it = media_packets.begin();
523 auto media_packet0 = media_it++;
524 auto media_packet1 = media_it++;
525 auto media_packet2 = media_it++;
526 auto media_packet3 = media_it++;
527 auto media_packet4 = media_it++;
528 auto media_packet5 = media_it++;
nisse5c29a7a2017-02-16 06:52:32 -0800529 receiver_.OnRtpPacket(ParsePacket(**media_packet5));
530 receiver_.OnRtpPacket(ParsePacket(**media_packet2));
531 receiver_.OnRtpPacket(ParsePacket(**media_packet3));
532 receiver_.OnRtpPacket(ParsePacket(**media_packet0));
brandtra8b38552016-10-10 16:44:57 -0700533
534 // Expect to recover lost media packets.
535 EXPECT_CALL(recovered_packet_receiver_,
Ilya Nikolaevskiyeec5fff2019-09-02 13:58:49 +0200536 OnRecoveredPacket(_, (*media_packet1)->data.size()))
537 .With(Args<0, 1>(ElementsAreArray((*media_packet1)->data.cdata(),
538 (*media_packet1)->data.size())));
brandtra8b38552016-10-10 16:44:57 -0700539 EXPECT_CALL(recovered_packet_receiver_,
Ilya Nikolaevskiyeec5fff2019-09-02 13:58:49 +0200540 OnRecoveredPacket(_, (*media_packet4)->data.size()))
541 .With(Args<0, 1>(ElementsAreArray((*media_packet4)->data.cdata(),
542 (*media_packet4)->data.size())));
brandtra8b38552016-10-10 16:44:57 -0700543
544 // Add FEC packets.
545 auto fec_it = fec_packets.begin();
546 std::unique_ptr<Packet> packet_with_rtp_header;
547 while (fec_it != fec_packets.end()) {
548 packet_with_rtp_header = packet_generator_.BuildFlexfecPacket(**fec_it);
nisse5c29a7a2017-02-16 06:52:32 -0800549 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700550 ++fec_it;
551 }
552}
553
brandtrf27c5b82017-05-23 08:38:43 -0700554// Recovered media packets may be fed back into the FlexfecReceiver by the
555// callback. This test ensures the idempotency of such a situation.
556TEST_F(FlexfecReceiverTest, RecoveryCallbackDoesNotLoopInfinitely) {
557 class LoopbackRecoveredPacketReceiver : public RecoveredPacketReceiver {
558 public:
559 const int kMaxRecursionDepth = 10;
560
561 LoopbackRecoveredPacketReceiver()
562 : receiver_(nullptr),
563 did_receive_call_back_(false),
564 recursion_depth_(0),
565 deep_recursion_(false) {}
566
567 void SetReceiver(FlexfecReceiver* receiver) { receiver_ = receiver; }
568 bool DidReceiveCallback() const { return did_receive_call_back_; }
569 bool DeepRecursion() const { return deep_recursion_; }
570
571 // Implements RecoveredPacketReceiver.
Danil Chapovalovdd7e2842018-03-09 15:37:03 +0000572 void OnRecoveredPacket(const uint8_t* packet, size_t length) override {
brandtrf27c5b82017-05-23 08:38:43 -0700573 RtpPacketReceived parsed_packet;
574 EXPECT_TRUE(parsed_packet.Parse(packet, length));
575
576 did_receive_call_back_ = true;
577
578 if (recursion_depth_ > kMaxRecursionDepth) {
579 deep_recursion_ = true;
580 return;
581 }
582 ++recursion_depth_;
583 RTC_DCHECK(receiver_);
584 receiver_->OnRtpPacket(parsed_packet);
585 --recursion_depth_;
586 }
587
588 private:
589 FlexfecReceiver* receiver_;
590 bool did_receive_call_back_;
591 int recursion_depth_;
592 bool deep_recursion_;
593 } loopback_recovered_packet_receiver;
594
595 // Feed recovered packets back into |receiver|.
Sebastian Jansson8026d602019-03-04 19:39:01 +0100596 FlexfecReceiver receiver(Clock::GetRealTimeClock(), kFlexfecSsrc, kMediaSsrc,
brandtrf27c5b82017-05-23 08:38:43 -0700597 &loopback_recovered_packet_receiver);
598 loopback_recovered_packet_receiver.SetReceiver(&receiver);
599
600 const size_t kNumMediaPackets = 2;
601 const size_t kNumFecPackets = 1;
602
603 PacketList media_packets;
604 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
605 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
606
607 // Receive first media packet but drop second.
608 auto media_it = media_packets.begin();
609 receiver.OnRtpPacket(ParsePacket(**media_it));
610
611 // Receive FEC packet and verify that a packet was recovered.
612 auto fec_it = fec_packets.begin();
613 std::unique_ptr<Packet> packet_with_rtp_header =
614 packet_generator_.BuildFlexfecPacket(**fec_it);
615 receiver.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
616 EXPECT_TRUE(loopback_recovered_packet_receiver.DidReceiveCallback());
617 EXPECT_FALSE(loopback_recovered_packet_receiver.DeepRecursion());
618}
619
brandtra8b38552016-10-10 16:44:57 -0700620TEST_F(FlexfecReceiverTest, CalculatesNumberOfPackets) {
621 const size_t kNumMediaPackets = 2;
622 const size_t kNumFecPackets = 1;
623
624 PacketList media_packets;
625 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
626 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
627
628 // Receive first media packet but drop second.
629 auto media_it = media_packets.begin();
nisse5c29a7a2017-02-16 06:52:32 -0800630 receiver_.OnRtpPacket(ParsePacket(**media_it));
brandtra8b38552016-10-10 16:44:57 -0700631
632 // Receive FEC packet and ensure recovery of lost media packet.
633 auto fec_it = fec_packets.begin();
634 std::unique_ptr<Packet> packet_with_rtp_header =
635 packet_generator_.BuildFlexfecPacket(**fec_it);
636 media_it++;
637 EXPECT_CALL(recovered_packet_receiver_,
Ilya Nikolaevskiyeec5fff2019-09-02 13:58:49 +0200638 OnRecoveredPacket(_, (*media_it)->data.size()))
639 .With(Args<0, 1>(ElementsAreArray((*media_it)->data.cdata(),
640 (*media_it)->data.size())));
nisse5c29a7a2017-02-16 06:52:32 -0800641 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700642
643 // Check stats calculations.
brandtr0a4c1612016-11-03 08:18:27 -0700644 FecPacketCounter packet_counter = receiver_.GetPacketCounter();
brandtra8b38552016-10-10 16:44:57 -0700645 EXPECT_EQ(2U, packet_counter.num_packets);
646 EXPECT_EQ(1U, packet_counter.num_fec_packets);
647 EXPECT_EQ(1U, packet_counter.num_recovered_packets);
648}
649
650} // namespace webrtc