blob: 199d7860b2348c39780ed1169f8979445d2af32a [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;
brandtra8b38552016-10-10 16:44:57 -070030
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;
Ilya Nikolaevskiya5d952f2019-09-03 11:07:37 +020041 EXPECT_TRUE(parsed_packet.Parse(packet.data));
brandtrb29e6522016-12-21 06:37:18 -080042 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)
Sebastian Jansson8026d602019-03-04 19:39:01 +010052 : FlexfecReceiver(Clock::GetRealTimeClock(),
53 ssrc,
54 protected_media_ssrc,
55 recovered_packet_receiver) {}
nisse5c29a7a2017-02-16 06:52:32 -080056 // Expose methods for tests.
57 using FlexfecReceiver::AddReceivedPacket;
nissea5f043f2017-09-18 07:58:59 -070058 using FlexfecReceiver::ProcessReceivedPacket;
nisse5c29a7a2017-02-16 06:52:32 -080059};
60
brandtra8b38552016-10-10 16:44:57 -070061class FlexfecReceiverTest : public ::testing::Test {
62 protected:
63 FlexfecReceiverTest()
brandtr0a4c1612016-11-03 08:18:27 -070064 : receiver_(kFlexfecSsrc, kMediaSsrc, &recovered_packet_receiver_),
brandtrd726a3f2017-06-29 02:45:35 -070065 erasure_code_(
66 ForwardErrorCorrection::CreateFlexfec(kFlexfecSsrc, kMediaSsrc)),
brandtra8b38552016-10-10 16:44:57 -070067 packet_generator_(kMediaSsrc, kFlexfecSsrc) {}
68
69 // Generates |num_media_packets| corresponding to a single frame.
70 void PacketizeFrame(size_t num_media_packets,
71 size_t frame_offset,
72 PacketList* media_packets);
73
74 // Generates |num_fec_packets| FEC packets, given |media_packets|.
75 std::list<Packet*> EncodeFec(const PacketList& media_packets,
76 size_t num_fec_packets);
77
nisse5c29a7a2017-02-16 06:52:32 -080078 FlexfecReceiverForTest receiver_;
brandtra8b38552016-10-10 16:44:57 -070079 std::unique_ptr<ForwardErrorCorrection> erasure_code_;
80
81 FlexfecPacketGenerator packet_generator_;
Mirko Bonadei6a489f22019-04-09 15:11:12 +020082 ::testing::StrictMock<MockRecoveredPacketReceiver> recovered_packet_receiver_;
brandtra8b38552016-10-10 16:44:57 -070083};
84
85void FlexfecReceiverTest::PacketizeFrame(size_t num_media_packets,
86 size_t frame_offset,
87 PacketList* media_packets) {
88 packet_generator_.NewFrame(num_media_packets);
89 for (size_t i = 0; i < num_media_packets; ++i) {
90 std::unique_ptr<Packet> next_packet(
91 packet_generator_.NextPacket(frame_offset + i, kPayloadLength));
92 media_packets->push_back(std::move(next_packet));
93 }
94}
95
96std::list<Packet*> FlexfecReceiverTest::EncodeFec(
97 const PacketList& media_packets,
98 size_t num_fec_packets) {
99 const uint8_t protection_factor =
100 num_fec_packets * 255 / media_packets.size();
101 constexpr int kNumImportantPackets = 0;
102 constexpr bool kUseUnequalProtection = false;
103 constexpr FecMaskType kFecMaskType = kFecMaskRandom;
104 std::list<Packet*> fec_packets;
105 EXPECT_EQ(0, erasure_code_->EncodeFec(
106 media_packets, protection_factor, kNumImportantPackets,
107 kUseUnequalProtection, kFecMaskType, &fec_packets));
108 EXPECT_EQ(num_fec_packets, fec_packets.size());
109 return fec_packets;
110}
111
112TEST_F(FlexfecReceiverTest, ReceivesMediaPacket) {
113 packet_generator_.NewFrame(1);
114 std::unique_ptr<Packet> media_packet(
115 packet_generator_.NextPacket(0, kPayloadLength));
116
nissea5f043f2017-09-18 07:58:59 -0700117 std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet =
118 receiver_.AddReceivedPacket(ParsePacket(*media_packet));
119 ASSERT_TRUE(received_packet);
120 receiver_.ProcessReceivedPacket(*received_packet);
brandtra8b38552016-10-10 16:44:57 -0700121}
122
123TEST_F(FlexfecReceiverTest, ReceivesMediaAndFecPackets) {
124 const size_t kNumMediaPackets = 1;
125 const size_t kNumFecPackets = 1;
126
127 PacketList media_packets;
128 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
129 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
brandtrb29e6522016-12-21 06:37:18 -0800130 const auto& media_packet = media_packets.front();
brandtra8b38552016-10-10 16:44:57 -0700131 auto fec_packet = packet_generator_.BuildFlexfecPacket(*fec_packets.front());
132
nissea5f043f2017-09-18 07:58:59 -0700133 std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet =
134 receiver_.AddReceivedPacket(ParsePacket(*media_packet));
135 ASSERT_TRUE(received_packet);
136 receiver_.ProcessReceivedPacket(*received_packet);
137 received_packet = receiver_.AddReceivedPacket(ParsePacket(*fec_packet));
138 ASSERT_TRUE(received_packet);
139 receiver_.ProcessReceivedPacket(*received_packet);
brandtra8b38552016-10-10 16:44:57 -0700140}
141
142TEST_F(FlexfecReceiverTest, FailsOnTruncatedFecPacket) {
143 const size_t kNumMediaPackets = 1;
144 const size_t kNumFecPackets = 1;
145
146 PacketList media_packets;
147 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
148 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
brandtrb29e6522016-12-21 06:37:18 -0800149 const auto& media_packet = media_packets.front();
brandtra8b38552016-10-10 16:44:57 -0700150 // Simulate truncated FlexFEC payload.
Ilya Nikolaevskiya5d952f2019-09-03 11:07:37 +0200151 fec_packets.front()->data.SetSize(1);
brandtra8b38552016-10-10 16:44:57 -0700152 auto fec_packet = packet_generator_.BuildFlexfecPacket(*fec_packets.front());
153
nissea5f043f2017-09-18 07:58:59 -0700154 std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet =
155 receiver_.AddReceivedPacket(ParsePacket(*media_packet));
156 ASSERT_TRUE(received_packet);
157 receiver_.ProcessReceivedPacket(*received_packet);
nisse5c29a7a2017-02-16 06:52:32 -0800158 EXPECT_FALSE(receiver_.AddReceivedPacket(ParsePacket(*fec_packet)));
brandtra8b38552016-10-10 16:44:57 -0700159}
160
161TEST_F(FlexfecReceiverTest, FailsOnUnknownMediaSsrc) {
162 const size_t kNumMediaPackets = 1;
163
164 PacketList media_packets;
165 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
brandtrb29e6522016-12-21 06:37:18 -0800166 auto& media_packet = media_packets.front();
brandtra8b38552016-10-10 16:44:57 -0700167 // Corrupt the SSRC.
168 media_packet->data[8] = 0;
169 media_packet->data[9] = 1;
170 media_packet->data[10] = 2;
171 media_packet->data[11] = 3;
172
nisse5c29a7a2017-02-16 06:52:32 -0800173 EXPECT_FALSE(receiver_.AddReceivedPacket(ParsePacket(*media_packet)));
brandtra8b38552016-10-10 16:44:57 -0700174}
175
176TEST_F(FlexfecReceiverTest, FailsOnUnknownFecSsrc) {
177 const size_t kNumMediaPackets = 1;
178 const size_t kNumFecPackets = 1;
179
180 PacketList media_packets;
181 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
182 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
brandtrb29e6522016-12-21 06:37:18 -0800183 const auto& media_packet = media_packets.front();
brandtra8b38552016-10-10 16:44:57 -0700184 auto fec_packet = packet_generator_.BuildFlexfecPacket(*fec_packets.front());
185 // Corrupt the SSRC.
186 fec_packet->data[8] = 4;
187 fec_packet->data[9] = 5;
188 fec_packet->data[10] = 6;
189 fec_packet->data[11] = 7;
190
nissea5f043f2017-09-18 07:58:59 -0700191 std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet =
192 receiver_.AddReceivedPacket(ParsePacket(*media_packet));
193 ASSERT_TRUE(received_packet);
194 receiver_.ProcessReceivedPacket(*received_packet);
nisse5c29a7a2017-02-16 06:52:32 -0800195 EXPECT_FALSE(receiver_.AddReceivedPacket(ParsePacket(*fec_packet)));
brandtra8b38552016-10-10 16:44:57 -0700196}
197
198TEST_F(FlexfecReceiverTest, ReceivesMultiplePackets) {
199 const size_t kNumMediaPackets = 2;
200 const size_t kNumFecPackets = 1;
201
202 PacketList media_packets;
203 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
204 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
205
206 // Receive all media packets.
207 for (const auto& media_packet : media_packets) {
nissea5f043f2017-09-18 07:58:59 -0700208 std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet =
209 receiver_.AddReceivedPacket(ParsePacket(*media_packet));
210 ASSERT_TRUE(received_packet);
211 receiver_.ProcessReceivedPacket(*received_packet);
brandtra8b38552016-10-10 16:44:57 -0700212 }
213
214 // Receive FEC packet.
Danil Chapovalovdd7e2842018-03-09 15:37:03 +0000215 auto* fec_packet = fec_packets.front();
brandtra8b38552016-10-10 16:44:57 -0700216 std::unique_ptr<Packet> packet_with_rtp_header =
217 packet_generator_.BuildFlexfecPacket(*fec_packet);
nissea5f043f2017-09-18 07:58:59 -0700218 std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet =
219 receiver_.AddReceivedPacket(ParsePacket(*packet_with_rtp_header));
220 ASSERT_TRUE(received_packet);
221 receiver_.ProcessReceivedPacket(*received_packet);
brandtra8b38552016-10-10 16:44:57 -0700222}
223
224TEST_F(FlexfecReceiverTest, RecoversFromSingleMediaLoss) {
225 const size_t kNumMediaPackets = 2;
226 const size_t kNumFecPackets = 1;
227
228 PacketList media_packets;
229 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
230 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
231
232 // Receive first media packet but drop second.
233 auto media_it = media_packets.begin();
nisse5c29a7a2017-02-16 06:52:32 -0800234 receiver_.OnRtpPacket(ParsePacket(**media_it));
brandtra8b38552016-10-10 16:44:57 -0700235
236 // Receive FEC packet and ensure recovery of lost media packet.
237 auto fec_it = fec_packets.begin();
238 std::unique_ptr<Packet> packet_with_rtp_header =
239 packet_generator_.BuildFlexfecPacket(**fec_it);
240 media_it++;
241 EXPECT_CALL(recovered_packet_receiver_,
Ilya Nikolaevskiya5d952f2019-09-03 11:07:37 +0200242 OnRecoveredPacket(_, (*media_it)->data.size()))
243 .With(Args<0, 1>(ElementsAreArray((*media_it)->data.cdata(),
244 (*media_it)->data.size())));
nisse5c29a7a2017-02-16 06:52:32 -0800245 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700246}
247
248TEST_F(FlexfecReceiverTest, RecoversFromDoubleMediaLoss) {
249 const size_t kNumMediaPackets = 2;
250 const size_t kNumFecPackets = 2;
251
252 PacketList media_packets;
253 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
254 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
255
256 // Drop both media packets.
257
258 // Receive first FEC packet and recover first lost media packet.
259 auto fec_it = fec_packets.begin();
260 std::unique_ptr<Packet> packet_with_rtp_header =
261 packet_generator_.BuildFlexfecPacket(**fec_it);
262 auto media_it = media_packets.begin();
263 EXPECT_CALL(recovered_packet_receiver_,
Ilya Nikolaevskiya5d952f2019-09-03 11:07:37 +0200264 OnRecoveredPacket(_, (*media_it)->data.size()))
265 .With(Args<0, 1>(ElementsAreArray((*media_it)->data.cdata(),
266 (*media_it)->data.size())));
nisse5c29a7a2017-02-16 06:52:32 -0800267 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700268
269 // Receive second FEC packet and recover second lost media packet.
270 fec_it++;
271 packet_with_rtp_header = packet_generator_.BuildFlexfecPacket(**fec_it);
272 media_it++;
273 EXPECT_CALL(recovered_packet_receiver_,
Ilya Nikolaevskiya5d952f2019-09-03 11:07:37 +0200274 OnRecoveredPacket(_, (*media_it)->data.size()))
275 .With(Args<0, 1>(ElementsAreArray((*media_it)->data.cdata(),
276 (*media_it)->data.size())));
nisse5c29a7a2017-02-16 06:52:32 -0800277 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700278}
279
280TEST_F(FlexfecReceiverTest, DoesNotRecoverFromMediaAndFecLoss) {
281 const size_t kNumMediaPackets = 2;
282 const size_t kNumFecPackets = 1;
283
284 PacketList media_packets;
285 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
286 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
287
288 // Receive first media packet.
289 auto media_it = media_packets.begin();
nisse5c29a7a2017-02-16 06:52:32 -0800290 receiver_.OnRtpPacket(ParsePacket(**media_it));
brandtra8b38552016-10-10 16:44:57 -0700291
292 // Drop second media packet and FEC packet. Do not expect call back.
293}
294
295TEST_F(FlexfecReceiverTest, DoesNotCallbackTwice) {
296 const size_t kNumMediaPackets = 2;
297 const size_t kNumFecPackets = 1;
298
299 PacketList media_packets;
300 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
301 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
302
303 // Receive first media packet but drop second.
304 auto media_it = media_packets.begin();
nisse5c29a7a2017-02-16 06:52:32 -0800305 receiver_.OnRtpPacket(ParsePacket(**media_it));
brandtra8b38552016-10-10 16:44:57 -0700306
307 // Receive FEC packet and ensure recovery of lost media packet.
308 auto fec_it = fec_packets.begin();
309 std::unique_ptr<Packet> packet_with_rtp_header =
310 packet_generator_.BuildFlexfecPacket(**fec_it);
311 media_it++;
312 EXPECT_CALL(recovered_packet_receiver_,
Ilya Nikolaevskiya5d952f2019-09-03 11:07:37 +0200313 OnRecoveredPacket(_, (*media_it)->data.size()))
314 .With(Args<0, 1>(ElementsAreArray((*media_it)->data.cdata(),
315 (*media_it)->data.size())));
nisse5c29a7a2017-02-16 06:52:32 -0800316 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700317
brandtrf27c5b82017-05-23 08:38:43 -0700318 // Receive the FEC packet again, but do not call back.
nisse5c29a7a2017-02-16 06:52:32 -0800319 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700320
brandtrf27c5b82017-05-23 08:38:43 -0700321 // Receive the first media packet again, but do not call back.
322 media_it = media_packets.begin();
323 receiver_.OnRtpPacket(ParsePacket(**media_it));
324
325 // Receive the second media packet again (the one recovered above),
326 // but do not call back again.
327 media_it++;
328 receiver_.OnRtpPacket(ParsePacket(**media_it));
brandtra8b38552016-10-10 16:44:57 -0700329}
330
331// Here we are implicitly assuming packet masks that are suitable for
332// this type of 50% correlated loss. If we are changing our precomputed
333// packet masks, this test might need to be updated.
334TEST_F(FlexfecReceiverTest, RecoversFrom50PercentLoss) {
335 const size_t kNumFecPackets = 5;
336 const size_t kNumFrames = 2 * kNumFecPackets;
337 const size_t kNumMediaPacketsPerFrame = 1;
338
339 PacketList media_packets;
340 for (size_t i = 0; i < kNumFrames; ++i) {
341 PacketizeFrame(kNumMediaPacketsPerFrame, i, &media_packets);
342 }
343 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
344
345 // Drop every second media packet.
346 auto media_it = media_packets.begin();
347 while (media_it != media_packets.end()) {
nisse5c29a7a2017-02-16 06:52:32 -0800348 receiver_.OnRtpPacket(ParsePacket(**media_it));
brandtra8b38552016-10-10 16:44:57 -0700349 ++media_it;
350 if (media_it == media_packets.end()) {
351 break;
352 }
353 ++media_it;
354 }
355
356 // Receive all FEC packets.
357 media_it = media_packets.begin();
Danil Chapovalovdd7e2842018-03-09 15:37:03 +0000358 for (const auto* fec_packet : fec_packets) {
brandtra8b38552016-10-10 16:44:57 -0700359 std::unique_ptr<Packet> fec_packet_with_rtp_header =
360 packet_generator_.BuildFlexfecPacket(*fec_packet);
361 ++media_it;
362 if (media_it == media_packets.end()) {
363 break;
364 }
365 EXPECT_CALL(recovered_packet_receiver_,
Ilya Nikolaevskiya5d952f2019-09-03 11:07:37 +0200366 OnRecoveredPacket(_, (*media_it)->data.size()))
367 .With(Args<0, 1>(ElementsAreArray((*media_it)->data.cdata(),
368 (*media_it)->data.size())));
nisse5c29a7a2017-02-16 06:52:32 -0800369 receiver_.OnRtpPacket(ParsePacket(*fec_packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700370 ++media_it;
371 }
372}
373
374TEST_F(FlexfecReceiverTest, DelayedFecPacketDoesHelp) {
375 // These values need to be updated if the underlying erasure code
376 // implementation changes.
377 const size_t kNumFrames = 48;
378 const size_t kNumMediaPacketsPerFrame = 1;
379 const size_t kNumFecPackets = 1;
380
381 PacketList media_packets;
382 PacketizeFrame(kNumMediaPacketsPerFrame, 0, &media_packets);
383 PacketizeFrame(kNumMediaPacketsPerFrame, 1, &media_packets);
384 // Protect two first frames.
385 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
386 for (size_t i = 2; i < kNumFrames; ++i) {
387 PacketizeFrame(kNumMediaPacketsPerFrame, i, &media_packets);
388 }
389
390 // Drop first media packet and delay FEC packet.
391 auto media_it = media_packets.begin();
392 ++media_it;
393
394 // Receive all other media packets.
395 while (media_it != media_packets.end()) {
nisse5c29a7a2017-02-16 06:52:32 -0800396 receiver_.OnRtpPacket(ParsePacket(**media_it));
brandtra8b38552016-10-10 16:44:57 -0700397 ++media_it;
398 }
399
400 // Receive FEC packet and recover first media packet.
401 auto fec_it = fec_packets.begin();
402 std::unique_ptr<Packet> packet_with_rtp_header =
403 packet_generator_.BuildFlexfecPacket(**fec_it);
404 media_it = media_packets.begin();
405 EXPECT_CALL(recovered_packet_receiver_,
Ilya Nikolaevskiya5d952f2019-09-03 11:07:37 +0200406 OnRecoveredPacket(_, (*media_it)->data.size()))
407 .With(Args<0, 1>(ElementsAreArray((*media_it)->data.cdata(),
408 (*media_it)->data.size())));
nisse5c29a7a2017-02-16 06:52:32 -0800409 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700410}
411
412TEST_F(FlexfecReceiverTest, TooDelayedFecPacketDoesNotHelp) {
413 // These values need to be updated if the underlying erasure code
414 // implementation changes.
415 const size_t kNumFrames = 49;
416 const size_t kNumMediaPacketsPerFrame = 1;
417 const size_t kNumFecPackets = 1;
418
419 PacketList media_packets;
420 PacketizeFrame(kNumMediaPacketsPerFrame, 0, &media_packets);
421 PacketizeFrame(kNumMediaPacketsPerFrame, 1, &media_packets);
422 // Protect two first frames.
423 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
424 for (size_t i = 2; i < kNumFrames; ++i) {
425 PacketizeFrame(kNumMediaPacketsPerFrame, i, &media_packets);
426 }
427
428 // Drop first media packet and delay FEC packet.
429 auto media_it = media_packets.begin();
430 ++media_it;
431
432 // Receive all other media packets.
433 while (media_it != media_packets.end()) {
nisse5c29a7a2017-02-16 06:52:32 -0800434 receiver_.OnRtpPacket(ParsePacket(**media_it));
brandtra8b38552016-10-10 16:44:57 -0700435 ++media_it;
436 }
437
438 // Receive FEC packet.
439 auto fec_it = fec_packets.begin();
440 std::unique_ptr<Packet> packet_with_rtp_header =
441 packet_generator_.BuildFlexfecPacket(**fec_it);
nisse5c29a7a2017-02-16 06:52:32 -0800442 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700443
444 // Do not expect a call back.
445}
446
Rasmus Brandta00137c2017-12-12 10:01:20 +0100447TEST_F(FlexfecReceiverTest, SurvivesOldRecoveredPacketBeingReinserted) {
448 // Simulates the behaviour of the
449 // Call->FlexfecReceiveStream->FlexfecReceiver->Call loop in production code.
450 class LoopbackRecoveredPacketReceiver : public RecoveredPacketReceiver {
451 public:
452 LoopbackRecoveredPacketReceiver() : receiver_(nullptr) {}
453
454 void SetReceiver(FlexfecReceiver* receiver) { receiver_ = receiver; }
455
456 // Implements RecoveredPacketReceiver.
Danil Chapovalovdd7e2842018-03-09 15:37:03 +0000457 void OnRecoveredPacket(const uint8_t* packet, size_t length) override {
Rasmus Brandta00137c2017-12-12 10:01:20 +0100458 RtpPacketReceived parsed_packet;
459 EXPECT_TRUE(parsed_packet.Parse(packet, length));
460 parsed_packet.set_recovered(true);
461
462 RTC_DCHECK(receiver_);
463 receiver_->OnRtpPacket(parsed_packet);
464 }
465
466 private:
467 FlexfecReceiver* receiver_;
468 } loopback_recovered_packet_receiver;
469
470 // Feed recovered packets back into |receiver|.
Sebastian Jansson8026d602019-03-04 19:39:01 +0100471 FlexfecReceiver receiver(Clock::GetRealTimeClock(), kFlexfecSsrc, kMediaSsrc,
Rasmus Brandta00137c2017-12-12 10:01:20 +0100472 &loopback_recovered_packet_receiver);
473 loopback_recovered_packet_receiver.SetReceiver(&receiver);
474
475 // Receive first set of packets.
476 PacketList first_media_packets;
477 for (int i = 0; i < 46; ++i) {
478 PacketizeFrame(1, 0, &first_media_packets);
479 }
480 for (const auto& media_packet : first_media_packets) {
481 receiver.OnRtpPacket(ParsePacket(*media_packet));
482 }
483
484 // Protect one media packet. Lose the media packet,
485 // but do not receive FEC packet yet.
486 PacketList protected_media_packet;
487 PacketizeFrame(1, 0, &protected_media_packet);
488 const std::list<Packet*> fec_packets = EncodeFec(protected_media_packet, 1);
489 EXPECT_EQ(1u, fec_packets.size());
490 std::unique_ptr<Packet> fec_packet_with_rtp_header =
491 packet_generator_.BuildFlexfecPacket(*fec_packets.front());
492
493 // Lose some packets, thus introducing a sequence number gap.
494 PacketList lost_packets;
495 for (int i = 0; i < 100; ++i) {
496 PacketizeFrame(1, 0, &lost_packets);
497 }
498
499 // Receive one more packet.
500 PacketList second_media_packets;
501 PacketizeFrame(1, 0, &second_media_packets);
502 for (const auto& media_packet : second_media_packets) {
503 receiver.OnRtpPacket(ParsePacket(*media_packet));
504 }
505
506 // Receive delayed FEC packet.
507 receiver.OnRtpPacket(ParsePacket(*fec_packet_with_rtp_header));
508
509 // Expect no crash.
510}
511
brandtra8b38552016-10-10 16:44:57 -0700512TEST_F(FlexfecReceiverTest, RecoversWithMediaPacketsOutOfOrder) {
513 const size_t kNumMediaPackets = 6;
514 const size_t kNumFecPackets = 2;
515
516 PacketList media_packets;
517 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
518 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
519
520 // Lose two media packets, and receive the others out of order.
521 auto media_it = media_packets.begin();
522 auto media_packet0 = media_it++;
523 auto media_packet1 = media_it++;
524 auto media_packet2 = media_it++;
525 auto media_packet3 = media_it++;
526 auto media_packet4 = media_it++;
527 auto media_packet5 = media_it++;
nisse5c29a7a2017-02-16 06:52:32 -0800528 receiver_.OnRtpPacket(ParsePacket(**media_packet5));
529 receiver_.OnRtpPacket(ParsePacket(**media_packet2));
530 receiver_.OnRtpPacket(ParsePacket(**media_packet3));
531 receiver_.OnRtpPacket(ParsePacket(**media_packet0));
brandtra8b38552016-10-10 16:44:57 -0700532
533 // Expect to recover lost media packets.
534 EXPECT_CALL(recovered_packet_receiver_,
Ilya Nikolaevskiya5d952f2019-09-03 11:07:37 +0200535 OnRecoveredPacket(_, (*media_packet1)->data.size()))
536 .With(Args<0, 1>(ElementsAreArray((*media_packet1)->data.cdata(),
537 (*media_packet1)->data.size())));
brandtra8b38552016-10-10 16:44:57 -0700538 EXPECT_CALL(recovered_packet_receiver_,
Ilya Nikolaevskiya5d952f2019-09-03 11:07:37 +0200539 OnRecoveredPacket(_, (*media_packet4)->data.size()))
540 .With(Args<0, 1>(ElementsAreArray((*media_packet4)->data.cdata(),
541 (*media_packet4)->data.size())));
brandtra8b38552016-10-10 16:44:57 -0700542
543 // Add FEC packets.
544 auto fec_it = fec_packets.begin();
545 std::unique_ptr<Packet> packet_with_rtp_header;
546 while (fec_it != fec_packets.end()) {
547 packet_with_rtp_header = packet_generator_.BuildFlexfecPacket(**fec_it);
nisse5c29a7a2017-02-16 06:52:32 -0800548 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700549 ++fec_it;
550 }
551}
552
brandtrf27c5b82017-05-23 08:38:43 -0700553// Recovered media packets may be fed back into the FlexfecReceiver by the
554// callback. This test ensures the idempotency of such a situation.
555TEST_F(FlexfecReceiverTest, RecoveryCallbackDoesNotLoopInfinitely) {
556 class LoopbackRecoveredPacketReceiver : public RecoveredPacketReceiver {
557 public:
558 const int kMaxRecursionDepth = 10;
559
560 LoopbackRecoveredPacketReceiver()
561 : receiver_(nullptr),
562 did_receive_call_back_(false),
563 recursion_depth_(0),
564 deep_recursion_(false) {}
565
566 void SetReceiver(FlexfecReceiver* receiver) { receiver_ = receiver; }
567 bool DidReceiveCallback() const { return did_receive_call_back_; }
568 bool DeepRecursion() const { return deep_recursion_; }
569
570 // Implements RecoveredPacketReceiver.
Danil Chapovalovdd7e2842018-03-09 15:37:03 +0000571 void OnRecoveredPacket(const uint8_t* packet, size_t length) override {
brandtrf27c5b82017-05-23 08:38:43 -0700572 RtpPacketReceived parsed_packet;
573 EXPECT_TRUE(parsed_packet.Parse(packet, length));
574
575 did_receive_call_back_ = true;
576
577 if (recursion_depth_ > kMaxRecursionDepth) {
578 deep_recursion_ = true;
579 return;
580 }
581 ++recursion_depth_;
582 RTC_DCHECK(receiver_);
583 receiver_->OnRtpPacket(parsed_packet);
584 --recursion_depth_;
585 }
586
587 private:
588 FlexfecReceiver* receiver_;
589 bool did_receive_call_back_;
590 int recursion_depth_;
591 bool deep_recursion_;
592 } loopback_recovered_packet_receiver;
593
594 // Feed recovered packets back into |receiver|.
Sebastian Jansson8026d602019-03-04 19:39:01 +0100595 FlexfecReceiver receiver(Clock::GetRealTimeClock(), kFlexfecSsrc, kMediaSsrc,
brandtrf27c5b82017-05-23 08:38:43 -0700596 &loopback_recovered_packet_receiver);
597 loopback_recovered_packet_receiver.SetReceiver(&receiver);
598
599 const size_t kNumMediaPackets = 2;
600 const size_t kNumFecPackets = 1;
601
602 PacketList media_packets;
603 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
604 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
605
606 // Receive first media packet but drop second.
607 auto media_it = media_packets.begin();
608 receiver.OnRtpPacket(ParsePacket(**media_it));
609
610 // Receive FEC packet and verify that a packet was recovered.
611 auto fec_it = fec_packets.begin();
612 std::unique_ptr<Packet> packet_with_rtp_header =
613 packet_generator_.BuildFlexfecPacket(**fec_it);
614 receiver.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
615 EXPECT_TRUE(loopback_recovered_packet_receiver.DidReceiveCallback());
616 EXPECT_FALSE(loopback_recovered_packet_receiver.DeepRecursion());
617}
618
brandtra8b38552016-10-10 16:44:57 -0700619TEST_F(FlexfecReceiverTest, CalculatesNumberOfPackets) {
620 const size_t kNumMediaPackets = 2;
621 const size_t kNumFecPackets = 1;
622
623 PacketList media_packets;
624 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
625 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
626
627 // Receive first media packet but drop second.
628 auto media_it = media_packets.begin();
nisse5c29a7a2017-02-16 06:52:32 -0800629 receiver_.OnRtpPacket(ParsePacket(**media_it));
brandtra8b38552016-10-10 16:44:57 -0700630
631 // Receive FEC packet and ensure recovery of lost media packet.
632 auto fec_it = fec_packets.begin();
633 std::unique_ptr<Packet> packet_with_rtp_header =
634 packet_generator_.BuildFlexfecPacket(**fec_it);
635 media_it++;
636 EXPECT_CALL(recovered_packet_receiver_,
Ilya Nikolaevskiya5d952f2019-09-03 11:07:37 +0200637 OnRecoveredPacket(_, (*media_it)->data.size()))
638 .With(Args<0, 1>(ElementsAreArray((*media_it)->data.cdata(),
639 (*media_it)->data.size())));
nisse5c29a7a2017-02-16 06:52:32 -0800640 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700641
642 // Check stats calculations.
brandtr0a4c1612016-11-03 08:18:27 -0700643 FecPacketCounter packet_counter = receiver_.GetPacketCounter();
brandtra8b38552016-10-10 16:44:57 -0700644 EXPECT_EQ(2U, packet_counter.num_packets);
645 EXPECT_EQ(1U, packet_counter.num_fec_packets);
646 EXPECT_EQ(1U, packet_counter.num_recovered_packets);
647}
648
649} // namespace webrtc