flexfec_receiver_unittest.cc (25329B)
1 /* 2 * Copyright (c) 2016 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 "modules/rtp_rtcp/include/flexfec_receiver.h" 12 13 #include <cstddef> 14 #include <cstdint> 15 #include <limits> 16 #include <list> 17 #include <memory> 18 #include <utility> 19 20 #include "modules/include/module_fec_types.h" 21 #include "modules/rtp_rtcp/include/recovered_packet_receiver.h" 22 #include "modules/rtp_rtcp/mocks/mock_recovered_packet_receiver.h" 23 #include "modules/rtp_rtcp/source/fec_test_helper.h" 24 #include "modules/rtp_rtcp/source/forward_error_correction.h" 25 #include "modules/rtp_rtcp/source/rtp_packet_received.h" 26 #include "modules/rtp_rtcp/source/ulpfec_receiver.h" 27 #include "rtc_base/checks.h" 28 #include "test/gmock.h" 29 #include "test/gtest.h" 30 31 namespace webrtc { 32 33 namespace { 34 35 using ::testing::Eq; 36 using ::testing::Property; 37 38 using test::fec::FlexfecPacketGenerator; 39 using Packet = ForwardErrorCorrection::Packet; 40 using PacketList = ForwardErrorCorrection::PacketList; 41 42 constexpr size_t kPayloadLength = 500; 43 constexpr uint32_t kFlexfecSsrc = 42984; 44 constexpr uint32_t kMediaSsrc = 8353; 45 46 RtpPacketReceived ParsePacket(const Packet& packet) { 47 RtpPacketReceived parsed_packet; 48 EXPECT_TRUE(parsed_packet.Parse(packet.data)); 49 return parsed_packet; 50 } 51 52 } // namespace 53 54 class FlexfecReceiverForTest : public FlexfecReceiver { 55 public: 56 FlexfecReceiverForTest(uint32_t ssrc, 57 uint32_t protected_media_ssrc, 58 RecoveredPacketReceiver* recovered_packet_receiver) 59 : FlexfecReceiver(Clock::GetRealTimeClock(), 60 ssrc, 61 protected_media_ssrc, 62 recovered_packet_receiver) {} 63 // Expose methods for tests. 64 using FlexfecReceiver::AddReceivedPacket; 65 using FlexfecReceiver::ProcessReceivedPacket; 66 }; 67 68 class FlexfecReceiverTest : public ::testing::Test { 69 protected: 70 FlexfecReceiverTest() 71 : receiver_(kFlexfecSsrc, kMediaSsrc, &recovered_packet_receiver_), 72 erasure_code_( 73 ForwardErrorCorrection::CreateFlexfec(kFlexfecSsrc, kMediaSsrc)), 74 packet_generator_(kMediaSsrc, kFlexfecSsrc) {} 75 76 // Generates `num_media_packets` corresponding to a single frame. 77 void PacketizeFrame(size_t num_media_packets, 78 size_t frame_offset, 79 PacketList* media_packets); 80 81 // Generates `num_fec_packets` FEC packets, given `media_packets`. 82 std::list<Packet*> EncodeFec(const PacketList& media_packets, 83 size_t num_fec_packets); 84 85 FlexfecReceiverForTest receiver_; 86 std::unique_ptr<ForwardErrorCorrection> erasure_code_; 87 88 FlexfecPacketGenerator packet_generator_; 89 ::testing::StrictMock<MockRecoveredPacketReceiver> recovered_packet_receiver_; 90 }; 91 92 void FlexfecReceiverTest::PacketizeFrame(size_t num_media_packets, 93 size_t frame_offset, 94 PacketList* media_packets) { 95 packet_generator_.NewFrame(num_media_packets); 96 for (size_t i = 0; i < num_media_packets; ++i) { 97 auto next_packet = std::make_unique<Packet>(); 98 next_packet->data = 99 packet_generator_.NextPacket(frame_offset + i, kPayloadLength).Buffer(); 100 media_packets->push_back(std::move(next_packet)); 101 } 102 } 103 104 std::list<Packet*> FlexfecReceiverTest::EncodeFec( 105 const PacketList& media_packets, 106 size_t num_fec_packets) { 107 const uint8_t protection_factor = 108 num_fec_packets * 255 / media_packets.size(); 109 constexpr int kNumImportantPackets = 0; 110 constexpr bool kUseUnequalProtection = false; 111 constexpr FecMaskType kFecMaskType = kFecMaskRandom; 112 std::list<Packet*> fec_packets; 113 EXPECT_EQ(0, erasure_code_->EncodeFec( 114 media_packets, protection_factor, kNumImportantPackets, 115 kUseUnequalProtection, kFecMaskType, &fec_packets)); 116 EXPECT_EQ(num_fec_packets, fec_packets.size()); 117 return fec_packets; 118 } 119 120 TEST_F(FlexfecReceiverTest, ReceivesMediaPacket) { 121 packet_generator_.NewFrame(1); 122 RtpPacketReceived media_packet = 123 packet_generator_.NextPacket<RtpPacketReceived>(0, kPayloadLength); 124 125 std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet = 126 receiver_.AddReceivedPacket(media_packet); 127 ASSERT_TRUE(received_packet); 128 receiver_.ProcessReceivedPacket(*received_packet); 129 } 130 131 TEST_F(FlexfecReceiverTest, ReceivesMediaAndFecPackets) { 132 const size_t kNumMediaPackets = 1; 133 const size_t kNumFecPackets = 1; 134 135 PacketList media_packets; 136 PacketizeFrame(kNumMediaPackets, 0, &media_packets); 137 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets); 138 const auto& media_packet = media_packets.front(); 139 auto fec_packet = packet_generator_.BuildFlexfecPacket(*fec_packets.front()); 140 141 std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet = 142 receiver_.AddReceivedPacket(ParsePacket(*media_packet)); 143 ASSERT_TRUE(received_packet); 144 receiver_.ProcessReceivedPacket(*received_packet); 145 received_packet = receiver_.AddReceivedPacket(fec_packet); 146 ASSERT_TRUE(received_packet); 147 receiver_.ProcessReceivedPacket(*received_packet); 148 } 149 150 TEST_F(FlexfecReceiverTest, FailsOnTruncatedFecPacket) { 151 const size_t kNumMediaPackets = 1; 152 const size_t kNumFecPackets = 1; 153 154 PacketList media_packets; 155 PacketizeFrame(kNumMediaPackets, 0, &media_packets); 156 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets); 157 const auto& media_packet = media_packets.front(); 158 // Simulate truncated FlexFEC payload. 159 fec_packets.front()->data.SetSize(1); 160 auto fec_packet = packet_generator_.BuildFlexfecPacket(*fec_packets.front()); 161 162 std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet = 163 receiver_.AddReceivedPacket(ParsePacket(*media_packet)); 164 ASSERT_TRUE(received_packet); 165 receiver_.ProcessReceivedPacket(*received_packet); 166 EXPECT_FALSE(receiver_.AddReceivedPacket(fec_packet)); 167 } 168 169 TEST_F(FlexfecReceiverTest, FailsOnUnknownMediaSsrc) { 170 const size_t kNumMediaPackets = 1; 171 172 PacketList media_packets; 173 PacketizeFrame(kNumMediaPackets, 0, &media_packets); 174 auto& media_packet = media_packets.front(); 175 // Corrupt the SSRC. 176 media_packet->data.MutableData()[8] = 0; 177 media_packet->data.MutableData()[9] = 1; 178 media_packet->data.MutableData()[10] = 2; 179 media_packet->data.MutableData()[11] = 3; 180 181 EXPECT_FALSE(receiver_.AddReceivedPacket(ParsePacket(*media_packet))); 182 } 183 184 TEST_F(FlexfecReceiverTest, FailsOnUnknownFecSsrc) { 185 const size_t kNumMediaPackets = 1; 186 const size_t kNumFecPackets = 1; 187 188 PacketList media_packets; 189 PacketizeFrame(kNumMediaPackets, 0, &media_packets); 190 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets); 191 const auto& media_packet = media_packets.front(); 192 auto fec_packet = packet_generator_.BuildFlexfecPacket(*fec_packets.front()); 193 // Corrupt the SSRC. 194 fec_packet.SetSsrc(0x04050607); 195 196 std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet = 197 receiver_.AddReceivedPacket(ParsePacket(*media_packet)); 198 ASSERT_TRUE(received_packet); 199 receiver_.ProcessReceivedPacket(*received_packet); 200 EXPECT_FALSE(receiver_.AddReceivedPacket(fec_packet)); 201 } 202 203 TEST_F(FlexfecReceiverTest, ReceivesMultiplePackets) { 204 const size_t kNumMediaPackets = 2; 205 const size_t kNumFecPackets = 1; 206 207 PacketList media_packets; 208 PacketizeFrame(kNumMediaPackets, 0, &media_packets); 209 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets); 210 211 // Receive all media packets. 212 for (const auto& media_packet : media_packets) { 213 std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet = 214 receiver_.AddReceivedPacket(ParsePacket(*media_packet)); 215 ASSERT_TRUE(received_packet); 216 receiver_.ProcessReceivedPacket(*received_packet); 217 } 218 219 // Receive FEC packet. 220 auto* fec_packet = fec_packets.front(); 221 RtpPacketReceived packet_with_rtp_header = 222 packet_generator_.BuildFlexfecPacket(*fec_packet); 223 std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet = 224 receiver_.AddReceivedPacket(packet_with_rtp_header); 225 ASSERT_TRUE(received_packet); 226 receiver_.ProcessReceivedPacket(*received_packet); 227 } 228 229 TEST_F(FlexfecReceiverTest, RecoversFromSingleMediaLoss) { 230 const size_t kNumMediaPackets = 2; 231 const size_t kNumFecPackets = 1; 232 233 PacketList media_packets; 234 PacketizeFrame(kNumMediaPackets, 0, &media_packets); 235 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets); 236 237 // Receive first media packet but drop second. 238 auto media_it = media_packets.begin(); 239 receiver_.OnRtpPacket(ParsePacket(**media_it)); 240 241 // Receive FEC packet and ensure recovery of lost media packet. 242 auto fec_it = fec_packets.begin(); 243 RtpPacketReceived packet_with_rtp_header = 244 packet_generator_.BuildFlexfecPacket(**fec_it); 245 media_it++; 246 EXPECT_CALL(recovered_packet_receiver_, 247 OnRecoveredPacket( 248 Property(&RtpPacketReceived::Buffer, Eq((*media_it)->data)))); 249 receiver_.OnRtpPacket(packet_with_rtp_header); 250 } 251 252 TEST_F(FlexfecReceiverTest, RecoversFromDoubleMediaLoss) { 253 const size_t kNumMediaPackets = 2; 254 const size_t kNumFecPackets = 2; 255 256 PacketList media_packets; 257 PacketizeFrame(kNumMediaPackets, 0, &media_packets); 258 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets); 259 260 // Drop both media packets. 261 262 // Receive first FEC packet and recover first lost media packet. 263 auto fec_it = fec_packets.begin(); 264 RtpPacketReceived packet_with_rtp_header = 265 packet_generator_.BuildFlexfecPacket(**fec_it); 266 auto media_it = media_packets.begin(); 267 EXPECT_CALL(recovered_packet_receiver_, 268 OnRecoveredPacket( 269 Property(&RtpPacketReceived::Buffer, Eq((*media_it)->data)))); 270 receiver_.OnRtpPacket(packet_with_rtp_header); 271 272 // Receive second FEC packet and recover second lost media packet. 273 fec_it++; 274 packet_with_rtp_header = packet_generator_.BuildFlexfecPacket(**fec_it); 275 media_it++; 276 EXPECT_CALL(recovered_packet_receiver_, 277 OnRecoveredPacket( 278 Property(&RtpPacketReceived::Buffer, Eq((*media_it)->data)))); 279 280 receiver_.OnRtpPacket(packet_with_rtp_header); 281 } 282 283 TEST_F(FlexfecReceiverTest, DoesNotRecoverFromMediaAndFecLoss) { 284 const size_t kNumMediaPackets = 2; 285 const size_t kNumFecPackets = 1; 286 287 PacketList media_packets; 288 PacketizeFrame(kNumMediaPackets, 0, &media_packets); 289 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets); 290 291 // Receive first media packet. 292 auto media_it = media_packets.begin(); 293 receiver_.OnRtpPacket(ParsePacket(**media_it)); 294 295 // Drop second media packet and FEC packet. Do not expect call back. 296 } 297 298 TEST_F(FlexfecReceiverTest, DoesNotCallbackTwice) { 299 const size_t kNumMediaPackets = 2; 300 const size_t kNumFecPackets = 1; 301 302 PacketList media_packets; 303 PacketizeFrame(kNumMediaPackets, 0, &media_packets); 304 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets); 305 306 // Receive first media packet but drop second. 307 auto media_it = media_packets.begin(); 308 receiver_.OnRtpPacket(ParsePacket(**media_it)); 309 310 // Receive FEC packet and ensure recovery of lost media packet. 311 auto fec_it = fec_packets.begin(); 312 RtpPacketReceived packet_with_rtp_header = 313 packet_generator_.BuildFlexfecPacket(**fec_it); 314 media_it++; 315 EXPECT_CALL(recovered_packet_receiver_, 316 OnRecoveredPacket( 317 Property(&RtpPacketReceived::Buffer, Eq((*media_it)->data)))); 318 receiver_.OnRtpPacket(packet_with_rtp_header); 319 320 // Receive the FEC packet again, but do not call back. 321 receiver_.OnRtpPacket(packet_with_rtp_header); 322 323 // Receive the first media packet again, but do not call back. 324 media_it = media_packets.begin(); 325 receiver_.OnRtpPacket(ParsePacket(**media_it)); 326 327 // Receive the second media packet again (the one recovered above), 328 // but do not call back again. 329 media_it++; 330 receiver_.OnRtpPacket(ParsePacket(**media_it)); 331 } 332 333 // Here we are implicitly assuming packet masks that are suitable for 334 // this type of 50% correlated loss. If we are changing our precomputed 335 // packet masks, this test might need to be updated. 336 TEST_F(FlexfecReceiverTest, RecoversFrom50PercentLoss) { 337 const size_t kNumFecPackets = 5; 338 const size_t kNumFrames = 2 * kNumFecPackets; 339 const size_t kNumMediaPacketsPerFrame = 1; 340 341 PacketList media_packets; 342 for (size_t i = 0; i < kNumFrames; ++i) { 343 PacketizeFrame(kNumMediaPacketsPerFrame, i, &media_packets); 344 } 345 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets); 346 347 // Drop every second media packet. 348 auto media_it = media_packets.begin(); 349 while (media_it != media_packets.end()) { 350 receiver_.OnRtpPacket(ParsePacket(**media_it)); 351 ++media_it; 352 if (media_it == media_packets.end()) { 353 break; 354 } 355 ++media_it; 356 } 357 358 // Receive all FEC packets. 359 media_it = media_packets.begin(); 360 for (const auto* fec_packet : fec_packets) { 361 RtpPacketReceived fec_packet_with_rtp_header = 362 packet_generator_.BuildFlexfecPacket(*fec_packet); 363 ++media_it; 364 if (media_it == media_packets.end()) { 365 break; 366 } 367 EXPECT_CALL(recovered_packet_receiver_, 368 OnRecoveredPacket(Property(&RtpPacketReceived::Buffer, 369 Eq((*media_it)->data)))); 370 receiver_.OnRtpPacket(fec_packet_with_rtp_header); 371 ++media_it; 372 } 373 } 374 375 TEST_F(FlexfecReceiverTest, DelayedFecPacketDoesHelp) { 376 // These values need to be updated if the underlying erasure code 377 // implementation changes. 378 // Delay FEC packet by maximum number of media packets tracked by receiver. 379 const size_t kNumFrames = 192; 380 const size_t kNumMediaPacketsPerFrame = 1; 381 const size_t kNumFecPackets = 1; 382 383 PacketList media_packets; 384 PacketizeFrame(kNumMediaPacketsPerFrame, 0, &media_packets); 385 PacketizeFrame(kNumMediaPacketsPerFrame, 1, &media_packets); 386 // Protect two first frames. 387 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets); 388 for (size_t i = 2; i < kNumFrames; ++i) { 389 PacketizeFrame(kNumMediaPacketsPerFrame, i, &media_packets); 390 } 391 392 // Drop first media packet and delay FEC packet. 393 auto media_it = media_packets.begin(); 394 ++media_it; 395 396 // Receive all other media packets. 397 while (media_it != media_packets.end()) { 398 receiver_.OnRtpPacket(ParsePacket(**media_it)); 399 ++media_it; 400 } 401 402 // Receive FEC packet and recover first media packet. 403 auto fec_it = fec_packets.begin(); 404 RtpPacketReceived packet_with_rtp_header = 405 packet_generator_.BuildFlexfecPacket(**fec_it); 406 media_it = media_packets.begin(); 407 EXPECT_CALL(recovered_packet_receiver_, 408 OnRecoveredPacket( 409 Property(&RtpPacketReceived::Buffer, Eq((*media_it)->data)))); 410 receiver_.OnRtpPacket(packet_with_rtp_header); 411 } 412 413 TEST_F(FlexfecReceiverTest, TooDelayedFecPacketDoesNotHelp) { 414 // These values need to be updated if the underlying erasure code 415 // implementation changes. 416 // Delay FEC packet by one more than maximum number of media packets 417 // tracked by receiver. 418 const size_t kNumFrames = 193; 419 const size_t kNumMediaPacketsPerFrame = 1; 420 const size_t kNumFecPackets = 1; 421 422 PacketList media_packets; 423 PacketizeFrame(kNumMediaPacketsPerFrame, 0, &media_packets); 424 PacketizeFrame(kNumMediaPacketsPerFrame, 1, &media_packets); 425 // Protect first two frames. 426 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets); 427 for (size_t i = 2; i < kNumFrames; ++i) { 428 PacketizeFrame(kNumMediaPacketsPerFrame, i, &media_packets); 429 } 430 431 // Drop first media packet and delay FEC packet. 432 auto media_it = media_packets.begin(); 433 ++media_it; 434 435 // Receive all other media packets. 436 while (media_it != media_packets.end()) { 437 receiver_.OnRtpPacket(ParsePacket(**media_it)); 438 ++media_it; 439 } 440 441 // Receive FEC packet. 442 auto fec_it = fec_packets.begin(); 443 RtpPacketReceived packet_with_rtp_header = 444 packet_generator_.BuildFlexfecPacket(**fec_it); 445 receiver_.OnRtpPacket(packet_with_rtp_header); 446 447 // Do not expect a call back. 448 } 449 450 TEST_F(FlexfecReceiverTest, SurvivesOldRecoveredPacketBeingReinserted) { 451 // Simulates the behaviour of the 452 // Call->FlexfecReceiveStream->FlexfecReceiver->Call loop in production code. 453 class LoopbackRecoveredPacketReceiver : public RecoveredPacketReceiver { 454 public: 455 LoopbackRecoveredPacketReceiver() : receiver_(nullptr) {} 456 457 void SetReceiver(FlexfecReceiver* receiver) { receiver_ = receiver; } 458 459 // Implements RecoveredPacketReceiver. 460 void OnRecoveredPacket(const RtpPacketReceived& packet) override { 461 EXPECT_TRUE(packet.recovered()); 462 RTC_DCHECK(receiver_); 463 receiver_->OnRtpPacket(packet); 464 } 465 466 private: 467 FlexfecReceiver* receiver_; 468 } loopback_recovered_packet_receiver; 469 470 // Feed recovered packets back into `receiver`. 471 FlexfecReceiver receiver(Clock::GetRealTimeClock(), kFlexfecSsrc, kMediaSsrc, 472 &loopback_recovered_packet_receiver); 473 loopback_recovered_packet_receiver.SetReceiver(&receiver); 474 475 // Receive first set of packets. 476 PacketList first_media_packets; 477 for (int i = 0; i < 46; ++i) { 478 PacketizeFrame(1, 0, &first_media_packets); 479 } 480 for (const auto& media_packet : first_media_packets) { 481 receiver.OnRtpPacket(ParsePacket(*media_packet)); 482 } 483 484 // Protect one media packet. Lose the media packet, 485 // but do not receive FEC packet yet. 486 PacketList protected_media_packet; 487 PacketizeFrame(1, 0, &protected_media_packet); 488 const std::list<Packet*> fec_packets = EncodeFec(protected_media_packet, 1); 489 EXPECT_EQ(1u, fec_packets.size()); 490 RtpPacketReceived fec_packet_with_rtp_header = 491 packet_generator_.BuildFlexfecPacket(*fec_packets.front()); 492 493 // Lose some packets, thus introducing a sequence number gap. 494 PacketList lost_packets; 495 for (int i = 0; i < 100; ++i) { 496 PacketizeFrame(1, 0, &lost_packets); 497 } 498 499 // Receive one more packet. 500 PacketList second_media_packets; 501 PacketizeFrame(1, 0, &second_media_packets); 502 for (const auto& media_packet : second_media_packets) { 503 receiver.OnRtpPacket(ParsePacket(*media_packet)); 504 } 505 506 // Receive delayed FEC packet. 507 receiver.OnRtpPacket(fec_packet_with_rtp_header); 508 509 // Expect no crash. 510 } 511 512 TEST_F(FlexfecReceiverTest, RecoversWithMediaPacketsOutOfOrder) { 513 const size_t kNumMediaPackets = 6; 514 const size_t kNumFecPackets = 2; 515 516 PacketList media_packets; 517 PacketizeFrame(kNumMediaPackets, 0, &media_packets); 518 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets); 519 520 // Lose two media packets, and receive the others out of order. 521 auto media_it = media_packets.begin(); 522 auto media_packet0 = media_it++; 523 auto media_packet1 = media_it++; 524 auto media_packet2 = media_it++; 525 auto media_packet3 = media_it++; 526 auto media_packet4 = media_it++; 527 auto media_packet5 = media_it++; 528 receiver_.OnRtpPacket(ParsePacket(**media_packet5)); 529 receiver_.OnRtpPacket(ParsePacket(**media_packet2)); 530 receiver_.OnRtpPacket(ParsePacket(**media_packet3)); 531 receiver_.OnRtpPacket(ParsePacket(**media_packet0)); 532 533 // Expect to recover lost media packets. 534 EXPECT_CALL(recovered_packet_receiver_, 535 OnRecoveredPacket(Property(&RtpPacketReceived::Buffer, 536 Eq((*media_packet1)->data)))); 537 EXPECT_CALL(recovered_packet_receiver_, 538 OnRecoveredPacket(Property(&RtpPacketReceived::Buffer, 539 Eq((*media_packet4)->data)))); 540 // Add FEC packets. 541 for (Packet* fec_packet : fec_packets) { 542 receiver_.OnRtpPacket(packet_generator_.BuildFlexfecPacket(*fec_packet)); 543 } 544 } 545 546 // Recovered media packets may be fed back into the FlexfecReceiver by the 547 // callback. This test ensures the idempotency of such a situation. 548 TEST_F(FlexfecReceiverTest, RecoveryCallbackDoesNotLoopInfinitely) { 549 class LoopbackRecoveredPacketReceiver : public RecoveredPacketReceiver { 550 public: 551 const int kMaxRecursionDepth = 10; 552 553 LoopbackRecoveredPacketReceiver() 554 : receiver_(nullptr), 555 did_receive_call_back_(false), 556 recursion_depth_(0), 557 deep_recursion_(false) {} 558 559 void SetReceiver(FlexfecReceiver* receiver) { receiver_ = receiver; } 560 bool DidReceiveCallback() const { return did_receive_call_back_; } 561 bool DeepRecursion() const { return deep_recursion_; } 562 563 // Implements RecoveredPacketReceiver. 564 void OnRecoveredPacket(const RtpPacketReceived& packet) override { 565 did_receive_call_back_ = true; 566 567 if (recursion_depth_ > kMaxRecursionDepth) { 568 deep_recursion_ = true; 569 return; 570 } 571 ++recursion_depth_; 572 RTC_DCHECK(receiver_); 573 receiver_->OnRtpPacket(packet); 574 --recursion_depth_; 575 } 576 577 private: 578 FlexfecReceiver* receiver_; 579 bool did_receive_call_back_; 580 int recursion_depth_; 581 bool deep_recursion_; 582 } loopback_recovered_packet_receiver; 583 584 // Feed recovered packets back into `receiver`. 585 FlexfecReceiver receiver(Clock::GetRealTimeClock(), kFlexfecSsrc, kMediaSsrc, 586 &loopback_recovered_packet_receiver); 587 loopback_recovered_packet_receiver.SetReceiver(&receiver); 588 589 const size_t kNumMediaPackets = 2; 590 const size_t kNumFecPackets = 1; 591 592 PacketList media_packets; 593 PacketizeFrame(kNumMediaPackets, 0, &media_packets); 594 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets); 595 596 // Receive first media packet but drop second. 597 auto media_it = media_packets.begin(); 598 receiver.OnRtpPacket(ParsePacket(**media_it)); 599 600 // Receive FEC packet and verify that a packet was recovered. 601 auto fec_it = fec_packets.begin(); 602 receiver.OnRtpPacket(packet_generator_.BuildFlexfecPacket(**fec_it)); 603 EXPECT_TRUE(loopback_recovered_packet_receiver.DidReceiveCallback()); 604 EXPECT_FALSE(loopback_recovered_packet_receiver.DeepRecursion()); 605 } 606 607 TEST_F(FlexfecReceiverTest, CalculatesNumberOfPackets) { 608 const size_t kNumMediaPackets = 2; 609 const size_t kNumFecPackets = 1; 610 611 PacketList media_packets; 612 PacketizeFrame(kNumMediaPackets, 0, &media_packets); 613 std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets); 614 615 // Receive first media packet but drop second. 616 auto media_it = media_packets.begin(); 617 receiver_.OnRtpPacket(ParsePacket(**media_it)); 618 619 // Receive FEC packet and ensure recovery of lost media packet. 620 auto fec_it = fec_packets.begin(); 621 RtpPacketReceived packet_with_rtp_header = 622 packet_generator_.BuildFlexfecPacket(**fec_it); 623 media_it++; 624 EXPECT_CALL(recovered_packet_receiver_, 625 OnRecoveredPacket( 626 Property(&RtpPacketReceived::Buffer, Eq((*media_it)->data)))); 627 receiver_.OnRtpPacket(packet_with_rtp_header); 628 629 // Check stats calculations. 630 FecPacketCounter packet_counter = receiver_.GetPacketCounter(); 631 EXPECT_EQ(2U, packet_counter.num_packets); 632 EXPECT_EQ(1U, packet_counter.num_fec_packets); 633 EXPECT_EQ(1U, packet_counter.num_recovered_packets); 634 } 635 636 TEST_F(FlexfecReceiverTest, DoesNotDecodeWrappedMediaSequenceUsingOldFec) { 637 const size_t kFirstFrameNumMediaPackets = 2; 638 const size_t kFirstFrameNumFecPackets = 1; 639 640 PacketList media_packets; 641 PacketizeFrame(kFirstFrameNumMediaPackets, 0, &media_packets); 642 643 // Protect first frame (sequences 0 and 1) with 1 FEC packet. 644 std::list<Packet*> fec_packets = 645 EncodeFec(media_packets, kFirstFrameNumFecPackets); 646 647 // Generate enough media packets to simulate media sequence number wraparound. 648 // Use no FEC for these frames to make sure old FEC is not purged due to age. 649 const size_t kNumFramesSequenceWrapAround = 650 std::numeric_limits<uint16_t>::max(); 651 const size_t kNumMediaPacketsPerFrame = 1; 652 653 for (size_t i = 1; i <= kNumFramesSequenceWrapAround; ++i) { 654 PacketizeFrame(kNumMediaPacketsPerFrame, i, &media_packets); 655 } 656 657 // Receive first (`kFirstFrameNumMediaPackets` + 192) media packets. 658 // Simulate an old FEC packet by separating it from its encoded media 659 // packets by at least 192 packets. 660 auto media_it = media_packets.begin(); 661 for (size_t i = 0; i < (kFirstFrameNumMediaPackets + 192); i++) { 662 if (i == 1) { 663 // Drop the second packet of the first frame. 664 media_it++; 665 } else { 666 receiver_.OnRtpPacket(ParsePacket(**media_it++)); 667 } 668 } 669 670 // Receive FEC packet. Although a protected packet was dropped, 671 // expect no recovery callback since it is delayed from first frame 672 // by more than 192 packets. 673 auto fec_it = fec_packets.begin(); 674 receiver_.OnRtpPacket(packet_generator_.BuildFlexfecPacket(**fec_it)); 675 676 // Receive remaining media packets. 677 // NOTE: Because we sent enough to simulate wrap around, sequence 0 is 678 // received again, but is a different packet than the original first 679 // packet of first frame. 680 while (media_it != media_packets.end()) { 681 receiver_.OnRtpPacket(ParsePacket(**media_it++)); 682 } 683 684 // Do not expect a recovery callback, the FEC packet is old 685 // and should not decode wrapped around media sequences. 686 } 687 688 } // namespace webrtc