blob: 7261280aefde0c18a808fd32b6aae9c87d0f3f3a [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.
Danil Chapovalove15dc582021-01-07 15:24:05 +0100168 media_packet->data.MutableData()[8] = 0;
169 media_packet->data.MutableData()[9] = 1;
170 media_packet->data.MutableData()[10] = 2;
171 media_packet->data.MutableData()[11] = 3;
brandtra8b38552016-10-10 16:44:57 -0700172
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.
Danil Chapovalove15dc582021-01-07 15:24:05 +0100186 fec_packet->data.MutableData()[8] = 4;
187 fec_packet->data.MutableData()[9] = 5;
188 fec_packet->data.MutableData()[10] = 6;
189 fec_packet->data.MutableData()[11] = 7;
brandtra8b38552016-10-10 16:44:57 -0700190
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.
Harsh Maniar085eceb2021-04-21 01:21:53 -0700377 // Delay FEC packet by maximum number of media packets tracked by receiver.
378 const size_t kNumFrames = 192;
brandtra8b38552016-10-10 16:44:57 -0700379 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 Nikolaevskiya5d952f2019-09-03 11:07:37 +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.
Harsh Maniar085eceb2021-04-21 01:21:53 -0700416 // Delay FEC packet by one more than maximum number of media packets
417 // tracked by receiver.
418 const size_t kNumFrames = 193;
brandtra8b38552016-10-10 16:44:57 -0700419 const size_t kNumMediaPacketsPerFrame = 1;
420 const size_t kNumFecPackets = 1;
421
422 PacketList media_packets;
423 PacketizeFrame(kNumMediaPacketsPerFrame, 0, &media_packets);
424 PacketizeFrame(kNumMediaPacketsPerFrame, 1, &media_packets);
Harsh Maniar085eceb2021-04-21 01:21:53 -0700425 // Protect first two frames.
brandtra8b38552016-10-10 16:44:57 -0700426 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
427 for (size_t i = 2; i < kNumFrames; ++i) {
428 PacketizeFrame(kNumMediaPacketsPerFrame, i, &media_packets);
429 }
430
431 // Drop first media packet and delay FEC packet.
432 auto media_it = media_packets.begin();
433 ++media_it;
434
435 // Receive all other media packets.
436 while (media_it != media_packets.end()) {
nisse5c29a7a2017-02-16 06:52:32 -0800437 receiver_.OnRtpPacket(ParsePacket(**media_it));
brandtra8b38552016-10-10 16:44:57 -0700438 ++media_it;
439 }
440
441 // Receive FEC packet.
442 auto fec_it = fec_packets.begin();
443 std::unique_ptr<Packet> packet_with_rtp_header =
444 packet_generator_.BuildFlexfecPacket(**fec_it);
nisse5c29a7a2017-02-16 06:52:32 -0800445 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700446
447 // Do not expect a call back.
448}
449
Rasmus Brandta00137c2017-12-12 10:01:20 +0100450TEST_F(FlexfecReceiverTest, SurvivesOldRecoveredPacketBeingReinserted) {
451 // Simulates the behaviour of the
452 // Call->FlexfecReceiveStream->FlexfecReceiver->Call loop in production code.
453 class LoopbackRecoveredPacketReceiver : public RecoveredPacketReceiver {
454 public:
455 LoopbackRecoveredPacketReceiver() : receiver_(nullptr) {}
456
457 void SetReceiver(FlexfecReceiver* receiver) { receiver_ = receiver; }
458
459 // Implements RecoveredPacketReceiver.
Danil Chapovalovdd7e2842018-03-09 15:37:03 +0000460 void OnRecoveredPacket(const uint8_t* packet, size_t length) override {
Rasmus Brandta00137c2017-12-12 10:01:20 +0100461 RtpPacketReceived parsed_packet;
462 EXPECT_TRUE(parsed_packet.Parse(packet, length));
463 parsed_packet.set_recovered(true);
464
465 RTC_DCHECK(receiver_);
466 receiver_->OnRtpPacket(parsed_packet);
467 }
468
469 private:
470 FlexfecReceiver* receiver_;
471 } loopback_recovered_packet_receiver;
472
473 // Feed recovered packets back into |receiver|.
Sebastian Jansson8026d602019-03-04 19:39:01 +0100474 FlexfecReceiver receiver(Clock::GetRealTimeClock(), kFlexfecSsrc, kMediaSsrc,
Rasmus Brandta00137c2017-12-12 10:01:20 +0100475 &loopback_recovered_packet_receiver);
476 loopback_recovered_packet_receiver.SetReceiver(&receiver);
477
478 // Receive first set of packets.
479 PacketList first_media_packets;
480 for (int i = 0; i < 46; ++i) {
481 PacketizeFrame(1, 0, &first_media_packets);
482 }
483 for (const auto& media_packet : first_media_packets) {
484 receiver.OnRtpPacket(ParsePacket(*media_packet));
485 }
486
487 // Protect one media packet. Lose the media packet,
488 // but do not receive FEC packet yet.
489 PacketList protected_media_packet;
490 PacketizeFrame(1, 0, &protected_media_packet);
491 const std::list<Packet*> fec_packets = EncodeFec(protected_media_packet, 1);
492 EXPECT_EQ(1u, fec_packets.size());
493 std::unique_ptr<Packet> fec_packet_with_rtp_header =
494 packet_generator_.BuildFlexfecPacket(*fec_packets.front());
495
496 // Lose some packets, thus introducing a sequence number gap.
497 PacketList lost_packets;
498 for (int i = 0; i < 100; ++i) {
499 PacketizeFrame(1, 0, &lost_packets);
500 }
501
502 // Receive one more packet.
503 PacketList second_media_packets;
504 PacketizeFrame(1, 0, &second_media_packets);
505 for (const auto& media_packet : second_media_packets) {
506 receiver.OnRtpPacket(ParsePacket(*media_packet));
507 }
508
509 // Receive delayed FEC packet.
510 receiver.OnRtpPacket(ParsePacket(*fec_packet_with_rtp_header));
511
512 // Expect no crash.
513}
514
brandtra8b38552016-10-10 16:44:57 -0700515TEST_F(FlexfecReceiverTest, RecoversWithMediaPacketsOutOfOrder) {
516 const size_t kNumMediaPackets = 6;
517 const size_t kNumFecPackets = 2;
518
519 PacketList media_packets;
520 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
521 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
522
523 // Lose two media packets, and receive the others out of order.
524 auto media_it = media_packets.begin();
525 auto media_packet0 = media_it++;
526 auto media_packet1 = media_it++;
527 auto media_packet2 = media_it++;
528 auto media_packet3 = media_it++;
529 auto media_packet4 = media_it++;
530 auto media_packet5 = media_it++;
nisse5c29a7a2017-02-16 06:52:32 -0800531 receiver_.OnRtpPacket(ParsePacket(**media_packet5));
532 receiver_.OnRtpPacket(ParsePacket(**media_packet2));
533 receiver_.OnRtpPacket(ParsePacket(**media_packet3));
534 receiver_.OnRtpPacket(ParsePacket(**media_packet0));
brandtra8b38552016-10-10 16:44:57 -0700535
536 // Expect to recover lost media packets.
537 EXPECT_CALL(recovered_packet_receiver_,
Ilya Nikolaevskiya5d952f2019-09-03 11:07:37 +0200538 OnRecoveredPacket(_, (*media_packet1)->data.size()))
539 .With(Args<0, 1>(ElementsAreArray((*media_packet1)->data.cdata(),
540 (*media_packet1)->data.size())));
brandtra8b38552016-10-10 16:44:57 -0700541 EXPECT_CALL(recovered_packet_receiver_,
Ilya Nikolaevskiya5d952f2019-09-03 11:07:37 +0200542 OnRecoveredPacket(_, (*media_packet4)->data.size()))
543 .With(Args<0, 1>(ElementsAreArray((*media_packet4)->data.cdata(),
544 (*media_packet4)->data.size())));
brandtra8b38552016-10-10 16:44:57 -0700545
546 // Add FEC packets.
547 auto fec_it = fec_packets.begin();
548 std::unique_ptr<Packet> packet_with_rtp_header;
549 while (fec_it != fec_packets.end()) {
550 packet_with_rtp_header = packet_generator_.BuildFlexfecPacket(**fec_it);
nisse5c29a7a2017-02-16 06:52:32 -0800551 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700552 ++fec_it;
553 }
554}
555
brandtrf27c5b82017-05-23 08:38:43 -0700556// Recovered media packets may be fed back into the FlexfecReceiver by the
557// callback. This test ensures the idempotency of such a situation.
558TEST_F(FlexfecReceiverTest, RecoveryCallbackDoesNotLoopInfinitely) {
559 class LoopbackRecoveredPacketReceiver : public RecoveredPacketReceiver {
560 public:
561 const int kMaxRecursionDepth = 10;
562
563 LoopbackRecoveredPacketReceiver()
564 : receiver_(nullptr),
565 did_receive_call_back_(false),
566 recursion_depth_(0),
567 deep_recursion_(false) {}
568
569 void SetReceiver(FlexfecReceiver* receiver) { receiver_ = receiver; }
570 bool DidReceiveCallback() const { return did_receive_call_back_; }
571 bool DeepRecursion() const { return deep_recursion_; }
572
573 // Implements RecoveredPacketReceiver.
Danil Chapovalovdd7e2842018-03-09 15:37:03 +0000574 void OnRecoveredPacket(const uint8_t* packet, size_t length) override {
brandtrf27c5b82017-05-23 08:38:43 -0700575 RtpPacketReceived parsed_packet;
576 EXPECT_TRUE(parsed_packet.Parse(packet, length));
577
578 did_receive_call_back_ = true;
579
580 if (recursion_depth_ > kMaxRecursionDepth) {
581 deep_recursion_ = true;
582 return;
583 }
584 ++recursion_depth_;
585 RTC_DCHECK(receiver_);
586 receiver_->OnRtpPacket(parsed_packet);
587 --recursion_depth_;
588 }
589
590 private:
591 FlexfecReceiver* receiver_;
592 bool did_receive_call_back_;
593 int recursion_depth_;
594 bool deep_recursion_;
595 } loopback_recovered_packet_receiver;
596
597 // Feed recovered packets back into |receiver|.
Sebastian Jansson8026d602019-03-04 19:39:01 +0100598 FlexfecReceiver receiver(Clock::GetRealTimeClock(), kFlexfecSsrc, kMediaSsrc,
brandtrf27c5b82017-05-23 08:38:43 -0700599 &loopback_recovered_packet_receiver);
600 loopback_recovered_packet_receiver.SetReceiver(&receiver);
601
602 const size_t kNumMediaPackets = 2;
603 const size_t kNumFecPackets = 1;
604
605 PacketList media_packets;
606 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
607 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
608
609 // Receive first media packet but drop second.
610 auto media_it = media_packets.begin();
611 receiver.OnRtpPacket(ParsePacket(**media_it));
612
613 // Receive FEC packet and verify that a packet was recovered.
614 auto fec_it = fec_packets.begin();
615 std::unique_ptr<Packet> packet_with_rtp_header =
616 packet_generator_.BuildFlexfecPacket(**fec_it);
617 receiver.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
618 EXPECT_TRUE(loopback_recovered_packet_receiver.DidReceiveCallback());
619 EXPECT_FALSE(loopback_recovered_packet_receiver.DeepRecursion());
620}
621
brandtra8b38552016-10-10 16:44:57 -0700622TEST_F(FlexfecReceiverTest, CalculatesNumberOfPackets) {
623 const size_t kNumMediaPackets = 2;
624 const size_t kNumFecPackets = 1;
625
626 PacketList media_packets;
627 PacketizeFrame(kNumMediaPackets, 0, &media_packets);
628 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
629
630 // Receive first media packet but drop second.
631 auto media_it = media_packets.begin();
nisse5c29a7a2017-02-16 06:52:32 -0800632 receiver_.OnRtpPacket(ParsePacket(**media_it));
brandtra8b38552016-10-10 16:44:57 -0700633
634 // Receive FEC packet and ensure recovery of lost media packet.
635 auto fec_it = fec_packets.begin();
636 std::unique_ptr<Packet> packet_with_rtp_header =
637 packet_generator_.BuildFlexfecPacket(**fec_it);
638 media_it++;
639 EXPECT_CALL(recovered_packet_receiver_,
Ilya Nikolaevskiya5d952f2019-09-03 11:07:37 +0200640 OnRecoveredPacket(_, (*media_it)->data.size()))
641 .With(Args<0, 1>(ElementsAreArray((*media_it)->data.cdata(),
642 (*media_it)->data.size())));
nisse5c29a7a2017-02-16 06:52:32 -0800643 receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
brandtra8b38552016-10-10 16:44:57 -0700644
645 // Check stats calculations.
brandtr0a4c1612016-11-03 08:18:27 -0700646 FecPacketCounter packet_counter = receiver_.GetPacketCounter();
brandtra8b38552016-10-10 16:44:57 -0700647 EXPECT_EQ(2U, packet_counter.num_packets);
648 EXPECT_EQ(1U, packet_counter.num_fec_packets);
649 EXPECT_EQ(1U, packet_counter.num_recovered_packets);
650}
651
Harsh Maniar6ef4af92021-04-12 12:49:37 -0700652TEST_F(FlexfecReceiverTest, DoesNotDecodeWrappedMediaSequenceUsingOldFec) {
653 const size_t kFirstFrameNumMediaPackets = 2;
654 const size_t kFirstFrameNumFecPackets = 1;
655
656 PacketList media_packets;
657 PacketizeFrame(kFirstFrameNumMediaPackets, 0, &media_packets);
658
659 // Protect first frame (sequences 0 and 1) with 1 FEC packet.
660 std::list<Packet*> fec_packets =
661 EncodeFec(media_packets, kFirstFrameNumFecPackets);
662
663 // Generate enough media packets to simulate media sequence number wraparound.
664 // Use no FEC for these frames to make sure old FEC is not purged due to age.
665 const size_t kNumFramesSequenceWrapAround =
666 std::numeric_limits<uint16_t>::max();
667 const size_t kNumMediaPacketsPerFrame = 1;
668
669 for (size_t i = 1; i <= kNumFramesSequenceWrapAround; ++i) {
670 PacketizeFrame(kNumMediaPacketsPerFrame, i, &media_packets);
671 }
672
Harsh Maniar085eceb2021-04-21 01:21:53 -0700673 // Receive first (|kFirstFrameNumMediaPackets| + 192) media packets.
Harsh Maniar6ef4af92021-04-12 12:49:37 -0700674 // Simulate an old FEC packet by separating it from its encoded media
Harsh Maniar085eceb2021-04-21 01:21:53 -0700675 // packets by at least 192 packets.
Harsh Maniar6ef4af92021-04-12 12:49:37 -0700676 auto media_it = media_packets.begin();
Harsh Maniar085eceb2021-04-21 01:21:53 -0700677 for (size_t i = 0; i < (kFirstFrameNumMediaPackets + 192); i++) {
Harsh Maniar6ef4af92021-04-12 12:49:37 -0700678 if (i == 1) {
679 // Drop the second packet of the first frame.
680 media_it++;
681 } else {
682 receiver_.OnRtpPacket(ParsePacket(**media_it++));
683 }
684 }
685
686 // Receive FEC packet. Although a protected packet was dropped,
687 // expect no recovery callback since it is delayed from first frame
Harsh Maniar085eceb2021-04-21 01:21:53 -0700688 // by more than 192 packets.
Harsh Maniar6ef4af92021-04-12 12:49:37 -0700689 auto fec_it = fec_packets.begin();
690 std::unique_ptr<Packet> fec_packet_with_rtp_header =
691 packet_generator_.BuildFlexfecPacket(**fec_it);
692 receiver_.OnRtpPacket(ParsePacket(*fec_packet_with_rtp_header));
693
694 // Receive remaining media packets.
695 // NOTE: Because we sent enough to simulate wrap around, sequence 0 is
696 // received again, but is a different packet than the original first
697 // packet of first frame.
698 while (media_it != media_packets.end()) {
699 receiver_.OnRtpPacket(ParsePacket(**media_it++));
700 }
701
702 // Do not expect a recovery callback, the FEC packet is old
703 // and should not decode wrapped around media sequences.
704}
705
brandtra8b38552016-10-10 16:44:57 -0700706} // namespace webrtc