blob: 0ef8085b6348d2c0da903914f91340ab5688ddd7 [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
Jonas Olssona4d87372019-07-05 19:08:33 +020011#include "modules/rtp_rtcp/include/ulpfec_receiver.h"
12
phoglund@webrtc.org9919ad52013-05-16 15:06:28 +000013#include <string.h>
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +000014
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000015#include <list>
kwiberg84be5112016-04-27 01:19:58 -070016#include <memory>
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000017
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;
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +000032
brandtr0aabdac2016-10-03 06:36:43 -070033using test::fec::AugmentedPacket;
brandtr71ca7472016-10-03 05:11:26 -070034using Packet = ForwardErrorCorrection::Packet;
brandtr71ca7472016-10-03 05:11:26 -070035using test::fec::UlpfecPacketGenerator;
36
37constexpr int kFecPayloadType = 96;
brandtr0aabdac2016-10-03 06:36:43 -070038constexpr uint32_t kMediaSsrc = 835424;
nisse30e89312017-05-29 08:16:37 -070039
40class NullRecoveredPacketReceiver : public RecoveredPacketReceiver {
41 public:
42 void OnRecoveredPacket(const uint8_t* packet, size_t length) override {}
43};
44
brandtr71ca7472016-10-03 05:11:26 -070045} // namespace
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +000046
brandtrd55c3f62016-10-31 04:51:33 -070047class UlpfecReceiverTest : public ::testing::Test {
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +000048 protected:
brandtrd55c3f62016-10-31 04:51:33 -070049 UlpfecReceiverTest()
brandtrd726a3f2017-06-29 02:45:35 -070050 : fec_(ForwardErrorCorrection::CreateUlpfec(kMediaSsrc)),
Ilya Nikolaevskiy2d821c32019-06-26 14:39:36 +020051 receiver_fec_(UlpfecReceiver::Create(kMediaSsrc,
52 &recovered_packet_receiver_,
53 {})),
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) {
Danil Chapovalov04fd2152019-09-20 11:40:12 +0200124 RtpPacket red_packet = packet_generator_.BuildMediaRedPacket(*packet);
125 EXPECT_TRUE(receiver_fec_->AddReceivedRedPacket(red_packet, kFecPayloadType));
brandtra2ece732016-10-04 00:00:06 -0700126}
127
brandtrd55c3f62016-10-31 04:51:33 -0700128void UlpfecReceiverTest::BuildAndAddRedFecPacket(Packet* packet) {
Danil Chapovalov04fd2152019-09-20 11:40:12 +0200129 RtpPacket red_packet = packet_generator_.BuildUlpfecRedPacket(*packet);
130 EXPECT_TRUE(receiver_fec_->AddReceivedRedPacket(red_packet, kFecPayloadType));
brandtra2ece732016-10-04 00:00:06 -0700131}
132
brandtrd55c3f62016-10-31 04:51:33 -0700133void UlpfecReceiverTest::VerifyReconstructedMediaPacket(
brandtra2ece732016-10-04 00:00:06 -0700134 const AugmentedPacket& packet,
135 size_t times) {
136 // Verify that the content of the reconstructed packet is equal to the
137 // content of |packet|, and that the same content is received |times| number
138 // of times in a row.
Ilya Nikolaevskiya5d952f2019-09-03 11:07:37 +0200139 EXPECT_CALL(recovered_packet_receiver_,
140 OnRecoveredPacket(_, packet.data.size()))
141 .With(
142 Args<0, 1>(ElementsAreArray(packet.data.cdata(), packet.data.size())))
nisse30e89312017-05-29 08:16:37 -0700143 .Times(times);
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000144}
145
brandtrd55c3f62016-10-31 04:51:33 -0700146void UlpfecReceiverTest::InjectGarbagePacketLength(size_t fec_garbage_offset) {
nisse30e89312017-05-29 08:16:37 -0700147 EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, _));
pbos2bad88d2015-07-06 03:09:08 -0700148
brandtr71ca7472016-10-03 05:11:26 -0700149 const size_t kNumFecPackets = 1;
brandtr0aabdac2016-10-03 06:36:43 -0700150 std::list<AugmentedPacket*> augmented_media_packets;
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200151 ForwardErrorCorrection::PacketList media_packets;
brandtra2ece732016-10-04 00:00:06 -0700152 PacketizeFrame(2, 0, &augmented_media_packets, &media_packets);
brandtr35c480c2016-08-09 01:23:23 -0700153 std::list<ForwardErrorCorrection::Packet*> fec_packets;
brandtr71ca7472016-10-03 05:11:26 -0700154 EncodeFec(media_packets, kNumFecPackets, &fec_packets);
pbos2bad88d2015-07-06 03:09:08 -0700155 ByteWriter<uint16_t>::WriteBigEndian(
156 &fec_packets.front()->data[fec_garbage_offset], 0x4711);
157
158 // Inject first media packet, then first FEC packet, skipping the second media
159 // packet to cause a recovery from the FEC packet.
brandtr0aabdac2016-10-03 06:36:43 -0700160 BuildAndAddRedMediaPacket(augmented_media_packets.front());
pbos2bad88d2015-07-06 03:09:08 -0700161 BuildAndAddRedFecPacket(fec_packets.front());
162 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
163
164 FecPacketCounter counter = receiver_fec_->GetPacketCounter();
brandtr71ca7472016-10-03 05:11:26 -0700165 EXPECT_EQ(2U, counter.num_packets);
166 EXPECT_EQ(1U, counter.num_fec_packets);
167 EXPECT_EQ(0U, counter.num_recovered_packets);
pbos2bad88d2015-07-06 03:09:08 -0700168}
169
brandtrd55c3f62016-10-31 04:51:33 -0700170void UlpfecReceiverTest::SurvivesMaliciousPacket(const uint8_t* data,
171 size_t length,
172 uint8_t ulpfec_payload_type) {
nisse30e89312017-05-29 08:16:37 -0700173 NullRecoveredPacketReceiver null_callback;
brandtrd55c3f62016-10-31 04:51:33 -0700174 std::unique_ptr<UlpfecReceiver> receiver_fec(
Ilya Nikolaevskiy2d821c32019-06-26 14:39:36 +0200175 UlpfecReceiver::Create(kMediaSsrc, &null_callback, {}));
brandtra2ece732016-10-04 00:00:06 -0700176
Danil Chapovalov04fd2152019-09-20 11:40:12 +0200177 RtpPacket rtp_packet;
178 ASSERT_TRUE(rtp_packet.Parse(data, length));
179 receiver_fec->AddReceivedRedPacket(rtp_packet, ulpfec_payload_type);
brandtra2ece732016-10-04 00:00:06 -0700180}
181
brandtrd55c3f62016-10-31 04:51:33 -0700182TEST_F(UlpfecReceiverTest, TwoMediaOneFec) {
brandtra2ece732016-10-04 00:00:06 -0700183 constexpr size_t kNumFecPackets = 1u;
184 std::list<AugmentedPacket*> augmented_media_packets;
185 ForwardErrorCorrection::PacketList media_packets;
186 PacketizeFrame(2, 0, &augmented_media_packets, &media_packets);
187 std::list<ForwardErrorCorrection::Packet*> fec_packets;
188 EncodeFec(media_packets, kNumFecPackets, &fec_packets);
189
asapersson0c43f772016-11-30 01:42:26 -0800190 FecPacketCounter counter = receiver_fec_->GetPacketCounter();
191 EXPECT_EQ(0u, counter.num_packets);
192 EXPECT_EQ(-1, counter.first_packet_time_ms);
193
brandtra2ece732016-10-04 00:00:06 -0700194 // Recovery
195 auto it = augmented_media_packets.begin();
196 BuildAndAddRedMediaPacket(*it);
197 VerifyReconstructedMediaPacket(**it, 1);
198 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
asapersson0c43f772016-11-30 01:42:26 -0800199 counter = receiver_fec_->GetPacketCounter();
200 EXPECT_EQ(1u, counter.num_packets);
201 EXPECT_EQ(0u, counter.num_fec_packets);
202 EXPECT_EQ(0u, counter.num_recovered_packets);
203 const int64_t first_packet_time_ms = counter.first_packet_time_ms;
204 EXPECT_NE(-1, first_packet_time_ms);
205
brandtra2ece732016-10-04 00:00:06 -0700206 // Drop one media packet.
207 auto fec_it = fec_packets.begin();
208 BuildAndAddRedFecPacket(*fec_it);
209 ++it;
210 VerifyReconstructedMediaPacket(**it, 1);
211 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
212
asapersson0c43f772016-11-30 01:42:26 -0800213 counter = receiver_fec_->GetPacketCounter();
brandtra2ece732016-10-04 00:00:06 -0700214 EXPECT_EQ(2u, counter.num_packets);
215 EXPECT_EQ(1u, counter.num_fec_packets);
216 EXPECT_EQ(1u, counter.num_recovered_packets);
asapersson0c43f772016-11-30 01:42:26 -0800217 EXPECT_EQ(first_packet_time_ms, counter.first_packet_time_ms);
brandtra2ece732016-10-04 00:00:06 -0700218}
219
brandtrd55c3f62016-10-31 04:51:33 -0700220TEST_F(UlpfecReceiverTest, InjectGarbageFecHeaderLengthRecovery) {
pbos2bad88d2015-07-06 03:09:08 -0700221 // Byte offset 8 is the 'length recovery' field of the FEC header.
222 InjectGarbagePacketLength(8);
223}
224
brandtrd55c3f62016-10-31 04:51:33 -0700225TEST_F(UlpfecReceiverTest, InjectGarbageFecLevelHeaderProtectionLength) {
pbos2bad88d2015-07-06 03:09:08 -0700226 // Byte offset 10 is the 'protection length' field in the first FEC level
227 // header.
228 InjectGarbagePacketLength(10);
229}
230
brandtrd55c3f62016-10-31 04:51:33 -0700231TEST_F(UlpfecReceiverTest, TwoMediaTwoFec) {
brandtr71ca7472016-10-03 05:11:26 -0700232 const size_t kNumFecPackets = 2;
brandtr0aabdac2016-10-03 06:36:43 -0700233 std::list<AugmentedPacket*> augmented_media_packets;
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200234 ForwardErrorCorrection::PacketList media_packets;
brandtra2ece732016-10-04 00:00:06 -0700235 PacketizeFrame(2, 0, &augmented_media_packets, &media_packets);
brandtr35c480c2016-08-09 01:23:23 -0700236 std::list<ForwardErrorCorrection::Packet*> fec_packets;
brandtr71ca7472016-10-03 05:11:26 -0700237 EncodeFec(media_packets, kNumFecPackets, &fec_packets);
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000238
239 // Recovery
240 // Drop both media packets.
brandtr0aabdac2016-10-03 06:36:43 -0700241 auto it = augmented_media_packets.begin();
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200242 auto fec_it = fec_packets.begin();
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000243 BuildAndAddRedFecPacket(*fec_it);
brandtr71ca7472016-10-03 05:11:26 -0700244 VerifyReconstructedMediaPacket(**it, 1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000245 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000246 ++fec_it;
247 BuildAndAddRedFecPacket(*fec_it);
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000248 ++it;
brandtr71ca7472016-10-03 05:11:26 -0700249 VerifyReconstructedMediaPacket(**it, 1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000250 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000251}
252
brandtrd55c3f62016-10-31 04:51:33 -0700253TEST_F(UlpfecReceiverTest, TwoFramesOneFec) {
brandtr71ca7472016-10-03 05:11:26 -0700254 const size_t kNumFecPackets = 1;
brandtr0aabdac2016-10-03 06:36:43 -0700255 std::list<AugmentedPacket*> augmented_media_packets;
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200256 ForwardErrorCorrection::PacketList media_packets;
brandtra2ece732016-10-04 00:00:06 -0700257 PacketizeFrame(1, 0, &augmented_media_packets, &media_packets);
258 PacketizeFrame(1, 1, &augmented_media_packets, &media_packets);
brandtr35c480c2016-08-09 01:23:23 -0700259 std::list<ForwardErrorCorrection::Packet*> fec_packets;
brandtr71ca7472016-10-03 05:11:26 -0700260 EncodeFec(media_packets, kNumFecPackets, &fec_packets);
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000261
262 // Recovery
brandtr0aabdac2016-10-03 06:36:43 -0700263 auto it = augmented_media_packets.begin();
264 BuildAndAddRedMediaPacket(augmented_media_packets.front());
brandtr71ca7472016-10-03 05:11:26 -0700265 VerifyReconstructedMediaPacket(**it, 1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000266 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000267 // Drop one media packet.
268 BuildAndAddRedFecPacket(fec_packets.front());
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000269 ++it;
brandtr71ca7472016-10-03 05:11:26 -0700270 VerifyReconstructedMediaPacket(**it, 1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000271 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000272}
273
brandtrd55c3f62016-10-31 04:51:33 -0700274TEST_F(UlpfecReceiverTest, OneCompleteOneUnrecoverableFrame) {
brandtr71ca7472016-10-03 05:11:26 -0700275 const size_t kNumFecPackets = 1;
brandtr0aabdac2016-10-03 06:36:43 -0700276 std::list<AugmentedPacket*> augmented_media_packets;
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200277 ForwardErrorCorrection::PacketList media_packets;
brandtra2ece732016-10-04 00:00:06 -0700278 PacketizeFrame(1, 0, &augmented_media_packets, &media_packets);
279 PacketizeFrame(2, 1, &augmented_media_packets, &media_packets);
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000280
brandtr35c480c2016-08-09 01:23:23 -0700281 std::list<ForwardErrorCorrection::Packet*> fec_packets;
brandtr71ca7472016-10-03 05:11:26 -0700282 EncodeFec(media_packets, kNumFecPackets, &fec_packets);
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000283
284 // Recovery
brandtr0aabdac2016-10-03 06:36:43 -0700285 auto it = augmented_media_packets.begin();
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000286 BuildAndAddRedMediaPacket(*it); // First frame: one packet.
brandtr71ca7472016-10-03 05:11:26 -0700287 VerifyReconstructedMediaPacket(**it, 1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000288 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000289 ++it;
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000290 BuildAndAddRedMediaPacket(*it); // First packet of second frame.
brandtr71ca7472016-10-03 05:11:26 -0700291 VerifyReconstructedMediaPacket(**it, 1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000292 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000293}
294
brandtrd55c3f62016-10-31 04:51:33 -0700295TEST_F(UlpfecReceiverTest, MaxFramesOneFec) {
brandtr71ca7472016-10-03 05:11:26 -0700296 const size_t kNumFecPackets = 1;
297 const size_t kNumMediaPackets = 48;
brandtr0aabdac2016-10-03 06:36:43 -0700298 std::list<AugmentedPacket*> augmented_media_packets;
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200299 ForwardErrorCorrection::PacketList media_packets;
brandtr71ca7472016-10-03 05:11:26 -0700300 for (size_t i = 0; i < kNumMediaPackets; ++i) {
brandtra2ece732016-10-04 00:00:06 -0700301 PacketizeFrame(1, i, &augmented_media_packets, &media_packets);
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000302 }
brandtr35c480c2016-08-09 01:23:23 -0700303 std::list<ForwardErrorCorrection::Packet*> fec_packets;
brandtr71ca7472016-10-03 05:11:26 -0700304 EncodeFec(media_packets, kNumFecPackets, &fec_packets);
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000305
306 // Recovery
brandtr0aabdac2016-10-03 06:36:43 -0700307 auto it = augmented_media_packets.begin();
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000308 ++it; // Drop first packet.
brandtr0aabdac2016-10-03 06:36:43 -0700309 for (; it != augmented_media_packets.end(); ++it) {
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000310 BuildAndAddRedMediaPacket(*it);
brandtr71ca7472016-10-03 05:11:26 -0700311 VerifyReconstructedMediaPacket(**it, 1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000312 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000313 }
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000314 BuildAndAddRedFecPacket(fec_packets.front());
brandtr0aabdac2016-10-03 06:36:43 -0700315 it = augmented_media_packets.begin();
brandtr71ca7472016-10-03 05:11:26 -0700316 VerifyReconstructedMediaPacket(**it, 1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000317 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000318}
319
brandtrd55c3f62016-10-31 04:51:33 -0700320TEST_F(UlpfecReceiverTest, TooManyFrames) {
brandtr71ca7472016-10-03 05:11:26 -0700321 const size_t kNumFecPackets = 1;
322 const size_t kNumMediaPackets = 49;
brandtr0aabdac2016-10-03 06:36:43 -0700323 std::list<AugmentedPacket*> augmented_media_packets;
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200324 ForwardErrorCorrection::PacketList media_packets;
brandtr71ca7472016-10-03 05:11:26 -0700325 for (size_t i = 0; i < kNumMediaPackets; ++i) {
brandtra2ece732016-10-04 00:00:06 -0700326 PacketizeFrame(1, i, &augmented_media_packets, &media_packets);
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000327 }
brandtr35c480c2016-08-09 01:23:23 -0700328 std::list<ForwardErrorCorrection::Packet*> fec_packets;
Rasmus Brandt78db1582016-09-21 09:19:34 +0200329 EXPECT_EQ(-1, fec_->EncodeFec(media_packets,
330 kNumFecPackets * 255 / kNumMediaPackets, 0,
331 false, kFecMaskBursty, &fec_packets));
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000332}
333
brandtrd55c3f62016-10-31 04:51:33 -0700334TEST_F(UlpfecReceiverTest, PacketNotDroppedTooEarly) {
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000335 // 1 frame with 2 media packets and one FEC packet. One media packet missing.
336 // Delay the FEC packet.
brandtr71ca7472016-10-03 05:11:26 -0700337 Packet* delayed_fec = nullptr;
338 const size_t kNumFecPacketsBatch1 = 1;
339 const size_t kNumMediaPacketsBatch1 = 2;
brandtr0aabdac2016-10-03 06:36:43 -0700340 std::list<AugmentedPacket*> augmented_media_packets_batch1;
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200341 ForwardErrorCorrection::PacketList media_packets_batch1;
brandtra2ece732016-10-04 00:00:06 -0700342 PacketizeFrame(kNumMediaPacketsBatch1, 0, &augmented_media_packets_batch1,
343 &media_packets_batch1);
brandtr35c480c2016-08-09 01:23:23 -0700344 std::list<ForwardErrorCorrection::Packet*> fec_packets;
brandtr71ca7472016-10-03 05:11:26 -0700345 EncodeFec(media_packets_batch1, kNumFecPacketsBatch1, &fec_packets);
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000346
brandtr0aabdac2016-10-03 06:36:43 -0700347 BuildAndAddRedMediaPacket(augmented_media_packets_batch1.front());
Yves Gerey665174f2018-06-19 15:03:05 +0200348 EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, _)).Times(1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000349 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000350 delayed_fec = fec_packets.front();
351
352 // Fill the FEC decoder. No packets should be dropped.
brandtr71ca7472016-10-03 05:11:26 -0700353 const size_t kNumMediaPacketsBatch2 = 46;
brandtr0aabdac2016-10-03 06:36:43 -0700354 std::list<AugmentedPacket*> augmented_media_packets_batch2;
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200355 ForwardErrorCorrection::PacketList media_packets_batch2;
brandtr71ca7472016-10-03 05:11:26 -0700356 for (size_t i = 0; i < kNumMediaPacketsBatch2; ++i) {
brandtra2ece732016-10-04 00:00:06 -0700357 PacketizeFrame(1, i, &augmented_media_packets_batch2,
358 &media_packets_batch2);
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000359 }
brandtr0aabdac2016-10-03 06:36:43 -0700360 for (auto it = augmented_media_packets_batch2.begin();
361 it != augmented_media_packets_batch2.end(); ++it) {
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000362 BuildAndAddRedMediaPacket(*it);
Yves Gerey665174f2018-06-19 15:03:05 +0200363 EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, _)).Times(1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000364 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000365 }
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000366
367 // Add the delayed FEC packet. One packet should be reconstructed.
368 BuildAndAddRedFecPacket(delayed_fec);
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());
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000371}
372
brandtrd55c3f62016-10-31 04:51:33 -0700373TEST_F(UlpfecReceiverTest, PacketDroppedWhenTooOld) {
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000374 // 1 frame with 2 media packets and one FEC packet. One media packet missing.
375 // Delay the FEC packet.
brandtr71ca7472016-10-03 05:11:26 -0700376 Packet* delayed_fec = nullptr;
377 const size_t kNumFecPacketsBatch1 = 1;
378 const size_t kNumMediaPacketsBatch1 = 2;
brandtr0aabdac2016-10-03 06:36:43 -0700379 std::list<AugmentedPacket*> augmented_media_packets_batch1;
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200380 ForwardErrorCorrection::PacketList media_packets_batch1;
brandtra2ece732016-10-04 00:00:06 -0700381 PacketizeFrame(kNumMediaPacketsBatch1, 0, &augmented_media_packets_batch1,
382 &media_packets_batch1);
brandtr35c480c2016-08-09 01:23:23 -0700383 std::list<ForwardErrorCorrection::Packet*> fec_packets;
brandtr71ca7472016-10-03 05:11:26 -0700384 EncodeFec(media_packets_batch1, kNumFecPacketsBatch1, &fec_packets);
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000385
brandtr0aabdac2016-10-03 06:36:43 -0700386 BuildAndAddRedMediaPacket(augmented_media_packets_batch1.front());
Yves Gerey665174f2018-06-19 15:03:05 +0200387 EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, _)).Times(1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000388 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000389 delayed_fec = fec_packets.front();
390
391 // Fill the FEC decoder and force the last packet to be dropped.
brandtr71ca7472016-10-03 05:11:26 -0700392 const size_t kNumMediaPacketsBatch2 = 48;
brandtr0aabdac2016-10-03 06:36:43 -0700393 std::list<AugmentedPacket*> augmented_media_packets_batch2;
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200394 ForwardErrorCorrection::PacketList media_packets_batch2;
brandtr71ca7472016-10-03 05:11:26 -0700395 for (size_t i = 0; i < kNumMediaPacketsBatch2; ++i) {
brandtra2ece732016-10-04 00:00:06 -0700396 PacketizeFrame(1, i, &augmented_media_packets_batch2,
397 &media_packets_batch2);
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000398 }
brandtr0aabdac2016-10-03 06:36:43 -0700399 for (auto it = augmented_media_packets_batch2.begin();
400 it != augmented_media_packets_batch2.end(); ++it) {
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000401 BuildAndAddRedMediaPacket(*it);
Yves Gerey665174f2018-06-19 15:03:05 +0200402 EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, _)).Times(1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000403 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000404 }
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000405
406 // Add the delayed FEC packet. No packet should be reconstructed since the
407 // first media packet of that frame has been dropped due to being too old.
408 BuildAndAddRedFecPacket(delayed_fec);
nisse30e89312017-05-29 08:16:37 -0700409 EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, _)).Times(0);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000410 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000411}
412
brandtrd55c3f62016-10-31 04:51:33 -0700413TEST_F(UlpfecReceiverTest, OldFecPacketDropped) {
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000414 // 49 frames with 2 media packets and one FEC packet. All media packets
415 // missing.
brandtr71ca7472016-10-03 05:11:26 -0700416 const size_t kNumMediaPackets = 49 * 2;
brandtr0aabdac2016-10-03 06:36:43 -0700417 std::list<AugmentedPacket*> augmented_media_packets;
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200418 ForwardErrorCorrection::PacketList media_packets;
brandtr71ca7472016-10-03 05:11:26 -0700419 for (size_t i = 0; i < kNumMediaPackets / 2; ++i) {
brandtr0aabdac2016-10-03 06:36:43 -0700420 std::list<AugmentedPacket*> frame_augmented_media_packets;
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200421 ForwardErrorCorrection::PacketList frame_media_packets;
brandtr35c480c2016-08-09 01:23:23 -0700422 std::list<ForwardErrorCorrection::Packet*> fec_packets;
brandtra2ece732016-10-04 00:00:06 -0700423 PacketizeFrame(2, 0, &frame_augmented_media_packets, &frame_media_packets);
brandtr71ca7472016-10-03 05:11:26 -0700424 EncodeFec(frame_media_packets, 1, &fec_packets);
Rasmus Brandtae4f7672016-07-07 09:40:51 +0200425 for (auto it = fec_packets.begin(); it != fec_packets.end(); ++it) {
marpan@webrtc.org3a6080d2012-03-30 16:16:21 +0000426 // Only FEC packets inserted. No packets recoverable at this time.
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000427 BuildAndAddRedFecPacket(*it);
nisse30e89312017-05-29 08:16:37 -0700428 EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, _)).Times(0);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000429 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000430 }
brandtr35c480c2016-08-09 01:23:23 -0700431 // Move unique_ptr's to media_packets for lifetime management.
432 media_packets.insert(media_packets.end(),
433 std::make_move_iterator(frame_media_packets.begin()),
434 std::make_move_iterator(frame_media_packets.end()));
brandtr0aabdac2016-10-03 06:36:43 -0700435 augmented_media_packets.insert(augmented_media_packets.end(),
436 frame_augmented_media_packets.begin(),
437 frame_augmented_media_packets.end());
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000438 }
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000439 // Insert the oldest media packet. The corresponding FEC packet is too old
brandtr71ca7472016-10-03 05:11:26 -0700440 // and should have been dropped. Only the media packet we inserted will be
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000441 // returned.
brandtr0aabdac2016-10-03 06:36:43 -0700442 BuildAndAddRedMediaPacket(augmented_media_packets.front());
Yves Gerey665174f2018-06-19 15:03:05 +0200443 EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, _)).Times(1);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000444 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
stefan@webrtc.org7adab092012-02-09 12:34:52 +0000445}
446
brandtrd55c3f62016-10-31 04:51:33 -0700447TEST_F(UlpfecReceiverTest, TruncatedPacketWithFBitSet) {
448 const uint8_t kTruncatedPacket[] = {0x80, 0x2a, 0x68, 0x71, 0x29, 0xa1, 0x27,
449 0x3a, 0x29, 0x12, 0x2a, 0x98, 0xe0, 0x29};
pbos70d5c472015-06-29 07:22:04 -0700450
451 SurvivesMaliciousPacket(kTruncatedPacket, sizeof(kTruncatedPacket), 100);
452}
453
brandtrd55c3f62016-10-31 04:51:33 -0700454TEST_F(UlpfecReceiverTest,
455 TruncatedPacketWithFBitSetEndingAfterFirstRedHeader) {
456 const uint8_t kPacket[] = {
457 0x89, 0x27, 0x3a, 0x83, 0x27, 0x3a, 0x3a, 0xf3, 0x67, 0xbe, 0x2a,
458 0xa9, 0x27, 0x54, 0x3a, 0x3a, 0x2a, 0x67, 0x3a, 0xf3, 0x67, 0xbe,
459 0x2a, 0x27, 0xe6, 0xf6, 0x03, 0x3e, 0x29, 0x27, 0x21, 0x27, 0x2a,
460 0x29, 0x21, 0x4b, 0x29, 0x3a, 0x28, 0x29, 0xbf, 0x29, 0x2a, 0x26,
461 0x29, 0xae, 0x27, 0xa6, 0xf6, 0x00, 0x03, 0x3e};
pbos2e43b262015-06-30 01:32:40 -0700462 SurvivesMaliciousPacket(kPacket, sizeof(kPacket), 100);
463}
464
brandtrd55c3f62016-10-31 04:51:33 -0700465TEST_F(UlpfecReceiverTest, TruncatedPacketWithoutDataPastFirstBlock) {
466 const uint8_t kPacket[] = {
467 0x82, 0x38, 0x92, 0x38, 0x92, 0x38, 0xde, 0x2a, 0x11, 0xc8, 0xa3, 0xc4,
468 0x82, 0x38, 0x2a, 0x21, 0x2a, 0x28, 0x92, 0x38, 0x92, 0x00, 0x00, 0x0a,
469 0x3a, 0xc8, 0xa3, 0x3a, 0x27, 0xc4, 0x2a, 0x21, 0x2a, 0x28};
pbos2e43b262015-06-30 01:32:40 -0700470 SurvivesMaliciousPacket(kPacket, sizeof(kPacket), 100);
471}
472
stefan@webrtc.org2fd1e1e2012-01-30 09:03:37 +0000473} // namespace webrtc