1/* 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 11#include <list> 12 13#include "testing/gtest/include/gtest/gtest.h" 14#include "webrtc/base/random.h" 15#include "webrtc/modules/rtp_rtcp/source/byte_io.h" 16#include "webrtc/modules/rtp_rtcp/source/forward_error_correction.h" 17 18using webrtc::ForwardErrorCorrection; 19 20// Minimum RTP header size in bytes. 21const uint8_t kRtpHeaderSize = 12; 22 23// Transport header size in bytes. Assume UDP/IPv4 as a reasonable minimum. 24const uint8_t kTransportOverhead = 28; 25 26// Maximum number of media packets used in the FEC (RFC 5109). 27const uint8_t kMaxNumberMediaPackets = ForwardErrorCorrection::kMaxMediaPackets; 28 29typedef std::list<ForwardErrorCorrection::Packet*> PacketList; 30typedef std::list<ForwardErrorCorrection::ReceivedPacket*> ReceivedPacketList; 31typedef std::list<ForwardErrorCorrection::RecoveredPacket*> RecoveredPacketList; 32 33template <typename T> void ClearList(std::list<T*>* my_list) { 34 T* packet = NULL; 35 while (!my_list->empty()) { 36 packet = my_list->front(); 37 delete packet; 38 my_list->pop_front(); 39 } 40} 41 42class RtpFecTest : public ::testing::Test { 43 protected: 44 RtpFecTest() 45 : random_(0xfec133700742), 46 fec_(new ForwardErrorCorrection()), 47 ssrc_(random_.Rand<uint32_t>()), 48 fec_seq_num_(0) {} 49 50 webrtc::Random random_; 51 ForwardErrorCorrection* fec_; 52 int ssrc_; 53 uint16_t fec_seq_num_; 54 55 PacketList media_packet_list_; 56 PacketList fec_packet_list_; 57 ReceivedPacketList received_packet_list_; 58 RecoveredPacketList recovered_packet_list_; 59 60 // Media packet "i" is lost if media_loss_mask_[i] = 1, 61 // received if media_loss_mask_[i] = 0. 62 int media_loss_mask_[kMaxNumberMediaPackets]; 63 64 // FEC packet "i" is lost if fec_loss_mask_[i] = 1, 65 // received if fec_loss_mask_[i] = 0. 66 int fec_loss_mask_[kMaxNumberMediaPackets]; 67 68 // Construct the media packet list, up to |num_media_packets| packets. 69 // Returns the next sequence number after the last media packet. 70 // (this will be the sequence of the first FEC packet) 71 int ConstructMediaPacketsSeqNum(int num_media_packets, int start_seq_num); 72 int ConstructMediaPackets(int num_media_packets); 73 74 // Construct the received packet list: a subset of the media and FEC packets. 75 void NetworkReceivedPackets(); 76 77 // Add packet from |packet_list| to list of received packets, using the 78 // |loss_mask|. 79 // The |packet_list| may be a media packet list (is_fec = false), or a 80 // FEC packet list (is_fec = true). 81 void ReceivedPackets(const PacketList& packet_list, int* loss_mask, 82 bool is_fec); 83 84 // Check for complete recovery after FEC decoding. 85 bool IsRecoveryComplete(); 86 87 // Delete the received packets. 88 void FreeRecoveredPacketList(); 89 90 // Delete the media and FEC packets. 91 void TearDown(); 92}; 93 94TEST_F(RtpFecTest, FecRecoveryNoLoss) { 95 const int kNumImportantPackets = 0; 96 const bool kUseUnequalProtection = false; 97 const int kNumMediaPackets = 4; 98 uint8_t kProtectionFactor = 60; 99 100 fec_seq_num_ = ConstructMediaPackets(kNumMediaPackets); 101 102 EXPECT_EQ(0, fec_->GenerateFEC(media_packet_list_, kProtectionFactor, 103 kNumImportantPackets, kUseUnequalProtection, 104 webrtc::kFecMaskBursty, &fec_packet_list_)); 105 106 // Expect 1 FEC packet. 107 EXPECT_EQ(1, static_cast<int>(fec_packet_list_.size())); 108 109 // No packets lost. 110 memset(media_loss_mask_, 0, sizeof(media_loss_mask_)); 111 memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_)); 112 NetworkReceivedPackets(); 113 114 EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_, 115 &recovered_packet_list_)); 116 117 // No packets lost, expect complete recovery. 118 EXPECT_TRUE(IsRecoveryComplete()); 119} 120 121TEST_F(RtpFecTest, FecRecoveryWithLoss) { 122 const int kNumImportantPackets = 0; 123 const bool kUseUnequalProtection = false; 124 const int kNumMediaPackets = 4; 125 uint8_t kProtectionFactor = 60; 126 127 fec_seq_num_ = ConstructMediaPackets(kNumMediaPackets); 128 129 EXPECT_EQ(0, fec_->GenerateFEC(media_packet_list_, kProtectionFactor, 130 kNumImportantPackets, kUseUnequalProtection, 131 webrtc::kFecMaskBursty, &fec_packet_list_)); 132 133 // Expect 1 FEC packet. 134 EXPECT_EQ(1, static_cast<int>(fec_packet_list_.size())); 135 136 // 1 media packet lost 137 memset(media_loss_mask_, 0, sizeof(media_loss_mask_)); 138 memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_)); 139 media_loss_mask_[3] = 1; 140 NetworkReceivedPackets(); 141 142 EXPECT_EQ(0, 143 fec_->DecodeFEC(&received_packet_list_, &recovered_packet_list_)); 144 145 // One packet lost, one FEC packet, expect complete recovery. 146 EXPECT_TRUE(IsRecoveryComplete()); 147 FreeRecoveredPacketList(); 148 149 // 2 media packets lost. 150 memset(media_loss_mask_, 0, sizeof(media_loss_mask_)); 151 memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_)); 152 media_loss_mask_[1] = 1; 153 media_loss_mask_[3] = 1; 154 NetworkReceivedPackets(); 155 156 EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_, 157 &recovered_packet_list_)); 158 159 // 2 packets lost, one FEC packet, cannot get complete recovery. 160 EXPECT_FALSE(IsRecoveryComplete()); 161} 162 163// Verify that we don't use an old FEC packet for FEC decoding. 164TEST_F(RtpFecTest, FecRecoveryWithSeqNumGapTwoFrames) { 165 const int kNumImportantPackets = 0; 166 const bool kUseUnequalProtection = false; 167 uint8_t kProtectionFactor = 20; 168 169 // Two frames: first frame (old) with two media packets and 1 FEC packet. 170 // Second frame (new) with 3 media packets, and no FEC packets. 171 // ---Frame 1---- ----Frame 2------ 172 // #0(media) #1(media) #2(FEC) #65535(media) #0(media) #1(media). 173 // If we lose either packet 0 or 1 of second frame, FEC decoding should not 174 // try to decode using "old" FEC packet #2. 175 176 // Construct media packets for first frame, starting at sequence number 0. 177 fec_seq_num_ = ConstructMediaPacketsSeqNum(2, 0); 178 179 EXPECT_EQ(0, fec_->GenerateFEC(media_packet_list_, kProtectionFactor, 180 kNumImportantPackets, kUseUnequalProtection, 181 webrtc::kFecMaskBursty, &fec_packet_list_)); 182 // Expect 1 FEC packet. 183 EXPECT_EQ(1, static_cast<int>(fec_packet_list_.size())); 184 // Add FEC packet (seq#2) of this first frame to received list (i.e., assume 185 // the two media packet were lost). 186 memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_)); 187 ReceivedPackets(fec_packet_list_, fec_loss_mask_, true); 188 189 // Construct media packets for second frame, with sequence number wrap. 190 ClearList(&media_packet_list_); 191 fec_seq_num_ = ConstructMediaPacketsSeqNum(3, 65535); 192 193 // Expect 3 media packets for this frame. 194 EXPECT_EQ(3, static_cast<int>(media_packet_list_.size())); 195 196 // Second media packet lost (seq#0). 197 memset(media_loss_mask_, 0, sizeof(media_loss_mask_)); 198 media_loss_mask_[1] = 1; 199 // Add packets #65535, and #1 to received list. 200 ReceivedPackets(media_packet_list_, media_loss_mask_, false); 201 202 EXPECT_EQ(0, 203 fec_->DecodeFEC(&received_packet_list_, &recovered_packet_list_)); 204 205 // Expect that no decoding is done to get missing packet (seq#0) of second 206 // frame, using old FEC packet (seq#2) from first (old) frame. So number of 207 // recovered packets is 2, and not equal to number of media packets (=3). 208 EXPECT_EQ(2, static_cast<int>(recovered_packet_list_.size())); 209 EXPECT_TRUE(recovered_packet_list_.size() != media_packet_list_.size()); 210 FreeRecoveredPacketList(); 211} 212 213// Verify we can still recovery frame if sequence number wrap occurs within 214// the frame and FEC packet following wrap is received after media packets. 215TEST_F(RtpFecTest, FecRecoveryWithSeqNumGapOneFrameRecovery) { 216 const int kNumImportantPackets = 0; 217 const bool kUseUnequalProtection = false; 218 uint8_t kProtectionFactor = 20; 219 220 // One frame, with sequence number wrap in media packets. 221 // -----Frame 1---- 222 // #65534(media) #65535(media) #0(media) #1(FEC). 223 fec_seq_num_ = ConstructMediaPacketsSeqNum(3, 65534); 224 225 EXPECT_EQ(0, fec_->GenerateFEC(media_packet_list_, kProtectionFactor, 226 kNumImportantPackets, kUseUnequalProtection, 227 webrtc::kFecMaskBursty, &fec_packet_list_)); 228 229 // Expect 1 FEC packet. 230 EXPECT_EQ(1, static_cast<int>(fec_packet_list_.size())); 231 232 // Lose one media packet (seq# 65535). 233 memset(media_loss_mask_, 0, sizeof(media_loss_mask_)); 234 memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_)); 235 media_loss_mask_[1] = 1; 236 ReceivedPackets(media_packet_list_, media_loss_mask_, false); 237 // Add FEC packet to received list following the media packets. 238 ReceivedPackets(fec_packet_list_, fec_loss_mask_, true); 239 240 EXPECT_EQ(0, 241 fec_->DecodeFEC(&received_packet_list_, &recovered_packet_list_)); 242 243 // Expect 3 media packets in recovered list, and complete recovery. 244 // Wrap-around won't remove FEC packet, as it follows the wrap. 245 EXPECT_EQ(3, static_cast<int>(recovered_packet_list_.size())); 246 EXPECT_TRUE(IsRecoveryComplete()); 247 FreeRecoveredPacketList(); 248} 249 250// Sequence number wrap occurs within the FEC packets for the frame. 251// In this case we will discard FEC packet and full recovery is not expected. 252// Same problem will occur if wrap is within media packets but FEC packet is 253// received before the media packets. This may be improved if timing information 254// is used to detect old FEC packets. 255// TODO(marpan): Update test if wrap-around handling changes in FEC decoding. 256TEST_F(RtpFecTest, FecRecoveryWithSeqNumGapOneFrameNoRecovery) { 257 const int kNumImportantPackets = 0; 258 const bool kUseUnequalProtection = false; 259 uint8_t kProtectionFactor = 200; 260 261 // 1 frame: 3 media packets and 2 FEC packets. 262 // Sequence number wrap in FEC packets. 263 // -----Frame 1---- 264 // #65532(media) #65533(media) #65534(media) #65535(FEC) #0(FEC). 265 fec_seq_num_ = ConstructMediaPacketsSeqNum(3, 65532); 266 267 EXPECT_EQ(0, fec_->GenerateFEC(media_packet_list_, kProtectionFactor, 268 kNumImportantPackets, kUseUnequalProtection, 269 webrtc::kFecMaskBursty, &fec_packet_list_)); 270 271 // Expect 2 FEC packets. 272 EXPECT_EQ(2, static_cast<int>(fec_packet_list_.size())); 273 274 // Lose the last two media packets (seq# 65533, 65534). 275 memset(media_loss_mask_, 0, sizeof(media_loss_mask_)); 276 memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_)); 277 media_loss_mask_[1] = 1; 278 media_loss_mask_[2] = 1; 279 ReceivedPackets(media_packet_list_, media_loss_mask_, false); 280 ReceivedPackets(fec_packet_list_, fec_loss_mask_, true); 281 282 EXPECT_EQ(0, 283 fec_->DecodeFEC(&received_packet_list_, &recovered_packet_list_)); 284 285 // The two FEC packets are received and should allow for complete recovery, 286 // but because of the wrap the second FEC packet will be discarded, and only 287 // one media packet is recoverable. So exepct 2 media packets on recovered 288 // list and no complete recovery. 289 EXPECT_EQ(2, static_cast<int>(recovered_packet_list_.size())); 290 EXPECT_TRUE(recovered_packet_list_.size() != media_packet_list_.size()); 291 EXPECT_FALSE(IsRecoveryComplete()); 292 FreeRecoveredPacketList(); 293} 294 295// Verify we can still recovery frame if FEC is received before media packets. 296TEST_F(RtpFecTest, FecRecoveryWithFecOutOfOrder) { 297 const int kNumImportantPackets = 0; 298 const bool kUseUnequalProtection = false; 299 uint8_t kProtectionFactor = 20; 300 301 // One frame: 3 media packets, 1 FEC packet. 302 // -----Frame 1---- 303 // #0(media) #1(media) #2(media) #3(FEC). 304 fec_seq_num_ = ConstructMediaPacketsSeqNum(3, 0); 305 306 EXPECT_EQ(0, fec_->GenerateFEC(media_packet_list_, kProtectionFactor, 307 kNumImportantPackets, kUseUnequalProtection, 308 webrtc::kFecMaskBursty, &fec_packet_list_)); 309 310 // Expect 1 FEC packet. 311 EXPECT_EQ(1, static_cast<int>(fec_packet_list_.size())); 312 313 // Lose one media packet (seq# 1). 314 memset(media_loss_mask_, 0, sizeof(media_loss_mask_)); 315 memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_)); 316 media_loss_mask_[1] = 1; 317 // Add FEC packet to received list before the media packets. 318 ReceivedPackets(fec_packet_list_, fec_loss_mask_, true); 319 // Add media packets to received list. 320 ReceivedPackets(media_packet_list_, media_loss_mask_, false); 321 322 EXPECT_EQ(0, 323 fec_->DecodeFEC(&received_packet_list_, &recovered_packet_list_)); 324 325 // Expect 3 media packets in recovered list, and complete recovery. 326 EXPECT_EQ(3, static_cast<int>(recovered_packet_list_.size())); 327 EXPECT_TRUE(IsRecoveryComplete()); 328 FreeRecoveredPacketList(); 329} 330 331// Test 50% protection with random mask type: Two cases are considered: 332// a 50% non-consecutive loss which can be fully recovered, and a 50% 333// consecutive loss which cannot be fully recovered. 334TEST_F(RtpFecTest, FecRecoveryWithLoss50percRandomMask) { 335 const int kNumImportantPackets = 0; 336 const bool kUseUnequalProtection = false; 337 const int kNumMediaPackets = 4; 338 const uint8_t kProtectionFactor = 255; 339 340 // Packet Mask for (4,4,0) code, from random mask table. 341 // (kNumMediaPackets = 4; num_fec_packets = 4, kNumImportantPackets = 0) 342 343 // media#0 media#1 media#2 media#3 344 // fec#0: 1 1 0 0 345 // fec#1: 1 0 1 0 346 // fec#2: 0 0 1 1 347 // fec#3: 0 1 0 1 348 // 349 350 fec_seq_num_ = ConstructMediaPackets(kNumMediaPackets); 351 352 EXPECT_EQ(0, fec_->GenerateFEC(media_packet_list_, kProtectionFactor, 353 kNumImportantPackets, kUseUnequalProtection, 354 webrtc::kFecMaskRandom, &fec_packet_list_)); 355 356 // Expect 4 FEC packets. 357 EXPECT_EQ(4, static_cast<int>(fec_packet_list_.size())); 358 359 // 4 packets lost: 3 media packets (0, 2, 3), and one FEC packet (0) lost. 360 memset(media_loss_mask_, 0, sizeof(media_loss_mask_)); 361 memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_)); 362 fec_loss_mask_[0] = 1; 363 media_loss_mask_[0] = 1; 364 media_loss_mask_[2] = 1; 365 media_loss_mask_[3] = 1; 366 NetworkReceivedPackets(); 367 368 EXPECT_EQ(0, 369 fec_->DecodeFEC(&received_packet_list_, &recovered_packet_list_)); 370 371 // With media packet#1 and FEC packets #1, #2, #3, expect complete recovery. 372 EXPECT_TRUE(IsRecoveryComplete()); 373 FreeRecoveredPacketList(); 374 375 // 4 consecutive packets lost: media packets 0, 1, 2, 3. 376 memset(media_loss_mask_, 0, sizeof(media_loss_mask_)); 377 memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_)); 378 media_loss_mask_[0] = 1; 379 media_loss_mask_[1] = 1; 380 media_loss_mask_[2] = 1; 381 media_loss_mask_[3] = 1; 382 NetworkReceivedPackets(); 383 384 EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_, 385 &recovered_packet_list_)); 386 387 // Cannot get complete recovery for this loss configuration with random mask. 388 EXPECT_FALSE(IsRecoveryComplete()); 389} 390 391// Test 50% protection with bursty type: Three cases are considered: 392// two 50% consecutive losses which can be fully recovered, and one 393// non-consecutive which cannot be fully recovered. 394TEST_F(RtpFecTest, FecRecoveryWithLoss50percBurstyMask) { 395 const int kNumImportantPackets = 0; 396 const bool kUseUnequalProtection = false; 397 const int kNumMediaPackets = 4; 398 const uint8_t kProtectionFactor = 255; 399 400 // Packet Mask for (4,4,0) code, from bursty mask table. 401 // (kNumMediaPackets = 4; num_fec_packets = 4, kNumImportantPackets = 0) 402 403 // media#0 media#1 media#2 media#3 404 // fec#0: 1 0 0 0 405 // fec#1: 1 1 0 0 406 // fec#2: 0 1 1 0 407 // fec#3: 0 0 1 1 408 // 409 410 fec_seq_num_ = ConstructMediaPackets(kNumMediaPackets); 411 412 EXPECT_EQ(0, fec_->GenerateFEC(media_packet_list_, kProtectionFactor, 413 kNumImportantPackets, kUseUnequalProtection, 414 webrtc::kFecMaskBursty, &fec_packet_list_)); 415 416 // Expect 4 FEC packets. 417 EXPECT_EQ(4, static_cast<int>(fec_packet_list_.size())); 418 419 // 4 consecutive packets lost: media packets 0,1,2,3. 420 memset(media_loss_mask_, 0, sizeof(media_loss_mask_)); 421 memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_)); 422 media_loss_mask_[0] = 1; 423 media_loss_mask_[1] = 1; 424 media_loss_mask_[2] = 1; 425 media_loss_mask_[3] = 1; 426 NetworkReceivedPackets(); 427 428 EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_, 429 &recovered_packet_list_)); 430 431 // Expect complete recovery for consecutive packet loss <= 50%. 432 EXPECT_TRUE(IsRecoveryComplete()); 433 FreeRecoveredPacketList(); 434 435 // 4 consecutive packets lost: media packets 1,2, 3, and FEC packet 0. 436 memset(media_loss_mask_, 0, sizeof(media_loss_mask_)); 437 memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_)); 438 fec_loss_mask_[0] = 1; 439 media_loss_mask_[1] = 1; 440 media_loss_mask_[2] = 1; 441 media_loss_mask_[3] = 1; 442 NetworkReceivedPackets(); 443 444 EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_, 445 &recovered_packet_list_)); 446 447 // Expect complete recovery for consecutive packet loss <= 50%. 448 EXPECT_TRUE(IsRecoveryComplete()); 449 FreeRecoveredPacketList(); 450 451 // 4 packets lost (non-consecutive loss): media packets 0, 3, and FEC# 0, 3. 452 memset(media_loss_mask_, 0, sizeof(media_loss_mask_)); 453 memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_)); 454 fec_loss_mask_[0] = 1; 455 fec_loss_mask_[3] = 1; 456 media_loss_mask_[0] = 1; 457 media_loss_mask_[3] = 1; 458 NetworkReceivedPackets(); 459 460 EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_, 461 &recovered_packet_list_)); 462 463 // Cannot get complete recovery for this loss configuration. 464 EXPECT_FALSE(IsRecoveryComplete()); 465} 466 467TEST_F(RtpFecTest, FecRecoveryNoLossUep) { 468 const int kNumImportantPackets = 2; 469 const bool kUseUnequalProtection = true; 470 const int kNumMediaPackets = 4; 471 const uint8_t kProtectionFactor = 60; 472 473 fec_seq_num_ = ConstructMediaPackets(kNumMediaPackets); 474 475 EXPECT_EQ(0, fec_->GenerateFEC(media_packet_list_, kProtectionFactor, 476 kNumImportantPackets, kUseUnequalProtection, 477 webrtc::kFecMaskBursty, &fec_packet_list_)); 478 479 // Expect 1 FEC packet. 480 EXPECT_EQ(1, static_cast<int>(fec_packet_list_.size())); 481 482 // No packets lost. 483 memset(media_loss_mask_, 0, sizeof(media_loss_mask_)); 484 memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_)); 485 NetworkReceivedPackets(); 486 487 EXPECT_EQ(0, 488 fec_->DecodeFEC(&received_packet_list_, &recovered_packet_list_)); 489 490 // No packets lost, expect complete recovery. 491 EXPECT_TRUE(IsRecoveryComplete()); 492} 493 494TEST_F(RtpFecTest, FecRecoveryWithLossUep) { 495 const int kNumImportantPackets = 2; 496 const bool kUseUnequalProtection = true; 497 const int kNumMediaPackets = 4; 498 const uint8_t kProtectionFactor = 60; 499 500 fec_seq_num_ = ConstructMediaPackets(kNumMediaPackets); 501 502 EXPECT_EQ(0, fec_->GenerateFEC(media_packet_list_, kProtectionFactor, 503 kNumImportantPackets, kUseUnequalProtection, 504 webrtc::kFecMaskBursty, &fec_packet_list_)); 505 506 // Expect 1 FEC packet. 507 EXPECT_EQ(1, static_cast<int>(fec_packet_list_.size())); 508 509 // 1 media packet lost. 510 memset(media_loss_mask_, 0, sizeof(media_loss_mask_)); 511 memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_)); 512 media_loss_mask_[3] = 1; 513 NetworkReceivedPackets(); 514 515 EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_, 516 &recovered_packet_list_)); 517 518 // One packet lost, one FEC packet, expect complete recovery. 519 EXPECT_TRUE(IsRecoveryComplete()); 520 FreeRecoveredPacketList(); 521 522 // 2 media packets lost. 523 memset(media_loss_mask_, 0, sizeof(media_loss_mask_)); 524 memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_)); 525 media_loss_mask_[1] = 1; 526 media_loss_mask_[3] = 1; 527 NetworkReceivedPackets(); 528 529 EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_, 530 &recovered_packet_list_)); 531 532 // 2 packets lost, one FEC packet, cannot get complete recovery. 533 EXPECT_FALSE(IsRecoveryComplete()); 534} 535 536// Test 50% protection with random mask type for UEP on. 537TEST_F(RtpFecTest, FecRecoveryWithLoss50percUepRandomMask) { 538 const int kNumImportantPackets = 1; 539 const bool kUseUnequalProtection = true; 540 const int kNumMediaPackets = 4; 541 const uint8_t kProtectionFactor = 255; 542 543 // Packet Mask for (4,4,1) code, from random mask table. 544 // (kNumMediaPackets = 4; num_fec_packets = 4, kNumImportantPackets = 1) 545 546 // media#0 media#1 media#2 media#3 547 // fec#0: 1 0 0 0 548 // fec#1: 1 1 0 0 549 // fec#2: 1 0 1 1 550 // fec#3: 0 1 1 0 551 // 552 553 fec_seq_num_ = ConstructMediaPackets(kNumMediaPackets); 554 555 EXPECT_EQ(0, fec_->GenerateFEC(media_packet_list_, kProtectionFactor, 556 kNumImportantPackets, kUseUnequalProtection, 557 webrtc::kFecMaskRandom, &fec_packet_list_)); 558 559 // Expect 4 FEC packets. 560 EXPECT_EQ(4, static_cast<int>(fec_packet_list_.size())); 561 562 // 4 packets lost: 3 media packets and FEC packet#1 lost. 563 memset(media_loss_mask_, 0, sizeof(media_loss_mask_)); 564 memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_)); 565 fec_loss_mask_[1] = 1; 566 media_loss_mask_[0] = 1; 567 media_loss_mask_[2] = 1; 568 media_loss_mask_[3] = 1; 569 NetworkReceivedPackets(); 570 571 EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_, 572 &recovered_packet_list_)); 573 574 // With media packet#3 and FEC packets #0, #1, #3, expect complete recovery. 575 EXPECT_TRUE(IsRecoveryComplete()); 576 FreeRecoveredPacketList(); 577 578 // 5 packets lost: 4 media packets and one FEC packet#2 lost. 579 memset(media_loss_mask_, 0, sizeof(media_loss_mask_)); 580 memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_)); 581 fec_loss_mask_[2] = 1; 582 media_loss_mask_[0] = 1; 583 media_loss_mask_[1] = 1; 584 media_loss_mask_[2] = 1; 585 media_loss_mask_[3] = 1; 586 NetworkReceivedPackets(); 587 588 EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_, 589 &recovered_packet_list_)); 590 591 // Cannot get complete recovery for this loss configuration. 592 EXPECT_FALSE(IsRecoveryComplete()); 593} 594 595TEST_F(RtpFecTest, FecRecoveryNonConsecutivePackets) { 596 const int kNumImportantPackets = 0; 597 const bool kUseUnequalProtection = false; 598 const int kNumMediaPackets = 5; 599 uint8_t kProtectionFactor = 60; 600 601 fec_seq_num_ = ConstructMediaPackets(kNumMediaPackets); 602 603 // Create a new temporary packet list for generating FEC packets. 604 // This list should have every other packet removed. 605 PacketList protected_media_packets; 606 int i = 0; 607 for (PacketList::iterator it = media_packet_list_.begin(); 608 it != media_packet_list_.end(); ++it, ++i) { 609 if (i % 2 == 0) protected_media_packets.push_back(*it); 610 } 611 612 EXPECT_EQ(0, fec_->GenerateFEC(protected_media_packets, kProtectionFactor, 613 kNumImportantPackets, kUseUnequalProtection, 614 webrtc::kFecMaskBursty, &fec_packet_list_)); 615 616 // Expect 1 FEC packet. 617 EXPECT_EQ(1, static_cast<int>(fec_packet_list_.size())); 618 619 // 1 protected media packet lost 620 memset(media_loss_mask_, 0, sizeof(media_loss_mask_)); 621 memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_)); 622 media_loss_mask_[2] = 1; 623 NetworkReceivedPackets(); 624 625 EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_, 626 &recovered_packet_list_)); 627 628 // One packet lost, one FEC packet, expect complete recovery. 629 EXPECT_TRUE(IsRecoveryComplete()); 630 FreeRecoveredPacketList(); 631 632 // Unprotected packet lost. 633 memset(media_loss_mask_, 0, sizeof(media_loss_mask_)); 634 memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_)); 635 media_loss_mask_[1] = 1; 636 NetworkReceivedPackets(); 637 638 EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_, 639 &recovered_packet_list_)); 640 641 // Unprotected packet lost. Recovery not possible. 642 EXPECT_FALSE(IsRecoveryComplete()); 643 FreeRecoveredPacketList(); 644 645 // 2 media packets lost. 646 memset(media_loss_mask_, 0, sizeof(media_loss_mask_)); 647 memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_)); 648 media_loss_mask_[0] = 1; 649 media_loss_mask_[2] = 1; 650 NetworkReceivedPackets(); 651 652 EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_, 653 &recovered_packet_list_)); 654 655 // 2 protected packets lost, one FEC packet, cannot get complete recovery. 656 EXPECT_FALSE(IsRecoveryComplete()); 657} 658 659TEST_F(RtpFecTest, FecRecoveryNonConsecutivePacketsExtension) { 660 const int kNumImportantPackets = 0; 661 const bool kUseUnequalProtection = false; 662 const int kNumMediaPackets = 21; 663 uint8_t kProtectionFactor = 127; 664 665 fec_seq_num_ = ConstructMediaPackets(kNumMediaPackets); 666 667 // Create a new temporary packet list for generating FEC packets. 668 // This list should have every other packet removed. 669 PacketList protected_media_packets; 670 int i = 0; 671 for (PacketList::iterator it = media_packet_list_.begin(); 672 it != media_packet_list_.end(); ++it, ++i) { 673 if (i % 2 == 0) protected_media_packets.push_back(*it); 674 } 675 676 // Zero column insertion will have to extend the size of the packet 677 // mask since the number of actual packets are 21, while the number 678 // of protected packets are 11. 679 EXPECT_EQ(0, fec_->GenerateFEC(protected_media_packets, kProtectionFactor, 680 kNumImportantPackets, kUseUnequalProtection, 681 webrtc::kFecMaskBursty, &fec_packet_list_)); 682 683 // Expect 5 FEC packet. 684 EXPECT_EQ(5, static_cast<int>(fec_packet_list_.size())); 685 686 // Last protected media packet lost 687 memset(media_loss_mask_, 0, sizeof(media_loss_mask_)); 688 memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_)); 689 media_loss_mask_[kNumMediaPackets - 1] = 1; 690 NetworkReceivedPackets(); 691 692 EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_, 693 &recovered_packet_list_)); 694 695 // One packet lost, one FEC packet, expect complete recovery. 696 EXPECT_TRUE(IsRecoveryComplete()); 697 FreeRecoveredPacketList(); 698 699 // Last unprotected packet lost. 700 memset(media_loss_mask_, 0, sizeof(media_loss_mask_)); 701 memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_)); 702 media_loss_mask_[kNumMediaPackets - 2] = 1; 703 NetworkReceivedPackets(); 704 705 EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_, 706 &recovered_packet_list_)); 707 708 // Unprotected packet lost. Recovery not possible. 709 EXPECT_FALSE(IsRecoveryComplete()); 710 FreeRecoveredPacketList(); 711 712 // 6 media packets lost. 713 memset(media_loss_mask_, 0, sizeof(media_loss_mask_)); 714 memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_)); 715 media_loss_mask_[kNumMediaPackets - 11] = 1; 716 media_loss_mask_[kNumMediaPackets - 9] = 1; 717 media_loss_mask_[kNumMediaPackets - 7] = 1; 718 media_loss_mask_[kNumMediaPackets - 5] = 1; 719 media_loss_mask_[kNumMediaPackets - 3] = 1; 720 media_loss_mask_[kNumMediaPackets - 1] = 1; 721 NetworkReceivedPackets(); 722 723 EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_, 724 &recovered_packet_list_)); 725 726 // 5 protected packets lost, one FEC packet, cannot get complete recovery. 727 EXPECT_FALSE(IsRecoveryComplete()); 728} 729 730TEST_F(RtpFecTest, FecRecoveryNonConsecutivePacketsWrap) { 731 const int kNumImportantPackets = 0; 732 const bool kUseUnequalProtection = false; 733 const int kNumMediaPackets = 21; 734 uint8_t kProtectionFactor = 127; 735 736 fec_seq_num_ = ConstructMediaPacketsSeqNum(kNumMediaPackets, 0xFFFF - 5); 737 738 // Create a new temporary packet list for generating FEC packets. 739 // This list should have every other packet removed. 740 PacketList protected_media_packets; 741 int i = 0; 742 for (PacketList::iterator it = media_packet_list_.begin(); 743 it != media_packet_list_.end(); ++it, ++i) { 744 if (i % 2 == 0) protected_media_packets.push_back(*it); 745 } 746 747 // Zero column insertion will have to extend the size of the packet 748 // mask since the number of actual packets are 21, while the number 749 // of protected packets are 11. 750 EXPECT_EQ(0, fec_->GenerateFEC(protected_media_packets, kProtectionFactor, 751 kNumImportantPackets, kUseUnequalProtection, 752 webrtc::kFecMaskBursty, &fec_packet_list_)); 753 754 // Expect 5 FEC packet. 755 EXPECT_EQ(5, static_cast<int>(fec_packet_list_.size())); 756 757 // Last protected media packet lost 758 memset(media_loss_mask_, 0, sizeof(media_loss_mask_)); 759 memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_)); 760 media_loss_mask_[kNumMediaPackets - 1] = 1; 761 NetworkReceivedPackets(); 762 763 EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_, 764 &recovered_packet_list_)); 765 766 // One packet lost, one FEC packet, expect complete recovery. 767 EXPECT_TRUE(IsRecoveryComplete()); 768 FreeRecoveredPacketList(); 769 770 // Last unprotected packet lost. 771 memset(media_loss_mask_, 0, sizeof(media_loss_mask_)); 772 memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_)); 773 media_loss_mask_[kNumMediaPackets - 2] = 1; 774 NetworkReceivedPackets(); 775 776 EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_, 777 &recovered_packet_list_)); 778 779 // Unprotected packet lost. Recovery not possible. 780 EXPECT_FALSE(IsRecoveryComplete()); 781 FreeRecoveredPacketList(); 782 783 // 6 media packets lost. 784 memset(media_loss_mask_, 0, sizeof(media_loss_mask_)); 785 memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_)); 786 media_loss_mask_[kNumMediaPackets - 11] = 1; 787 media_loss_mask_[kNumMediaPackets - 9] = 1; 788 media_loss_mask_[kNumMediaPackets - 7] = 1; 789 media_loss_mask_[kNumMediaPackets - 5] = 1; 790 media_loss_mask_[kNumMediaPackets - 3] = 1; 791 media_loss_mask_[kNumMediaPackets - 1] = 1; 792 NetworkReceivedPackets(); 793 794 EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_, 795 &recovered_packet_list_)); 796 797 // 5 protected packets lost, one FEC packet, cannot get complete recovery. 798 EXPECT_FALSE(IsRecoveryComplete()); 799} 800 801void RtpFecTest::TearDown() { 802 fec_->ResetState(&recovered_packet_list_); 803 delete fec_; 804 FreeRecoveredPacketList(); 805 ClearList(&media_packet_list_); 806 EXPECT_TRUE(media_packet_list_.empty()); 807} 808 809void RtpFecTest::FreeRecoveredPacketList() { 810 ClearList(&recovered_packet_list_); 811} 812 813bool RtpFecTest::IsRecoveryComplete() { 814 // Check that the number of media and recovered packets are equal. 815 if (media_packet_list_.size() != recovered_packet_list_.size()) { 816 return false; 817 } 818 819 ForwardErrorCorrection::Packet* media_packet; 820 ForwardErrorCorrection::RecoveredPacket* recovered_packet; 821 822 bool recovery = true; 823 824 PacketList::iterator media_packet_list_item = media_packet_list_.begin(); 825 RecoveredPacketList::iterator recovered_packet_list_item = 826 recovered_packet_list_.begin(); 827 while (media_packet_list_item != media_packet_list_.end()) { 828 if (recovered_packet_list_item == recovered_packet_list_.end()) { 829 return false; 830 } 831 media_packet = *media_packet_list_item; 832 recovered_packet = *recovered_packet_list_item; 833 if (recovered_packet->pkt->length != media_packet->length) { 834 return false; 835 } 836 if (memcmp(recovered_packet->pkt->data, media_packet->data, 837 media_packet->length) != 0) { 838 return false; 839 } 840 media_packet_list_item++; 841 recovered_packet_list_item++; 842 } 843 return recovery; 844} 845 846void RtpFecTest::NetworkReceivedPackets() { 847 const bool kFecPacket = true; 848 ReceivedPackets(media_packet_list_, media_loss_mask_, !kFecPacket); 849 ReceivedPackets(fec_packet_list_, fec_loss_mask_, kFecPacket); 850} 851 852void RtpFecTest::ReceivedPackets(const PacketList& packet_list, int* loss_mask, 853 bool is_fec) { 854 ForwardErrorCorrection::Packet* packet; 855 ForwardErrorCorrection::ReceivedPacket* received_packet; 856 int seq_num = fec_seq_num_; 857 int packet_idx = 0; 858 859 PacketList::const_iterator packet_list_item = packet_list.begin(); 860 861 while (packet_list_item != packet_list.end()) { 862 packet = *packet_list_item; 863 if (loss_mask[packet_idx] == 0) { 864 received_packet = new ForwardErrorCorrection::ReceivedPacket; 865 received_packet->pkt = new ForwardErrorCorrection::Packet; 866 received_packet_list_.push_back(received_packet); 867 received_packet->pkt->length = packet->length; 868 memcpy(received_packet->pkt->data, packet->data, packet->length); 869 received_packet->is_fec = is_fec; 870 if (!is_fec) { 871 // For media packets, the sequence number and marker bit is 872 // obtained from RTP header. These were set in ConstructMediaPackets(). 873 received_packet->seq_num = 874 webrtc::ByteReader<uint16_t>::ReadBigEndian(&packet->data[2]); 875 } else { 876 // The sequence number, marker bit, and ssrc number are defined in the 877 // RTP header of the FEC packet, which is not constructed in this test. 878 // So we set these values below based on the values generated in 879 // ConstructMediaPackets(). 880 received_packet->seq_num = seq_num; 881 // The ssrc value for FEC packets is set to the one used for the 882 // media packets in ConstructMediaPackets(). 883 received_packet->ssrc = ssrc_; 884 } 885 } 886 packet_idx++; 887 packet_list_item++; 888 // Sequence number of FEC packets are defined as increment by 1 from 889 // last media packet in frame. 890 if (is_fec) seq_num++; 891 } 892} 893 894int RtpFecTest::ConstructMediaPacketsSeqNum(int num_media_packets, 895 int start_seq_num) { 896 assert(num_media_packets > 0); 897 ForwardErrorCorrection::Packet* media_packet = NULL; 898 int sequence_number = start_seq_num; 899 int time_stamp = random_.Rand<int>(); 900 901 for (int i = 0; i < num_media_packets; ++i) { 902 media_packet = new ForwardErrorCorrection::Packet; 903 media_packet_list_.push_back(media_packet); 904 const uint32_t kMinPacketSize = kRtpHeaderSize; 905 const uint32_t kMaxPacketSize = IP_PACKET_SIZE - kRtpHeaderSize - 906 kTransportOverhead - 907 ForwardErrorCorrection::PacketOverhead(); 908 media_packet->length = random_.Rand(kMinPacketSize, kMaxPacketSize); 909 910 // Generate random values for the first 2 bytes 911 media_packet->data[0] = random_.Rand<uint8_t>(); 912 media_packet->data[1] = random_.Rand<uint8_t>(); 913 914 // The first two bits are assumed to be 10 by the FEC encoder. 915 // In fact the FEC decoder will set the two first bits to 10 regardless of 916 // what they actually were. Set the first two bits to 10 so that a memcmp 917 // can be performed for the whole restored packet. 918 media_packet->data[0] |= 0x80; 919 media_packet->data[0] &= 0xbf; 920 921 // FEC is applied to a whole frame. 922 // A frame is signaled by multiple packets without the marker bit set 923 // followed by the last packet of the frame for which the marker bit is set. 924 // Only push one (fake) frame to the FEC. 925 media_packet->data[1] &= 0x7f; 926 927 webrtc::ByteWriter<uint16_t>::WriteBigEndian(&media_packet->data[2], 928 sequence_number); 929 webrtc::ByteWriter<uint32_t>::WriteBigEndian(&media_packet->data[4], 930 time_stamp); 931 webrtc::ByteWriter<uint32_t>::WriteBigEndian(&media_packet->data[8], ssrc_); 932 933 // Generate random values for payload. 934 for (size_t j = 12; j < media_packet->length; ++j) { 935 media_packet->data[j] = random_.Rand<uint8_t>(); 936 } 937 sequence_number++; 938 } 939 // Last packet, set marker bit. 940 assert(media_packet != NULL); 941 media_packet->data[1] |= 0x80; 942 return sequence_number; 943} 944 945int RtpFecTest::ConstructMediaPackets(int num_media_packets) { 946 return ConstructMediaPacketsSeqNum(num_media_packets, random_.Rand<int>()); 947} 948