blob: c3bd5a730458198db44c8935bcc89082552280a0 [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"
18#include "modules/rtp_rtcp/mocks/mock_rtp_rtcp.h"
19#include "modules/rtp_rtcp/mocks/mock_recovered_packet_receiver.h"
20#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());
nisse30e89312017-05-29 08:16:37 -0700354 EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, _))
355 .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);
nisse30e89312017-05-29 08:16:37 -0700370 EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, _))
371 .Times(1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000372 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000373 }
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000374
375 // Add the delayed FEC packet. One packet should be reconstructed.
376 BuildAndAddRedFecPacket(delayed_fec);
nisse30e89312017-05-29 08:16:37 -0700377 EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, _))
378 .Times(1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000379 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000380}
381
brandtrd55c3f62016-10-31 04:51:33 -0700382TEST_F(UlpfecReceiverTest, PacketDroppedWhenTooOld) {
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000383 // 1 frame with 2 media packets and one FEC packet. One media packet missing.
384 // Delay the FEC packet.
brandtr71ca7472016-10-03 05:11:26 -0700385 Packet* delayed_fec = nullptr;
386 const size_t kNumFecPacketsBatch1 = 1;
387 const size_t kNumMediaPacketsBatch1 = 2;
brandtr0aabdac2016-10-03 06:36:43 -0700388 std::list<AugmentedPacket*> augmented_media_packets_batch1;
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200389 ForwardErrorCorrection::PacketList media_packets_batch1;
brandtra2ece732016-10-04 00:00:06 -0700390 PacketizeFrame(kNumMediaPacketsBatch1, 0, &augmented_media_packets_batch1,
391 &media_packets_batch1);
brandtr35c480c2016-08-09 01:23:23 -0700392 std::list<ForwardErrorCorrection::Packet*> fec_packets;
brandtr71ca7472016-10-03 05:11:26 -0700393 EncodeFec(media_packets_batch1, kNumFecPacketsBatch1, &fec_packets);
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000394
brandtr0aabdac2016-10-03 06:36:43 -0700395 BuildAndAddRedMediaPacket(augmented_media_packets_batch1.front());
nisse30e89312017-05-29 08:16:37 -0700396 EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, _))
397 .Times(1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000398 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000399 delayed_fec = fec_packets.front();
400
401 // Fill the FEC decoder and force the last packet to be dropped.
brandtr71ca7472016-10-03 05:11:26 -0700402 const size_t kNumMediaPacketsBatch2 = 48;
brandtr0aabdac2016-10-03 06:36:43 -0700403 std::list<AugmentedPacket*> augmented_media_packets_batch2;
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200404 ForwardErrorCorrection::PacketList media_packets_batch2;
brandtr71ca7472016-10-03 05:11:26 -0700405 for (size_t i = 0; i < kNumMediaPacketsBatch2; ++i) {
brandtra2ece732016-10-04 00:00:06 -0700406 PacketizeFrame(1, i, &augmented_media_packets_batch2,
407 &media_packets_batch2);
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000408 }
brandtr0aabdac2016-10-03 06:36:43 -0700409 for (auto it = augmented_media_packets_batch2.begin();
410 it != augmented_media_packets_batch2.end(); ++it) {
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000411 BuildAndAddRedMediaPacket(*it);
nisse30e89312017-05-29 08:16:37 -0700412 EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, _))
413 .Times(1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000414 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000415 }
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000416
417 // Add the delayed FEC packet. No packet should be reconstructed since the
418 // first media packet of that frame has been dropped due to being too old.
419 BuildAndAddRedFecPacket(delayed_fec);
nisse30e89312017-05-29 08:16:37 -0700420 EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, _)).Times(0);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000421 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000422}
423
brandtrd55c3f62016-10-31 04:51:33 -0700424TEST_F(UlpfecReceiverTest, OldFecPacketDropped) {
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000425 // 49 frames with 2 media packets and one FEC packet. All media packets
426 // missing.
brandtr71ca7472016-10-03 05:11:26 -0700427 const size_t kNumMediaPackets = 49 * 2;
brandtr0aabdac2016-10-03 06:36:43 -0700428 std::list<AugmentedPacket*> augmented_media_packets;
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200429 ForwardErrorCorrection::PacketList media_packets;
brandtr71ca7472016-10-03 05:11:26 -0700430 for (size_t i = 0; i < kNumMediaPackets / 2; ++i) {
brandtr0aabdac2016-10-03 06:36:43 -0700431 std::list<AugmentedPacket*> frame_augmented_media_packets;
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200432 ForwardErrorCorrection::PacketList frame_media_packets;
brandtr35c480c2016-08-09 01:23:23 -0700433 std::list<ForwardErrorCorrection::Packet*> fec_packets;
brandtra2ece732016-10-04 00:00:06 -0700434 PacketizeFrame(2, 0, &frame_augmented_media_packets, &frame_media_packets);
brandtr71ca7472016-10-03 05:11:26 -0700435 EncodeFec(frame_media_packets, 1, &fec_packets);
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200436 for (auto it = fec_packets.begin(); it != fec_packets.end(); ++it) {
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000437 // Only FEC packets inserted. No packets recoverable at this time.
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000438 BuildAndAddRedFecPacket(*it);
nisse30e89312017-05-29 08:16:37 -0700439 EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, _)).Times(0);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000440 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000441 }
brandtr35c480c2016-08-09 01:23:23 -0700442 // Move unique_ptr's to media_packets for lifetime management.
443 media_packets.insert(media_packets.end(),
444 std::make_move_iterator(frame_media_packets.begin()),
445 std::make_move_iterator(frame_media_packets.end()));
brandtr0aabdac2016-10-03 06:36:43 -0700446 augmented_media_packets.insert(augmented_media_packets.end(),
447 frame_augmented_media_packets.begin(),
448 frame_augmented_media_packets.end());
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000449 }
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000450 // Insert the oldest media packet. The corresponding FEC packet is too old
brandtr71ca7472016-10-03 05:11:26 -0700451 // and should have been dropped. Only the media packet we inserted will be
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000452 // returned.
brandtr0aabdac2016-10-03 06:36:43 -0700453 BuildAndAddRedMediaPacket(augmented_media_packets.front());
nisse30e89312017-05-29 08:16:37 -0700454 EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, _))
455 .Times(1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000456 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000457}
458
brandtrd55c3f62016-10-31 04:51:33 -0700459TEST_F(UlpfecReceiverTest, TruncatedPacketWithFBitSet) {
460 const uint8_t kTruncatedPacket[] = {0x80, 0x2a, 0x68, 0x71, 0x29, 0xa1, 0x27,
461 0x3a, 0x29, 0x12, 0x2a, 0x98, 0xe0, 0x29};
pbos70d5c472015-06-29 07:22:04 -0700462
463 SurvivesMaliciousPacket(kTruncatedPacket, sizeof(kTruncatedPacket), 100);
464}
465
brandtrd55c3f62016-10-31 04:51:33 -0700466TEST_F(UlpfecReceiverTest,
467 TruncatedPacketWithFBitSetEndingAfterFirstRedHeader) {
468 const uint8_t kPacket[] = {
469 0x89, 0x27, 0x3a, 0x83, 0x27, 0x3a, 0x3a, 0xf3, 0x67, 0xbe, 0x2a,
470 0xa9, 0x27, 0x54, 0x3a, 0x3a, 0x2a, 0x67, 0x3a, 0xf3, 0x67, 0xbe,
471 0x2a, 0x27, 0xe6, 0xf6, 0x03, 0x3e, 0x29, 0x27, 0x21, 0x27, 0x2a,
472 0x29, 0x21, 0x4b, 0x29, 0x3a, 0x28, 0x29, 0xbf, 0x29, 0x2a, 0x26,
473 0x29, 0xae, 0x27, 0xa6, 0xf6, 0x00, 0x03, 0x3e};
pbos2e43b262015-06-30 01:32:40 -0700474 SurvivesMaliciousPacket(kPacket, sizeof(kPacket), 100);
475}
476
brandtrd55c3f62016-10-31 04:51:33 -0700477TEST_F(UlpfecReceiverTest, TruncatedPacketWithoutDataPastFirstBlock) {
478 const uint8_t kPacket[] = {
479 0x82, 0x38, 0x92, 0x38, 0x92, 0x38, 0xde, 0x2a, 0x11, 0xc8, 0xa3, 0xc4,
480 0x82, 0x38, 0x2a, 0x21, 0x2a, 0x28, 0x92, 0x38, 0x92, 0x00, 0x00, 0x0a,
481 0x3a, 0xc8, 0xa3, 0x3a, 0x27, 0xc4, 0x2a, 0x21, 0x2a, 0x28};
pbos2e43b262015-06-30 01:32:40 -0700482 SurvivesMaliciousPacket(kPacket, sizeof(kPacket), 100);
483}
484
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000485} // namespace webrtc