blob: e050f807d0d86dcf3a83f36a1b74be6cdc2ac562 [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)),
52 receiver_fec_(
53 UlpfecReceiver::Create(kMediaSsrc, &recovered_packet_receiver_)),
brandtr0aabdac2016-10-03 06:36:43 -070054 packet_generator_(kMediaSsrc) {}
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +000055
brandtra2ece732016-10-04 00:00:06 -070056 // Generates |num_fec_packets| FEC packets, given |media_packets|.
brandtr71ca7472016-10-03 05:11:26 -070057 void EncodeFec(const ForwardErrorCorrection::PacketList& media_packets,
58 size_t num_fec_packets,
brandtra2ece732016-10-04 00:00:06 -070059 std::list<ForwardErrorCorrection::Packet*>* fec_packets);
stefan@webrtc.org7adab092012-02-09 12:34:52 +000060
brandtra2ece732016-10-04 00:00:06 -070061 // Generates |num_media_packets| corresponding to a single frame.
62 void PacketizeFrame(size_t num_media_packets,
63 size_t frame_offset,
64 std::list<AugmentedPacket*>* augmented_packets,
65 ForwardErrorCorrection::PacketList* packets);
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +000066
brandtra2ece732016-10-04 00:00:06 -070067 // Build a media packet using |packet_generator_| and add it
68 // to the receiver.
69 void BuildAndAddRedMediaPacket(AugmentedPacket* packet);
70
71 // Build a FEC packet using |packet_generator_| and add it
72 // to the receiver.
73 void BuildAndAddRedFecPacket(Packet* packet);
74
nisse30e89312017-05-29 08:16:37 -070075 // Ensure that |recovered_packet_receiver_| will be called correctly
brandtra2ece732016-10-04 00:00:06 -070076 // and that the recovered packet will be identical to the lost packet.
brandtr0aabdac2016-10-03 06:36:43 -070077 void VerifyReconstructedMediaPacket(const AugmentedPacket& packet,
brandtra2ece732016-10-04 00:00:06 -070078 size_t times);
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +000079
pbos2bad88d2015-07-06 03:09:08 -070080 void InjectGarbagePacketLength(size_t fec_garbage_offset);
brandtra2ece732016-10-04 00:00:06 -070081
pbos70d5c472015-06-29 07:22:04 -070082 static void SurvivesMaliciousPacket(const uint8_t* data,
83 size_t length,
84 uint8_t ulpfec_payload_type);
85
nisse30e89312017-05-29 08:16:37 -070086 MockRecoveredPacketReceiver recovered_packet_receiver_;
Rasmus Brandt78db1582016-09-21 09:19:34 +020087 std::unique_ptr<ForwardErrorCorrection> fec_;
brandtrd55c3f62016-10-31 04:51:33 -070088 std::unique_ptr<UlpfecReceiver> receiver_fec_;
brandtr0aabdac2016-10-03 06:36:43 -070089 UlpfecPacketGenerator packet_generator_;
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +000090};
91
brandtrd55c3f62016-10-31 04:51:33 -070092void UlpfecReceiverTest::EncodeFec(
brandtra2ece732016-10-04 00:00:06 -070093 const ForwardErrorCorrection::PacketList& media_packets,
94 size_t num_fec_packets,
95 std::list<ForwardErrorCorrection::Packet*>* fec_packets) {
96 const uint8_t protection_factor =
97 num_fec_packets * 255 / media_packets.size();
98 // Unequal protection is turned off, and the number of important
99 // packets is thus irrelevant.
100 constexpr int kNumImportantPackets = 0;
101 constexpr bool kUseUnequalProtection = false;
102 constexpr FecMaskType kFecMaskType = kFecMaskBursty;
103 EXPECT_EQ(
104 0, fec_->EncodeFec(media_packets, protection_factor, kNumImportantPackets,
105 kUseUnequalProtection, kFecMaskType, fec_packets));
106 ASSERT_EQ(num_fec_packets, fec_packets->size());
107}
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000108
brandtrd55c3f62016-10-31 04:51:33 -0700109void UlpfecReceiverTest::PacketizeFrame(
brandtra2ece732016-10-04 00:00:06 -0700110 size_t num_media_packets,
111 size_t frame_offset,
112 std::list<AugmentedPacket*>* augmented_packets,
113 ForwardErrorCorrection::PacketList* packets) {
114 packet_generator_.NewFrame(num_media_packets);
115 for (size_t i = 0; i < num_media_packets; ++i) {
116 std::unique_ptr<AugmentedPacket> next_packet(
117 packet_generator_.NextPacket(frame_offset + i, kRtpHeaderSize + 10));
118 augmented_packets->push_back(next_packet.get());
119 packets->push_back(std::move(next_packet));
120 }
121}
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000122
brandtrd55c3f62016-10-31 04:51:33 -0700123void UlpfecReceiverTest::BuildAndAddRedMediaPacket(AugmentedPacket* packet) {
brandtra2ece732016-10-04 00:00:06 -0700124 std::unique_ptr<AugmentedPacket> red_packet(
125 packet_generator_.BuildMediaRedPacket(*packet));
126 EXPECT_EQ(0, receiver_fec_->AddReceivedRedPacket(
127 red_packet->header.header, red_packet->data,
128 red_packet->length, kFecPayloadType));
129}
130
brandtrd55c3f62016-10-31 04:51:33 -0700131void UlpfecReceiverTest::BuildAndAddRedFecPacket(Packet* packet) {
brandtra2ece732016-10-04 00:00:06 -0700132 std::unique_ptr<AugmentedPacket> red_packet(
133 packet_generator_.BuildUlpfecRedPacket(*packet));
134 EXPECT_EQ(0, receiver_fec_->AddReceivedRedPacket(
135 red_packet->header.header, red_packet->data,
136 red_packet->length, kFecPayloadType));
137}
138
brandtrd55c3f62016-10-31 04:51:33 -0700139void UlpfecReceiverTest::VerifyReconstructedMediaPacket(
brandtra2ece732016-10-04 00:00:06 -0700140 const AugmentedPacket& packet,
141 size_t times) {
142 // Verify that the content of the reconstructed packet is equal to the
143 // content of |packet|, and that the same content is received |times| number
144 // of times in a row.
nisse30e89312017-05-29 08:16:37 -0700145 EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, packet.length))
brandtra2ece732016-10-04 00:00:06 -0700146 .With(Args<0, 1>(ElementsAreArray(packet.data, packet.length)))
nisse30e89312017-05-29 08:16:37 -0700147 .Times(times);
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000148}
149
brandtrd55c3f62016-10-31 04:51:33 -0700150void UlpfecReceiverTest::InjectGarbagePacketLength(size_t fec_garbage_offset) {
nisse30e89312017-05-29 08:16:37 -0700151 EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, _));
pbos2bad88d2015-07-06 03:09:08 -0700152
brandtr71ca7472016-10-03 05:11:26 -0700153 const size_t kNumFecPackets = 1;
brandtr0aabdac2016-10-03 06:36:43 -0700154 std::list<AugmentedPacket*> augmented_media_packets;
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200155 ForwardErrorCorrection::PacketList media_packets;
brandtra2ece732016-10-04 00:00:06 -0700156 PacketizeFrame(2, 0, &augmented_media_packets, &media_packets);
brandtr35c480c2016-08-09 01:23:23 -0700157 std::list<ForwardErrorCorrection::Packet*> fec_packets;
brandtr71ca7472016-10-03 05:11:26 -0700158 EncodeFec(media_packets, kNumFecPackets, &fec_packets);
pbos2bad88d2015-07-06 03:09:08 -0700159 ByteWriter<uint16_t>::WriteBigEndian(
160 &fec_packets.front()->data[fec_garbage_offset], 0x4711);
161
162 // Inject first media packet, then first FEC packet, skipping the second media
163 // packet to cause a recovery from the FEC packet.
brandtr0aabdac2016-10-03 06:36:43 -0700164 BuildAndAddRedMediaPacket(augmented_media_packets.front());
pbos2bad88d2015-07-06 03:09:08 -0700165 BuildAndAddRedFecPacket(fec_packets.front());
166 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
167
168 FecPacketCounter counter = receiver_fec_->GetPacketCounter();
brandtr71ca7472016-10-03 05:11:26 -0700169 EXPECT_EQ(2U, counter.num_packets);
170 EXPECT_EQ(1U, counter.num_fec_packets);
171 EXPECT_EQ(0U, counter.num_recovered_packets);
pbos2bad88d2015-07-06 03:09:08 -0700172}
173
brandtrd55c3f62016-10-31 04:51:33 -0700174void UlpfecReceiverTest::SurvivesMaliciousPacket(const uint8_t* data,
175 size_t length,
176 uint8_t ulpfec_payload_type) {
177 RTPHeader header;
178 std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
brandtra2ece732016-10-04 00:00:06 -0700179 ASSERT_TRUE(parser->Parse(data, length, &header));
180
nisse30e89312017-05-29 08:16:37 -0700181 NullRecoveredPacketReceiver null_callback;
brandtrd55c3f62016-10-31 04:51:33 -0700182 std::unique_ptr<UlpfecReceiver> receiver_fec(
brandtrd726a3f2017-06-29 02:45:35 -0700183 UlpfecReceiver::Create(kMediaSsrc, &null_callback));
brandtra2ece732016-10-04 00:00:06 -0700184
185 receiver_fec->AddReceivedRedPacket(header, data, length, ulpfec_payload_type);
186}
187
brandtrd55c3f62016-10-31 04:51:33 -0700188TEST_F(UlpfecReceiverTest, TwoMediaOneFec) {
brandtra2ece732016-10-04 00:00:06 -0700189 constexpr size_t kNumFecPackets = 1u;
190 std::list<AugmentedPacket*> augmented_media_packets;
191 ForwardErrorCorrection::PacketList media_packets;
192 PacketizeFrame(2, 0, &augmented_media_packets, &media_packets);
193 std::list<ForwardErrorCorrection::Packet*> fec_packets;
194 EncodeFec(media_packets, kNumFecPackets, &fec_packets);
195
asapersson0c43f772016-11-30 01:42:26 -0800196 FecPacketCounter counter = receiver_fec_->GetPacketCounter();
197 EXPECT_EQ(0u, counter.num_packets);
198 EXPECT_EQ(-1, counter.first_packet_time_ms);
199
brandtra2ece732016-10-04 00:00:06 -0700200 // Recovery
201 auto it = augmented_media_packets.begin();
202 BuildAndAddRedMediaPacket(*it);
203 VerifyReconstructedMediaPacket(**it, 1);
204 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
asapersson0c43f772016-11-30 01:42:26 -0800205 counter = receiver_fec_->GetPacketCounter();
206 EXPECT_EQ(1u, counter.num_packets);
207 EXPECT_EQ(0u, counter.num_fec_packets);
208 EXPECT_EQ(0u, counter.num_recovered_packets);
209 const int64_t first_packet_time_ms = counter.first_packet_time_ms;
210 EXPECT_NE(-1, first_packet_time_ms);
211
brandtra2ece732016-10-04 00:00:06 -0700212 // Drop one media packet.
213 auto fec_it = fec_packets.begin();
214 BuildAndAddRedFecPacket(*fec_it);
215 ++it;
216 VerifyReconstructedMediaPacket(**it, 1);
217 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
218
asapersson0c43f772016-11-30 01:42:26 -0800219 counter = receiver_fec_->GetPacketCounter();
brandtra2ece732016-10-04 00:00:06 -0700220 EXPECT_EQ(2u, counter.num_packets);
221 EXPECT_EQ(1u, counter.num_fec_packets);
222 EXPECT_EQ(1u, counter.num_recovered_packets);
asapersson0c43f772016-11-30 01:42:26 -0800223 EXPECT_EQ(first_packet_time_ms, counter.first_packet_time_ms);
brandtra2ece732016-10-04 00:00:06 -0700224}
225
brandtrd55c3f62016-10-31 04:51:33 -0700226TEST_F(UlpfecReceiverTest, InjectGarbageFecHeaderLengthRecovery) {
pbos2bad88d2015-07-06 03:09:08 -0700227 // Byte offset 8 is the 'length recovery' field of the FEC header.
228 InjectGarbagePacketLength(8);
229}
230
brandtrd55c3f62016-10-31 04:51:33 -0700231TEST_F(UlpfecReceiverTest, InjectGarbageFecLevelHeaderProtectionLength) {
pbos2bad88d2015-07-06 03:09:08 -0700232 // Byte offset 10 is the 'protection length' field in the first FEC level
233 // header.
234 InjectGarbagePacketLength(10);
235}
236
brandtrd55c3f62016-10-31 04:51:33 -0700237TEST_F(UlpfecReceiverTest, TwoMediaTwoFec) {
brandtr71ca7472016-10-03 05:11:26 -0700238 const size_t kNumFecPackets = 2;
brandtr0aabdac2016-10-03 06:36:43 -0700239 std::list<AugmentedPacket*> augmented_media_packets;
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200240 ForwardErrorCorrection::PacketList media_packets;
brandtra2ece732016-10-04 00:00:06 -0700241 PacketizeFrame(2, 0, &augmented_media_packets, &media_packets);
brandtr35c480c2016-08-09 01:23:23 -0700242 std::list<ForwardErrorCorrection::Packet*> fec_packets;
brandtr71ca7472016-10-03 05:11:26 -0700243 EncodeFec(media_packets, kNumFecPackets, &fec_packets);
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000244
245 // Recovery
246 // Drop both media packets.
brandtr0aabdac2016-10-03 06:36:43 -0700247 auto it = augmented_media_packets.begin();
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200248 auto fec_it = fec_packets.begin();
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000249 BuildAndAddRedFecPacket(*fec_it);
brandtr71ca7472016-10-03 05:11:26 -0700250 VerifyReconstructedMediaPacket(**it, 1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000251 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000252 ++fec_it;
253 BuildAndAddRedFecPacket(*fec_it);
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000254 ++it;
brandtr71ca7472016-10-03 05:11:26 -0700255 VerifyReconstructedMediaPacket(**it, 1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000256 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000257}
258
brandtrd55c3f62016-10-31 04:51:33 -0700259TEST_F(UlpfecReceiverTest, TwoFramesOneFec) {
brandtr71ca7472016-10-03 05:11:26 -0700260 const size_t kNumFecPackets = 1;
brandtr0aabdac2016-10-03 06:36:43 -0700261 std::list<AugmentedPacket*> augmented_media_packets;
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200262 ForwardErrorCorrection::PacketList media_packets;
brandtra2ece732016-10-04 00:00:06 -0700263 PacketizeFrame(1, 0, &augmented_media_packets, &media_packets);
264 PacketizeFrame(1, 1, &augmented_media_packets, &media_packets);
brandtr35c480c2016-08-09 01:23:23 -0700265 std::list<ForwardErrorCorrection::Packet*> fec_packets;
brandtr71ca7472016-10-03 05:11:26 -0700266 EncodeFec(media_packets, kNumFecPackets, &fec_packets);
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000267
268 // Recovery
brandtr0aabdac2016-10-03 06:36:43 -0700269 auto it = augmented_media_packets.begin();
270 BuildAndAddRedMediaPacket(augmented_media_packets.front());
brandtr71ca7472016-10-03 05:11:26 -0700271 VerifyReconstructedMediaPacket(**it, 1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000272 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000273 // Drop one media packet.
274 BuildAndAddRedFecPacket(fec_packets.front());
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000275 ++it;
brandtr71ca7472016-10-03 05:11:26 -0700276 VerifyReconstructedMediaPacket(**it, 1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000277 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000278}
279
brandtrd55c3f62016-10-31 04:51:33 -0700280TEST_F(UlpfecReceiverTest, OneCompleteOneUnrecoverableFrame) {
brandtr71ca7472016-10-03 05:11:26 -0700281 const size_t kNumFecPackets = 1;
brandtr0aabdac2016-10-03 06:36:43 -0700282 std::list<AugmentedPacket*> augmented_media_packets;
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200283 ForwardErrorCorrection::PacketList media_packets;
brandtra2ece732016-10-04 00:00:06 -0700284 PacketizeFrame(1, 0, &augmented_media_packets, &media_packets);
285 PacketizeFrame(2, 1, &augmented_media_packets, &media_packets);
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000286
brandtr35c480c2016-08-09 01:23:23 -0700287 std::list<ForwardErrorCorrection::Packet*> fec_packets;
brandtr71ca7472016-10-03 05:11:26 -0700288 EncodeFec(media_packets, kNumFecPackets, &fec_packets);
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000289
290 // Recovery
brandtr0aabdac2016-10-03 06:36:43 -0700291 auto it = augmented_media_packets.begin();
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000292 BuildAndAddRedMediaPacket(*it); // First frame: one packet.
brandtr71ca7472016-10-03 05:11:26 -0700293 VerifyReconstructedMediaPacket(**it, 1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000294 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000295 ++it;
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000296 BuildAndAddRedMediaPacket(*it); // First packet of second frame.
brandtr71ca7472016-10-03 05:11:26 -0700297 VerifyReconstructedMediaPacket(**it, 1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000298 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000299}
300
brandtrd55c3f62016-10-31 04:51:33 -0700301TEST_F(UlpfecReceiverTest, MaxFramesOneFec) {
brandtr71ca7472016-10-03 05:11:26 -0700302 const size_t kNumFecPackets = 1;
303 const size_t kNumMediaPackets = 48;
brandtr0aabdac2016-10-03 06:36:43 -0700304 std::list<AugmentedPacket*> augmented_media_packets;
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200305 ForwardErrorCorrection::PacketList media_packets;
brandtr71ca7472016-10-03 05:11:26 -0700306 for (size_t i = 0; i < kNumMediaPackets; ++i) {
brandtra2ece732016-10-04 00:00:06 -0700307 PacketizeFrame(1, i, &augmented_media_packets, &media_packets);
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000308 }
brandtr35c480c2016-08-09 01:23:23 -0700309 std::list<ForwardErrorCorrection::Packet*> fec_packets;
brandtr71ca7472016-10-03 05:11:26 -0700310 EncodeFec(media_packets, kNumFecPackets, &fec_packets);
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000311
312 // Recovery
brandtr0aabdac2016-10-03 06:36:43 -0700313 auto it = augmented_media_packets.begin();
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000314 ++it; // Drop first packet.
brandtr0aabdac2016-10-03 06:36:43 -0700315 for (; it != augmented_media_packets.end(); ++it) {
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000316 BuildAndAddRedMediaPacket(*it);
brandtr71ca7472016-10-03 05:11:26 -0700317 VerifyReconstructedMediaPacket(**it, 1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000318 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000319 }
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000320 BuildAndAddRedFecPacket(fec_packets.front());
brandtr0aabdac2016-10-03 06:36:43 -0700321 it = augmented_media_packets.begin();
brandtr71ca7472016-10-03 05:11:26 -0700322 VerifyReconstructedMediaPacket(**it, 1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000323 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000324}
325
brandtrd55c3f62016-10-31 04:51:33 -0700326TEST_F(UlpfecReceiverTest, TooManyFrames) {
brandtr71ca7472016-10-03 05:11:26 -0700327 const size_t kNumFecPackets = 1;
328 const size_t kNumMediaPackets = 49;
brandtr0aabdac2016-10-03 06:36:43 -0700329 std::list<AugmentedPacket*> augmented_media_packets;
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200330 ForwardErrorCorrection::PacketList media_packets;
brandtr71ca7472016-10-03 05:11:26 -0700331 for (size_t i = 0; i < kNumMediaPackets; ++i) {
brandtra2ece732016-10-04 00:00:06 -0700332 PacketizeFrame(1, i, &augmented_media_packets, &media_packets);
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000333 }
brandtr35c480c2016-08-09 01:23:23 -0700334 std::list<ForwardErrorCorrection::Packet*> fec_packets;
Rasmus Brandt78db1582016-09-21 09:19:34 +0200335 EXPECT_EQ(-1, fec_->EncodeFec(media_packets,
336 kNumFecPackets * 255 / kNumMediaPackets, 0,
337 false, kFecMaskBursty, &fec_packets));
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000338}
339
brandtrd55c3f62016-10-31 04:51:33 -0700340TEST_F(UlpfecReceiverTest, PacketNotDroppedTooEarly) {
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000341 // 1 frame with 2 media packets and one FEC packet. One media packet missing.
342 // Delay the FEC packet.
brandtr71ca7472016-10-03 05:11:26 -0700343 Packet* delayed_fec = nullptr;
344 const size_t kNumFecPacketsBatch1 = 1;
345 const size_t kNumMediaPacketsBatch1 = 2;
brandtr0aabdac2016-10-03 06:36:43 -0700346 std::list<AugmentedPacket*> augmented_media_packets_batch1;
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200347 ForwardErrorCorrection::PacketList media_packets_batch1;
brandtra2ece732016-10-04 00:00:06 -0700348 PacketizeFrame(kNumMediaPacketsBatch1, 0, &augmented_media_packets_batch1,
349 &media_packets_batch1);
brandtr35c480c2016-08-09 01:23:23 -0700350 std::list<ForwardErrorCorrection::Packet*> fec_packets;
brandtr71ca7472016-10-03 05:11:26 -0700351 EncodeFec(media_packets_batch1, kNumFecPacketsBatch1, &fec_packets);
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000352
brandtr0aabdac2016-10-03 06:36:43 -0700353 BuildAndAddRedMediaPacket(augmented_media_packets_batch1.front());
Yves Gerey665174f2018-06-19 15:03:05 +0200354 EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, _)).Times(1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000355 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000356 delayed_fec = fec_packets.front();
357
358 // Fill the FEC decoder. No packets should be dropped.
brandtr71ca7472016-10-03 05:11:26 -0700359 const size_t kNumMediaPacketsBatch2 = 46;
brandtr0aabdac2016-10-03 06:36:43 -0700360 std::list<AugmentedPacket*> augmented_media_packets_batch2;
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200361 ForwardErrorCorrection::PacketList media_packets_batch2;
brandtr71ca7472016-10-03 05:11:26 -0700362 for (size_t i = 0; i < kNumMediaPacketsBatch2; ++i) {
brandtra2ece732016-10-04 00:00:06 -0700363 PacketizeFrame(1, i, &augmented_media_packets_batch2,
364 &media_packets_batch2);
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000365 }
brandtr0aabdac2016-10-03 06:36:43 -0700366 for (auto it = augmented_media_packets_batch2.begin();
367 it != augmented_media_packets_batch2.end(); ++it) {
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000368 BuildAndAddRedMediaPacket(*it);
Yves Gerey665174f2018-06-19 15:03:05 +0200369 EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, _)).Times(1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000370 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000371 }
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000372
373 // Add the delayed FEC packet. One packet should be reconstructed.
374 BuildAndAddRedFecPacket(delayed_fec);
Yves Gerey665174f2018-06-19 15:03:05 +0200375 EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, _)).Times(1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000376 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000377}
378
brandtrd55c3f62016-10-31 04:51:33 -0700379TEST_F(UlpfecReceiverTest, PacketDroppedWhenTooOld) {
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000380 // 1 frame with 2 media packets and one FEC packet. One media packet missing.
381 // Delay the FEC packet.
brandtr71ca7472016-10-03 05:11:26 -0700382 Packet* delayed_fec = nullptr;
383 const size_t kNumFecPacketsBatch1 = 1;
384 const size_t kNumMediaPacketsBatch1 = 2;
brandtr0aabdac2016-10-03 06:36:43 -0700385 std::list<AugmentedPacket*> augmented_media_packets_batch1;
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200386 ForwardErrorCorrection::PacketList media_packets_batch1;
brandtra2ece732016-10-04 00:00:06 -0700387 PacketizeFrame(kNumMediaPacketsBatch1, 0, &augmented_media_packets_batch1,
388 &media_packets_batch1);
brandtr35c480c2016-08-09 01:23:23 -0700389 std::list<ForwardErrorCorrection::Packet*> fec_packets;
brandtr71ca7472016-10-03 05:11:26 -0700390 EncodeFec(media_packets_batch1, kNumFecPacketsBatch1, &fec_packets);
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000391
brandtr0aabdac2016-10-03 06:36:43 -0700392 BuildAndAddRedMediaPacket(augmented_media_packets_batch1.front());
Yves Gerey665174f2018-06-19 15:03:05 +0200393 EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, _)).Times(1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000394 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000395 delayed_fec = fec_packets.front();
396
397 // Fill the FEC decoder and force the last packet to be dropped.
brandtr71ca7472016-10-03 05:11:26 -0700398 const size_t kNumMediaPacketsBatch2 = 48;
brandtr0aabdac2016-10-03 06:36:43 -0700399 std::list<AugmentedPacket*> augmented_media_packets_batch2;
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200400 ForwardErrorCorrection::PacketList media_packets_batch2;
brandtr71ca7472016-10-03 05:11:26 -0700401 for (size_t i = 0; i < kNumMediaPacketsBatch2; ++i) {
brandtra2ece732016-10-04 00:00:06 -0700402 PacketizeFrame(1, i, &augmented_media_packets_batch2,
403 &media_packets_batch2);
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000404 }
brandtr0aabdac2016-10-03 06:36:43 -0700405 for (auto it = augmented_media_packets_batch2.begin();
406 it != augmented_media_packets_batch2.end(); ++it) {
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000407 BuildAndAddRedMediaPacket(*it);
Yves Gerey665174f2018-06-19 15:03:05 +0200408 EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, _)).Times(1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000409 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000410 }
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000411
412 // Add the delayed FEC packet. No packet should be reconstructed since the
413 // first media packet of that frame has been dropped due to being too old.
414 BuildAndAddRedFecPacket(delayed_fec);
nisse30e89312017-05-29 08:16:37 -0700415 EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, _)).Times(0);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000416 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000417}
418
brandtrd55c3f62016-10-31 04:51:33 -0700419TEST_F(UlpfecReceiverTest, OldFecPacketDropped) {
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000420 // 49 frames with 2 media packets and one FEC packet. All media packets
421 // missing.
brandtr71ca7472016-10-03 05:11:26 -0700422 const size_t kNumMediaPackets = 49 * 2;
brandtr0aabdac2016-10-03 06:36:43 -0700423 std::list<AugmentedPacket*> augmented_media_packets;
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200424 ForwardErrorCorrection::PacketList media_packets;
brandtr71ca7472016-10-03 05:11:26 -0700425 for (size_t i = 0; i < kNumMediaPackets / 2; ++i) {
brandtr0aabdac2016-10-03 06:36:43 -0700426 std::list<AugmentedPacket*> frame_augmented_media_packets;
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200427 ForwardErrorCorrection::PacketList frame_media_packets;
brandtr35c480c2016-08-09 01:23:23 -0700428 std::list<ForwardErrorCorrection::Packet*> fec_packets;
brandtra2ece732016-10-04 00:00:06 -0700429 PacketizeFrame(2, 0, &frame_augmented_media_packets, &frame_media_packets);
brandtr71ca7472016-10-03 05:11:26 -0700430 EncodeFec(frame_media_packets, 1, &fec_packets);
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200431 for (auto it = fec_packets.begin(); it != fec_packets.end(); ++it) {
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000432 // Only FEC packets inserted. No packets recoverable at this time.
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000433 BuildAndAddRedFecPacket(*it);
nisse30e89312017-05-29 08:16:37 -0700434 EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, _)).Times(0);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000435 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000436 }
brandtr35c480c2016-08-09 01:23:23 -0700437 // Move unique_ptr's to media_packets for lifetime management.
438 media_packets.insert(media_packets.end(),
439 std::make_move_iterator(frame_media_packets.begin()),
440 std::make_move_iterator(frame_media_packets.end()));
brandtr0aabdac2016-10-03 06:36:43 -0700441 augmented_media_packets.insert(augmented_media_packets.end(),
442 frame_augmented_media_packets.begin(),
443 frame_augmented_media_packets.end());
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000444 }
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000445 // Insert the oldest media packet. The corresponding FEC packet is too old
brandtr71ca7472016-10-03 05:11:26 -0700446 // and should have been dropped. Only the media packet we inserted will be
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000447 // returned.
brandtr0aabdac2016-10-03 06:36:43 -0700448 BuildAndAddRedMediaPacket(augmented_media_packets.front());
Yves Gerey665174f2018-06-19 15:03:05 +0200449 EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, _)).Times(1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000450 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000451}
452
brandtrd55c3f62016-10-31 04:51:33 -0700453TEST_F(UlpfecReceiverTest, TruncatedPacketWithFBitSet) {
454 const uint8_t kTruncatedPacket[] = {0x80, 0x2a, 0x68, 0x71, 0x29, 0xa1, 0x27,
455 0x3a, 0x29, 0x12, 0x2a, 0x98, 0xe0, 0x29};
pbos70d5c472015-06-29 07:22:04 -0700456
457 SurvivesMaliciousPacket(kTruncatedPacket, sizeof(kTruncatedPacket), 100);
458}
459
brandtrd55c3f62016-10-31 04:51:33 -0700460TEST_F(UlpfecReceiverTest,
461 TruncatedPacketWithFBitSetEndingAfterFirstRedHeader) {
462 const uint8_t kPacket[] = {
463 0x89, 0x27, 0x3a, 0x83, 0x27, 0x3a, 0x3a, 0xf3, 0x67, 0xbe, 0x2a,
464 0xa9, 0x27, 0x54, 0x3a, 0x3a, 0x2a, 0x67, 0x3a, 0xf3, 0x67, 0xbe,
465 0x2a, 0x27, 0xe6, 0xf6, 0x03, 0x3e, 0x29, 0x27, 0x21, 0x27, 0x2a,
466 0x29, 0x21, 0x4b, 0x29, 0x3a, 0x28, 0x29, 0xbf, 0x29, 0x2a, 0x26,
467 0x29, 0xae, 0x27, 0xa6, 0xf6, 0x00, 0x03, 0x3e};
pbos2e43b262015-06-30 01:32:40 -0700468 SurvivesMaliciousPacket(kPacket, sizeof(kPacket), 100);
469}
470
brandtrd55c3f62016-10-31 04:51:33 -0700471TEST_F(UlpfecReceiverTest, TruncatedPacketWithoutDataPastFirstBlock) {
472 const uint8_t kPacket[] = {
473 0x82, 0x38, 0x92, 0x38, 0x92, 0x38, 0xde, 0x2a, 0x11, 0xc8, 0xa3, 0xc4,
474 0x82, 0x38, 0x2a, 0x21, 0x2a, 0x28, 0x92, 0x38, 0x92, 0x00, 0x00, 0x0a,
475 0x3a, 0xc8, 0xa3, 0x3a, 0x27, 0xc4, 0x2a, 0x21, 0x2a, 0x28};
pbos2e43b262015-06-30 01:32:40 -0700476 SurvivesMaliciousPacket(kPacket, sizeof(kPacket), 100);
477}
478
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000479} // namespace webrtc