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 <string.h> 12 13 #include <list> 14 15 #include "testing/gmock/include/gmock/gmock.h" 16 #include "testing/gtest/include/gtest/gtest.h" 17 #include "webrtc/base/scoped_ptr.h" 18 #include "webrtc/modules/rtp_rtcp/include/fec_receiver.h" 19 #include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h" 20 #include "webrtc/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h" 21 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" 22 #include "webrtc/modules/rtp_rtcp/source/fec_test_helper.h" 23 #include "webrtc/modules/rtp_rtcp/source/forward_error_correction.h" 24 25 using ::testing::_; 26 using ::testing::Args; 27 using ::testing::ElementsAreArray; 28 using ::testing::Return; 29 30 namespace webrtc { 31 32 class ReceiverFecTest : public ::testing::Test { 33 protected: 34 virtual void SetUp() { 35 fec_.reset(new ForwardErrorCorrection()); 36 receiver_fec_.reset(FecReceiver::Create(&rtp_data_callback_)); 37 generator_.reset(new FrameGenerator()); 38 } 39 40 void GenerateFEC(std::list<Packet*>* media_packets, 41 std::list<Packet*>* fec_packets, 42 unsigned int num_fec_packets) { 43 uint8_t protection_factor = num_fec_packets * 255 / media_packets->size(); 44 EXPECT_EQ(0, fec_->GenerateFEC(*media_packets, protection_factor, 45 0, false, kFecMaskBursty, fec_packets)); 46 ASSERT_EQ(num_fec_packets, fec_packets->size()); 47 } 48 49 void GenerateFrame(int num_media_packets, int frame_offset, 50 std::list<RtpPacket*>* media_rtp_packets, 51 std::list<Packet*>* media_packets) { 52 generator_->NewFrame(num_media_packets); 53 for (int i = 0; i < num_media_packets; ++i) { 54 media_rtp_packets->push_back( 55 generator_->NextPacket(frame_offset + i, kRtpHeaderSize + 10)); 56 media_packets->push_back(media_rtp_packets->back()); 57 } 58 } 59 60 void VerifyReconstructedMediaPacket(const RtpPacket* packet, int times) { 61 // Verify that the content of the reconstructed packet is equal to the 62 // content of |packet|, and that the same content is received |times| number 63 // of times in a row. 64 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, packet->length)) 65 .With(Args<0, 1>(ElementsAreArray(packet->data, 66 packet->length))) 67 .Times(times).WillRepeatedly(Return(true)); 68 } 69 70 void BuildAndAddRedMediaPacket(RtpPacket* packet) { 71 RtpPacket* red_packet = generator_->BuildMediaRedPacket(packet); 72 EXPECT_EQ(0, receiver_fec_->AddReceivedRedPacket( 73 red_packet->header.header, red_packet->data, 74 red_packet->length, kFecPayloadType)); 75 delete red_packet; 76 } 77 78 void BuildAndAddRedFecPacket(Packet* packet) { 79 RtpPacket* red_packet = generator_->BuildFecRedPacket(packet); 80 EXPECT_EQ(0, receiver_fec_->AddReceivedRedPacket( 81 red_packet->header.header, red_packet->data, 82 red_packet->length, kFecPayloadType)); 83 delete red_packet; 84 } 85 86 void InjectGarbagePacketLength(size_t fec_garbage_offset); 87 static void SurvivesMaliciousPacket(const uint8_t* data, 88 size_t length, 89 uint8_t ulpfec_payload_type); 90 91 MockRtpData rtp_data_callback_; 92 rtc::scoped_ptr<ForwardErrorCorrection> fec_; 93 rtc::scoped_ptr<FecReceiver> receiver_fec_; 94 rtc::scoped_ptr<FrameGenerator> generator_; 95 }; 96 97 void DeletePackets(std::list<Packet*>* packets) { 98 while (!packets->empty()) { 99 delete packets->front(); 100 packets->pop_front(); 101 } 102 } 103 104 TEST_F(ReceiverFecTest, TwoMediaOneFec) { 105 const unsigned int kNumFecPackets = 1u; 106 std::list<RtpPacket*> media_rtp_packets; 107 std::list<Packet*> media_packets; 108 GenerateFrame(2, 0, &media_rtp_packets, &media_packets); 109 std::list<Packet*> fec_packets; 110 GenerateFEC(&media_packets, &fec_packets, kNumFecPackets); 111 112 // Recovery 113 std::list<RtpPacket*>::iterator it = media_rtp_packets.begin(); 114 BuildAndAddRedMediaPacket(*it); 115 VerifyReconstructedMediaPacket(*it, 1); 116 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); 117 // Drop one media packet. 118 std::list<Packet*>::iterator fec_it = fec_packets.begin(); 119 BuildAndAddRedFecPacket(*fec_it); 120 ++it; 121 VerifyReconstructedMediaPacket(*it, 1); 122 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); 123 124 FecPacketCounter counter = receiver_fec_->GetPacketCounter(); 125 EXPECT_EQ(2U, counter.num_packets); 126 EXPECT_EQ(1U, counter.num_fec_packets); 127 EXPECT_EQ(1U, counter.num_recovered_packets); 128 129 DeletePackets(&media_packets); 130 } 131 132 void ReceiverFecTest::InjectGarbagePacketLength(size_t fec_garbage_offset) { 133 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _)) 134 .WillRepeatedly(Return(true)); 135 136 const unsigned int kNumFecPackets = 1u; 137 std::list<RtpPacket*> media_rtp_packets; 138 std::list<Packet*> media_packets; 139 GenerateFrame(2, 0, &media_rtp_packets, &media_packets); 140 std::list<Packet*> fec_packets; 141 GenerateFEC(&media_packets, &fec_packets, kNumFecPackets); 142 ByteWriter<uint16_t>::WriteBigEndian( 143 &fec_packets.front()->data[fec_garbage_offset], 0x4711); 144 145 // Inject first media packet, then first FEC packet, skipping the second media 146 // packet to cause a recovery from the FEC packet. 147 BuildAndAddRedMediaPacket(media_rtp_packets.front()); 148 BuildAndAddRedFecPacket(fec_packets.front()); 149 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); 150 151 FecPacketCounter counter = receiver_fec_->GetPacketCounter(); 152 EXPECT_EQ(2u, counter.num_packets); 153 EXPECT_EQ(1u, counter.num_fec_packets); 154 EXPECT_EQ(0u, counter.num_recovered_packets); 155 156 DeletePackets(&media_packets); 157 } 158 159 TEST_F(ReceiverFecTest, InjectGarbageFecHeaderLengthRecovery) { 160 // Byte offset 8 is the 'length recovery' field of the FEC header. 161 InjectGarbagePacketLength(8); 162 } 163 164 TEST_F(ReceiverFecTest, InjectGarbageFecLevelHeaderProtectionLength) { 165 // Byte offset 10 is the 'protection length' field in the first FEC level 166 // header. 167 InjectGarbagePacketLength(10); 168 } 169 170 TEST_F(ReceiverFecTest, TwoMediaTwoFec) { 171 const unsigned int kNumFecPackets = 2u; 172 std::list<RtpPacket*> media_rtp_packets; 173 std::list<Packet*> media_packets; 174 GenerateFrame(2, 0, &media_rtp_packets, &media_packets); 175 std::list<Packet*> fec_packets; 176 GenerateFEC(&media_packets, &fec_packets, kNumFecPackets); 177 178 // Recovery 179 // Drop both media packets. 180 std::list<RtpPacket*>::iterator it = media_rtp_packets.begin(); 181 std::list<Packet*>::iterator fec_it = fec_packets.begin(); 182 BuildAndAddRedFecPacket(*fec_it); 183 VerifyReconstructedMediaPacket(*it, 1); 184 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); 185 ++fec_it; 186 BuildAndAddRedFecPacket(*fec_it); 187 ++it; 188 VerifyReconstructedMediaPacket(*it, 1); 189 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); 190 191 DeletePackets(&media_packets); 192 } 193 194 TEST_F(ReceiverFecTest, TwoFramesOneFec) { 195 const unsigned int kNumFecPackets = 1u; 196 std::list<RtpPacket*> media_rtp_packets; 197 std::list<Packet*> media_packets; 198 GenerateFrame(1, 0, &media_rtp_packets, &media_packets); 199 GenerateFrame(1, 1, &media_rtp_packets, &media_packets); 200 std::list<Packet*> fec_packets; 201 GenerateFEC(&media_packets, &fec_packets, kNumFecPackets); 202 203 // Recovery 204 std::list<RtpPacket*>::iterator it = media_rtp_packets.begin(); 205 BuildAndAddRedMediaPacket(media_rtp_packets.front()); 206 VerifyReconstructedMediaPacket(*it, 1); 207 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); 208 // Drop one media packet. 209 BuildAndAddRedFecPacket(fec_packets.front()); 210 ++it; 211 VerifyReconstructedMediaPacket(*it, 1); 212 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); 213 214 DeletePackets(&media_packets); 215 } 216 217 TEST_F(ReceiverFecTest, OneCompleteOneUnrecoverableFrame) { 218 const unsigned int kNumFecPackets = 1u; 219 std::list<RtpPacket*> media_rtp_packets; 220 std::list<Packet*> media_packets; 221 GenerateFrame(1, 0, &media_rtp_packets, &media_packets); 222 GenerateFrame(2, 1, &media_rtp_packets, &media_packets); 223 224 std::list<Packet*> fec_packets; 225 GenerateFEC(&media_packets, &fec_packets, kNumFecPackets); 226 227 // Recovery 228 std::list<RtpPacket*>::iterator it = media_rtp_packets.begin(); 229 BuildAndAddRedMediaPacket(*it); // First frame: one packet. 230 VerifyReconstructedMediaPacket(*it, 1); 231 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); 232 ++it; 233 BuildAndAddRedMediaPacket(*it); // First packet of second frame. 234 VerifyReconstructedMediaPacket(*it, 1); 235 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); 236 237 DeletePackets(&media_packets); 238 } 239 240 TEST_F(ReceiverFecTest, MaxFramesOneFec) { 241 const unsigned int kNumFecPackets = 1u; 242 const unsigned int kNumMediaPackets = 48u; 243 std::list<RtpPacket*> media_rtp_packets; 244 std::list<Packet*> media_packets; 245 for (unsigned int i = 0; i < kNumMediaPackets; ++i) { 246 GenerateFrame(1, i, &media_rtp_packets, &media_packets); 247 } 248 std::list<Packet*> fec_packets; 249 GenerateFEC(&media_packets, &fec_packets, kNumFecPackets); 250 251 // Recovery 252 std::list<RtpPacket*>::iterator it = media_rtp_packets.begin(); 253 ++it; // Drop first packet. 254 for (; it != media_rtp_packets.end(); ++it) { 255 BuildAndAddRedMediaPacket(*it); 256 VerifyReconstructedMediaPacket(*it, 1); 257 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); 258 } 259 BuildAndAddRedFecPacket(fec_packets.front()); 260 it = media_rtp_packets.begin(); 261 VerifyReconstructedMediaPacket(*it, 1); 262 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); 263 264 DeletePackets(&media_packets); 265 } 266 267 TEST_F(ReceiverFecTest, TooManyFrames) { 268 const unsigned int kNumFecPackets = 1u; 269 const unsigned int kNumMediaPackets = 49u; 270 std::list<RtpPacket*> media_rtp_packets; 271 std::list<Packet*> media_packets; 272 for (unsigned int i = 0; i < kNumMediaPackets; ++i) { 273 GenerateFrame(1, i, &media_rtp_packets, &media_packets); 274 } 275 std::list<Packet*> fec_packets; 276 EXPECT_EQ(-1, fec_->GenerateFEC(media_packets, 277 kNumFecPackets * 255 / kNumMediaPackets, 0, 278 false, kFecMaskBursty, &fec_packets)); 279 280 DeletePackets(&media_packets); 281 } 282 283 TEST_F(ReceiverFecTest, PacketNotDroppedTooEarly) { 284 // 1 frame with 2 media packets and one FEC packet. One media packet missing. 285 // Delay the FEC packet. 286 Packet* delayed_fec = NULL; 287 const unsigned int kNumFecPacketsBatch1 = 1u; 288 const unsigned int kNumMediaPacketsBatch1 = 2u; 289 std::list<RtpPacket*> media_rtp_packets_batch1; 290 std::list<Packet*> media_packets_batch1; 291 GenerateFrame(kNumMediaPacketsBatch1, 0, &media_rtp_packets_batch1, 292 &media_packets_batch1); 293 std::list<Packet*> fec_packets; 294 GenerateFEC(&media_packets_batch1, &fec_packets, kNumFecPacketsBatch1); 295 296 BuildAndAddRedMediaPacket(media_rtp_packets_batch1.front()); 297 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _)) 298 .Times(1).WillRepeatedly(Return(true)); 299 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); 300 delayed_fec = fec_packets.front(); 301 302 // Fill the FEC decoder. No packets should be dropped. 303 const unsigned int kNumMediaPacketsBatch2 = 46u; 304 std::list<RtpPacket*> media_rtp_packets_batch2; 305 std::list<Packet*> media_packets_batch2; 306 for (unsigned int i = 0; i < kNumMediaPacketsBatch2; ++i) { 307 GenerateFrame(1, i, &media_rtp_packets_batch2, &media_packets_batch2); 308 } 309 for (std::list<RtpPacket*>::iterator it = media_rtp_packets_batch2.begin(); 310 it != media_rtp_packets_batch2.end(); ++it) { 311 BuildAndAddRedMediaPacket(*it); 312 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _)) 313 .Times(1).WillRepeatedly(Return(true)); 314 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); 315 } 316 317 // Add the delayed FEC packet. One packet should be reconstructed. 318 BuildAndAddRedFecPacket(delayed_fec); 319 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _)) 320 .Times(1).WillRepeatedly(Return(true)); 321 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); 322 323 DeletePackets(&media_packets_batch1); 324 DeletePackets(&media_packets_batch2); 325 } 326 327 TEST_F(ReceiverFecTest, PacketDroppedWhenTooOld) { 328 // 1 frame with 2 media packets and one FEC packet. One media packet missing. 329 // Delay the FEC packet. 330 Packet* delayed_fec = NULL; 331 const unsigned int kNumFecPacketsBatch1 = 1u; 332 const unsigned int kNumMediaPacketsBatch1 = 2u; 333 std::list<RtpPacket*> media_rtp_packets_batch1; 334 std::list<Packet*> media_packets_batch1; 335 GenerateFrame(kNumMediaPacketsBatch1, 0, &media_rtp_packets_batch1, 336 &media_packets_batch1); 337 std::list<Packet*> fec_packets; 338 GenerateFEC(&media_packets_batch1, &fec_packets, kNumFecPacketsBatch1); 339 340 BuildAndAddRedMediaPacket(media_rtp_packets_batch1.front()); 341 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _)) 342 .Times(1).WillRepeatedly(Return(true)); 343 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); 344 delayed_fec = fec_packets.front(); 345 346 // Fill the FEC decoder and force the last packet to be dropped. 347 const unsigned int kNumMediaPacketsBatch2 = 48u; 348 std::list<RtpPacket*> media_rtp_packets_batch2; 349 std::list<Packet*> media_packets_batch2; 350 for (unsigned int i = 0; i < kNumMediaPacketsBatch2; ++i) { 351 GenerateFrame(1, i, &media_rtp_packets_batch2, &media_packets_batch2); 352 } 353 for (std::list<RtpPacket*>::iterator it = media_rtp_packets_batch2.begin(); 354 it != media_rtp_packets_batch2.end(); ++it) { 355 BuildAndAddRedMediaPacket(*it); 356 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _)) 357 .Times(1).WillRepeatedly(Return(true)); 358 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); 359 } 360 361 // Add the delayed FEC packet. No packet should be reconstructed since the 362 // first media packet of that frame has been dropped due to being too old. 363 BuildAndAddRedFecPacket(delayed_fec); 364 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _)) 365 .Times(0); 366 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); 367 368 DeletePackets(&media_packets_batch1); 369 DeletePackets(&media_packets_batch2); 370 } 371 372 TEST_F(ReceiverFecTest, OldFecPacketDropped) { 373 // 49 frames with 2 media packets and one FEC packet. All media packets 374 // missing. 375 const unsigned int kNumMediaPackets = 49 * 2; 376 std::list<RtpPacket*> media_rtp_packets; 377 std::list<Packet*> media_packets; 378 for (unsigned int i = 0; i < kNumMediaPackets / 2; ++i) { 379 std::list<RtpPacket*> frame_media_rtp_packets; 380 std::list<Packet*> frame_media_packets; 381 std::list<Packet*> fec_packets; 382 GenerateFrame(2, 0, &frame_media_rtp_packets, &frame_media_packets); 383 GenerateFEC(&frame_media_packets, &fec_packets, 1); 384 for (std::list<Packet*>::iterator it = fec_packets.begin(); 385 it != fec_packets.end(); ++it) { 386 // Only FEC packets inserted. No packets recoverable at this time. 387 BuildAndAddRedFecPacket(*it); 388 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _)) 389 .Times(0); 390 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); 391 } 392 media_packets.insert(media_packets.end(), frame_media_packets.begin(), 393 frame_media_packets.end()); 394 media_rtp_packets.insert(media_rtp_packets.end(), 395 frame_media_rtp_packets.begin(), 396 frame_media_rtp_packets.end()); 397 } 398 // Insert the oldest media packet. The corresponding FEC packet is too old 399 // and should've been dropped. Only the media packet we inserted will be 400 // returned. 401 BuildAndAddRedMediaPacket(media_rtp_packets.front()); 402 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _)) 403 .Times(1).WillRepeatedly(Return(true)); 404 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); 405 406 DeletePackets(&media_packets); 407 } 408 409 void ReceiverFecTest::SurvivesMaliciousPacket(const uint8_t* data, 410 size_t length, 411 uint8_t ulpfec_payload_type) { 412 webrtc::RTPHeader header; 413 rtc::scoped_ptr<webrtc::RtpHeaderParser> parser( 414 webrtc::RtpHeaderParser::Create()); 415 ASSERT_TRUE(parser->Parse(data, length, &header)); 416 417 webrtc::NullRtpData null_callback; 418 rtc::scoped_ptr<webrtc::FecReceiver> receiver_fec( 419 webrtc::FecReceiver::Create(&null_callback)); 420 421 receiver_fec->AddReceivedRedPacket(header, data, length, ulpfec_payload_type); 422 } 423 424 TEST_F(ReceiverFecTest, TruncatedPacketWithFBitSet) { 425 const uint8_t kTruncatedPacket[] = {0x80, 426 0x2a, 427 0x68, 428 0x71, 429 0x29, 430 0xa1, 431 0x27, 432 0x3a, 433 0x29, 434 0x12, 435 0x2a, 436 0x98, 437 0xe0, 438 0x29}; 439 440 SurvivesMaliciousPacket(kTruncatedPacket, sizeof(kTruncatedPacket), 100); 441 } 442 443 TEST_F(ReceiverFecTest, TruncatedPacketWithFBitSetEndingAfterFirstRedHeader) { 444 const uint8_t kPacket[] = {0x89, 445 0x27, 446 0x3a, 447 0x83, 448 0x27, 449 0x3a, 450 0x3a, 451 0xf3, 452 0x67, 453 0xbe, 454 0x2a, 455 0xa9, 456 0x27, 457 0x54, 458 0x3a, 459 0x3a, 460 0x2a, 461 0x67, 462 0x3a, 463 0xf3, 464 0x67, 465 0xbe, 466 0x2a, 467 0x27, 468 0xe6, 469 0xf6, 470 0x03, 471 0x3e, 472 0x29, 473 0x27, 474 0x21, 475 0x27, 476 0x2a, 477 0x29, 478 0x21, 479 0x4b, 480 0x29, 481 0x3a, 482 0x28, 483 0x29, 484 0xbf, 485 0x29, 486 0x2a, 487 0x26, 488 0x29, 489 0xae, 490 0x27, 491 0xa6, 492 0xf6, 493 0x00, 494 0x03, 495 0x3e}; 496 SurvivesMaliciousPacket(kPacket, sizeof(kPacket), 100); 497 } 498 499 TEST_F(ReceiverFecTest, TruncatedPacketWithoutDataPastFirstBlock) { 500 const uint8_t kPacket[] = {0x82, 501 0x38, 502 0x92, 503 0x38, 504 0x92, 505 0x38, 506 0xde, 507 0x2a, 508 0x11, 509 0xc8, 510 0xa3, 511 0xc4, 512 0x82, 513 0x38, 514 0x2a, 515 0x21, 516 0x2a, 517 0x28, 518 0x92, 519 0x38, 520 0x92, 521 0x00, 522 0x00, 523 0x0a, 524 0x3a, 525 0xc8, 526 0xa3, 527 0x3a, 528 0x27, 529 0xc4, 530 0x2a, 531 0x21, 532 0x2a, 533 0x28}; 534 SurvivesMaliciousPacket(kPacket, sizeof(kPacket), 100); 535 } 536 537 } // namespace webrtc 538