diff --git a/modules/rtp_rtcp/source/forward_error_correction.cc b/modules/rtp_rtcp/source/forward_error_correction.cc index 23c9fa08cd..33829c4fb2 100644 --- a/modules/rtp_rtcp/source/forward_error_correction.cc +++ b/modules/rtp_rtcp/source/forward_error_correction.cc @@ -165,6 +165,9 @@ int ForwardErrorCorrection::EncodeFec(const PacketList& media_packets, // Adapt packet masks to missing media packets. int num_mask_bits = InsertZerosInPacketMasks(media_packets, num_fec_packets); if (num_mask_bits < 0) { + RTC_LOG(LS_INFO) << "Due to sequence number gaps, cannot protect media " + "packets with a single block of FEC packets."; + fec_packets->clear(); return -1; } packet_mask_size_ = internal::PacketMaskSize(num_mask_bits); diff --git a/modules/rtp_rtcp/source/rtp_fec_unittest.cc b/modules/rtp_rtcp/source/rtp_fec_unittest.cc index 606dafbbf2..1abed150f1 100644 --- a/modules/rtp_rtcp/source/rtp_fec_unittest.cc +++ b/modules/rtp_rtcp/source/rtp_fec_unittest.cc @@ -31,6 +31,8 @@ constexpr size_t kTransportOverhead = 28; constexpr uint32_t kMediaSsrc = 83542; constexpr uint32_t kFlexfecSsrc = 43245; +constexpr size_t kMaxMediaPackets = 48; + // Deep copies |src| to |dst|, but only keeps every Nth packet. void DeepCopyEveryNthPacket(const ForwardErrorCorrection::PacketList& src, int n, @@ -217,6 +219,51 @@ using FecTypes = Types; TYPED_TEST_CASE(RtpFecTest, FecTypes); +TYPED_TEST(RtpFecTest, WillProtectMediaPacketsWithLargeSequenceNumberGap) { + constexpr int kNumImportantPackets = 0; + constexpr bool kUseUnequalProtection = false; + constexpr int kNumMediaPackets = 2; + constexpr uint8_t kProtectionFactor = 127; + + this->media_packets_ = + this->media_packet_generator_.ConstructMediaPackets(kNumMediaPackets); + + // Create |kMaxMediaPackets - 1| sequence number difference. + ByteWriter::WriteBigEndian(&this->media_packets_.front()->data[2], + 1); + ByteWriter::WriteBigEndian(&this->media_packets_.back()->data[2], + kMaxMediaPackets); + + EXPECT_EQ( + 0, this->fec_.EncodeFec(this->media_packets_, kProtectionFactor, + kNumImportantPackets, kUseUnequalProtection, + kFecMaskBursty, &this->generated_fec_packets_)); + EXPECT_EQ(1u, this->generated_fec_packets_.size()); +} + +TYPED_TEST(RtpFecTest, + WillNotProtectMediaPacketsWithTooLargeSequenceNumberGap) { + constexpr int kNumImportantPackets = 0; + constexpr bool kUseUnequalProtection = false; + constexpr int kNumMediaPackets = 2; + constexpr uint8_t kProtectionFactor = 127; + + this->media_packets_ = + this->media_packet_generator_.ConstructMediaPackets(kNumMediaPackets); + + // Create |kMaxMediaPackets| sequence number difference. + ByteWriter::WriteBigEndian(&this->media_packets_.front()->data[2], + 1); + ByteWriter::WriteBigEndian(&this->media_packets_.back()->data[2], + kMaxMediaPackets + 1); + + EXPECT_EQ( + -1, this->fec_.EncodeFec(this->media_packets_, kProtectionFactor, + kNumImportantPackets, kUseUnequalProtection, + kFecMaskBursty, &this->generated_fec_packets_)); + EXPECT_TRUE(this->generated_fec_packets_.empty()); +} + TYPED_TEST(RtpFecTest, FecRecoveryNoLoss) { constexpr int kNumImportantPackets = 0; constexpr bool kUseUnequalProtection = false;