blob: dd33d6b6e90848c27097affa215cd9dfaaf610be [file] [log] [blame]
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +00001/*
2 * Copyright (c) 2012 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
phoglund@webrtc.org9919ad52013-05-16 15:06:28 +000011#include <string.h>
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +000012
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000013#include <list>
kwiberg84be5112016-04-27 01:19:58 -070014#include <memory>
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000015
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020016#include "modules/rtp_rtcp/include/rtp_header_parser.h"
17#include "modules/rtp_rtcp/include/ulpfec_receiver.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "modules/rtp_rtcp/mocks/mock_recovered_packet_receiver.h"
Yves Gerey665174f2018-06-19 15:03:05 +020019#include "modules/rtp_rtcp/mocks/mock_rtp_rtcp.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "modules/rtp_rtcp/source/byte_io.h"
21#include "modules/rtp_rtcp/source/fec_test_helper.h"
22#include "modules/rtp_rtcp/source/forward_error_correction.h"
23#include "test/gmock.h"
24#include "test/gtest.h"
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +000025
brandtrece4aba2016-09-20 23:16:28 -070026namespace webrtc {
27
28namespace {
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +000029using ::testing::_;
30using ::testing::Args;
31using ::testing::ElementsAreArray;
wu@webrtc.org822fbd82013-08-15 23:38:54 +000032using ::testing::Return;
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +000033
brandtr0aabdac2016-10-03 06:36:43 -070034using test::fec::AugmentedPacket;
brandtr71ca7472016-10-03 05:11:26 -070035using Packet = ForwardErrorCorrection::Packet;
brandtr71ca7472016-10-03 05:11:26 -070036using test::fec::UlpfecPacketGenerator;
37
38constexpr int kFecPayloadType = 96;
brandtr0aabdac2016-10-03 06:36:43 -070039constexpr uint32_t kMediaSsrc = 835424;
nisse30e89312017-05-29 08:16:37 -070040
41class NullRecoveredPacketReceiver : public RecoveredPacketReceiver {
42 public:
43 void OnRecoveredPacket(const uint8_t* packet, size_t length) override {}
44};
45
brandtr71ca7472016-10-03 05:11:26 -070046} // namespace
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +000047
brandtrd55c3f62016-10-31 04:51:33 -070048class UlpfecReceiverTest : public ::testing::Test {
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +000049 protected:
brandtrd55c3f62016-10-31 04:51:33 -070050 UlpfecReceiverTest()
brandtrd726a3f2017-06-29 02:45:35 -070051 : fec_(ForwardErrorCorrection::CreateUlpfec(kMediaSsrc)),
Ilya Nikolaevskiy2d821c32019-06-26 14:39:36 +020052 receiver_fec_(UlpfecReceiver::Create(kMediaSsrc,
53 &recovered_packet_receiver_,
54 {})),
brandtr0aabdac2016-10-03 06:36:43 -070055 packet_generator_(kMediaSsrc) {}
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +000056
brandtra2ece732016-10-04 00:00:06 -070057 // Generates |num_fec_packets| FEC packets, given |media_packets|.
brandtr71ca7472016-10-03 05:11:26 -070058 void EncodeFec(const ForwardErrorCorrection::PacketList& media_packets,
59 size_t num_fec_packets,
brandtra2ece732016-10-04 00:00:06 -070060 std::list<ForwardErrorCorrection::Packet*>* fec_packets);
stefan@webrtc.org7adab092012-02-09 12:34:52 +000061
brandtra2ece732016-10-04 00:00:06 -070062 // Generates |num_media_packets| corresponding to a single frame.
63 void PacketizeFrame(size_t num_media_packets,
64 size_t frame_offset,
65 std::list<AugmentedPacket*>* augmented_packets,
66 ForwardErrorCorrection::PacketList* packets);
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +000067
brandtra2ece732016-10-04 00:00:06 -070068 // Build a media packet using |packet_generator_| and add it
69 // to the receiver.
70 void BuildAndAddRedMediaPacket(AugmentedPacket* packet);
71
72 // Build a FEC packet using |packet_generator_| and add it
73 // to the receiver.
74 void BuildAndAddRedFecPacket(Packet* packet);
75
nisse30e89312017-05-29 08:16:37 -070076 // Ensure that |recovered_packet_receiver_| will be called correctly
brandtra2ece732016-10-04 00:00:06 -070077 // and that the recovered packet will be identical to the lost packet.
brandtr0aabdac2016-10-03 06:36:43 -070078 void VerifyReconstructedMediaPacket(const AugmentedPacket& packet,
brandtra2ece732016-10-04 00:00:06 -070079 size_t times);
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +000080
pbos2bad88d2015-07-06 03:09:08 -070081 void InjectGarbagePacketLength(size_t fec_garbage_offset);
brandtra2ece732016-10-04 00:00:06 -070082
pbos70d5c472015-06-29 07:22:04 -070083 static void SurvivesMaliciousPacket(const uint8_t* data,
84 size_t length,
85 uint8_t ulpfec_payload_type);
86
nisse30e89312017-05-29 08:16:37 -070087 MockRecoveredPacketReceiver recovered_packet_receiver_;
Rasmus Brandt78db1582016-09-21 09:19:34 +020088 std::unique_ptr<ForwardErrorCorrection> fec_;
brandtrd55c3f62016-10-31 04:51:33 -070089 std::unique_ptr<UlpfecReceiver> receiver_fec_;
brandtr0aabdac2016-10-03 06:36:43 -070090 UlpfecPacketGenerator packet_generator_;
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +000091};
92
brandtrd55c3f62016-10-31 04:51:33 -070093void UlpfecReceiverTest::EncodeFec(
brandtra2ece732016-10-04 00:00:06 -070094 const ForwardErrorCorrection::PacketList& media_packets,
95 size_t num_fec_packets,
96 std::list<ForwardErrorCorrection::Packet*>* fec_packets) {
97 const uint8_t protection_factor =
98 num_fec_packets * 255 / media_packets.size();
99 // Unequal protection is turned off, and the number of important
100 // packets is thus irrelevant.
101 constexpr int kNumImportantPackets = 0;
102 constexpr bool kUseUnequalProtection = false;
103 constexpr FecMaskType kFecMaskType = kFecMaskBursty;
104 EXPECT_EQ(
105 0, fec_->EncodeFec(media_packets, protection_factor, kNumImportantPackets,
106 kUseUnequalProtection, kFecMaskType, fec_packets));
107 ASSERT_EQ(num_fec_packets, fec_packets->size());
108}
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000109
brandtrd55c3f62016-10-31 04:51:33 -0700110void UlpfecReceiverTest::PacketizeFrame(
brandtra2ece732016-10-04 00:00:06 -0700111 size_t num_media_packets,
112 size_t frame_offset,
113 std::list<AugmentedPacket*>* augmented_packets,
114 ForwardErrorCorrection::PacketList* packets) {
115 packet_generator_.NewFrame(num_media_packets);
116 for (size_t i = 0; i < num_media_packets; ++i) {
117 std::unique_ptr<AugmentedPacket> next_packet(
118 packet_generator_.NextPacket(frame_offset + i, kRtpHeaderSize + 10));
119 augmented_packets->push_back(next_packet.get());
120 packets->push_back(std::move(next_packet));
121 }
122}
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000123
brandtrd55c3f62016-10-31 04:51:33 -0700124void UlpfecReceiverTest::BuildAndAddRedMediaPacket(AugmentedPacket* packet) {
brandtra2ece732016-10-04 00:00:06 -0700125 std::unique_ptr<AugmentedPacket> red_packet(
126 packet_generator_.BuildMediaRedPacket(*packet));
127 EXPECT_EQ(0, receiver_fec_->AddReceivedRedPacket(
Niels Möller70a83942019-03-12 09:54:30 +0100128 red_packet->header, red_packet->data, red_packet->length,
129 kFecPayloadType));
brandtra2ece732016-10-04 00:00:06 -0700130}
131
brandtrd55c3f62016-10-31 04:51:33 -0700132void UlpfecReceiverTest::BuildAndAddRedFecPacket(Packet* packet) {
brandtra2ece732016-10-04 00:00:06 -0700133 std::unique_ptr<AugmentedPacket> red_packet(
134 packet_generator_.BuildUlpfecRedPacket(*packet));
135 EXPECT_EQ(0, receiver_fec_->AddReceivedRedPacket(
Niels Möller70a83942019-03-12 09:54:30 +0100136 red_packet->header, red_packet->data, red_packet->length,
137 kFecPayloadType));
brandtra2ece732016-10-04 00:00:06 -0700138}
139
brandtrd55c3f62016-10-31 04:51:33 -0700140void UlpfecReceiverTest::VerifyReconstructedMediaPacket(
brandtra2ece732016-10-04 00:00:06 -0700141 const AugmentedPacket& packet,
142 size_t times) {
143 // Verify that the content of the reconstructed packet is equal to the
144 // content of |packet|, and that the same content is received |times| number
145 // of times in a row.
nisse30e89312017-05-29 08:16:37 -0700146 EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, packet.length))
brandtra2ece732016-10-04 00:00:06 -0700147 .With(Args<0, 1>(ElementsAreArray(packet.data, packet.length)))
nisse30e89312017-05-29 08:16:37 -0700148 .Times(times);
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000149}
150
brandtrd55c3f62016-10-31 04:51:33 -0700151void UlpfecReceiverTest::InjectGarbagePacketLength(size_t fec_garbage_offset) {
nisse30e89312017-05-29 08:16:37 -0700152 EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, _));
pbos2bad88d2015-07-06 03:09:08 -0700153
brandtr71ca7472016-10-03 05:11:26 -0700154 const size_t kNumFecPackets = 1;
brandtr0aabdac2016-10-03 06:36:43 -0700155 std::list<AugmentedPacket*> augmented_media_packets;
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200156 ForwardErrorCorrection::PacketList media_packets;
brandtra2ece732016-10-04 00:00:06 -0700157 PacketizeFrame(2, 0, &augmented_media_packets, &media_packets);
brandtr35c480c2016-08-09 01:23:23 -0700158 std::list<ForwardErrorCorrection::Packet*> fec_packets;
brandtr71ca7472016-10-03 05:11:26 -0700159 EncodeFec(media_packets, kNumFecPackets, &fec_packets);
pbos2bad88d2015-07-06 03:09:08 -0700160 ByteWriter<uint16_t>::WriteBigEndian(
161 &fec_packets.front()->data[fec_garbage_offset], 0x4711);
162
163 // Inject first media packet, then first FEC packet, skipping the second media
164 // packet to cause a recovery from the FEC packet.
brandtr0aabdac2016-10-03 06:36:43 -0700165 BuildAndAddRedMediaPacket(augmented_media_packets.front());
pbos2bad88d2015-07-06 03:09:08 -0700166 BuildAndAddRedFecPacket(fec_packets.front());
167 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
168
169 FecPacketCounter counter = receiver_fec_->GetPacketCounter();
brandtr71ca7472016-10-03 05:11:26 -0700170 EXPECT_EQ(2U, counter.num_packets);
171 EXPECT_EQ(1U, counter.num_fec_packets);
172 EXPECT_EQ(0U, counter.num_recovered_packets);
pbos2bad88d2015-07-06 03:09:08 -0700173}
174
brandtrd55c3f62016-10-31 04:51:33 -0700175void UlpfecReceiverTest::SurvivesMaliciousPacket(const uint8_t* data,
176 size_t length,
177 uint8_t ulpfec_payload_type) {
178 RTPHeader header;
179 std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
brandtra2ece732016-10-04 00:00:06 -0700180 ASSERT_TRUE(parser->Parse(data, length, &header));
181
nisse30e89312017-05-29 08:16:37 -0700182 NullRecoveredPacketReceiver null_callback;
brandtrd55c3f62016-10-31 04:51:33 -0700183 std::unique_ptr<UlpfecReceiver> receiver_fec(
Ilya Nikolaevskiy2d821c32019-06-26 14:39:36 +0200184 UlpfecReceiver::Create(kMediaSsrc, &null_callback, {}));
brandtra2ece732016-10-04 00:00:06 -0700185
186 receiver_fec->AddReceivedRedPacket(header, data, length, ulpfec_payload_type);
187}
188
brandtrd55c3f62016-10-31 04:51:33 -0700189TEST_F(UlpfecReceiverTest, TwoMediaOneFec) {
brandtra2ece732016-10-04 00:00:06 -0700190 constexpr size_t kNumFecPackets = 1u;
191 std::list<AugmentedPacket*> augmented_media_packets;
192 ForwardErrorCorrection::PacketList media_packets;
193 PacketizeFrame(2, 0, &augmented_media_packets, &media_packets);
194 std::list<ForwardErrorCorrection::Packet*> fec_packets;
195 EncodeFec(media_packets, kNumFecPackets, &fec_packets);
196
asapersson0c43f772016-11-30 01:42:26 -0800197 FecPacketCounter counter = receiver_fec_->GetPacketCounter();
198 EXPECT_EQ(0u, counter.num_packets);
199 EXPECT_EQ(-1, counter.first_packet_time_ms);
200
brandtra2ece732016-10-04 00:00:06 -0700201 // Recovery
202 auto it = augmented_media_packets.begin();
203 BuildAndAddRedMediaPacket(*it);
204 VerifyReconstructedMediaPacket(**it, 1);
205 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
asapersson0c43f772016-11-30 01:42:26 -0800206 counter = receiver_fec_->GetPacketCounter();
207 EXPECT_EQ(1u, counter.num_packets);
208 EXPECT_EQ(0u, counter.num_fec_packets);
209 EXPECT_EQ(0u, counter.num_recovered_packets);
210 const int64_t first_packet_time_ms = counter.first_packet_time_ms;
211 EXPECT_NE(-1, first_packet_time_ms);
212
brandtra2ece732016-10-04 00:00:06 -0700213 // Drop one media packet.
214 auto fec_it = fec_packets.begin();
215 BuildAndAddRedFecPacket(*fec_it);
216 ++it;
217 VerifyReconstructedMediaPacket(**it, 1);
218 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
219
asapersson0c43f772016-11-30 01:42:26 -0800220 counter = receiver_fec_->GetPacketCounter();
brandtra2ece732016-10-04 00:00:06 -0700221 EXPECT_EQ(2u, counter.num_packets);
222 EXPECT_EQ(1u, counter.num_fec_packets);
223 EXPECT_EQ(1u, counter.num_recovered_packets);
asapersson0c43f772016-11-30 01:42:26 -0800224 EXPECT_EQ(first_packet_time_ms, counter.first_packet_time_ms);
brandtra2ece732016-10-04 00:00:06 -0700225}
226
brandtrd55c3f62016-10-31 04:51:33 -0700227TEST_F(UlpfecReceiverTest, InjectGarbageFecHeaderLengthRecovery) {
pbos2bad88d2015-07-06 03:09:08 -0700228 // Byte offset 8 is the 'length recovery' field of the FEC header.
229 InjectGarbagePacketLength(8);
230}
231
brandtrd55c3f62016-10-31 04:51:33 -0700232TEST_F(UlpfecReceiverTest, InjectGarbageFecLevelHeaderProtectionLength) {
pbos2bad88d2015-07-06 03:09:08 -0700233 // Byte offset 10 is the 'protection length' field in the first FEC level
234 // header.
235 InjectGarbagePacketLength(10);
236}
237
brandtrd55c3f62016-10-31 04:51:33 -0700238TEST_F(UlpfecReceiverTest, TwoMediaTwoFec) {
brandtr71ca7472016-10-03 05:11:26 -0700239 const size_t kNumFecPackets = 2;
brandtr0aabdac2016-10-03 06:36:43 -0700240 std::list<AugmentedPacket*> augmented_media_packets;
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200241 ForwardErrorCorrection::PacketList media_packets;
brandtra2ece732016-10-04 00:00:06 -0700242 PacketizeFrame(2, 0, &augmented_media_packets, &media_packets);
brandtr35c480c2016-08-09 01:23:23 -0700243 std::list<ForwardErrorCorrection::Packet*> fec_packets;
brandtr71ca7472016-10-03 05:11:26 -0700244 EncodeFec(media_packets, kNumFecPackets, &fec_packets);
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000245
246 // Recovery
247 // Drop both media packets.
brandtr0aabdac2016-10-03 06:36:43 -0700248 auto it = augmented_media_packets.begin();
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200249 auto fec_it = fec_packets.begin();
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000250 BuildAndAddRedFecPacket(*fec_it);
brandtr71ca7472016-10-03 05:11:26 -0700251 VerifyReconstructedMediaPacket(**it, 1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000252 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000253 ++fec_it;
254 BuildAndAddRedFecPacket(*fec_it);
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000255 ++it;
brandtr71ca7472016-10-03 05:11:26 -0700256 VerifyReconstructedMediaPacket(**it, 1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000257 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000258}
259
brandtrd55c3f62016-10-31 04:51:33 -0700260TEST_F(UlpfecReceiverTest, TwoFramesOneFec) {
brandtr71ca7472016-10-03 05:11:26 -0700261 const size_t kNumFecPackets = 1;
brandtr0aabdac2016-10-03 06:36:43 -0700262 std::list<AugmentedPacket*> augmented_media_packets;
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200263 ForwardErrorCorrection::PacketList media_packets;
brandtra2ece732016-10-04 00:00:06 -0700264 PacketizeFrame(1, 0, &augmented_media_packets, &media_packets);
265 PacketizeFrame(1, 1, &augmented_media_packets, &media_packets);
brandtr35c480c2016-08-09 01:23:23 -0700266 std::list<ForwardErrorCorrection::Packet*> fec_packets;
brandtr71ca7472016-10-03 05:11:26 -0700267 EncodeFec(media_packets, kNumFecPackets, &fec_packets);
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000268
269 // Recovery
brandtr0aabdac2016-10-03 06:36:43 -0700270 auto it = augmented_media_packets.begin();
271 BuildAndAddRedMediaPacket(augmented_media_packets.front());
brandtr71ca7472016-10-03 05:11:26 -0700272 VerifyReconstructedMediaPacket(**it, 1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000273 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000274 // Drop one media packet.
275 BuildAndAddRedFecPacket(fec_packets.front());
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000276 ++it;
brandtr71ca7472016-10-03 05:11:26 -0700277 VerifyReconstructedMediaPacket(**it, 1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000278 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000279}
280
brandtrd55c3f62016-10-31 04:51:33 -0700281TEST_F(UlpfecReceiverTest, OneCompleteOneUnrecoverableFrame) {
brandtr71ca7472016-10-03 05:11:26 -0700282 const size_t kNumFecPackets = 1;
brandtr0aabdac2016-10-03 06:36:43 -0700283 std::list<AugmentedPacket*> augmented_media_packets;
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200284 ForwardErrorCorrection::PacketList media_packets;
brandtra2ece732016-10-04 00:00:06 -0700285 PacketizeFrame(1, 0, &augmented_media_packets, &media_packets);
286 PacketizeFrame(2, 1, &augmented_media_packets, &media_packets);
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000287
brandtr35c480c2016-08-09 01:23:23 -0700288 std::list<ForwardErrorCorrection::Packet*> fec_packets;
brandtr71ca7472016-10-03 05:11:26 -0700289 EncodeFec(media_packets, kNumFecPackets, &fec_packets);
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000290
291 // Recovery
brandtr0aabdac2016-10-03 06:36:43 -0700292 auto it = augmented_media_packets.begin();
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000293 BuildAndAddRedMediaPacket(*it); // First frame: one packet.
brandtr71ca7472016-10-03 05:11:26 -0700294 VerifyReconstructedMediaPacket(**it, 1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000295 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000296 ++it;
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000297 BuildAndAddRedMediaPacket(*it); // First packet of second frame.
brandtr71ca7472016-10-03 05:11:26 -0700298 VerifyReconstructedMediaPacket(**it, 1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000299 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000300}
301
brandtrd55c3f62016-10-31 04:51:33 -0700302TEST_F(UlpfecReceiverTest, MaxFramesOneFec) {
brandtr71ca7472016-10-03 05:11:26 -0700303 const size_t kNumFecPackets = 1;
304 const size_t kNumMediaPackets = 48;
brandtr0aabdac2016-10-03 06:36:43 -0700305 std::list<AugmentedPacket*> augmented_media_packets;
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200306 ForwardErrorCorrection::PacketList media_packets;
brandtr71ca7472016-10-03 05:11:26 -0700307 for (size_t i = 0; i < kNumMediaPackets; ++i) {
brandtra2ece732016-10-04 00:00:06 -0700308 PacketizeFrame(1, i, &augmented_media_packets, &media_packets);
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000309 }
brandtr35c480c2016-08-09 01:23:23 -0700310 std::list<ForwardErrorCorrection::Packet*> fec_packets;
brandtr71ca7472016-10-03 05:11:26 -0700311 EncodeFec(media_packets, kNumFecPackets, &fec_packets);
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000312
313 // Recovery
brandtr0aabdac2016-10-03 06:36:43 -0700314 auto it = augmented_media_packets.begin();
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000315 ++it; // Drop first packet.
brandtr0aabdac2016-10-03 06:36:43 -0700316 for (; it != augmented_media_packets.end(); ++it) {
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000317 BuildAndAddRedMediaPacket(*it);
brandtr71ca7472016-10-03 05:11:26 -0700318 VerifyReconstructedMediaPacket(**it, 1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000319 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000320 }
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000321 BuildAndAddRedFecPacket(fec_packets.front());
brandtr0aabdac2016-10-03 06:36:43 -0700322 it = augmented_media_packets.begin();
brandtr71ca7472016-10-03 05:11:26 -0700323 VerifyReconstructedMediaPacket(**it, 1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000324 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000325}
326
brandtrd55c3f62016-10-31 04:51:33 -0700327TEST_F(UlpfecReceiverTest, TooManyFrames) {
brandtr71ca7472016-10-03 05:11:26 -0700328 const size_t kNumFecPackets = 1;
329 const size_t kNumMediaPackets = 49;
brandtr0aabdac2016-10-03 06:36:43 -0700330 std::list<AugmentedPacket*> augmented_media_packets;
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200331 ForwardErrorCorrection::PacketList media_packets;
brandtr71ca7472016-10-03 05:11:26 -0700332 for (size_t i = 0; i < kNumMediaPackets; ++i) {
brandtra2ece732016-10-04 00:00:06 -0700333 PacketizeFrame(1, i, &augmented_media_packets, &media_packets);
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000334 }
brandtr35c480c2016-08-09 01:23:23 -0700335 std::list<ForwardErrorCorrection::Packet*> fec_packets;
Rasmus Brandt78db1582016-09-21 09:19:34 +0200336 EXPECT_EQ(-1, fec_->EncodeFec(media_packets,
337 kNumFecPackets * 255 / kNumMediaPackets, 0,
338 false, kFecMaskBursty, &fec_packets));
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000339}
340
brandtrd55c3f62016-10-31 04:51:33 -0700341TEST_F(UlpfecReceiverTest, PacketNotDroppedTooEarly) {
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000342 // 1 frame with 2 media packets and one FEC packet. One media packet missing.
343 // Delay the FEC packet.
brandtr71ca7472016-10-03 05:11:26 -0700344 Packet* delayed_fec = nullptr;
345 const size_t kNumFecPacketsBatch1 = 1;
346 const size_t kNumMediaPacketsBatch1 = 2;
brandtr0aabdac2016-10-03 06:36:43 -0700347 std::list<AugmentedPacket*> augmented_media_packets_batch1;
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200348 ForwardErrorCorrection::PacketList media_packets_batch1;
brandtra2ece732016-10-04 00:00:06 -0700349 PacketizeFrame(kNumMediaPacketsBatch1, 0, &augmented_media_packets_batch1,
350 &media_packets_batch1);
brandtr35c480c2016-08-09 01:23:23 -0700351 std::list<ForwardErrorCorrection::Packet*> fec_packets;
brandtr71ca7472016-10-03 05:11:26 -0700352 EncodeFec(media_packets_batch1, kNumFecPacketsBatch1, &fec_packets);
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000353
brandtr0aabdac2016-10-03 06:36:43 -0700354 BuildAndAddRedMediaPacket(augmented_media_packets_batch1.front());
Yves Gerey665174f2018-06-19 15:03:05 +0200355 EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, _)).Times(1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000356 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000357 delayed_fec = fec_packets.front();
358
359 // Fill the FEC decoder. No packets should be dropped.
brandtr71ca7472016-10-03 05:11:26 -0700360 const size_t kNumMediaPacketsBatch2 = 46;
brandtr0aabdac2016-10-03 06:36:43 -0700361 std::list<AugmentedPacket*> augmented_media_packets_batch2;
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200362 ForwardErrorCorrection::PacketList media_packets_batch2;
brandtr71ca7472016-10-03 05:11:26 -0700363 for (size_t i = 0; i < kNumMediaPacketsBatch2; ++i) {
brandtra2ece732016-10-04 00:00:06 -0700364 PacketizeFrame(1, i, &augmented_media_packets_batch2,
365 &media_packets_batch2);
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000366 }
brandtr0aabdac2016-10-03 06:36:43 -0700367 for (auto it = augmented_media_packets_batch2.begin();
368 it != augmented_media_packets_batch2.end(); ++it) {
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000369 BuildAndAddRedMediaPacket(*it);
Yves Gerey665174f2018-06-19 15:03:05 +0200370 EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, _)).Times(1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000371 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000372 }
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000373
374 // Add the delayed FEC packet. One packet should be reconstructed.
375 BuildAndAddRedFecPacket(delayed_fec);
Yves Gerey665174f2018-06-19 15:03:05 +0200376 EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, _)).Times(1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000377 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000378}
379
brandtrd55c3f62016-10-31 04:51:33 -0700380TEST_F(UlpfecReceiverTest, PacketDroppedWhenTooOld) {
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000381 // 1 frame with 2 media packets and one FEC packet. One media packet missing.
382 // Delay the FEC packet.
brandtr71ca7472016-10-03 05:11:26 -0700383 Packet* delayed_fec = nullptr;
384 const size_t kNumFecPacketsBatch1 = 1;
385 const size_t kNumMediaPacketsBatch1 = 2;
brandtr0aabdac2016-10-03 06:36:43 -0700386 std::list<AugmentedPacket*> augmented_media_packets_batch1;
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200387 ForwardErrorCorrection::PacketList media_packets_batch1;
brandtra2ece732016-10-04 00:00:06 -0700388 PacketizeFrame(kNumMediaPacketsBatch1, 0, &augmented_media_packets_batch1,
389 &media_packets_batch1);
brandtr35c480c2016-08-09 01:23:23 -0700390 std::list<ForwardErrorCorrection::Packet*> fec_packets;
brandtr71ca7472016-10-03 05:11:26 -0700391 EncodeFec(media_packets_batch1, kNumFecPacketsBatch1, &fec_packets);
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000392
brandtr0aabdac2016-10-03 06:36:43 -0700393 BuildAndAddRedMediaPacket(augmented_media_packets_batch1.front());
Yves Gerey665174f2018-06-19 15:03:05 +0200394 EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, _)).Times(1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000395 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000396 delayed_fec = fec_packets.front();
397
398 // Fill the FEC decoder and force the last packet to be dropped.
brandtr71ca7472016-10-03 05:11:26 -0700399 const size_t kNumMediaPacketsBatch2 = 48;
brandtr0aabdac2016-10-03 06:36:43 -0700400 std::list<AugmentedPacket*> augmented_media_packets_batch2;
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200401 ForwardErrorCorrection::PacketList media_packets_batch2;
brandtr71ca7472016-10-03 05:11:26 -0700402 for (size_t i = 0; i < kNumMediaPacketsBatch2; ++i) {
brandtra2ece732016-10-04 00:00:06 -0700403 PacketizeFrame(1, i, &augmented_media_packets_batch2,
404 &media_packets_batch2);
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000405 }
brandtr0aabdac2016-10-03 06:36:43 -0700406 for (auto it = augmented_media_packets_batch2.begin();
407 it != augmented_media_packets_batch2.end(); ++it) {
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000408 BuildAndAddRedMediaPacket(*it);
Yves Gerey665174f2018-06-19 15:03:05 +0200409 EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, _)).Times(1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000410 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000411 }
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000412
413 // Add the delayed FEC packet. No packet should be reconstructed since the
414 // first media packet of that frame has been dropped due to being too old.
415 BuildAndAddRedFecPacket(delayed_fec);
nisse30e89312017-05-29 08:16:37 -0700416 EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, _)).Times(0);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000417 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000418}
419
brandtrd55c3f62016-10-31 04:51:33 -0700420TEST_F(UlpfecReceiverTest, OldFecPacketDropped) {
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000421 // 49 frames with 2 media packets and one FEC packet. All media packets
422 // missing.
brandtr71ca7472016-10-03 05:11:26 -0700423 const size_t kNumMediaPackets = 49 * 2;
brandtr0aabdac2016-10-03 06:36:43 -0700424 std::list<AugmentedPacket*> augmented_media_packets;
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200425 ForwardErrorCorrection::PacketList media_packets;
brandtr71ca7472016-10-03 05:11:26 -0700426 for (size_t i = 0; i < kNumMediaPackets / 2; ++i) {
brandtr0aabdac2016-10-03 06:36:43 -0700427 std::list<AugmentedPacket*> frame_augmented_media_packets;
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200428 ForwardErrorCorrection::PacketList frame_media_packets;
brandtr35c480c2016-08-09 01:23:23 -0700429 std::list<ForwardErrorCorrection::Packet*> fec_packets;
brandtra2ece732016-10-04 00:00:06 -0700430 PacketizeFrame(2, 0, &frame_augmented_media_packets, &frame_media_packets);
brandtr71ca7472016-10-03 05:11:26 -0700431 EncodeFec(frame_media_packets, 1, &fec_packets);
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200432 for (auto it = fec_packets.begin(); it != fec_packets.end(); ++it) {
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000433 // Only FEC packets inserted. No packets recoverable at this time.
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000434 BuildAndAddRedFecPacket(*it);
nisse30e89312017-05-29 08:16:37 -0700435 EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, _)).Times(0);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000436 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000437 }
brandtr35c480c2016-08-09 01:23:23 -0700438 // Move unique_ptr's to media_packets for lifetime management.
439 media_packets.insert(media_packets.end(),
440 std::make_move_iterator(frame_media_packets.begin()),
441 std::make_move_iterator(frame_media_packets.end()));
brandtr0aabdac2016-10-03 06:36:43 -0700442 augmented_media_packets.insert(augmented_media_packets.end(),
443 frame_augmented_media_packets.begin(),
444 frame_augmented_media_packets.end());
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000445 }
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000446 // Insert the oldest media packet. The corresponding FEC packet is too old
brandtr71ca7472016-10-03 05:11:26 -0700447 // and should have been dropped. Only the media packet we inserted will be
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000448 // returned.
brandtr0aabdac2016-10-03 06:36:43 -0700449 BuildAndAddRedMediaPacket(augmented_media_packets.front());
Yves Gerey665174f2018-06-19 15:03:05 +0200450 EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, _)).Times(1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000451 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000452}
453
brandtrd55c3f62016-10-31 04:51:33 -0700454TEST_F(UlpfecReceiverTest, TruncatedPacketWithFBitSet) {
455 const uint8_t kTruncatedPacket[] = {0x80, 0x2a, 0x68, 0x71, 0x29, 0xa1, 0x27,
456 0x3a, 0x29, 0x12, 0x2a, 0x98, 0xe0, 0x29};
pbos70d5c472015-06-29 07:22:04 -0700457
458 SurvivesMaliciousPacket(kTruncatedPacket, sizeof(kTruncatedPacket), 100);
459}
460
brandtrd55c3f62016-10-31 04:51:33 -0700461TEST_F(UlpfecReceiverTest,
462 TruncatedPacketWithFBitSetEndingAfterFirstRedHeader) {
463 const uint8_t kPacket[] = {
464 0x89, 0x27, 0x3a, 0x83, 0x27, 0x3a, 0x3a, 0xf3, 0x67, 0xbe, 0x2a,
465 0xa9, 0x27, 0x54, 0x3a, 0x3a, 0x2a, 0x67, 0x3a, 0xf3, 0x67, 0xbe,
466 0x2a, 0x27, 0xe6, 0xf6, 0x03, 0x3e, 0x29, 0x27, 0x21, 0x27, 0x2a,
467 0x29, 0x21, 0x4b, 0x29, 0x3a, 0x28, 0x29, 0xbf, 0x29, 0x2a, 0x26,
468 0x29, 0xae, 0x27, 0xa6, 0xf6, 0x00, 0x03, 0x3e};
pbos2e43b262015-06-30 01:32:40 -0700469 SurvivesMaliciousPacket(kPacket, sizeof(kPacket), 100);
470}
471
brandtrd55c3f62016-10-31 04:51:33 -0700472TEST_F(UlpfecReceiverTest, TruncatedPacketWithoutDataPastFirstBlock) {
473 const uint8_t kPacket[] = {
474 0x82, 0x38, 0x92, 0x38, 0x92, 0x38, 0xde, 0x2a, 0x11, 0xc8, 0xa3, 0xc4,
475 0x82, 0x38, 0x2a, 0x21, 0x2a, 0x28, 0x92, 0x38, 0x92, 0x00, 0x00, 0x0a,
476 0x3a, 0xc8, 0xa3, 0x3a, 0x27, 0xc4, 0x2a, 0x21, 0x2a, 0x28};
pbos2e43b262015-06-30 01:32:40 -0700477 SurvivesMaliciousPacket(kPacket, sizeof(kPacket), 100);
478}
479
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000480} // namespace webrtc